Electronic – VHDL process requires multiple clock cycles

latchmodelsimvhdl

I wrote a simple counter in VHDL for a program counter. Everything is done in a process, but what I dont understand is that in the simulation, the addition of the program counter, is only done at the next clock event, rather than immediately after PCNext has been output.

Here is the code as well as the simulation:

 LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.ALL;

    ENTITY dlatch IS 
    PORT (
         Reset, Clock : IN std_logic;
         PC_out : OUT std_logic_vector(31 downto 0)
         );
    end dlatch;

    ARCHITECTURE d_arch OF dlatch IS

    SIGNAL PC      : std_logic_vector(31 downto 0);  
    SIGNAL PCNext  : std_logic_vector(31 downto 0);  

    BEGIN 
    PROCESS(Clock, Reset)  
    BEGIN 
         IF Reset = '1' THEN
              PC <= x"00000000";
         ELSIF Clock'event and Clock = '1' THEN
                PC <= PCNext;
         END IF;

        PCNext <= std_logic_vector(unsigned(PC) + 4); 

    END PROCESS;

    PC_out <= PC;

    END d_arch;

enter image description here

Do you see how PCNext is only calculated at the falling edge of the clock? Why isn't it calculated immediately after PC <= PCNext?

Best Answer

First of all, both doubts (1) & (2) which is actually asking same question

(1) The addition of the program counter is only done at the next clock event [i.e. here it's falling edge], rather than immediately after PCNext has been output.

(2) Do you see how PCNext is only calculated at the falling edge of the clock? Why isn't it calculated immediately after PC <= PCNext?]

Answer: It is because the signal PC is not present in the sensitivity list. As shown in simulation below when I add it in sensitivity list the addition takes place immediately because PCNext <= std_logic_vector(unsigned(PC) + 4); executed concurrently as change on signal PC in sensitivity list invokes process again.

enter image description here

Earlier in your case immediate assignment was no happening till next clock event (which is falling edge of clock present in sensitivity list).

I hope now you will actually understand the sensitivity list and be more careful about it next time.

One more thing you can do is that declare signal PC as variable PC and use blocking assignment := this will also update addition result immediately and also you can learn more about the difference between blocking assignment and Non-blocking assignment.

edit: As Dave Tweed already said to move the statement PCNext <= std_logic_vector(unsigned(PC) + 4); outside the process block altogether will also work.