Gradual Introduction to Verilog Syntax: Basic Sequential Circuits

E.R.Doering

October 4, 2002

 

 

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)

 

reg SlowClock;
reg [3:0] ClockDiv;

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

 

ClockDiv� needs to be sized to accommodate the value you set for �MaxCount�. In the example at left, a maximum count of 12 means the counter register needs four bits. If your maximum count was 1000, you would need a 10-bit counter.

You can calculate the required number of bits as:

,

 

where the � � operator (�ceiling operator�) means go to the next higher integer.