///
LSU EE 3755 Fall
2009 Computer
Organization
//
///
Verilog Notes 7 -- Procedural Code & Behavioral
Modeling
//
//
///
Contents
//
//
Procedural Code Overview
//
Procedural Code Basics (initial,always,begin,end,#,$display)
//
More Procedural Code Basics
(always)
//
Variables (reg, integer, etc)
///
References
//
//
:P: Palnitkar, "Verilog
HDL"
//
:Q: Qualis, "Verilog HDL
Quick Reference Card Revision 1.0"
//
:PH: Patterson & Hennessy,
"Computer Organization & Design"
////////////////////////////////////////////////////////////////////////////////
///
Procedural Code Overview
//
:P: 7, 7.1, 7.1.1
///
Structural Model
//
//
A description of hardware in terms of
//
an interconnection of simpler
//
components. The Verilog examples
presented in class up to this
//
point have been structural models.
///
Behavioral Model
//
//
A description of what hardware does.
That is, a description of
//
what the outputs should be given some input.
//
/// Procedural Verilog
Code
//
//
Used for writing behavioral models.
//
//
Like a Simple C Program:
// Statements executed in program
order.
//
//
Unlike a Simple C Program
// Multiple pieces of code can run
concurrently.
// Need to think about how code
starts and stops.
// Time (simulated) part of
language(think about delay).
// when we have /delay/, the /delay/
is unit time
//
(simulated time).
//This
example is NOT a completed code
//This shows 3 blocks are running concurrently
//
at time 3, each block generates output of and-gate
//each
block has its own activity flow(what it does).
//module
activity_flow( )
/*
initial
begin
#3
and
a1(a1,b1,c1);
end
initial
begin
#3
and
a2(a2,b2,c2);
end
initial
begin
#3
and
a3(a3,b3,c3);
end
endmodule
*/
///
Activity Flow (within procedural code)
//
//
//
A Verilog description can have many activity flows.
// Each "initial" and "always" (see
below) block has
// its own activity
flow.
//
How Code Starts in an ordinary C Program
// Starts with call to
"main."
//
//
How Procedural Code Starts in Verilog
// Code in all "initial" and "always"
blocks (see below)
// starts at
t=0.
/// Reminder
//
//
Pay attention to how simulated time is handled.
//
//
Remember that several pieces of procedural code can
execute
//
concurrently, and so several activity flows are
concurrently
//
advancing.
////////////////////////////////////////////////////////////////////////////////
///
Procedural Code Basics (initial,always,begin,end,#,$display)
//
:P: 7.1, 7.1.1, 7.1.2 initial,
always
//
:P: 7.7, 7.7.1 begin/end.
//
:P: 7.3, 7.3.1 Delay (#)
//
:P: 3.3.1 System tasks, including $display.
//
:Keywords: initial, always, begin, end, #, $display, $stop
//
Procedural Code
//
//
Starts with either "initial" or "always"...
//
... followed by a single statement ...
//
... or a begin / end block [or a fork/join block].
//
//
Details follow example.
//
:Example:
//
//
A module using procedural code to print simple messages.
module
my_first_procedural_module();
integer i;
initial // Indicate start of
procedural code.
// Activity flow (execution) starts at t=0.
begin // begin/end used to bracket
code.
//
Lines below execute sequentially,
//
like an ordinary program.
i = 0;
$display("Hello,World!, i=%d t=%t", i,
$time); //time t = 0;
i = 1;
$display("Hello,World!, i=%d
t=%t",i,$time); //time t =
0;
end
endmodule
/// Specifying Procedural Code: initial,
always
//
//
:Syntax: initial STATEMENT;
//
//
Start activity flow (start executing) with STATEMENT at
t=0.
//
STATEMENT may finish at t=0 or later (depending on what it
is).
//
block of codes inside initial begin-end
will be
//
executed ONLY once.
//
Note: STATEMENT may be a single statement, a begin/end block, // [or a fork/join
block].
//
//
//
:Syntax: always STATEMENT;
//
//
Start activity flow (start executing) with STATEMENT at
t=0.
//
STATEMENT may finish at t=0 or later (depending on what it
is).
//
When STATEMENT finishes start it again. (Loop infinitely.)
/// Procedural [Sequential] Block: begin,
end
//
//
:Syntax: begin STATEMENT1; STATEMENT2; ... end
//
//
Used to bracket statements. begin,
end, and statements between
//
treated as a statement.
//
//
The entire begin/end block below is treated
//
as a single statement.
//
:Sample: initial begin a=0; b=2; end
//
//
:Sample: initial begin clk = 0; x = 3; end
/// System Task:
$display
//
//
:Syntax: $display(FORMAT,EXPR1,EXPR2,...);
//
//
Used to display messages on simulator console. Similar to C
//
printf. FORMAT specifies what text
to print and, using escape
//
sequences( %,\) , how expressions should be formatted.
//
EXPR1, EXPR2, etc
//
are evaluated and their values printed.
//
//
Format Escape Sequences
//
//
Start with a % and are followed by a format character.
//
Format characters: %d (decimal), %h (hex), %o (octal),
//
%b (binary),%c (character), %s(string), %t(time), ...
//
//
See module for examples.
/// System Task:
$stop
//
//
:Syntax: $stop;
//
//
Stop simulator. Typically used at
the end of a testbench or
//
where the testbench discovers an error.
/// Procedural
Delay
//
//
:Syntax: # NUM;
//
//
Delay NUM time units. See behavioral_2
example.
//
//
:Syntax: # ( EXPR );// # (a+b);
// for example ,when a =1, b =3,
//
# 4;
//
//
Delay by value of EXPR;
//
//
:Syntax: # NUM STATEMENT;
//
# 5 and a1(a,b,c);
//
Delay NUM time units then execute
STATEMENT. This is
//
equivalent to: begin # NUM;
STATEMENT; end
//begin #5; and a1(a,b,c); end
//
//
:Syntax: # ( EXPR ) STATEMENT;
//
//
Delay by value of EXPR then execute STATEMENT.
//
This is equivalent to :
//
begin # (EXPR); STATEMENT;
end
//
:Example:
//
//
Procedural code using initial. Code
below starts at t=0, and
//
because there are no delays, finishes at t=0.
//
module
behavioral_1(x);
output x;
reg [7:0] x;
initial
// Activity flow
starts here at t=0.
// Procedural Code
Starts Here
begin
x =
1;
$display("Hello, x=%d,
t=%t",x,$time);
x =
2;
$display("Hello, x=%d, t=%t",x,$time);
x =
3;
$display("Hello, x=%d, t=%t",x,$time);
end
endmodule
//
Simulator Output
//
//
# Hello, x= 1, t= 0
//
# Hello, x= 2, t=
0
//
# Hello, x= 3, t=
0
//
:Example:
//
//
An example of behavioral code using delays. The initial block
//
starts at t=0 and finishes at t=3.
module
behavioral_2(x);
output x;
reg [7:0] x;
initial
begin
x =
1;
$display("Hello, x=%d, t=%t",x,$time);
#1;
x =
2;
$display("Hello, x=%d, t=%t",x,$time);
#1;
x =
3;
$display("Hello, x=%d, t=%t",x,$time);
#1;
end
endmodule
//
Simulator Output
//
//
# Hello, x= 1, t=
0
//
# Hello, x= 2, t=
1
//
# Hello, x= 3, t=
2
//
:Example:
//
//
Use of two initials in a module.
Both start execution at t=0.
module
behavioral_3(x);
output x;
reg [7:0] x;
// Initial block
A
initial
// Activity flow
starts here at t=0.
begin
x =
1;
$display("Hello, x=%d, t=%t",x,$time);
#10;
x =
2;
$display("Hello, x=%d, t=%t",x,$time);
#10;
//
The two statements below and in the next initial block
//
execute at t=20. There is no way to
tell
//
for sure whether
//
the final value of x will be 3 or 30.
x =
3;
$display("Hello, x=%d, t=%t",x,$time);
#10;
end
// Initial block
B
initial
// Activity flow
starts here at t=0.
begin
#5;
x =
10;
$display("Hello, x=%d, t=%t",x,$time);
#10;
x =
20;
$display("Hello, x=%d, t=%t",x,$time);
#5;
//
The two statements below and the two in the previous
//
initial block execute at t=20.
There is no way to tell
//
for sure whether the final value of x will be 3 or 30.
x =
30;
$display("Hello, x=%d, t=%t",x,$time);
#10;
end
endmodule
// t 0 5 10 15 20
// A x=1 x=2
x=3
// B
x=10
x=20 x=30
//
// Both blocks execute at t=20. One of them will execute before // the other but there is not way to
predict which one.
//
//
Simulator Output:
//
//
# Hello, x= 1, t=
0
//
# Hello, x= 10, t=
5
//
# Hello, x= 2, t=
10
//
# Hello, x= 20, t=
15
//
# Hello, x= 3, t=
20
//
# Hello, x= 30, t=
20
//
:Example:
//
//
The module below is a behavioral description of an xor gate
//
that doesn't work. Why
not?
module
this_xor_gate_doesnt_work(x,a,b);
input a, b;
output x;
reg x;
initial
begin
x =
a ^ b;
end
endmodule
//
Because it sets the output to a xor b only once, at t=0.
//
Inputs a and b might change after t=0, but x won't.
//
execution starts at t = 0, and executes only once.
//
:Example:
//
//
Testbench for the xor gate above.
module
demo_xor();
reg a, b;
wire x;
this_xor_gate_doesnt_work
x0(x,a,b);
integer i;
initial
for(i=0; i<4;
i=i+1)
begin
a = i[0];
b = i[1];
#1;
end
endmodule
////////////////////////////////////////////////////////////////////////////////
///
More Procedural Code Basics
(always)
//
:P: 7.1.2
always
//
:Keyword: always
//
//
:Syntax: always STATEMENT;
//
//
Execute STATEMENT at t=0.
//
When it completes execute it again. And again, and
again,...
/// Use of initial and
always
//
//
Use of initial
// Testbench
code.
// Initializing modules for
simulation, NOT for synthesis.
//
:Example:
//
//
A simple always demo. Message will
be printed endlessly
//
as simulated time advances.
module
shouldnt_do_this();
always
begin
$display("This is an infinite loop.");
#10;
end
endmodule
//
:Example:
//
//
An example of how NOT to use always.
It starts at t=0 and
//
loops endlessly without advancing time.
//
Therefore the code in the
//
initial block never gets past the #1 delay.
//
Two blocks always and initial running concurrently
//
because there is job to finish at time t = 0
//(
which never finishes..always block).
//
simulated time clock never reaches time t = 1;
//
so the initial block's $display will never enter
//(it
will be executed at time t =1.)
module
never_do_this();
always
begin
$display("This is an infinite loop too.");
end
initial
begin
#1;
$display("The simulator will never print this
one.");
end
endmodule
//
:Example:
//
//
An example of how to use always.
The code in the initial block
//
initializes the clock to 0.
//
The code in the always block inverts
//
it every ten cycles.
//
This sort of code is used by testbenches.
module
clock_generator(clk);
output clk;
reg clk;
initial clk =
0;
always
begin
#10;
clk
= ~clk;
end
endmodule
//
:Example:
//
//
Another proper use of always. This
generates a clock that is
//high
for 90% of the time. (The clock above was a square wave.)
module
another_clock_generator(clk);
output clk;
reg clk;
always
begin
clk
= 0;
#1;
clk
= 1;
#9;
end
endmodule
////////////////////////////////////////////////////////////////////////////////
///
Variables (reg, integer, etc)
//
:P: 4.2.3 Port connection rules.
//
:P: 3.2.3, 3.2.5 Registers (Variables), variable types.
/// Variable Types
//
//
Hold values, unlike wires (nets)
//
Variable Types
//
//
reg: Holds
physical values. (Vector of 0, 1, x, z)
//
Declared with a specific number of bits.
//
Unsigned integer (or x or z).
//
//
integer: Signed integer.
//
Usually 32 bits (based on host machine).
//
//
real: Floating-point
number.
//
//
time: At least a 64-bit
integer.
//
For holding simulated time.
module
var_usage();
reg [7:0] r;
integer i;
real
f;
time
t;
initial
begin
r =
5;
i =
r;
f =
1.0 / i; // Take reciprocal of
i.
t =
$time; // Get current time.
//
Display values in appropriate formats.
$display(" r = %h, i =
%d, f = %f, t = %t",r,i,f,t);
end
endmodule
/// Variable and Net Assignment
Rules
//
//
Nets and variables are not interchangeable.
//
Here is how they can be used:
//
Letters refer to example below.
//
//
Note: net types: wire.
// variable
types: reg, integer, real, time.
//
//
A:Procedural Code
// Can assign to
variables.
// Cannot assign to
nets.
//
//
B:Continuous Assignment (assign)
// Left-hand side must be a
net.
// Cannot be used to assign
variables.
//
//
C:Instantiation Input Connection
// Can use net, variable, or
expression.
//
: bfa bfa1(sum,carryout,a,b)
//
: a, b can be net or variable.
//
//
D:Instantiation Output Connection
// Must use net. (Cannot use
variable.)
//
: bfa bfa1(sum,carryout,a,b)
//
: sum, carryout should be net.
//
//
E:Module Input Port
// Must use net. (Cannot use
variable.)
//
: module bfa (sum,carryout,a,b)
//
: a, b should be net.
//
F:Module Output Ports
// Can use nets or
variables.
//
When make a module, inputs should be wires.
//
When instantiate a module, outputs should be wires.
//
:Example:
//
//
Examples of how nets and registers used.
module
reg_v_net();
reg [7:0] x,
y;
wire [7:0] a,
b;
// B: Continuous assignment to a
net.
assign a =
x;
// B: The commented-out line below
would be an error
// because reg's cannot be
assigned using assign.
// assign y = x;
initial
begin
//
A: Assignment to a variable.
x =
1;
//
A: The commented-out line below would be an error
//
because
//
net's cannot be assigned in procedural code.
// b
= 1;
end
endmodule
//
:Example:
//
//
Examples of how nets and registers used for ports
//
and connections.
module
port_example_1();
wire s, co;
// D: Commented-out line below
would be an error
// because variables
// (including reg's) cannot
connect to instantiation output
// connections, in this case
sum and carry out.
// reg s,
co;
// C: Instantiation input
connections
//(inputs to an
instantiated
// module, bfa_implicit.b1
below) can be either reg's
//or net's.
reg a, b;
// C: Input connections to
instantiated module
//are regs (a,b)
and
// an expression
(1'b0).
// D: Output connections are nets
(s,co),
// and cannot be variables
(regs).
bfa_implicit
b1(s,co,a,b,1'b0);
initial
begin
#1; a = 0; b = 0;
#1;
a = 0; b = 1;
#1;
a = 1; b = 0;
#1;
a = 1; b = 1;
#1;
end
endmodule
//
:Example:
//
//
Additional examples of how to use variables and nets.
//
focus on usage of nets and variables,
//
not to focus on module's functionality...
module
port_example_2(x,s,a);
// E: Module inputs must be wires.
(The default.)
input a;
// F: Module outputs can be either
variables or nets.
// Here x is a variable (reg)
and s is a net
//(wire, by
default).
output x, s;
reg x;
// E: The commented out line below
would be an error
// since module
inputs
// cannot be
variables.
// reg a;
wire co;
// D: Commented-out line below is
an error because variables
// (including reg's) cannot
connect to output ports,
//in this
case
// sum and carry
out.
// below we intantiate
BFA.
// When intantiate a module,
outputs should be nets
// reg co;
// C: Input connections to
//an instantiated module
(bfa_implicit.b1
// below) can be either reg's
or net's.
// Here, net type wire is used.
wire b, ci;
integer i;
assign b =
i[0];
assign ci =
i[1];
bfa_implicit
b1(s,co,a,b,ci);
initial
begin
x =
1; // x is not a very useful output.
#1;
i = 0;
#1;
i = 1;
#1;
i = 2;
#1;
i = 3;
#1;
end
endmodule