user3013172
user3013172

Reputation: 1783

Counter not working in FPGA

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 FPGAs actually work because this is simple and I can't get it to work.

Upvotes: 0

Views: 287

Answers (1)

Oldfart
Oldfart

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

Related Questions