You are on page 1of 25

Verilog Tutorial

Fall 2005-2006
Combinational logic
Two-input NAND gate based on assign keyword

module example1(c,a,b);
input a, b;
output c;

// Functionality a
c
assign c = ~(a & b); b

endmodule

The “assign” technique is called a “continuous assignment.”

If there are several continuous assignments, the order does not matter, they are executed
concurrently.
Example: assign c=~(a&b);
assign d=a^b;
The code has to be modified accordingly adding the signal “d” as an output.
Signals a, b, c are wires by default, but we do not have to declare them in this example.

Note: The code must be written to a file, typically with a “.v” extension. Use the same name for the
file and the module to avoid confusion.
Two-Input NAND gate based on the always keyword

module example2 (a,b,c);


// Port modes
input a,b;
output c;
// Registered identifiers a
reg c; c
Sensitivity list b
// Functionality
always @ (a or b)
      c = ~(a & b);
endmodule

• All inputs used in the procedure must appear in the sensitivity list (event/trigger list).
• The “always” keyword means that the circuit always (continuously) watches the signals in the input list
( the @ (a or b) part) and responds to changes in those signals by immediately updating the output. This
is procedural assignment.
• Combinational circuit outputs must also be declared as registered identifiers when the “always” method
(“procedural assignment”) is used. In Verilog code reg variables can be used to model either
combinational or sequential parts of the circuit.
• The ‘=‘ blocking assignment was used in this example (inside the always block).
• Verilog compiler evaluates the statements in an always block in the order in which they are written i.e. in
sequential order. If a variable is given a value by a blocking assignment, then this new value is used in
evaluating all subsequent statements in the block .
Two-input NAND and Exclusive OR using non-blocking assignments

module example3(a,b,c,d);
// Port modes
input a, b;
output c; a
output d; c
// Registered identifiers b
reg c,d;
// Functionality d
always @ (a or b)
begin
      c <= ~(a & b);
      d <= a ^ b;
end
endmodule

Enclose multiple output signal assignments inside a “begin” - “end” block;
• The “<= “ non-blocking assignment was used in this example.
• Inside an always block, non-blocking and blocking assignments cannot be mixed.
• All non-blocking assignments are evaluated using the values that the variables have when the always block
is entered. Thus a given variable has the same value for all the statements in the block. The meaning of
non-blocking is that the result of each assignment is not seen until the end of an always block. All non-
blocking assignments are evaluated in parallel.
Example :
always @(a or b or c)
b<= a
if (b) // “b” will be the old “b”
• When there are multiple assignments to the same variable inside an always block, the result of the last
assignment is maintained.
• Blocking assignments are recommended for combinational circuits.
Two-input MUX
module Mux2 (A, B, Sel, Y);
input A, B, Sel; B
output Y;
reg Y; SEL
Y

// Functionality
always @ (A or B or Sel) A

      if (Sel==0)
            Y = A;
      else
            Y = B;
endmodule

• Use “if-else” to connect output “Y” to one of the two data inputs based on the value of the data
selector “Sel”.
• The expression inside the parentheses after “if” must evaluate to either “1” (true) or “0” (false).
2-to-1 MUX: an alternate method

module Mux2(A, B, Sel,Y);


// Port modes
input A, B, Sel;
output Y;
// Registered identifiers
reg Y;
//Functionality
always @ (A or B or Sel)
      Y = (Sel) ? B : A;

endmodule

Here the conditional (ternary) operator is used. Read the statement like this: “Is
the control signal ‘Sel’ equal to 1? If yes, Y is assigned the value B else A.”
4-to-1 Multiplexor
module Mux4 (Data, Sel, Y);

//Port modes
input [3:0] Data;
input [1:0] Sel;
output Y; EN
reg Y;
S[1:0] S1
S0
always @ (Data or Sel)
      if (Sel ==2’b00) D3
D2 Y
            Y = Data[0]; Q
      else if (Sel ==2’b01) Data[3:0] D1
            Y = Data[1]; D0
      else if (Sel == 2’b10)
            Y = Data[2];
      else if (Sel == 2’b11)
Y = Data[3];

endmodule

• “if-else-if” is used.
• A four-bit bus (vector). The square brackets define the bus width. The left-side number is the
MSB. A two-bit bus is used for the data selector.
• 2’b1 => implies a 2-bit value specified in binary form. Here, it is the binary value 01. The value
is zero-extended.
Four-Input MUX: an alternate method
module Mux4 (Data, Sel, Y);
//Port modes
input [3:0] Data;
input [1:0] Sel;
output Y;
reg Y;

always @ (Data or Sel)


      case (Sel)
      0: Y = Data[0];
      1: Y = Data[1];
      2: Y = Data[2];
      2’b11: Y = Data[3];
      default: Y =1’bx;
      endcase
endmodule

• “case” is used. The controlling expression (Sel) and each alternative (0,1,2,3) are compared
bit by bit. The first successful match causes the associated statements to be evaluated.
• When the specified alternatives do not cover all possible valuations of the controlling
expression (Sel), the default clause (optional) is used.
• “default” keyword is a catch-all – if a match is not found, the default assignment is made.
• If possible, use don’t-care as the default output to reduce hardware.
4-to1 MUX
module Mux16 (Data, Sel, Y);
parameter DataWidth = 16;

input [DataWidth-1:0] Data;


input [3:0] Sel;
output Y;
reg Y;
// Functionality
always @ (Data or Sel)
      casez (Sel)
      4’b0000: Y = Data[0];
      4’b0001: Y = Data[1];
      4’b01??: Y = Data[2];
      default: Y = Data[3];
      endcase
endmodule
• The question mark is a “don’t care” when it appears inside a numerical constant. In this example,
the case selection ignores the two lowest bits and looks for a match on the two highest bits. You
need to use the ‘casez’ version of the ‘case’ statement when using “don’t cares”. All other values of
the “Sel” control signal cause the fourth data bit to be selected. Data bits 15 through 4 are
effectively not used in this example.
• “parameter” can be used to define any constants.
Bitwise operators Relational Operators:
~     NOT ==    Equal to
&     AND !=    Not equal
|     OR <     Less than
^     EXOR >     Greater than
<=    Less than or equal
More Operators: >=    Greater than or equal
>>    Shift right &&    AND
<<    Shift left ||    OR
+     Add
-     Subtract
*     Multiply
/     Divide
%     Modulus
Exercise 1
 You are given the Verilog code for a 4-bit
adder.
 The inputs are A[3:0], B[3:0]
 The outputs are Sum[4:0] (includes Cout)
 Modify the program to include subtraction.
 The inputs are in twos complement form.
Exercise 2
 Write a Verilog program to create a 1-bit ALU
 The ALU can perform bitwise-AND, bitwise-
OR, Addition and Subtraction
 The inputs are A,B, Cin, Operation
 The output is Result
Sequential circuits
D flip-flop, positive-edge triggered

module D_FF (D, Clock, Q);


input D, Clock;
output Q;
// Registered identifiers 1 D
reg Q; 0 Q
// Functionality D Q
20,20
always @ (posedge Clock) CLK
      Q <= D; C

endmodule

 The sensitivity list contains only the signal that is responsible for triggering the flip flop, i.e., the
‘Clock’ signal; It is possible to specify that the response should take place only at a particular edge
of the signal, using the keywords “posedge” and “negedge”.
 The keyword “….edge” specifies that a change may occur only on the edge of the Clock. At this
time the output Q is set to the value of input D. Since Q is reg type it will maintain the value
between the edges of the clock.
 Other inputs such as ‘D’ may be used inside the ‘always’ block, but they must not appear in the
sensitivity list.
 Use non-blocking assignments to describe sequential circuits.
D flip-flop, positive-edge triggered, with Q_bar

module D_FF (D, Clock, Q);


input D, Clock;
output Q;
// Registered identifiers
reg Q;
wire Q_bar;

assign Q_bar = ~Q;


always @ (posedge Clock)
      Q <= D;
endmodule
• In this example the ‘assign’ statement is used.
• 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.
• A variable on the left side of the equal sign must not be in the trigger list or the machine may go into an
infinite loop.
always@(state or A or B or C….)
begin
A<=B+C; //A will immediately retrigger the always procedure
D flip-flop, positive-edge triggered, with inverted and non-inverted outputs,
and asynchronous reset (active high)

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


input D,Clock,Reset;
output Q, Q_bar;
reg Q;
always @ (posedge Clock or posedge Reset)
      if (Reset == 1)
            Q <= 0;
      else
            Q <= D;
assign Q_bar = ~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.
• The ‘always’ block needs to be “triggered” either by the Clock or the Reset, so the Reset signal is
added to the sensitivity list. Note that the sensitivity list specifies the posedge or negedge of reset
as an event trigger along with the positive edge of the clock.
• We cannot omit the keyword “....edge” because the sensitivity list cannot have both edge triggered
and level sensitivity signals
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 similar to “reset”, except that the Q output is set to 1 instead of 0.

Avoid the temptation to design arbitrary flip-flop behavior, e.g., ability to trigger on both edges of the
same 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 physically
possible, that is, can be mapped onto existing (known) hardware elements such as standard D flip-
flops.
D flip-flop, positive-edge triggered, with synchronous reset (active low)

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


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

// Functionality
always @ (posedge Clock)      
if (Reset==0)
Q <=0;
else
Q<= 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.

Another way to write the code:


Q <= (!Reset)? 0 : D;
Exercise 3
 Write a Verilog program that creates a 16-bit
register with an asynchronous reset.
 The inputs are D[15:0], Clk, Reset.
 The output is Q[15:0].
Finite State Machine

A Finite State Machine is described by:


 Its states and a description of their physical meaning.
 The way the machine makes the transitions to the next state.
These must be based on the present state and/or the present
inputs only. The state is the collective contents of all Flip-flops; The
state memory is a set of n flip-flops that store the current state of
the machine, and it has 2n distinct states.
 The outputs from each state.

Mealy versus Moore FSM


Moore outputs depend only on the state of the machine. Moore
machines are easier to design.
Mealy outputs depend on the present state and the inputs. Mealy
machines usually have fewer states and thus are often smaller.
Standard form for FSM in VERILOG
Break FSMs into four blocks:
State definitions-Next state calculations (decoder)-Registers or flip-flops calculation-Output
calculations (logic)

//state flip-flops
reg [2:0] state, next_state;

//state definitions
parameter S0=2’b00 S1=2’b 01, S2=2’b 10, S3=2’b11,…
// State machine descriptions
//Next state calculations
always @(state or….)
begin
case (state)
…..
end
//register or flip-flop calculation
always@(posedge clk)
state<=next_state
//Output calculations
Output=f(state, inputs)
FSM of a Mealy machine
Module FSM (clk, x, z);
input clk, x;
output z;
//state flip-flops
reg[2:0] state, next_state;
// State definition
parameter S0=0, S1=1, S2=2, S3=3, S4=4;
//State machine description using case
always@ (state or x)
begin
case(state)
S0: if (x) next_state=S1;
else next_state=S0;
Present Next state Output
S1: if (x) next_state=S3; state X=0 X=1 z
else next_state=S2;
S2: if (x) next_state=S0; S0=000 S0=0 S1=1 0
else next_state=S4;
S3: if (x) next_state=S2; S1=001 S2=2 S3=3 0
else next_state=S4;
S4: next_state=S0;
default: next_state=S0; S2=010 S4=4 S2=2 0
endcase
end S3=011 S4=4 S0=0 0
//flip-flops calculations
always @ (posedge clk) S4=100 S0=0 S0=0 1
begin
state<=next_state;
end Default S0=0 S0=0 0
//output calculations
assign z=(state==S4);
endmodule
Recommendations for FSM
 The state must always be of type reg.
 The states should be given meaningful names rather than
numbers. Define state codes using symbolic constants defined
using parameter. Assign the parameter a size to avoid errors:
parameter [3:0] INIT=4’d0000, SETUP=4’d0001,
 Do not mix the next state calculations with the flip-flop
definitions.
 For next state calculations, it is very common to use a
combination of case and if for this block.
 Assign a default next state to gracefully handle what happens
when the FSM winds up in an unknown state. (Otherwise
latches will be generated.)
 Output calculations: one simple assign statement can be easily
used.
References
 Dr. Radu’s website
 Dr. Doering’s website
 http://www.sutherland-hdl.com/on-line_ref_gu
ide/vlog_ref_top.html
 http://www.asic-world.com/verilog/veritut.html

You might also like