/// 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