lightbulb Tip of the Month


We can update you automatically when our Tip of the Month changes.
To receive regular notification of updates to our Tip of the Month section, click here.


Top-down Design and Synthesis Issues for
Sequential Always Blocks

This month — structured design of synthesizable always blocks to implement sequential logic.

The circuit under consideration is an 8 bit synchronous counter, with an enable, a parallel load, and an asynchronous reset. The counter loads or counts only when the enable is active. When the load is active, Data is loaded into count.

The counter has two modes: binary and decade. In binary mode, it is an 8 bit binary counter. In decade mode, it counts in two 4 bit nibbles, each nibble counting from 0 to 9, and the bottom nibble carrying into the top nibble, such that it counts from 00 to 99 decimal.

The truth table of the counter is as follows (- means don’t care):

Reset	Clock	Enable	Load	Mode	Count	
0	-	-	-	-	0	
1	^	1	-	-	Count	
1	^	0	0	-	Data	
1	^	0	1	0	Count + 1 (binary)	
1	^	0	1	1	Count + 1 (decade)	

and this is the Verilog module declaration:

module COUNTER (Clock, Reset, Enable, Load, Mode, Data, Count);
  input Clock ;
  input Reset ;
  input Enable;
  input Load  ;
  input Mode  ;
  input  [7:0] Data ;
  output [7:0] Count;
// module functionality
endmodule

So, how do you apply top-down design principles, a knowledge of synthesizable Verilog constructs and good coding finesse to this problem? Let’s have a look...

It is important to understand that conceptually, a counter is a register with the output fed back to the input via an incrementer. Hence the Verilog code will reflect this concept. For example,

  // inside a procedure
    Q <= Q + 1;

The design process introduces some key Verilog coding aspects that need to borne in mind for synthesis. The most fundamental is the use of the classic asynchronous-reset-plus-clock single-procedure style of Verilog code.

  always @ (posedge Clock or negedge Reset)
  begin
    if (!Reset)
      // reset register, Q <= 0
    else
      // increment register, Q <= Q + 1;
  end

The essence of the code structure is that the clock and reset need to be in the sensitivity list; the appropriate event on either signal will cause one of the two ‘if’ branches to execute. Note that the always statement must execute only on the rising edge of the clock and the falling edge of the reset, hence we must have posedge Clock and negedge Reset as the timing control of the always statement. Now that we have defined the basic structure of the procedure, we will go on to fill in the two ‘if’ branches.

The reset branch is very simple:

    // inside a procedure
    if (!Reset)
      Q <= 0; 

The clock branch needs to contain the functionality of the other four truth table entries; the code reflects the priority of those inputs directly. The enable signal has the highest priority, with nothing happening when it is high; next in priority is the load signal. Hence inside the enable block we will have,

    // inside a procedure
      if (!Enable)
        // enable counter functionality
        if (!Load)
          // load data
        else
          // implement counting based on mode signal

For the actual increment statement (remember, Q <= Q + 1;), it is desirable to combine this functionality for either mode to ensure that only one piece of incrementer hardware is synthesised. So far, the detailed structure of the process has been derived from the truth table in a top-down design manner. Now we need to code the Verilog with a view to its implementation.

    // inside a procedure
      if (!Load)
        // load data
      else
        if (lower_nibble_count != max_in_either_mode)
          // increment lower nibble
        else
          // wrap lower nibble back to zero
          if (upper_nibble_count != max_in_either_mode)
            // increment upper nibble
          else
            // wrap upper nibble back to zero

Although we are only providing a structure for the detail of the Verilog code in the above code snippet, it is notable that the word ‘increment’ appears only twice and that it applies to nibbles - the code is structured to synthesise two 4-bit incrementers. This is a subtle point — you are relying on a synthesis tool’s resource sharing capabilities to optimize the Verilog unless you write the code as presented above. If your synthesis tool doesn’t support resource sharing, you have to write the code as shown above!

OK, let’s fill out the detail of the code structure presented so far in order to generate a model solution. This is given at the end of the section.

So, filling out the detail,

  // inside a clocked procedure
    if (!mode)                     // 8-bit binary
      Q <= Q + 1;
    else                           // two decade counters
      if (Q[3:0] == 9)             // wrap lower decade
      begin
        Q[3:0] <= 0;
        if (Q[7:4] != 9)           // increment upper decade
          Q[7:4] <= Q[7:4] + 1;
        else                       // wrap upper decade
          Q[7:4] <= 0;
      end
      else                         // increment lower decade
        Q[3:0] <= Q[3:0] + 1;

In summary, we have applied top-down design principles to create a synthesizable Verilog architecture containing a single procedure. The detailed code implementation was produced with the pitfalls of synthesis clearly borne in mind.

The rest of this section gives a model solution:

// counter
// 8 bits
// synchronous, positive edge
// binary/decade
// asynchronous reset, active low
// synchronous parallel load, active low
// synchronous enable, active low
// binary counter mode 0 = 8 bits
// decade counter mode 1 = 2x4 bits
// reset has priority over enable over load

module COUNTER (Clock, Reset, Enable, Load, Mode, Data, Q);
  input Clock ;
  input Reset ;
  input Enable;
  input Load  ;
  input Mode  ;
  input  [7:0] Data ;
  output [7:0] Q;

  reg [7:0] Q;

  always @ (posedge Clock or negedge Reset)
  begin
    if (!Reset)
      Q <= 0;
    else
      if (!Enable)
        if (!Load)
          Q <= Data;
        else if (!Mode && (Q[3:0] != 15)) ||
              (Mode && (Q[3:0] != 9))
          Q[3:0] <= Q[3:0] + 1;
        else
        begin
          Q[3:0] <= 0;
          if (!Mode && (Q[7:4] != 15)) or
             (Mode && (Q[7:4] != 9))
            Q[7:4] <= Q[7:4] + 1;
          else
            Q[7:4] <= 0;
        end
  end

endmodule

Previous Tips of the Month can be downloaded from here...


chip iconVerilog for ASIC Design
reading a bookVerilog Golden Reference Guide


river sceneDoulos Home Page

Copyright 1995-1996 Doulos
This page was last updated 4th August 1996.

mail iconWe welcome your e-mail comments. Please contact us at: webmaste@doulos.co.uk