I encounter problems with my UART receiver module. It is supposed to work at 9600 bauds without parity bit and only one stop bit.
The problem is that my UART misses some characters (or to indicate that it received some characters) in a non-deterministic way.
My two main but unsucessful ideas about this problem were
1) a problem with the reception with the clock at 9600Hz, it is maybe not accurate enough or I don't have any error margin. I tried oversampling but it did not solve the problem.
2) A problem with the acknowledge coming from the outside (CPU). I use a little trick with a DFF to let the CPU acknowledge correctly his reading while having a much higher clock that the receiver (50MHz vs 9600Hz).
I am perfectly sure that my clock is at 9600Hz (I am able to receive correctly a lot of characters).
Here is the small code of the receiver I use.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity UART_Receive is port( clk_9600Hz : in std_logic; reset_n : in std_logic; ackNewData : in std_logic; ready : out std_logic; dataToRead : out std_logic_vector(7 downto 0); Rx : in std_logic ); end entity UART_Receive; architecture RTL of UART_Receive is signal counter : unsigned(3 downto 0); signal buffer_read : std_logic_vector(7 downto 0); signal lastData : std_logic_vector(7 downto 0); signal newDataReady: std_logic; begin dataToRead <= lastData; process(ackNewData, newDataReady) begin if(ackNewData = '1') then ready <= '0'; elsif(rising_edge(newDataReady)) then ready <= '1'; end if; end process; process(clk_9600Hz, reset_n) is begin if reset_n = '0' then lastData <= (others => '0'); counter <= (others => '0'); buffer_read <= (others => '0'); elsif rising_edge(clk_9600Hz) then if counter = 0 and Rx = '0' then counter <= counter + 1; elsif counter = 9 then counter <= (others => '0'); lastData <= buffer_read; newDataReady <= '1'; elsif counter /= 0 then buffer_read <= Rx & buffer_read(7 downto 1); counter <= counter + 1; end if; end if; end process reg_slow_process; end architecture RTL