flag26838

newbie: why is taking 2 clock cycles to update the output? AKA are statements inside a process() block really sequential?

5 posts in this topic

I don't understand why this register file:

 

entity reg16_8 is
    Port ( I_clk : in  STD_LOGIC;
           I_en : in  STD_LOGIC;
              I_we : in  STD_LOGIC;
           I_selA : in  STD_LOGIC_VECTOR (2 downto 0);
           I_selB : in  STD_LOGIC_VECTOR (2 downto 0);
           I_selD : in  STD_LOGIC_VECTOR (2 downto 0);
              I_dataD : in  STD_LOGIC_VECTOR (15 downto 0);
           O_dataA : out  STD_LOGIC_VECTOR (15 downto 0);
           O_dataB : out  STD_LOGIC_VECTOR (15 downto 0));
end reg16_8;

architecture Behavioral of reg16_8 is
    type store_t is array(0 to 7) of std_logic_vector(15 downto 0);
    signal regs: store_t := (others => X"0000");
begin
    process(I_clk)
    begin
        if rising_edge(I_clk) then
        if I_en='1' then
            if I_we='1' then
                regs(to_integer(unsigned(I_selD))) <= I_dataD;
            end if;
            O_dataA <= regs(to_integer(unsigned(I_selA)));
            O_dataB <= regs(to_integer(unsigned(I_selB)));
        end if;
        end if;
    end process;

end Behavioral;

 

if run against this test bench:

 

...

   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for 100 ns;    

      wait for I_clk_period*10;

      -- insert stimulus here

        I_selA <= "000";
        I_selB <= "001";
        I_selD <= "000";
        I_dataD <= X"BEEF";
        I_we <= '1';
        I_en <= '1';

        wait for I_clk_period*10;

      wait;
   end process;
...

 

takes two clock cycles to update the O_dataA bus - post-37315-0-61822300-1444236626_thumb.p

 

IOW, after 200ns my test bench starts, all input signals are set and i expect at the first rising edge of the clock (205ns), the ouput of the register file to be update, in particular i expect O_dataA to take the value of I_dataD, but that doesn't happen until another clock cycle passes (215ns), when my process() in the register file is executed again.

 

Aren't the staments inside a process executed sequentially? So if i set a register as the first thing in a process(), i expect later statements to pick up this change, am i right? I guess no, since that's not what is happening...

Share this post


Link to post
Share on other sites

The quick answer is no.  Signal assignments within a process are all done in parallel and for the case you've given, the assigned values are those that exist at the time of the clock edge.

 

I_dataD takes two cycles to propagate to O_dataA because on the first rising edge of the clock I_dataD is latched into regs and O_dataA takes on the value that was in regs when the clock edge occurred.  It isn't until the next clock edge (the second) that the original value of I_dataD is available in regs to be latched into O_dataA.  Kind of like a bucket brigade.

Share this post


Link to post
Share on other sites

O_data is being updated at each clock cycle. It changes every time clock rising edge comes.

 

This is how RTL works.

Share this post


Link to post
Share on other sites

 

Aren't the staments inside a process executed sequentially? So if i set a register as the first thing in a process(), i expect later statements to pick up this change, am i right? I guess no, since that's not what is happening...

 

Not in synchronous processes with signals. If you want to do that you can use variables.

 

What you seem to be trying to model is a Write-First memory, where when a write happens the output will be set to the write value, not the previous value.

 

Using a shared variable instead of a signal may help here. See https://github.com/alvieboy/xtc-base/blob/master/generic_dp_ram_r.vhd this for example, and it's usage on a register bank https://github.com/alvieboy/xtc-base/blob/master/regbank_2p.vhd

 

Alvie

Share this post


Link to post
Share on other sites

Alvieboy, indeed, switching from 'signal' to 'shared variable' made it behave as i expected - any drawback of using a 'shared variable' vs a 'signal'?

 

Thanks for all the answer guys.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now