Reputation: 1783
I have a VHDL
component that is connected to a UART
receiver. The uart
has 2 output signals, one for the byte received and one for a flag that is set to 1 when the byte is done being received.
I have written the following module that should increment a counter for every new char and show it lighting up some leds.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
entity test is
port (
clk : in std_logic;
rst : in std_logic;
ena : in std_logic;
rx : in std_logic;
led0 : out std_logic;
led1 : out std_logic;
led2 : out std_logic;
led3 : out std_logic;
led4 : out std_logic;
led5 : out std_logic;
led6 : out std_logic;
led7 : out std_logic
);
end test;
architecture arch of test is
component UART_RX
generic (
g_CLKS_PER_BIT : integer := 115 -- Needs to be set correctly
);
port (
i_Clk : in std_logic;
i_RX_Serial : in std_logic;
o_RX_DV : out std_logic;
o_RX_Byte : out std_logic_vector(7 downto 0)
);
end component;
signal sig_Din : std_logic_vector(7 downto 0);
signal sig_Dout : std_logic_vector(7 downto 0);
signal sig_RxErr : std_logic;
signal sig_RxRdy : std_logic;
signal sig_TxBusy : std_logic;
signal sig_StartTx: std_logic;
begin
UUT : UART_RX
generic map (
g_CLKS_PER_BIT => 434
)
port map (
i_clk => clk,
i_rx_serial => rx,
o_rx_dv => sig_RxRdy,
o_rx_byte => sig_Dout
);
process(clk)
variable position : integer := 0;
variable position_v : std_logic_vector(7 downto 0) := "00000000";
begin
if(sig_RxRdy = '1') then
position := position + 1;
position_v := std_logic_vector((unsigned(position_v1), 1));
led0 <= position_v(0);
led1 <= position_v(1);
led2 <= position_v(2);
led3 <= position_v(3);
led4 <= position_v(4);
led5 <= position_v(5);
led6 <= position_v(6);
led7 <= position_v(7);
end if;
end process;
end arch;
Is there any problem with the implementation? Every new char i send ends up incrementing the counter by more than 1. And is not even the same value every time.
I must not be understanding how FPGA
s actually work because this is simple and I can't get it to work.
Upvotes: 0
Views: 287
Reputation: 6259
You are using sig_RxRdy
as condition for incrementing. But we can not see how that signal behaves as it comes out of a module for which we have no code.
From the behavior you describe the o_rx_dv
output (where sig_RxRdy comes from) is likely to be high for more then one of your clk cycles. As the UART input comes from an external source the time it is high may be variable which makes that you counter increment differs.
Solution is to detect a rising edge on sig_RxRdy
by using a delayed version:
prev_sig_RxRdy <= sig_RxRdy;
sig_RxRdy_rising <= sig_RxRdy and not prev_sig_RxRdy;
Then increment your counters on that signal. This only works if o_rx_dv is already synchronous to your clock.
Upvotes: 1