3
\$\begingroup\$

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?

\$\endgroup\$
1
  • \$\begingroup\$ Not really sure why you need PCnext at all here. You a can just increment PC on every clock edge. In any case you would need to have the increment statement inside the clock edge condition. \$\endgroup\$
    – John
    Commented Jun 25, 2017 at 7:00

2 Answers 2

1
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks @Sourabh ! But out of curiosity, I thought that process' were sequential (like C programming), so why wasnt PCNext <= std_logic_vector(unsigned(PC) + 4); being executed right after the if statement ? \$\endgroup\$
    – Liam F-A
    Commented Jun 25, 2017 at 14:32
  • \$\begingroup\$ This is not software, in VHDL the order of statements in a process controls priority, not sequence at least as far as signals are concerned, there is only a single assignment point at the end of the process and it assigns whatever the last value each signal had, then starts a new delta cycle if any assignment changed something in the sensitivity list. \$\endgroup\$
    – Dan Mills
    Commented Jun 25, 2017 at 15:55
  • \$\begingroup\$ @LiamF-A : yeah inside process block it follows sequential ( like C program) for if else statements, for loops, Case statements etc. coz they are conditional priorities but 2 or more signal assignments written inside or outside these conditional sub-blocks but within the process gets executed concurrently/simultaneously [ like VHDL program :) ] e.g PCNext_1 <= std_logic_vector(unsigned(PC) + 4); PCNext_2 <= std_logic_vector(unsigned(PC) + 3); both PCNext_1 & PCNext_2 gets resultant value simultaneously. \$\endgroup\$ Commented Jun 26, 2017 at 5:55
0
\$\begingroup\$

The reason that PCNext doesn't change until the next edge of the clock is that you have that statement inside the process. The process is only evaluated when one of the signals in its sensitivity list changes.

Note that this is one of the key differences between simulation and the real world. The simulator pays attention to sensitivity lists, but if you actually synthesize this logic, PCNext would in fact change right away.

To get the behavior you're expecting in the simulator, you need to move that statement outside the process altogether.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks @Dave ! I'd use this answer, only the requirements of this project say that I have to code the PC in a process \$\endgroup\$
    – Liam F-A
    Commented Jun 25, 2017 at 14:35
  • \$\begingroup\$ In that case, why have PCNext at all? Just updatePC the same way you do cycle -- i.e., PC <= std_logic_vector(unsigned(PC) + 4); \$\endgroup\$
    – Dave Tweed
    Commented Jun 25, 2017 at 18:42
  • \$\begingroup\$ I completely agree, but our teacher gave us a list of signals that we had to use. I guess he wants us to recreate this diagram using VHDL \$\endgroup\$
    – Liam F-A
    Commented Jun 25, 2017 at 19:55
  • \$\begingroup\$ By the time you get that diagram fully implemented, you'll have additional logic to handle unconditional/conditional absolute/relative branches (and subroutine call/return? But I see no paths to transfer the PC to/from memory). In any case, it makes even less sense to have a separate bus dedicated to PCNext alone. \$\endgroup\$
    – Dave Tweed
    Commented Jun 25, 2017 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.