Estoy tratando de hacer funcionar un receptor UART simple y estoy cerca, pero recibo valores ligeramente off (algunos bits se desplazan un par de lugares desde donde deberían estar).
Basado en esta respuesta. Intenté ejecutar RX a través de un flip flop (no estoy seguro de haberlo hecho). que correctamente) y sobreexplotado RX. Mi tasa de baudios objetivo es 2500000, por lo que es de 400 nudos por baudio y 20 muestras por baudio (el reloj FPGA es de 50 MHz).
¿Alguien puede ver lo que estoy haciendo mal? ¿Estoy poniendo RX en el flip flop y haciendo un sobremuestreo correctamente?
entity uart is port(
clk_50 : in std_logic;
reset : in std_logic;
tx : out std_logic;
rx : in std_logic;
data_in : out std_logic_vector(7 downto 0); -- data being received
data_out : in std_logic_vector(7 downto 0); -- data being sent
leds : out std_logic_vector(7 downto 0));
end uart;
architecture behavioral of uart is
signal sample_counter : unsigned(7 downto 0);
signal data_count : unsigned(3 downto 0);
type uart_state_t is (IDLE, START, DATA, STOP, STALL);
signal uart_state: uart_state_t;
signal next_uart_state: uart_state_t;
signal rx_data : std_logic_vector(7 downto 0);
signal rx_d : std_logic;
begin
process(clk_50, reset)
begin
if (reset = '1') then
uart_state <= START;
data_count <= (others => '0');
sample_counter <= (others => '1');
leds <= (others => '0');
rx_data <= (others => '0');
elsif (rising_edge(clk_50)) then
uart_state <= next_uart_state;
rx_d <= rx;
if (next_uart_state = START) then
data_count <= (others => '1');
if (sample_counter = x"ff") then
if (rx_d = '0') then
sample_counter <= sample_counter + 1;
end if;
elsif (sample_counter = x"31") then -- 20 samples per baud
sample_counter <= (others => '1');
else
sample_counter <= sample_counter + 1;
end if;
end if;
elsif (next_uart_state = DATA) then
if (sample_counter = x"0a") then -- check rx at sample 10
rx_data(to_integer(data_count)) <= rx_d;
leds(to_integer(data_count)) <= rx_d;
sample_counter <= sample_counter + 1;
elsif (sample_counter = x"13") then
sample_counter <= (others => '1');
data_count <= data_count + 1;
else
sample_counter <= sample_counter + 1;
end if;
elsif (next_uart_state = STOP) then
if (sample_counter = x"0a") then -- check rx at sample 10
data_in <= rx_data;
sample_counter <= sample_counter + 1;
elsif (sample_counter = x"13") then
sample_counter <= (others => '1');
else
sample_counter <= sample_counter + 1;
end if;
end if;
end if;
end process;
process(uart_state, reset, data_count, sample_counter)
begin
if (reset = '1') then
next_uart_state <= START;
end if;
case uart_state is
when START =>
if (sample_counter = x"13") then
next_uart_state <= DATA;
else
next_uart_state <= START;
end if;
when DATA =>
if (data_count = x"8" and sample_counter = x"13") then
next_uart_state <= STOP;
else
next_uart_state <= DATA;
end if;
when STOP =>
if (sample_counter = x"13") then
next_uart_state <= START;
else
next_uart_state <= STOP;
end if;
when others =>
next_uart_state <= START;
end case;
end process;
end behavioral;
e: Creo que lo conseguí: reduje la velocidad de transmisión a 1000000 y cambié la lógica para el estado de INICIO.