Estoy intentando implementar algún tipo de protocolo de comunicación sobre rs232 entre PC y FPGA.
Como punto de partida, tomé esta implementación VHDL de UART rs232 y funciona (es un ejemplo simple de bucle invertido).
He intentado agregar un segundo búfer para colocar datos de respuesta y luego retransmitirlo cuando UART esté listo. Pero mis cambios causan la duplicación de datos en respuesta.
¿Qué está causando la duplicación de datos?
Editar:
se ve como una línea
if fifo_in_empty = '0' and fifo_out_full = '0' then
se ignora por completo cuando la entrada FIFO ya está vacía (consulte la forma de onda adjunta, 93,050 - 93,090 ns) y las señales fifo_in_data_out_stb
, fifo_out_data_in_stb
duran 2 ciclos.
¿Cuál puede ser la causa posible?
Edición 2:
La entrada FIFO se vacía al final del ciclo, después de que el proceso uart_loopback
finaliza la ejecución. Así que envolví las instrucciones para mover datos de un búfer a otro con una verificación de condición adicional:
if fifo_in_data_out_stb = '1' then
fifo_in_data_out_stb <= '0';
fifo_out_data_in_stb <= '0';
else
if fifo_in_empty = '0' and fifo_out_full = '0' then
fifo_in_data_out_stb <= '1';
fifo_out_data_in_stb <= '1';
fifo_out_data_in <= fifo_in_data_out;
end if;
end if;
No estoy seguro si "solucioné" este problema correctamente, incluso si ahora funciona correctamente.
Aquí está el código del loopback.vhd
modificado:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity loopback is
generic (
baud : positive;
clock_frequency : positive
);
port (
clock : in std_logic;
reset : in std_logic;
rx : in std_logic;
tx : out std_logic
);
end loopback;
architecture rtl of loopback is
---------------------------------------------------------------------------
-- Component declarations
---------------------------------------------------------------------------
component uart is
generic (
baud : positive;
clock_frequency : positive
);
port (
clock : in std_logic;
reset : in std_logic;
data_stream_in : in std_logic_vector(7 downto 0);
data_stream_in_stb : in std_logic;
data_stream_in_ack : out std_logic;
data_stream_out : out std_logic_vector(7 downto 0);
data_stream_out_stb : out std_logic;
tx : out std_logic;
rx : in std_logic
);
end component uart;
component generic_fifo is
generic (
fifo_width : positive := 32;
fifo_depth : positive := 1024
);
port (
clock : in std_logic;
reset : in std_logic;
write_data : in std_logic_vector(FIFO_WIDTH-1 downto 0);
read_data : out std_logic_vector(FIFO_WIDTH-1 downto 0);
write_en : in std_logic;
read_en : in std_logic;
full : out std_logic;
empty : out std_logic;
level : out std_logic_vector(
integer(ceil(log2(real(fifo_depth))))-1 downto 0
)
);
end component;
---------------------------------------------------------------------------
-- UART signals
---------------------------------------------------------------------------
signal uart_data_in : std_logic_vector(7 downto 0);
signal uart_data_out : std_logic_vector(7 downto 0);
signal uart_data_in_stb : std_logic := '0';
signal uart_data_in_ack : std_logic := '0';
signal uart_data_out_stb : std_logic := '0';
constant buffer_depth : integer := 1024;
-- Input buffer signals
signal fifo_in_data_out : std_logic_vector(7 downto 0);
signal fifo_in_data_in : std_logic_vector(7 downto 0);
signal fifo_in_data_in_stb : std_logic;
signal fifo_in_data_out_stb : std_logic;
signal fifo_in_full : std_logic;
signal fifo_in_empty : std_logic;
-- Output buffer signals
signal fifo_out_data_out : std_logic_vector(7 downto 0);
signal fifo_out_data_in : std_logic_vector(7 downto 0);
signal fifo_out_data_in_stb : std_logic;
signal fifo_out_data_out_stb : std_logic;
signal fifo_out_full : std_logic;
signal fifo_out_empty : std_logic;
begin
---------------------------------------------------------------------------
-- UART instantiation
---------------------------------------------------------------------------
uart_inst : uart
generic map (
baud => baud,
clock_frequency => clock_frequency
)
port map (
-- general
clock => clock,
reset => reset,
data_stream_in => uart_data_in,
data_stream_in_stb => uart_data_in_stb,
data_stream_in_ack => uart_data_in_ack,
data_stream_out => uart_data_out,
data_stream_out_stb => uart_data_out_stb,
tx => tx,
rx => rx
);
-- Intermediate buffer for storing bytes received by the UART
receive_buffer : generic_fifo
generic map(
fifo_width => 8,
fifo_depth => buffer_depth
)
port map(
clock => clock,
reset => reset,
write_data => fifo_in_data_in,
read_data => fifo_in_data_out,
write_en => fifo_in_data_in_stb,
read_en => fifo_in_data_out_stb,
full => fifo_in_full,
empty => fifo_in_empty,
level => open
);
-- Intermediate buffer for storing bytes to be transmitted
transmit_buffer : generic_fifo
generic map(
fifo_width => 8,
fifo_depth => buffer_depth
)
port map(
clock => clock,
reset => reset,
write_data => fifo_out_data_in,
read_data => fifo_out_data_out,
write_en => fifo_out_data_in_stb,
read_en => fifo_out_data_out_stb,
full => fifo_out_full,
empty => fifo_out_empty,
level => open
);
uart_loopback : process (clock)
begin
if rising_edge(clock) then
if reset = '1' then
uart_data_in_stb <= '0';
uart_data_in <= (others => '0');
fifo_in_data_out_stb <= '0';
fifo_in_data_in_stb <= '0';
fifo_out_data_out_stb <= '0';
fifo_out_data_in_stb <= '0';
else
-- Acknowledge data receive strobes and set up a transmission
-- request
fifo_in_data_in_stb <= '0';
if uart_data_out_stb = '1' and fifo_in_full = '0' then
fifo_in_data_in_stb <= '1';
fifo_in_data_in <= uart_data_out;
end if;
-- Clear transmission request strobe upon acknowledge.
if uart_data_in_ack = '1' then
uart_data_in_stb <= '0';
end if;
fifo_in_data_out_stb <= '0';
fifo_out_data_in_stb <= '0';
if fifo_in_empty = '0' and fifo_out_full = '0' then
fifo_in_data_out_stb <= '1';
fifo_out_data_in_stb <= '1';
fifo_out_data_in <= fifo_in_data_out;
end if;
fifo_out_data_out_stb <= '0';
-- Transmit any data in the buffer
if fifo_out_empty = '0' then
if uart_data_in_stb = '0' then
uart_data_in_stb <= '1';
fifo_out_data_out_stb <= '1';
uart_data_in <= fifo_out_data_out;
end if;
end if;
end if;
end if;
end process;
end rtl;