I am trying to send data from a Windows 10 computer to a Basys 3 board (Artix7 FPGA). I am using UART, and the data is entered via PuTTY, at 9600 bauds, with a stop bit and no parity. My VHDL module is based on a Finite State Machine (FSM), and two internal signals ensure the correct sampling (middle of the received bits).
To test my VHDL module, I drive 8 LEDs on the board according to the received data.
The problem : I manage to switch on / off the LEDs, but it doesn't seem to correspond to anyting (wrong ASCII code, or no difference between different key inputs...). So it seems I well receive data (TX lits on the Basys 3), but it is not processed correctly, and I cannot find why ! Could you please help me finding what's wrong ?
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;
Question
greg765
Hello everybody,
I am trying to send data from a Windows 10 computer to a Basys 3 board (Artix7 FPGA). I am using UART, and the data is entered via PuTTY, at 9600 bauds, with a stop bit and no parity. My VHDL module is based on a Finite State Machine (FSM), and two internal signals ensure the correct sampling (middle of the received bits).
To test my VHDL module, I drive 8 LEDs on the board according to the received data.
The problem : I manage to switch on / off the LEDs, but it doesn't seem to correspond to anyting (wrong ASCII code, or no difference between different key inputs...). So it seems I well receive data (TX lits on the Basys 3), but it is not processed correctly, and I cannot find why ! Could you please help me finding what's wrong ?
****** EDIT 1 ***********************
I forgot to say that I tried to use another module found on the Internet ( https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html ), without any success (same issue).
******* END OF EDIT 1 **********
Please find hereafter my VHDL code & my .xdc :
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;
Link to comment
Share on other sites
15 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.