0

I'm using VHDL and Vivado for a sort of clocked filter that reads one bit at a time from an i_w channel when an input i_start is given and stays active, converting it into a memory address from which it then reads, and finally it loads the value inside of the address in one of four different registers, also depending on the first two bits read of the i_w signal, and outputs a "done" signal to notify that it has finished.

I've created an internal counter that keeps track of how many clock cycles have elapsed from the reading start.

architecture rtl of project is
    --Counter
    signal internal_counter: std_logic_vector(4 downto 0);
    signal internal_done: std_logic := '0';
    --Addresses
    signal internal_regChannel: std_logic_vector(1 downto 0);
    signal internal_memAddress: std_logic_vector(15 downto 0);
    --Registry Bank
    signal internal_regValue0: std_logic_vector(7 downto 0);
    signal internal_regValue1: std_logic_vector(7 downto 0);
    signal internal_regValue2: std_logic_vector(7 downto 0);
    signal internal_regValue3: std_logic_vector(7 downto 0);

begin

    COUNTER: process(i_clk)
    begin   
    if i_rst ='1' then 
        --reset the counter
        internal_counter <= (others => '0');
        internal_done <= '0';
    else
        if i_clk = '1' and i_start = '1' then
            --start counting
            internal_counter <= internal_counter + 1;
            internal_done <= '0';
        else
            internal_counter <= internal_counter;
        end if;
        if i_clk = '1' and internal_counter /= "00000" then
            --keep counting
            internal_counter <= internal_counter + 1;
            internal_done <= '0';
        end if;
        if i_clk = '1' and internal_counter = "10100" then
            --the counter has finished
            --count for one more cycle so then the done signal can be put back to 0
            internal_counter<= internal_counter + 1;
            internal_done <= '1';
        end if;
        
        if i_clk = '1' and internal_counter = "10101" then
            internal_counter <= "00000";
            internal_done <= '0';
        end if;
    end if;
    end process;

    W_FILTER: process(i_clk)
    begin
        if i_rst ='1' then
        internal_memAddress <= (others => '0');
        internal_regChannel <= (others => '0');
    else
        if i_clk = '1' and i_clk'event then
            if  i_start = '1' and internal_counter < "00010" then
                                --generate the registry Flag
                internal_regChannel <= internal_regChannel(0) & i_w;
            else if i_start = '1' and internal_counter >= "00010" then 
                                --generate the memory Address
                internal_memAddress <= internal_memAddress(14 downto 0) & i_w;
                end if;
            end if;
            
            if i_start = '0' and internal_counter > "00000" then
                                --memory address is safe to output
                o_mem_addr <= internal_memAddress;
            end if;
            
            if internal_done = '1' then
                internal_memAddress <= (others => '0');
                internal_regChannel <= (others => '0');
            end if;
        end if;
       end if;
    end process;
    
    REG_BANK: process(i_clk)
    begin
        if i_rst = '1' then
        internal_regValue0 <= (others => '0');
        internal_regValue1 <= (others => '0');
        internal_regValue2 <= (others => '0');
        internal_regValue3 <= (others => '0');
    else
        if internal_counter = "10100" then
            case internal_regChannel is
                when "00" =>
                    internal_regValue0 <= i_mem_data;
                when "01" =>
                    internal_regValue1 <= i_mem_data;
                when "10" =>
                    internal_regValue2 <= i_mem_data;
                when "11" =>
                    internal_regValue3 <= i_mem_data;
                when others =>
                                    --placeholder; others condition can never occur
                    internal_regValue0 <= i_mem_data;
            end case;
        end if;

    end if;
    end process;

    o_done <= internal_done;
    
end rtl;

However, when synthesizing the project, Vivado signals 6 inferred latches on all the signals, except for the one used by the W_FILTER process, internal_regChannel and internal_memAddress.

WARNING: [Synth 8-327] inferring latch for variable 'internal_done_reg' [C:/.../project.vhd:57]
WARNING: [Synth 8-327] inferring latch for variable 'internal_regValue0_reg' [C:/.../project.vhd:114]
WARNING: [Synth 8-327] inferring latch for variable 'internal_regValue1_reg' [C:/.../project.vhd:115]
WARNING: [Synth 8-327] inferring latch for variable 'internal_regValue2_reg' [C:/.../project.vhd:116]
WARNING: [Synth 8-327] inferring latch for variable 'internal_regValue3_reg' [C:/.../project.vhd:117]
WARNING: [Synth 8-327] inferring latch for variable 'internal_counter_reg' [C:/.../project.vhd:56]

I tried looking at the lines of code listed in the warnings, and I tried to follow what little guidance I could find online, but I still fail to understand what I should be doing to fix this issue.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    Welcome to Stack Overflow! Do not delete your posts the moment you get an answer. Instead, see [what should I do when someone answers](https://stackoverflow.com/help/someone-answers). (Deleting knowledge and robbing someone of the chance of a few more points in the tag aren't on that list) – Adriaan May 12 '23 at 08:26

1 Answers1

2

To properly synthesize clocked registers, make the process sensitive to the rising clock edge. You don't have this issue for the second process because there you use i_clk = '1' and i_clk'event.

But in the first process you use:

else
    if i_clk = '1' and i_start = '1' then

Change it to

elsif i_clk = '1' and i_clk'event then
    if i_start = '1' then

or better

elsif rising_edge(i_clk) then
    if i_start = '1' then

(see: clk'event vs rising_edge())

mkrieger1
  • 19,194
  • 5
  • 54
  • 65