greg765

Members
  • Content Count

    5
  • Joined

  • Last visited

About greg765

  • Rank
    Newbie

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. @hamster : Indeed, 0x55 = 85, so nothing to worry about. I didn't think about hexa... I've run the simulation, the results are the ones I expect, so I tried the project on the board, and it works fine ! The LEDs display the expected combination for a very small amount of time, then display the 13 number, which in ASCII is carriage return, which is normal. I've tested multiple inputs, one after another, and it works after multiple consecutive inputs. The data valid seems to work as well. I would like to thank everybody who helped me improve my code for this project. Special thanks to @D@n for his long answers with many useful information !
  2. I didn't think there would be a conflict betwwen the two RST_UART_counter, but now I understand why. I'm too used to classic programming languages and get easily confused with hardware description... I moved the RST_UART_counter <= '0' to the next state, as follows : when idle => if RxD_sync = '0' then -- If in idle and low level detected on RxD_sync state <= start; end if; RST_UART_counter <= '1'; -- Prevent from counting while in idle when start =>if (UART_counter = 1) then -- If RxD_sync is low and half a period elapsed state <= demiStart; end if; RST_UART_counter <= '0'; -- Begin counting data_out <= "00000000"; -- Reset former output data data_valid <= '0'; -- Data is not valid Now, like you said, it works better ! But I still got some issues, and there is something I don't understand in the simulation : Over RxD, I transmit 10101010 which is 85. In the simulation, data_out takes the proper value (10101010), the data_valid works fine, so far so good... BUT : The simulation says the data_out is equal to 55 (instead of 85 !) If we check data_out bit after bit, it shouldn't be equal to 55 ! I don't know if I am clear, but I think the attached picture will best decribe my problem. Is it a simulation issue ? Because it seems the previous displayed values (1, 5) are correct ! So I don't understand what's wrong with 85 ?
  3. Hello, @D@n, thank you for your inputs. I've modified my code following your latest comments : - No more asynchronous reset ; - Addition of a data_valid output; - counter >= 5208 instead of = 5208; - when others case for the states of the FSM; - I've managed to run a simulation. Hereafter is my new code : 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); data_valid : out STD_LOGIC); end UART_RX; architecture Behavioral of UART_RX is type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7); -- States of the FSM signal state :state_type := idle; -- Default state signal RST_UART_counter : STD_LOGIC; -- Reset of the counter signal UART_counter_internal : integer range 0 to 5210; -- Number of clk rising edges to increment counter signal UART_counter : integer range 0 to 19; -- Counter value signal RxD_temp : STD_LOGIC; -- Temporary RxD between the two FF signal RxD_sync : STD_LOGIC; -- RxD properly synchronized with 100 MHz clk begin D_flip_flop_1:process(clk) -- Clock crossing, first flip flop begin if clk = '1' and clk'event then RxD_temp <= RxD_in; end if; end process; D_flip_flop_2:process(clk) -- Clock crossing, second flip flop begin if clk = '1' and clk'event then RxD_sync <= RxD_temp; end if; end process; doubleTickUART:process(clk) -- Counter begin if clk = '1' and clk'event then if ((RAZ='1') or (RST_UART_counter = '1')) then UART_counter <= 0; UART_counter_internal <= 0; elsif (UART_counter_internal >= 5208) then UART_counter <= (UART_counter + 1); UART_counter_internal <= 0; else UART_counter_internal <= UART_counter_internal + 1; end if; end if; end process; fsm:process(clk, RAZ) -- Finite state machine begin if clk = '1' and clk'event then if (RAZ = '1') then state <= idle; data_out <= "00000000"; RST_UART_counter <= '1'; data_valid <= '0'; else case state is when idle => if RxD_sync = '0' then -- If in idle and low level detected on RxD_sync state <= start; RST_UART_counter <= '0'; -- Begin counting end if; RST_UART_counter <= '1'; -- Prevent from counting while in idle when start =>if (UART_counter = 1) then -- If RxD_sync is low and half a period elapsed state <= demiStart; end if; data_out <= "00000000"; -- Reset former output data data_valid <= '0'; -- Data is not valid when demiStart => if (UART_counter = 3) then state <= b0; data_out(0) <= RxD_sync; -- Acquisition bit 1 of 8 end if; when b0 => if (UART_counter = 5) then state <= b1; data_out(1) <= RxD_sync; -- Acquisition bit 2 of 8 end if; when b1 => if (UART_counter = 7) then state <= b2; data_out(2) <= RxD_sync; -- Acquisition bit 3 of 8 end if; when b2 => if (UART_counter = 9) then state <= b3; data_out(3) <= RxD_sync; -- Acquisition bit 4 of 8 end if; when b3 => if (UART_counter = 11) then state <= b4; data_out(4) <= RxD_sync; -- Acquisition bit 5 of 8 end if; when b4 => if (UART_counter = 13) then state <= b5; data_out(5) <= RxD_sync; -- Acquisition bit 6 of 8 end if; when b5 => if (UART_counter = 15) then state <= b6; data_out(6) <= RxD_sync; -- Acquisition bit 7 of 8 end if; when b6 => if (UART_counter = 17) then state <= b7; data_out(7) <= RxD_sync; -- Acquisition bit 8 of 8 end if; when b7 => if (UART_counter = 19) then state <= idle; -- state <= idle data_valid <= '1'; -- Data becomes valid end if; when others => state <= idle; end case; end if; end if; end process; end Behavioral; Here are my simulation results : - Reset seems to work great; - The starting bit is well detected (FSM state changes accordingly from idle to start) - But FSM stays in its start state (the counter didin't kick in - it stays at 0 whereas I want it to start counting). ==> The problem comes from the RST_UART_counter signal I believe the problem is in the following lines : when idle => if RxD_sync = '0' then -- If in idle and low level detected on RxD_sync state <= start; RST_UART_counter <= '0'; -- Begin counting end if; RST_UART_counter <= '1'; -- Prevent from counting while in idle The idea is to start the counter only if RxD_sync = '0', but I guess that's not what it does. How should I write this part of the code ? Thank you very much !
  4. Hello, thank you for your answers !! Following your recommendations, I modified my code, which now uses a single counter, saving ressources and removing some of the complexity. I also modified my finite state machine, which wasn't sampling correctly. I think I am getting closer (the code looks a little bit cleaner at least). Nevertheless, it still doesn't work (this time the LEDs refuse to be lit). Hereafter is my new .vhdl code (with more English variable names since my first version included some French...) : 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 type state_type is (idle, start, demiStart, b0, b1, b2, b3, b4, b5, b6, b7); -- States of the FSM signal state :state_type := idle; -- Default state signal RST_UART_counter : STD_LOGIC; -- Reset of the counter signal UART_counter_internal : integer range 0 to 5210; -- Number of clk rising edges to increment counter signal UART_counter : integer range 0 to 19; -- Counter value signal RxD_temp : STD_LOGIC; -- Temporary RxD between the two FF signal RxD_sync : STD_LOGIC; -- RxD properly synchronized with 100 MHz clk begin D_flip_flop_1:process(clk) -- Clock crossing, first flip flop begin if clk = '1' and clk'event then RxD_temp <= RxD_in; end if; end process; D_flip_flop_2:process(clk) -- Clock crossing, second flip flop begin if clk = '1' and clk'event then RxD_sync <= RxD_temp; end if; end process; doubleTickUART:process(clk) -- Counter begin if clk = '1' and clk'event then if ((RAZ='1') or (RST_UART_counter = '1')) then UART_counter <= 0; UART_counter_internal <= 0; elsif UART_counter_internal = 5208 then UART_counter <= (UART_counter + 1); UART_counter_internal <= 0; else UART_counter_internal <= UART_counter_internal + 1; end if; end if; end process; fsm:process(clk, RAZ) -- Finite state machine begin if (RAZ = '1') then state <= idle; data_out <= "00000000"; RST_UART_counter <= '1'; elsif clk = '1' and clk'event then case state is when idle => if RxD_sync = '0' then -- If in idle and low level detected on RxD_sync state <= start; RST_UART_counter <= '0'; -- Begin counting end if; RST_UART_counter <= '1'; -- Prevent from counting while in idle when start =>if (UART_counter = 1) then -- If RxD_sync is low and half a period elapsed state <= demiStart; end if; data_out <= "00000000"; -- Reset former output data when demiStart => if (UART_counter = 3) then state <= b0; data_out(0) <= RxD_sync; -- Acquisition bit 1 of 8 end if; when b0 => if (UART_counter = 5) then state <= b1; data_out(1) <= RxD_sync; -- Acquisition bit 2 of 8 end if; when b1 => if (UART_counter = 7) then state <= b2; data_out(2) <= RxD_sync; -- Acquisition bit 3 of 8 end if; when b2 => if (UART_counter = 9) then state <= b3; data_out(3) <= RxD_sync; -- Acquisition bit 4 of 8 end if; when b3 => if (UART_counter = 11) then state <= b4; data_out(4) <= RxD_sync; -- Acquisition bit 5 of 8 end if; when b4 => if (UART_counter = 13) then state <= b5; data_out(5) <= RxD_sync; -- Acquisition bit 6 of 8 end if; when b5 => if (UART_counter = 15) then state <= b6; data_out(6) <= RxD_sync; -- Acquisition bit 7 of 8 end if; when b6 => if (UART_counter = 17) then state <= b7; data_out(7) <= RxD_sync; -- Acquisition bit 8 of 8 end if; when b7 => if (UART_counter = 19) then state <= idle; -- state <= idle end if; end case; end if; end process; end Behavioral; @hamster : I didn't follow exactly your post word by word but I think it's now closer to what you said, as I remove one of my counters and now use only one (going from 0 to 19). The main difference is that I count 5208 clock cycles instead of 5902, I will need to find out why (I'll check my calculations). @ jpeyron : Thank you very much for the links, I didn't have time to pay attention to those for now (I would like to get my own code working in order to find out whats is wrong, even if it isn't as optimized as what you provided). Still, I keep your links in mind in case I keep being stuck - which for now is still the case ! @ D@n : I didn't use simulation for now. In fact I formely used ISE and I need to pay a closer attention to how simulation works in Vivado 2016 ! Seems things are a little bit different. Again, thank you to the three of you for your recommendations. It still isn't working but I am getting closer !
  5. 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 : ## 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_in] set_property IOSTANDARD LVCMOS33 [get_ports RxD_in] 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;