vhdl.gif

Implementing Counters (VHDL)

 


Counters use sequential logic to count clock pulses. A counter can be implemented implicitly with a Register Inference. The Quartus II software can infer a counter from an If Statement that specifies a clock edge together with logic that adds or subtracts a value from the signal or variable. The If Statement and additional logic should be inside a Process Statement.

The following example shows a VHDL Design File (.vhd) that includes a variety of 8-bit counters, controlled by the clk, clear, ld, d, enable, and up_down signals, that are implemented with If Statements.

ENTITY counters IS
   PORT
   (
      d         : IN    INTEGER RANGE 0 TO 255;
      clk       : IN  STD_LOGIC;
      clear     : IN  STD_LOGIC;
      ld        : IN  STD_LOGIC;
      enable    : IN  STD_LOGIC;
      up_down   : IN  STD_LOGIC;
      qa        : OUT INTEGER RANGE 0 TO 255;
      qb        : OUT INTEGER RANGE 0 TO 255;
      qc        : OUT INTEGER RANGE 0 TO 255;
      qd        : OUT INTEGER RANGE 0 TO 255;
      qe        : OUT INTEGER RANGE 0 TO 255;
      qf        : OUT INTEGER RANGE 0 TO 255;
      qg        : OUT INTEGER RANGE 0 TO 255;
      qh        : OUT INTEGER RANGE 0 TO 255;
      qi        : OUT INTEGER RANGE 0 TO 255;
      qj        : OUT INTEGER RANGE 0 TO 255;
      qk        : OUT INTEGER RANGE 0 TO 255;
      ql        : OUT INTEGER RANGE 0 TO 255;
      qm        : OUT INTEGER RANGE 0 TO 255;
      qn        : OUT INTEGER RANGE 0 TO 255
   );
   
END counters;
ARCHITECTURE a OF counters IS
BEGIN
   -- An enable counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF enable = '1' THEN
            cnt := cnt + 1;
         END IF;
      END IF;
      
      qa <= cnt;
   END PROCESS;
   -- A synchronous load counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF ld = '0' THEN
            cnt := d;
         ELSE
            cnt := cnt + 1;
         END IF;
      END IF;
      qb <= cnt;
   END PROCESS;
   -- A synchronous clear counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            cnt := cnt + 1;
         END IF;
      END IF;
      qc <= cnt;
   
   END PROCESS;
   -- An up/down counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         cnt := cnt + direction;
      END IF;
      qd <= cnt;
   
   END PROCESS;
   -- A synchronous load enable counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF ld = '0' THEN
            cnt := d;
         ELSE
            IF enable = '1' THEN
               cnt := cnt + 1;
            END IF;
         END IF;
      END IF;
      qe <= cnt;
   
   END PROCESS;
   -- An enable up/down counter
   PROCESS (clk)
      VARIABLE   cnt                                  : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         IF enable = '1' THEN
            cnt := cnt + direction;
         END IF;
      END IF;
      qf <= cnt;
   
   END PROCESS;
   -- A synchronous clear enable counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            IF enable = '1' THEN
               cnt := cnt + 1;
            END IF;
         END IF;
      END IF;
      qg <= cnt;
   
   END PROCESS;
   -- A synchronous load clear counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            IF ld = '0' THEN
               cnt := d;
            ELSE
               cnt := cnt + 1;
            END IF;
         END IF;
      END IF;
      qh <= cnt;
   
   END PROCESS;
   -- A synchronous load up/down counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         IF ld = '0' THEN
            cnt := d;
         ELSE
            cnt := cnt + direction;
         END IF;
      END IF;
      qi <= cnt;
   
   END PROCESS;
   -- A synchronous load enable up/down counter
   PROCESS (clk)
      VARIABLE   cnt          : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         IF ld = '0' THEN
            cnt := d;
         ELSE
            IF enable = '1' THEN
               cnt := cnt + direction;
            END IF;
         END IF;
      END IF;
      qj <= cnt;
   END PROCESS;
   -- A synchronous clear load enable counter
   PROCESS (clk)
      VARIABLE   cnt         : INTEGER RANGE 0 TO 255;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            IF ld = '0' THEN
               cnt := d;
            ELSE
               IF enable = '1' THEN
                  cnt := cnt + 1;
               END IF;
            END IF;
         END IF;
      END IF;
      
      qk <= cnt;
   
   END PROCESS;
   -- A synchronous clear up/down counter
   PROCESS (clk)
      VARIABLE   cnt          : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            cnt := cnt + direction;
         END IF;
      END IF;
      ql <= cnt;
   
   END PROCESS;
   -- A synchronous clear enable up/down counter
   PROCESS (clk)
      VARIABLE   cnt          : INTEGER RANGE 0 TO 255;
      VARIABLE   direction    : INTEGER;
   BEGIN
      IF (up_down = '1') THEN
         direction := 1;
      ELSE
         direction := -1;
      END IF;
      
      IF (clk'EVENT AND clk = '1') THEN
         IF clear = '0' THEN
            cnt := 0;
         ELSE
            IF enable = '1' THEN
               cnt := cnt + direction;
            END IF;
         END IF;
      END IF;
      qm <= cnt;
   
   END PROCESS;
   -- A modulus 200 up counter
   PROCESS (clk)
      VARIABLE   cnt        : INTEGER RANGE 0 TO 255;
      CONSTANT modulus      : INTEGER := 200;
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF cnt = modulus - 1 THEN
            cnt := 0;
         ELSE
            cnt := cnt + 1;
         END IF;
      END IF;
      qn <= cnt;
   
   END PROCESS;
END a;

In this example, all 14 processes are sensitive only to changes on the clk signal. All other control signals are synchronous.

The first Process Statement describes an enabled counter. An If Statement describes the clock edge, and an additional embedded If Statement uses the enable signal to control counter operation. At each rising clock edge, the cnt variable is incremented by 1 and assigned to itself if the enable signal is '1'.

 

note.gif

Note: Refer to Implementing Registers for information on how to infer registers by specifying clock edges with If Statements.

 

The next 12 counters are described in the same manner. An If Statement describes the clock edge, and one or more embedded If Statement(s) use the enable, ld, d, clear, and up_down signals to control counter operation. The last counter uses the constant modulus declared in the process to control when the counter is reset to zero. At each clock edge, the counter variable is cleared; loaded with the value d; or incremented or decremented by 1, then assigned to itself based on the value of the control signal(s).

For more information, see the following sections of the IEEE Std 1076-1993 IEEE Standard VHDL Language Reference Manual:

 

 

Rate This Page