Windows 10 컴퓨터에서 BASYS 3 보드 (ARTIX7 FPGA)로 데이터를 보내야하는 프로젝트가 있습니다. UART를 사용합니다. 전송할 데이터는 PuTTY 시리얼 콘솔에 입력됩니다.컴퓨터와 BASYS 3 FPGA 간의 UART 통신
테스트 목적으로 보드에 8 개의 LED를 사용하여 수신 된 데이터를 표시하기로 결정했습니다.
나는 Vivado 2016.4를 사용하고 있습니다.
내가 가지고있는 문제는 내가 LED에 얻는 데이터가 있어야하는 것과 완전히 다릅니다. PuTTY의 전송 속도와 VHDL 모듈 간의 동기화 문제라고 생각합니다.
.vhd 파일이 프로젝트의 .xdc 파일 이하 발견 사항 :하여 .vhd은 유한 상태 머신 (FSM)에 기초
를 상기 동기 있도록 두 개의 신호가있다 :
은tick_UART : 10417 클럭주기마다 틱합니다. 클럭주기가 10ns이기 때문에 tick_UART는 초당 9600 번 올라갑니다 (9600 보에서 사용할 예정입니다).
double_tick_UART : 중간에있는 비트를 샘플링하는 데 사용되는 tick_UART의 빈도의 두 배입니다.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port (RxD : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7, stop); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
begin
process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if (raz='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif clk = '1' and clk'event then
if compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if (raz='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif clk = '1' and clk'event then
if double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD = '0' then -- Si front descendant de RxD et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start => if double_tick_UART = '1' then
state <= demiStart;
RAZ_tick_UART <= '0';
end if;
data_out <= "00000000";
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= stop;
end if;
when stop => if tick_UART = '1' then
state <= idle; -- Renvoi en idle
end if;
end case;
end if;
end process;
end Behavioral;
XDC 파일 :
## Clock signal
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## LEDs
set_property PACKAGE_PIN U16 [get_ports data_out[0]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[0]]
set_property PACKAGE_PIN E19 [get_ports data_out[1]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[1]]
set_property PACKAGE_PIN U19 [get_ports data_out[2]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[2]]
set_property PACKAGE_PIN V19 [get_ports data_out[3]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[3]]
set_property PACKAGE_PIN W18 [get_ports data_out[4]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[4]]
set_property PACKAGE_PIN U15 [get_ports data_out[5]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[5]]
set_property PACKAGE_PIN U14 [get_ports data_out[6]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[6]]
set_property PACKAGE_PIN V14 [get_ports data_out[7]]
set_property IOSTANDARD LVCMOS33 [get_ports data_out[7]]
##Buttons
set_property PACKAGE_PIN T18 [get_ports RAZ]
set_property IOSTANDARD LVCMOS33 [get_ports RAZ]
##USB-RS232 Interface
set_property PACKAGE_PIN B18 [get_ports RxD]
set_property IOSTANDARD LVCMOS33 [get_ports RxD]
당신이 어떤 실수를 발견 하는가?
나는 또 다른 .vhd (자신이 쓴 것이 아니며 작동해야 함)를 사용하려고했습니다. 이 작동하지 않았다 중 하나 https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html는 은 (내가 아니라 내 시계 & 전송 속도에 따라 일반 g_CLKS_PER_BIT 수정)
문제는 퍼티에서 올 수 있지만 9600 보드, 8 데이터의 전송 속도를 설정 한 비트, 1 정지 비트, 패리티 없음, 그래서 내가 뭘 잘못 볼 수 없어!
이상한 것을 찾을 수 없기 때문에 더 많은 아이디어/의견이 있으시면!
대단히 감사합니다!
편집 2017년 3월 16일 :
는 @ J.H.Bonarius & @ recommandations user1155120 후, 나는 내 100 MHz 클럭 도메인으로 때 RxD 입력 신호를 동기화하는 2 단계 플립 플롭 동기를 추가했다.
또한 수정 된 일부 비동기식 재설정을 수정했습니다. 그럼에도 불구하고, 나는 여전히 동일한 문제를 가지고 있습니다 (LED는 PuTTY를 통해 전송 된 것과 일치하지 않습니다).
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_RX is
Port (RxD_in : in STD_LOGIC;
clk : in STD_LOGIC;
RAZ : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end UART_RX;
architecture Behavioral of UART_RX is
signal tick_UART : STD_LOGIC; -- Signal "top" passage d'un état à l'autre selon vitesse connexion série
signal double_tick_UART : STD_LOGIC; -- Signal précédent, fréquence * 2
signal compteur_tick_UART : integer range 0 to 10420; -- Compteur pour tick_UART
signal double_compteur_tick_UART : integer range 0 to 5210; -- Compteur pour demi-périodes
type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7); -- Etats de la FSM
signal state :state_type := idle; -- Etat par défaut
signal RAZ_tick_UART : STD_LOGIC; -- RAZ du signal tick_UART;
signal RxD_temp : STD_LOGIC; -- RxD provisoire entre deux FF
signal RxD_sync : STD_LOGIC; -- RxD synchronisé sur l'horloge
begin
D_flip_flop_1:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_temp <= RxD_in;
end if;
end process;
D_flip_flop_2:process(clk) -- Clock crossing
begin
if clk = '1' and clk'event then
RxD_sync <= RxD_temp;
end if;
end process;
tickUART:process(clk, RAZ, state, RAZ_tick_UART) -- Compteur classique (tick_UART)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) or (RAZ_tick_UART = '1') then
compteur_tick_UART <= 0;
tick_UART <= '0';
elsif compteur_tick_UART = 10417 then
tick_UART <= '1';
compteur_tick_UART <= 0;
else
compteur_tick_UART <= compteur_tick_UART + 1;
tick_UART <= '0';
end if;
end if;
end process;
doubleTickUART:process(clk, RAZ, state) -- Compteur demi-périodes (double_tick_UART car fréquence double)
begin
if clk = '1' and clk'event then
if (RAZ='1') or (state = idle) then
double_compteur_tick_UART <= 0;
double_tick_UART <= '0';
elsif double_compteur_tick_UART = 5209 then
double_tick_UART <= '1';
double_compteur_tick_UART <= 0;
else
double_compteur_tick_UART <= double_compteur_tick_UART + 1;
double_tick_UART <= '0';
end if;
end if;
end process;
fsm:process(clk, RAZ) -- Machine à état
begin
if (RAZ = '1') then
state <= idle;
data_out <= "00000000";
RAZ_tick_UART <= '1';
elsif clk = '1' and clk'event then
case state is
when idle => if RxD_sync = '0' then -- Si front descendant de RxD (= bit de start) et en idle
state <= start;
RAZ_tick_UART <= '1';
end if;
when start =>if double_tick_UART = '1' then -- Demi période écoulée (pour échantillonage)
state <= demiStart;
RAZ_tick_UART <= '0'; -- Le compteur tick_UART commence à compter
end if;
data_out <= "00000000"; -- Reset des anciennes données
when demiStart => if tick_UART = '1' then
state <= b0;
RAZ_tick_UART <= '0';
end if;
data_out(0) <= RxD_sync; -- Acquisition bit 0
when b0 => if tick_UART = '1' then
state <= b1;
end if;
data_out(1) <= RxD_sync; -- Acquisition bit 1
when b1 => if tick_UART = '1' then
state <= b2;
end if;
data_out(2) <= RxD_sync; -- Acquisition bit 2
when b2 => if tick_UART = '1' then
state <= b3;
end if;
data_out(3) <= RxD_sync; -- Acquisition bit 3
when b3 => if tick_UART = '1' then
state <= b4;
end if;
data_out(4) <= RxD_sync; -- Acquisition bit 4
when b4 => if tick_UART = '1' then
state <= b5;
end if;
data_out(5) <= RxD_sync; -- Acquisition bit 5
when b5 => if tick_UART = '1' then
state <= b6;
end if;
data_out(6) <= RxD_sync; -- Acquisition bit 6
when b6 => if tick_UART = '1' then
state <= b7;
end if;
data_out(7) <= RxD_sync; -- Acquisition bit 7
when b7 => if tick_UART = '1' then
state <= idle; -- state <= stop;
end if;
end case;
end if;
end process;
end Behavioral;
당신은 내 문제의 근원에 대해 어떤 생각을 가지고 있습니까 :
는 hearafter에게 새로운하여 .vhd 코드를 찾기? 대단히 감사합니다!
uart_rx는 비트 당 클럭 수에 대한 추가 일반을 시뮬레이션합니다 (시뮬레이션에서 클럭 수를 줄이기 위해). JHB가 rxd에 맞춰 플립 플롭 (두 개는 100MHz 클럭을 기준으로 함)을 넣는 것이 좋습니다. – user1155120
질문을 편집 할 때 업데이트가 제공되지 않습니다. 그러나 어쨌든 : 아마도 RS232 입력 신호 동작을 시뮬레이션하기 위해 테스트 벤치를 작성해야합니다. 그렇다면 코드가 잘못되었는지, 그리고 무엇이 잘못되었는지 확인할 수 있습니다. 합성 전에 코드를 테스트하는 것은 항상 좋은 생각입니다 ... – JHBonarius