1
votes

Below is a simple 3-bit counter.

When reset(rst) is 0, counter value is "000", else it increments by 1 for rising edge of each clock.

 LIBRARY ieee;
 USE ieee.std_logic_1164.all;
 use IEEE.std_logic_unsigned.all;
 use IEEE.numeric_std.all;
 ---------------------------------------------
 ENTITY counter IS
 PORT (clk : IN STD_LOGIC;
    rst : in std_logic;
       digit : out std_logic_vector (2 downto 0)
       );
 END counter;
 ---------------------------------------------
 ARCHITECTURE counter OF counter IS
 BEGIN

 count: PROCESS(clk,rst)
 VARIABLE temp : std_logic_vector(2 downto 0);
 BEGIN
 IF (clk'EVENT AND clk='1') THEN
     if (rst = '1') then
        temp := temp + "001";
     else
        temp := "000";
     END IF;
 END IF;
 digit <= temp;
 END PROCESS count;
 END counter;

Below is the simulation result I got :

enter image description here

In the result, output is correct. But there is an one clock delay between the time rst = 1 and output='001'. ie counter doesn't increment instantaneously when rst = '1'.

As per my understanding, whenever a change in clk or rst happens, process is executed. So when rst changes from low to high, an event occurs. Process checks if rising edge of clk, YES. Then check if rst = 1, YES. So normally counter has to increment in that clk itself. But it doesn't.

Questions:

  1. Why one clock period delay between reset = 1 and output = 001?
  2. And what is wrong in my understanding?
3
Oops, Image seems small in question. Please open the image to see it clearly.Abid Rahman K
if addition answer is available long before the next rising edge, why it is not passed to the output and shown in simulation result? why it has to wait until next rising edge of clock?Abid Rahman K
The question is: is it available? and where it is? It can be available internally in the inputs of a flip-flop. Toggling the reset makes it available at the output. Generally you just can't probe the temp register, which is the same, as the input of the flip-flop.Aki Suihkonen
So, is there no way to increment the counter simultaneously with the rst = 1?Abid Rahman K
Lets put it this way: no. If you could have output at the same clock cycle, you'd have infinitely fast machine.Aki Suihkonen

3 Answers

3
votes

(Disclaimer: It's been long time since I programmed in VHDL, so this only answers to generic logic design.)

Anyway, one can't expect the result of addition to be ready immediately when a process is triggered. The point is, that calculating even the first bit of 000 + 001 is affected by the propagation delay equivalent to one xor operation. The second bit is calculated from the first bit's carry (if both bits were 1) and xor operation of the second bits. And so on.

If one would probe the 'temp' variable asynchronously, one would see something like this:

                        ^ ________________
result_bit_0    __________|
                        0123456789
                _____________
result_bit_1            ^    |____________
                        0123456789
                ____________ _____
result_bit_2            ^  |_|   |________
                        0123456789abcde
                        ________       
clock:          ________|      |______|

The figure tries to illustrate in more detail the waveforms of a generic add operation.
At time 0 the process of adding is started.
After a small delay '2' the first bit stabilizes to 1.
At time '5' the second bit stabilizes to 0 and at time '9' the third bit stabilizes to 0. But also it's quite common, that as in result_bit_2, the output toggles between various states.

It's the total / maximum delay of each temporary variable to take to stabilize, that determines the minimum clock period. At this case the time instant 'e' is that one, where we have decided that the result of counter increment is available.

Still, from the perspective result (which is a vector), everything happens instantly at the next clock cycle.

5
votes

The most likely cause in that "rst" is generated by a clocked process, clocked by the same "clk" signal.

So "rst" occurs one delta cycle after "clk". When "rst" changes it will wake the process up, but "clk'event" was on the previous delta cycle, therefore the "if" statement will not execute.

On the next clock edge, rst = 1 so the counter works as expected.

Three minor points:

  • it would be worth naming the reset signal rst_n to make it clearer that it is an active-low reset!
  • rst really doesn't need to be in the sensitivity list
  • there is no need for parentheses around the boolean expressions
1
votes

the "issue" is in the way you have described your "rst". The way you did it would result in a "synchronous" reset, i.e. the reset would take effect only after a rising edge of the clock.

In general this is just a matter of coding style/preferences. I usually prefer asynchronous reset (with maybe a reset synchronizer at top-level to avoid meta-stability when releasing the reset), but there is nothing wrong in adopting a synchronous reset approach.

In case of an asynchronous reset, you would need to change your code to something like this:

PROCESS (clk, rst_n) BEGIN
   IF rst_n = '0' THEN
      ...
   ELSIF rising_edge(clk) THEN
    ...
   END IF;
END PROCESS;