Gradual Introduction to Verilog Syntax: Basic Sequential Circuits

E.R.Doering

August 9, 2001

 

 

Key to typestyle: Italics => Verilog keyword; Bold => new concept introduced

 

Visualize the Hardware:

Describe the Hardware:

Comments:

D flip-flop, positive-edge triggered

module D_FF (D,Clock,Q);

/* Port modes */
input D,Clock;
output Q;

// Registered identifiers
reg Q;

// Functionality
always @ (posedge Clock)
      Q <= D;

endmodule








The input list only contains the signal that is responsible for triggering the flip-flop, i.e., the ‘Clock’ signal; other inputs such as ‘D’ may be used inside the ‘always’ block, but they must not appear in the parenthesized list.

T flip-flop, negative-edge triggered

module T_FF (T,Clock,Q);

/* Port modes */
input T,Clock;
output Q,;

// Registered identifiers
reg Q;

// Functionality
always @ (negedge Clock)
      if (T == 1)
            Q <= ~Q;

endmodule

T (“toggle”) flip-flop behavior is such that applying a 1 to the T input causes the output to change state on the clock edge, and applying a 0 maintains the state.



‘negedge’ for negative-edge trigger.

NOTE: The behavior when T is zero is not explicitly described here. The inferred behavior is that the state of Q should remain unchanged if the ‘if’ test evaluates false (when T is zero).

T flip-flop, negative-edge triggered, with inverted and noninverted outputs

module T_FF (T,Clock,Q,_Q);

/* Port modes */
input T,Clock;
output Q,_Q;

// Registered identifiers
reg Q;

// Functionality
always @ (negedge Clock)
      if (T == 1)
            Q <= ~Q;

assign _Q = ~Q;

endmodule

In this example the ‘assign’ technique is put to good use.




The ‘always’ block implements most of the desired behavior, namely, a single-bit storage device with appropriate behavior and clocking.


The ‘assign’ statement simply copies the Q signal to an additional output while performing the necessary inversion along the way.

D flip-flop, negative-edge triggered, with inverted and noninverted outputs, and asynchronous reset (active high)

module D_FF (D,Clock,Q,_Q,Reset);

/* Port modes */
input D,Clock,Reset;
output Q,_Q;

// Registered identifiers
reg Q;

// Functionality
always @ (negedge Clock or
   posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= D;

assign _Q = ~Q;

endmodule

“Asynchronous reset” means that asserting the reset will instantly set the Q output to zero, regardless of the activity of D or Clock. Q will remain zero as long as Reset is asserted. This behavior matches standard flip-flop circuits.

The ‘always’ block needs to be “triggered” either by the Clock or the Reset, so the Reset signal is added to the parenthesized list.

Once inside the ‘always’ block, a test is made to determine whether the clock or reset was responsible for the trigger, hence the ‘if’ test.

NOTE: Do not try to invent shortcuts here! You will only cause yourself grief!!

D flip-flop, positive-edge triggered, and asynchronous preset (active low)

module D_FF (D,Clock,Q,_Preset);

/* Port modes */
input D,Clock,_Preset;
output Q;

// Registered identifiers
reg Q;

// Functionality
always @ (posedge Clock or
   negedge _Preset)
      if (_Preset == 0)
            Q <= 1;
      else
            Q <= D;

endmodule

“Asynchronous preset” behaves similarly to “reset”, except that the Q output is set to 1 instead of zero.





Technique for making active-low asynchronous control input.

D flip-flop, positive-edge triggered, with synchronous reset (active high)

module D_FF (D,Clock,Q,Reset);

/* Port modes */
input D,Clock,Reset;
output Q;

// Registered identifiers
reg Q;

// Functionality
always @ (posedge Clock)
      Q <= (Reset)? 0 : D;

endmodule

“Synchronous reset” means that the reset action does not occur until the next clock edge.




‘Reset’ does not appear in the input list now, but it appears inside the ‘always’ block.

 

 

NOTE: Avoid the temptation to design arbitrary flip-flop behavior, e.g., ability to trigger on both edges of the clock, ability to trigger on multiple clock signals, etc. The hardware synthesis tool does not “magically” create new hardware from thin air! You have to write circuit descriptions that are realizable, that is, can be mapped onto existing (known) hardware elements such as standard D flip-flops.

Bottom line: Use the constructs listed above exactly as shown... don’t invent your own!!

16-bit data register

module Reg16 (D,Clock,Q,Reset);

/* Port modes */
input [15:0] D;
input Clock,Reset;
output [15:0] Q;

// Registered identifiers
reg [15:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= D;

endmodule

A register is typically composed of an array of D flip-flops.

N-bit data register

module RegN (D,Clock,Q,Reset);

// Constants
parameter NumBits = 34;

// Port modes
input [Numbits-1:0] D;
input Clock,Reset;
output [Numbits-1:0] Q;

// Registered identifiers
reg [Numbits-1:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= D;

endmodule

The ‘parameter’ keyword is used to declare a global constant for register width. This is a simple example of parameterized description. Changing only a single number can update the entire design.

‘NumBits’ parameter can be used to do mathematical calculations that evaluate to a constant value, such as register width.

8-bit up counter with asynchronous reset

module CountUp (Clock,Reset,Q);

// Port modes
 input Clock,Reset;
output [7:0] Q;

// Registered identifiers
reg [7:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= Q + 1;

endmodule

Free-running up counter














Increments by one in this example. Can easily increment by a different constant. Use ‘-‘ to make a down counter.

8-bit up counter with count enable, and asynchronous reset

module CountUp (Clock,Reset,Enable,Q);

// Port modes
 input Clock,Reset,Enable;
output [7:0] Q;

// Registered identifiers
reg [7:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= (Enable) ? Q + 1                   : Q;

endmodule

Counter only increments when ENABLE signal is asserted.














Use ternary operator to add a condition to the count operation.

8-bit down counter with count enable and initialize control inputs, asynchronous reset

module CountDown (Clock,Reset,Enable,Init,Q);

// Port modes
input Clock,Reset,Enable,Init;
output [7:0] Q;

// Registered identifiers
reg [7:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
         Q <= 0;
      else
         if
(Init)
            Q <= 8’hFF;
         else if (Enable)
            Q <= Q – 1;

endmodule

Counter is similar to previous example, except it counts down. An additional control input initializes the counter to 8’hFF.













In this example, asserting “Init” has priority over “Enable” if they are both asserted simultaneously. If neither is asserted, then “Q” remains unchanged.

8-bit loadable shift register

module Shifter (Clock,Reset,Load,D,Q);

// Port modes
input Clock,Reset,Load;
input [7:0] D;
output [7:0] Q;

// Registered identifiers
reg [7:0] Q;

// Functionality
always @ (posedge Clock or
   posedge Reset)
      if (Reset == 1)
         Q <= 0;
      else
        
Q <= (Load) ? D :
            {1’b0,Q[7:1]};


endmodule

Right-shifts the data, filling the MSB with zero.

Clock divider (produces a pulse every N clock cycles)

parameter MaxCount = 12;

 

always @ (posedge Clock or posedge Reset)

   if (Reset) begin

      ClockDiv <= 0;

      SlowClock <= 0;

   end

   else if (ClockDiv == MaxCount)

      begin

         SlowClock <= 1;

         ClockDiv <= 0;

      end

      else begin

         SlowClock <= 0;

         ClockDiv <= ClockDiv+1;

      end