/// LSU EE 3755 Computer Organization
//
/// Verilog Notes 8 -- Procedural Code
& Behavioral Modeling
//
//
/// Contents
// Event Control (@)
// Syntax and Simulation of if else
// Syntax and Simulation of case
// Syntax and Simulation of for, while,
repeat,forever
// Ripple Adder: Combinational v.
Sequential
// Miscellaneous Examples
/// References
//
// :P:
Palnitkar, "Verilog HDL"
// :Q:
Qualis, "Verilog HDL Quick Reference Card Revision 1.0"
// :PH:
Patterson & Hennessy, "Computer Organization & Design"
////////////////////////////////////////////////////////////////////////////////
/// Event Control (@)
// :P: 7.3.2
// An /event control/ statement pauses the
execution of
// the procedural code in which it appears
// until the specified event occurs.
// The general use of event control
statements will be briefly
// described here.
// :Syntax: @( EXPR ) STATEMENT;
//
// Evaluate EXPR and resume execution
starting with STATEMENT when
// value of EXPR changes.
// :Syntax: @( EXPR1 or EXPR2 or... )
STATEMENT;
//
// Evaluate EXPR1, EXPR2, ... and resume
execution starting with
// STATEMENT when the value of any of the
EXPR change.
// :Syntax: @( posedge EXPR ) STATEMENT;
//
// Resume execution starting with
STATEMENT when EXPR changes from // 0 to anything or from anything to 1.
// :Syntax: @( negedge EXPR ) STATEMENT;
//
// Resume execution starting with
STATEMENT when EXPR changes from
// anything to 0 or from 1 to anything.
// :Syntax: @( EDGE1 EXPR1 or EDGE1 EXPR2
or ... ) STATEMENT;
//
// EDGE1 can be posedge, negedge, or
nothing.
// Resume execution at STATEMENT when any
of the EXPR change to
// the specified value (nothing, which
means just EXPRx,
// means any change, @(EXPR) Statement;).
//
// The event controls can be used anywhere
a statement can go. In
// practice they are almost always used
right after "always @,"
// which is the way they will be covered
in the following
// sections.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Syntax and Simulation of if else
// :P: 7.4
// Similar to C language.
// :Syntax: if( EXPR ) STATEMENT;
//
// If EXPR evaluates to a non-zero number,
execute STATEMENT.
// Note that STATEMENT could be a
begin/end block.
//
// :Syntax: if( EXPR ) STATEMENT1; else
STATEMENT2
//
// If EXPR evaluates to a non-zero number,
execute STATEMENT1
// otherwise execute STATEMENT2.
// :Example:
//
// Examples of if/else.
//
Doing nothing useful.
//
Focus on usage of if statement..
module if_examples();
integer a, b, c, d, x;
initial
begin
if( a < b ) c = 1;
if( a < b ) c = 2; else d = 3;
// Note: x = 5 is always executed; c = 3 only if a < b.
// This is an example of bad style, x = 5 should be put on
// the next line.
if( a < b ) c = 3;x = 5;
// Unlike the statement above, c=3 and x=5
// are executed only if a < b.
if( a < b ) begin c = 3; x = 5; end
if( a < b )
begin
c = 3;
x = 5;
end
else
begin
c = 7;
x = 2;
end
if( a == 0 ) d = 7'b1110111;
else if( a == 1 ) d = 7'b0100100;
else if( a == 2 ) d = 7'b1011101;
else if( a == 3 ) d = 7'b1101101;
else if( a == 4 ) d = 7'b0101110;
else d = 7'b1111111;
end
endmodule
////////////////////////////////////////////////////////////////////////////////
//Example of event control.
module cond_example2(x,y,a,b,c,clk);
input a,b,c;
input clk;
output x,y;
wire [7:0] b, c;
reg [8:0] x, y;
always @( posedge clk )
begin
if( a ) begin
x = b + c;
y = b - c;
end else begin
x = b - c;
end
end
endmodule
// Example of an if/else
module anotherif(x,a);
input [7:0] a;
output x;
reg [7:0] x;
always @( a )
begin
if( a < 10 )
x = 1;
else
if ( a < 20 )
x = 2;
else
if ( a < 30 ) x = 3;
else x = 4;
// x = a < 10 ? 1: a < 20
? 2 : a < 30 ? 3 : 4;
end
endmodule
// An example with lots of if's.
// Focus on usage of if.
// Don't have to worry about what the
module is doing.
module andyetanotherif(x,a);
input [7:0] a;
output x;
reg [7:0] x;
always @( a )
begin
x = a;
if( a[0] )
begin
x = x + 2;
if( a[1] & a[2] ) x = x + 1;
end
else
begin
if( a[3] ^ a[4] ) x = x + ( a >> 1 );
else x = x + ( a << 1 );
x = 3 * x;
end
if( x[7] ) x = x - 1;
end
endmodule
// :Example:
//
//
ALU.
module alu(result,a,b,add);
input [31:0] a, b;
input add;
output result;
reg [31:0] result;
always @( a or b or add )
begin
if( add ) result = a + b; else result = a - b;
end
endmodule
// :Example:
//
// An up/down counter.
module
up_down_counter(count,up,reset,clk);
input up, reset, clk;
output count;
reg [7:0] count;
always @( posedge clk )
begin
if( reset ) count = 0;
else if( up ) count = count + 1;
else count = count - 1;
end
endmodule
//Mux using if statement.We will give mux
// using case statement after this .
// :Example:
//
// A mux, look at how the if/else chain
works.
module mux(x,select,i0,i1,i2,i3);
input [1:0] select;
input [7:0] i0, i1, i2, i3;
output x;
reg [7:0] x;
always @( select or i0 or i1 or i2 or i3 )
begin
if( select == 0 ) x = i0;
else if( select == 1 ) x = i1;
else if( select == 2 ) x = i2;
else x = i3;
end
endmodule
////////////////////////////////////////////////////////////////////////////////
/// Syntax and Simulation of case
// :P: 7.5, 7.5.1 case
// :Syntax: case ( EXPR )
// CEXP1:ST1;
// CEXP2:ST2;
// ...
// [default:STD;]
// Optional
// endcase
//
// EXPR is an expression that evaluates to
a number
// [or physical value].
// CEXP1, CEXP2, etc. are expressions that
evaluate to a number
//[or physical value].
//
// Evaluate EXPR, find the first CEXP that
is equal to EXPR,
// execute the corresponding ST. If none match and default is
// present execute STD.
// :Example:
//
// Description of a multiplexor using a
case statement.
// Using a case statement is much less
tedious
// than using the conditional operator.
module mux_case(x,select,i0,i1,i2,i3);
input [1:0] select;
input [7:0] i0, i1, i2, i3;
output x;
reg [7:0] x;
always @( select or i0 or i1 or i2 or i3 )
begin
case ( select )
0: x = i0;
1: x = i1;
2: x = i2;
3: x = i3;
endcase
end
endmodule
// :Example:
//
// Module describing a selector. There are four data inputs,
// i0,i1,i2,i3, four control inputs c0,
c1, c2, c3, c4, and a data
// output, x. The output is set to the first input with a
// corresponding control input of 1, or
zero if all control inputs
// are zero. See the truth table below.
//
// c3 c2 c1 c0 | x
//
"""""""""""""""
// 0
0 0 0 | 0
// 0
0 0 1 | i0
// 0
0 1 0 | i1
// 0
0 1 1 | i0
// 0
1 0 0 | i2
// 0
1 0 1 | i0
// 0
1 1 0 | i1
// 0
1 1 1 | i0
// 1
0 0 0 | i3
// 1
0 0 1 | i0
// 1
0 1 0 | i1
// 1
0 1 1 | i0
// 1
1 0 0 | i2
// 1
1 0 1 | i0
// 1
1 1 0 | i1
// 1
1 1 1 | i0
module
selector(x,c0,c1,c2,c3,i0,i1,i2,i3);
input c0, c1, c2, c3;
input [7:0] i0, i1, i2, i3;
output x;
reg [7:0] x;
always @( c0 or c1 or c2 or c3 or i0 or i1 or i2 or i3 )
begin
case( 1 )
c0: x = i0;
c1: x = i1;
c2: x = i2;
c3: x = i3;
default: x = 0;
endcase
end
//
//if
co == 1 then x = i0 else if
//
c1 == 1 then x = i1 else if
//
c2 == 1 then x = i2 else if
//
c3 == 1 then x = i3
// usually in case statement the ordering
of CEXPR(co,c1..)
// is not important.
// but in this case , the ordering of
CEXPR is important.
//
//
case( 1 )
//
c3: x = i3;
//
c2: x = i2;
//
c1: x = i1;
//
c0: x = i0;
//
default: x = 0;
//
endcase
// this will generate different result..
// c3 c2 c1 c0 | x
//
"""""""""""""""
// 0
0 0 0 | 0
// 0
0 0 1 | i0
// 0
0 1 0 | i1
// 0
0 1 1 | i1 i0
// 0
1 0 0 | i2
// 0
1 0 1 | i2 i0
// 0
1 1 0 | i2 i1
// 0
1 1 1 | i2 i0
// 1
0 0 0 | i3
// 1
0 0 1 | i3 i0
// 1
0 1 0 | i3 i1
// 1
0 1 1 | i3 i0
// 1
1 0 0 | i3 i2
// 1
1 0 1 | i3 i0
// 1
1 1 0 | i3 i1
// 1
1 1 1 | i3 i0
endmodule
// :Example:
//
// Description of an ALU using case. This version is more
// readable than the structural
descriptions.
module yet_another_alu(result,a,b,op);
input [31:0] a, b;
input [2:0] op;
output result;
reg [31:0] result;
parameter op_add = 0;
parameter op_sub = 1;
parameter op_and = 2;
parameter op_or = 3;
parameter op_slt = 4;
parameter op_a = 5;
parameter op_b = 6;
always @( a or b or op )
begin
case( op )
op_add : result = a + b; // 0 : result = a + b;
// using parameters is easier
// than using just numbers.
op_sub : result = a - b; // 1 : result = a - b;
op_and : result = a & b;
op_or : result = a | b;
op_slt : result = a < b; // evaluate a < b logical
// operation , so result will
// be true or false(1,0)
op_a : result = a;
op_b : result = b;
default : result = 0;
endcase
end
endmodule
////////////////////////////////////////////////////////////////////////////////
/// Syntax and Simulation of for, while,
repeat,forever
// :P: 7.6, 7.6.1, 7.6.2, 7.6.3
// In descriptions below remember
STATEMENT can be
// a single statement or:
//
STATEMENT -> begin STATEMENT1; STATEMENT2; ... end
//
multiple statements inside begin
end block.
// :Syntax: for( INIT_ASSIGN; CONDITION;
STEP_ASSIGN ) STATEMENT
//
#for(i = 0, j = 0 ; i <=4; j = j+1, i = i +1)// this is C.
//
Some C programmers might find the for loop disappointing:
//
INIT_ASSIGN must be an assignment,
// not an arbitrary statement.(not like
...i = 0, j = 0)
//
STEP_ASSIGN must be an assignment,
// not an arbitrary statement.(not like j
= j+1, i = i +1)
//
CONDITION is an expression that evaluates to
// an integer.(commonly using logical
operator for condition)
//
//
1. Execute INIT_ASSIGN.
//
2. Evaluate CONDITION, if true go to next step, else done.
//
3. Execute STATEMENT
//
4. Execute STEP_ASSIGN;
//
5. Go to step 2.
// :Syntax: while( CONDITION) ) STATEMENT
//
//
1. Evaluate CONDITION, if false done, else go to next step.
//
2. Execute STATEMENT.
//
3. Go to step 1.
// :Syntax: repeat( COUNT ) STATEMENT
//
//
COUNT is an expression that evaluates to an integer.
//
//
1. Evaluate COUNT, call result the_count.
//
2. Execute STATEMENT the_count times.
// :Syntax: forever STATEMENT
//
Execute STATEMENT forever.
// :Example:
//
// Easy looping (for, while, repeat)
examples.
module for_example();
integer i, sum;
initial
begin
sum = 0;
for(i=0; i<10; i=i+1)
begin
$display("So far i=%d and sum=%d",i,sum);
sum = sum + i;
end
$display("Finally i=%d and sum=%d",i,sum);
sum = 0; i = 0;
while( i < 10 )
begin
$display("So far i=%d and sum=%d",i,sum);
sum = sum + i;
i = i + 1;
end
$display("Finally i=%d and sum=%d",i,sum);
sum = 0; i = 0;
repeat( 10 )
begin
$display("So far i=%d and sum=%d",i,sum);
sum = sum + i;
i = i + 1;
end
$display("Finally i=%d and sum=%d",i,sum);
end
endmodule
// :Example:
//
// Looping (for,while,repeat) with
additional information.
module looping_examples();
integer a, b, c;
integer i, pop, x;
reg clock, clock2;
initial begin
/// for
// Basic for loop.
for(i=0; i<3; i=i+1) $display("Hello");
// There is no postincrement operator.
// for(i=0; i<3; i++) $display("Hello");
// Syntax error. For C, it is
OK.
// Can only have a single initialization assignment.
//for(i=0, j=0; i<3; i=i+1) $display("Hello");
// Syntax error. For C, it is
OK.
/// while
// Basic while loop.
while( x < 10 ) x = x + 1;
// Assignment (=) is not an operator as in C.
// Verilog does not allow assignment
// inside while loop condidion.
// while( i = i - 1 ) x = x + 1;
// Syntax error.
/// Three Ways to Iterate Ten Times:
// The simplest way is the best.
(repeat).
repeat( 10 ) x = x + 1;
for(i=0; i<10; i=i+1) x = x + 1;
i = 10; while( i ) begin i = i - 1; x = x + 1; end
// while example, count the 1's in b.
pop = 0;
while( b )
begin
pop = pop + b[0];
b = b >> 1;
end
end
endmodule
// the above module may repeat(while) zero
times
// or upto 32 times maximum.
// :Example:
//
// A module that computes the population
of its integer input.
//The population of an integer is simply
the number of 1's in its
// binary representation. (The population of: 1 is 1, 2 is 1,
// 3 is 2, 5 is 2, and 15 is 4.)
module pop_combinational(p,a);
input [31:0] a;
output p;
reg [5:0] p;
integer i;
always @( a )
begin
p = 0;
for(i=0; i<32; i=i+1) p = p + a[i];
end
endmodule
// the above module repeats( for) 32
times.
//looping forever example.
module forever_loop();
reg
clock; // the value stays 0 for a period of time and
// stays 1 for the other time.
initial
begin
// forever is normally used with a delay
control.
// Example below implements a clock with
// a period of 20 cycles.
clock = 0;
forever begin #10 clock =
~clock; end
end
endmodule
//
There is a mechanism for breaking
//out of these loops(for, while ,
repeat,forever), but it's not
//
as convenient as C's break.
// students are not responsible for this
material
// [named blocks and disable statement]
// [disabling blocks and breaking out of
loop]
//
Naming Blocks
/// begin: NAME ...end
//
Example
//
begin: BLOCK1
//
//
end
// disable can be used to exit from loops.
// Example
module disable_example(a,b);
input a,b;
integer
i,x;
initial begin
x = 1;
begin:BLOCK1 //note:BLOCK1 is outside of for loop.
for(i =1; i<10; i = i +1) begin
x = x*i;
// =
1* 1 * 2 * 3 * 4 ....
//Early exit if x >100.
if (x > 100)
disable BLOCK1;
// exit when x > 100 actually x = 1*2*3*4*5 = 120
// when disabled, execution goes
out of the block.**
end //for begin-end
end //BLOCK1 begin-end
x =1; i =1;
//** execution comes here
begin : BLOCK2
forever begin
x = x*i; i = i+ 1;
//Exit if x >100.
if( x> 100) disable BLOCK2;
end//forever begin-end
end //BLOCK2 begin-end
end //initial
begin-end
endmodule
//
// :Example:
//
// A comparison module. Output lt is asserted if a < b
// and gt is asserted if a > b.
module compare(gt, lt, a, b);
input [2:0] a, b;
output gt, lt;
reg gt, lt;
integer i;
always @( a or b ) begin
gt = 0; lt = 0;
for(i=2; i>=0; i=i-1)
if( !gt && !lt ) begin
if( a[i] < b[i] ) lt = 1;
if( a[i] > b[i] ) gt = 1;
end
end
endmodule // compare
// Example1
// a = 101
// b = 011
// at the beginnig.
// gt = 0, lt =0;
// for loop i = 2..
// if statement (condition is true)
// if(a[2] < b[2]).... (1 <
0) //.condition not true...
//doing
nothing.lt still zero.
// if(a[2] > b[2]).... (1 >
0) //.condition true... gt = 1.
// i = 1..
// if statement (condition is not
true)//gt became 1....
//doing nothing.
// i = 0..
// if statement (condition is not
true)//gt became 1....
//doing nothing.
// i = -1...End of for loop.....
// Example2
// a = 101
// b = 111
// at the beginnig.
// gt = 0, lt =0;
// for loop i = 2..
// if statement (condition is true)
// if(a[2] < b[2]).... (1 <
1) // .condition not true...
//doing
nothing.lt still zero.
// if(a[2] > b[2]).... (1 >
1) // .condition not true...
//doing
nothing gt still zero.
// i = 1..
// if statement (condition is true)
// if(a[1] < b[1]).... (0 <
1) // .condition true... lt = 1
// if(a[1] > b[1]).... (0 >
1) // .condition not true...
//doing
nothing gt still zero.
// i = 0..
// if statement (condition is not
true)//lt became 1....
//doing nothing.
// i = -1...End of for loop.....
////////////////////////////////////////////////////////////////////////////////
/// Ripple Adder: Combinational v.
Sequential
///
// Three approaches to ripple adder will
be shown:
//
// (1) Ripple Classic:
//
Combinational Logic using structural code.
//
// (2) Ripple Procedural Combinational:
//
// (3) Ripple Sequential:
//
Uses sequential logic.
//
// :Example:
//
// Classic ripple adder.
module ripple_classic(sum,cout,a,b);
input [3:0] a, b;
output [3:0] sum;
output cout;
wire c0, c1, c2;
bfa_implicit bfa0(sum[0],c0,a[0],b[0],1'b0);
bfa_implicit bfa1(sum[1],c1,a[1],b[1],c0);
bfa_implicit bfa2(sum[2],c2,a[2],b[2],c1);
bfa_implicit bfa3(sum[3],cout,a[3],b[3],c2);
endmodule
// :Example:
//
// A ripple adder made from binary full
adders, but using
// procedural code. Except for the number of bits, equivalent
// to the one above.
module ripple_2(sum,a,b);
input [31:0] a, b;
output sum;
reg [32:0] sum;
reg carry;
integer
i;
always @( a or b )
begin
carry = 0;
for(i=0; i<32; i=i+1) begin
sum[i] = a[i] ^ b[i] ^ carry;
carry = a[i] & b[i] | a[i] & carry | b[i] & carry;
end
sum[32] = carry;
end
endmodule
// :Example:
//
// A sequential ripple adder.
module ripple_seq(sum,a,b,clk);
input [31:0] a, b;
input clk;
output sum;
reg [32:0] sum;
reg carry;
reg [4:0]
i;
initial i = 0;
always @( posedge clk )
begin
if( i == 0 ) begin
sum[32] = carry;// at the
beginning carry is unknown..
//
11111 (31) ----> 00000 (32)
// changing i value.
// sum[32]
= carry generated by
// a[31]
& b[31] | a[31 & carry | b[31] & carry;
carry = 0;
end
sum[i] = a[i] ^ b[i] ^ carry;
carry = a[i] & b[i] | a[i]
& carry | b[i] & carry;
i = i + 1;
end
endmodule
////////////////////////////////////////////////////////////////////////////////
/// Miscellaneous Examples
// :Example:
//
//
Clocked population count module.
//
there is no way to tell that the
//
output is ready.
//so we need a flag to tell when output is
ready.
//
Example for a = 0000 0000 0000 0000 0000 0000 0000 0001 ,
// output will be available early.
// for a = 1000 0000 0000 0000 0000 0000 0000 0000 ,
// output will be available later.
module pop(p,a,clk);
input [31:0] a;
input clk;
output p;
reg [5:0] p;
reg [31:0] acopy;
reg [5:0] pcopy;
initial acopy = 0;
initial pcopy = 0;
always @( posedge clk )
begin
if( acopy == 0 )
begin
p = pcopy;
pcopy = 0;
acopy = a;
end
else
begin
pcopy = pcopy + acopy[0];
acopy = acopy >> 1;
end
end
endmodule
//Example
// a =
0000 0000 0000 0000 0000 0000 0000 0110
//
//
1 cycle..
// doing if.
// p = pcopy =0
// pcopy = 0.
// acopy = a =0000 0000 0000 0000 0000 0000 0000 0110
//
2 cycle..
//
doing else part.
// pcopy = pcopy + acopy[0] = 0 + 0 =0;
// shift.0.0000 0000 0000 0000 0000 0000 0000 011
//
3cycle..
//
doing else part.
// pcopy = pcopy + acopy[0] = 0 + 1 =1;
// shift.00.0000 0000 0000 0000 0000 0000 0000 01
//
4cycle..
// doing else part.
// pcopy = pcopy + acopy[0] = 1 + 1 =2;
// shift.000.0000 0000 0000 0000 0000 0000 0000 0 //acopy becomes zero...
//
5 cycle...
// (acopy became zero at 4cycle)
// doing if part
// p = pcopy =2
//correct p value..//if the module is
// smart,the module should say.."ready".
//finished the process or ready to accept new input....
// pcopy = 0. // instead,
the module is repeating
// the process over again.
//
acopy = a =0000 0000 0000 0000 0000 0000 0000 0110
//
6 cycle.....will repeat 2cycle.....
//
doing else part.
//
pcopy = pcopy + acopy[0] = 0 + 0 =0;
//
shift.0.0000 0000 0000 0000 0000 0000 0000 011
//
7 cycle will repeat 3cycle...
//
8 cycle will repeat 4cycle...
//
9 cycle will repeat
5cycle...update p value
//
10 cycle will repeat 6cycle. which is 2cycle....
//and so on.....
//
//
if we have one at 31 bit position ,
// p will be available at 34 cycles.
// :Example:
//
// Population count with handshaking. Handshaking is the use of
// control signals between two modules to
coordinate activities.
//
// In this case:
//
The external module waits for ready to be 1.
//
ready is output of the module which tells the module is
//
ready to accept inputs.
// If ready = 0 , the module is busy(don't
accept inputs).
//
The external module then puts a number on "a"
// and asserts start.
//
start is output of external module(input to the module)
// which tells inputs to the module are
//
ready, so start to process the inputs.
//
when start is 1,pop_with_handshaking copies the number and
// sets ready to zero(initialize the
module to compute).
//
When start goes to zero, pop_with_handshaking starts
// computing(external module will change
the start value to zero).
//
When pop_with_handshaking is finished it asserts
//
ready(telling the module is not busy so
//
it is ready to accept new inputs to process).
module
pop_with_handshaking(p,ready,a,start,clk);
input [31:0] a;
input start, clk;
output p, ready;
reg [5:0] p;
reg ready;
reg [31:0] acopy;
initial ready = 1;
always @( posedge clk )
begin
if( start )
begin
acopy = a;
p = 0;
ready = 0;
end
else if( !ready && acopy )
begin
p = p + acopy[0];
acopy = acopy >> 1;
end
else if( !ready && !acopy )
begin
ready = 1;//output is ready,also means the module is
// ready to accept new input.
end
end
endmodule
// :Keyword: $stop (System task)
//
// Stops simulation. Used for testbenches and debugging.
##########################################################
module demo_counter();
wire [7:0] count;
reg up, reset, clk;
up_down_counter c1(count,up,reset,clk);
integer i;
initial
begin
i = 0;
up = 1; //up-counting.
reset = 1; //reset the counter
to zero
//after
posedge clk comes.
//see next line(for loop).
for(i=0; i<4; i=i+1) @( posedge clk );
reset = 0; //now the counter is
ready to count.
for(i=0; i < 255; i=i+1)
begin
if( i != count )// at i = 0 : since we reset
// the counter, no clock occured,
//so count remains zero.
begin
$display("Something wrong at i=%d,
count=%d",i,count);
$stop;
end
@( posedge clk ); #1;//just waiting 1 time unit,
//so giving the counter sometime
//to update count value.
end
up = 0;// down counting
for(i=i; i >= 0; i=i-1)
//from previous for loop,
//i is now 255.
begin
if( i != count )
begin
$display("Something wrong at i=%d,
count=%d",i,count);
$stop;
end
@( posedge clk ); #1;
end
$display("Done with tests.");
end
always begin clk = 0; #5; clk = 1; #5; end //clock generator,
//cycle of 10.
endmodule