/// LSU EE 3755 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