Encuentro problemas con mi módulo receptor UART. Se supone que funciona a 9600 baudios sin bit de paridad y solo un bit de parada.
El problema es que mi UART pierde algunos caracteres (o para indicar que recibió algunos caracteres) de una manera no determinista.
Mis dos ideas principales pero no exitosas sobre este problema fueron
1) un problema con la recepción con el reloj a 9600Hz, tal vez no sea lo suficientemente preciso o no tengo margen de error. Intenté el muestreo excesivo pero no resolvió el problema.
2) Un problema con el reconocimiento proveniente del exterior (CPU). Uso un pequeño truco con un DFF para que la CPU reconozca correctamente su lectura mientras tiene un reloj mucho más alto que el receptor (50MHz frente a 9600Hz).
Estoy perfectamente seguro de que mi reloj está en 9600Hz (puedo recibir correctamente muchos caracteres).
Aquí está el pequeño código del receptor que utilizo.
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