/// LSU EE 3755 --Spring 2009-- Computer
Organization
//
/// Verilog Notes 12
-- Synthesis
//
// More illustrations of synthesized
hardware.
/// Contents
//
//
//
// Synthesis of Procedural Code (Three
Forms)
// Form 1 - Combinational Logic and
Level-Triggered Reg
// Form 2 - Edge-Triggered
Flip-Flops
// Synthesis of Forms 1 and 2 (Summary of
Classes)
// Synthesis: Assignments Class, some FormEnd
Class cases.
// Synthesis of Conditional Class
(if/else)
// Synthesis of Conditional Class (case,
if/else chains)
// Synthesis of Iteration Class (for, while,
repeat)
/// References
//
// :P: Palnitkar, "Verilog
HDL"
// :Q: Qualis, "Verilog HDL Quick
Reference Card Revision 1.0"
// :PH:
Patterson & Hennessy, "Computer Organization &
Design"
///////////////////////////////////////////////////////////////////////////
/// Synthesis of Procedural Code (Three
Forms)
// :P: 14.3.3
/// Synthesizable
Definition
//
// A property of an HDL description
indicating that a synthesis program
// will correctly synthesize it. Whether a description is
synthesizable
// depends upon the synthesis program
used.
//
// Not all procedural code is
synthesizable.
//
/// Note
//
// In these notes flip-flop and registers are
used interchangeably.
// (A register is a collection of flip-flops
meant to store data. A
// one-bit register is equivalent to a
flip-flop as used here.)
/// The Three Synthesizable
Forms
//
// An always block is synthesizable if it is
in one of three forms:
//
// Form 1
// Synthesizes into combinational
logic and level-triggered flip-flops.
//
// Form 2
// Synthesizes into edge triggered
flip flops.
//
// Form 3
// Synthesizes into a state machine.
//
// The form applies to a procedural block
starting with "always."
// A module can have any number of such
blocks, each block can
// be in any form.
//
// Blocks starting with initial are not
synthesizable.
/// Synthesis of Forms 1 and
2
//
//
// See the Synthesis of Forms 1 and 2 section
further below.
////////////////////////////////////////////////////////////////////////////////
/// Form 1 - Combinational Logic and
Level-Triggered Reg
// Describes combinational logic and
level-triggered flip-flops (latches)
// :Syntax: always @( OBJ1 or OBJ2 or ... ) begin
ST1; ST2; ... end
//
// OBJ1, OBJ2, etc are the names of nets
or names of variables; these
are
// said to be in the /sensitivity
list/.
//
// ST1, ST2, etc are statements that conform
to the following rules:
//
// Every net or variable appearing in an
expression must be in the
// sensitivity list unless that value is
written by an earlier
// statement(If this rule is not followed
simulation will not
// match synthesis; synthesizer program will
give the wrong realization.).
//
// ST1, ST2, etc. must not contain
delays or event controls (#5,
// @( a ), wait); sometimes not
synthesizable or wrong result.
// Example :
wait
//
always
//
wait(count_enable) #20 count = count +1; //it is
waiting
//for count_enable to become 1
//when it becomes 1 ,
//it will increment count
//after 20 time
units.
//
//
The number of iterations performed by looping constructs
//
must be determinable(known in advance) by the synthesis
program
// at analysis time (sort of like compile
time);
//
otherwise it is not synthesizable.
//
for ( i = 0; i <= 4 ; i = i +1)
// synthesizable.
//
c =
2;
//
a =
c+1;;
// for
( i = 0; i <= a ; i = i +1)// Not synthesizable ;
//a is unknown at analysis time.
// knowing "a" value requires
// arithmetic operation, a = c+1;
// System tasks ($display, etc.) are
not allowed;
// if included , the module is
not synthesizable.
//
// :Example:
//
// An 8-bit adder in Form
1.
module
sum_using_form_1(sum,a,b);
input [7:0] a, b;
output
sum;
reg [8:0]
sum;
// Code below executes each time a or b changes.
// always @( OBJ1 or OBJ2 or ... ) -> always @( a or b
)
always @( a or b )
begin
sum
= a + b; //
ST1
end
endmodule
//See Fig.1
// :Example:
//
// Example of something which is almost Form
1. Unlike the
adder
// above, the output of the module will not
change when b changes,
// at least according to the simulator. (Some
synthesis programs
// incorrectly synthesize
this.)
module
sum_using_not_quite_form_1(sum,a,b);
input [7:0] a, b;
output
sum;
reg [8:0]
sum;
// Code below executes each time a changes. This is close to
// Form 1, but not the same. (Simulated and synthesized
versions
// will differ.)
always @( a )
begin
sum
= a + b;// b does not appear in the sensitivity list;
//so wrong result.
end
// Remember, code above is NOT Form 1
// (nor any other synthesizable form).
endmodule
// :Example:
//
// A module for computing a complex
product.
module
complex_prod(xr,xi,ar,ai,br,bi);
input [31:0] ar, ai, br, bi;
output xr,
xi;
reg [31:0] xr,
xi;
// Temporary variables to hold products.
reg [31:0] p1,
p2;
always @( ar or ai or br or bi )
begin
xr =
ar * br - ai * bi;
p1 =
ar * bi;
p2 =
ai * br;
xi =
p1 + p2; // p1,p2 are written by
earlier statements;
// although p1, p2 are not appearing in the
// sensitivity list, it is
Ok.
end
endmodule
// See fig.2
////////////////////////////////////////////////////////////////////////////////
/// Form 2 - Edge-Triggered
Flip-Flops
// Describes edge-triggered flip
flops.
// The description below is a simplified
version of Form 2.
// :Syntax: always @( posedge CLK ) begin ST1; ST2;
... end
//
//
// ST1, ST2, etc are statements that conform
to the following rules:
//
// ST1, ST2, etc. must not contain
delays or event controls (#5,
// @( a ), wait);sometimes not
synthesizable or wrong result.
//
// Each variable can be assigned in
only one always block.
// The following is not synthesizable
or gives wrong result.
// Example :
// reg ab;
//
always(a)
//
begin
//
ab = c;
//
end
//
//
always(c)
//
begin
//
ab = d;
//
end
// because varialbe ab is written in two always
blocks.
//
// The number of iterations performed
by looping constructs
// must be determinable (known in
advance)
//
by the synthesis program at
analysis time (sort of like compile time).
// This will be explained further
when looping constructs are
covered.
// System tasks ($display, etc.) not
allowed;
// if included , the module is not
synthesizable.
// :Example:
//
// Module describing an adder with a buffered
output(we store the output). // On
the positive edge of clk output sum is set to a+b;
// that sum stays there until the next
positive edge.
module
sum_using_form_2(sum,a,b,clk);
input [7:0] a, b;
input
clk;
output
sum;
reg [7:0]
sum;
// Code below executed each time clk changes to 1.
always @( posedge clk )
begin
sum
= a + b; //
ST1
end
endmodule
// See Fig.3
// :Example:
//
// A module for computing a complex
product. The
product
// is updated on the positive edge of the
clock.
// buffered output(we store the output).
module
complex_prod_2(xr,xi,ar,ai,br,bi,clk);
input [31:0] ar, ai, br, bi;
input
clk;
output xr,
xi;
reg [31:0] xr,
xi;
// Holds products.
reg [31:0] p1,
p2;
always @( posedge clk )
begin
xr =
ar * br - ai * bi;
p1 =
ar * bi;
p2 =
ai * br;
xi =
p1 + p2;
end
endmodule
// Same as Fig.2 except that we store xi and
xr into Flip-Flops.
////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Forms 1 and 2
// Synthesis
//
// Synthesizable code will be
decomposed into four classes,
// each with its own simple synthesis
rules.
//
// The Classes:
//
// Assignment:
//
Conditional: if/else and
case.
// Iterative: for, while,
repeat.
// FormEnd: Indicates the
end of a procedural block.
//
// Notation:
//
// SStatement
-> Assignment | Conditional | Iterative
// (SStatement can
refer to either Assignment, Conditional,
//
or
Iterative.)
// Structure of Form 1 always
Block:
//
// :Syntax: always @( SLIST )
SStatement FormEnd
// :Syntax: always @( SLIST ) begin
SStatement SStatement ... end FormEnd
//
// See first example
below.
// Structure of Form 2 always
Block:
//
// :Syntax: always @( posedge CLK )
SStatement FormEnd
// :Syntax: always @( posedge CLK
)
//
begin SStatement SStatement ... end FormEnd
// :Example:
//
// Module with comments indicating how the
code is classified.
module
syn_example_f1(x,y,a,b,c);
input [7:0] a, b, c;
output
x, y;
reg [8:0] x,
y;
// SLIST -> a or b or c
always @( a or b or c ) //
Form 1.
begin
x =
a + b;
// SStatement -> Assignment -> x = a + b;
y =
x & c | b;
// SStatement -> Assignment -> y = x & c |
b;
x =
b + 7;
// SStatement -> Assignment -> x = b + 7;
end
// FormEnd There is no
code here.
endmodule
// See Fig.4
/// Classes
//
// For Each Class:
//
//
Hardware is synthesized.
//
The hardware emits(produces) updated values of
variables.
//
// So, for each class we need
to:
//
//
Determine what hardware is
synthesized(adder,multiplexor,etc).
//
Determine which variables get updated values.
//
/// Summary of Classes
//
// Assignment
//
//
:Sample: x = a +
b;
//
// Hardware:
// Combinational
logic for right-hand side (RHS) of assignment.
// An adder for the
sample above.
// Updated Variable:
// The assigned
variable. Variable x in the sample above.
//
// Conditional
//
//
:Sample: if( a ) begin x = y; c = 5; end else begin c = z;
end
// Note: also includes
case.
//
// Hardware:
// One multiplexor
for each updated variable, each input
// from a different
path (if, else).
// Updated Variables:
// All variables
modified in "if" or "else" parts.
// See Fig.5.
//
// Iterative
//
//
:Sample: for(i=0;i<5;i=i+1) begin s = s + a[i];
end
// Note: also includes while,
repeat.
//
// Hardware:
// Synthesize n
copies of hardware corresponding to the loop body,
// where n is the
number of iterations.
// Updated Variables:
// All variables
updated in last iteration.
// See Fig.6.
// FormEnd
//
// This one is important and is
described in several places below.
//
// Each variable may synthesize into
a register, which means
// a variable may NOT synthesize into
a register. This
has
// nothing to do with the declared
type, since that should be
// reg.
// if a variable is updated
always,
// it is synthesized as wire,otherwise
it is synthesized as a
reg.
//
// Hardware:
// Form 1:
Level-triggered registers (latches)
//
for some modified variables.
// Form 2:
Edge-triggered registers for some modified variables.
// Updated Variables:
// Those for which
registers synthesized(outputs of registers).
////////////////////////////////////////////////////////////////////////////////
/// Synthesis: Assignments Class, some
FormEnd Class cases.
/// Assignment
Class
//
// :Sample: sum = a +
b;
//
// Hardware:
//
// Combinational logic corresponding
to
// RHS(the RHS requires an adder the
output of
// which will be assigned to the
variable at the LHS).
//
// Updated Variable
//
// Variable on LHS(which is
sum).
/// FormEnd Class -- Form 1, No Conditional
Code
//
// Hardware:
//
// None.
//
// Updated Variables.
//
// None, since there is no
hardware.
/// FormEnd Class -- Form 2, No
Conditional Code
//
// Hardware:
//
// For each variable assigned(sum) in
the always block an edge-triggered
// flip-flop is synthesized. The
latest value connects to the data
// (d) input (a+b) and CLK connects
to the clock input.
//
The q output is the variable
sum.
// The q output(sum) is the value
used by all non-procedural code
// and the first statement of all
procedural code.
//
// Updated Variables:
//
// One for each flip-flop
output(sum).
// See Fig.3 again and module
sum_using_form_2(sum,a,b,clk);
// :Example:
//
// Module showing how its code is classified
by structure above.
module
syn_example2_f1(z,x,y,a,b,c);
input [7:0] a, b, c;
output
x, y, z;
reg [8:0] x,
y;
wire [8:0]
z;
assign
z = x + 5;
always @( a or b or c )
begin
x =
a + b;
// HW: adder. Updated
Variable: x
y =
x & c | b; // HW: AND and
OR. Updated Variable:
y.
x =
b + 7;
// HW: adder. Updated
Variable: x
end
// FormEnd: Nothing
synthesized(No hardware).
endmodule
//similar to Fig.4.
// :Example:
//
// Module showing how its code is classified
by structure above.
module
syn_example2_f2(z,x,y,a,b,c,clk);
input [7:0] a, b, c;
input
clk;
output
x, y, z;
reg [8:0] x,
y;
wire [8:0]
z;
assign
z = x + 5;
always @( posedge clk )
begin
x =
a + b;
// HW: adder. Updated
Variable: x
y =
x & c | b; // HW: AND and
OR. Updated Variable:
y.
x =
b + 7;
// HW: adder. Updated
Variable: x
end
// FormEnd:
Edge-triggered FF for y and x.
endmodule
//similar to Fig.4.except we store x and y
into Flip-Flops.
//We also need an adder for
x+5;
////////////////////////////////////////////////////////////////////////////////
/// Syntax of if else(covered
before)
// :Syntax: if( EXPR )
STATEMENT;
// :Syntax: if( EXPR ) STATEMENT1; else
STATEMENT2
// :Example:
//
// Example of if/else.
// This module is not synthesizable because
it contains initial statement.
//
//
module
if_not_syn_examples();
integer a, b, c,x;
initial
begin
if( a <
b ) c = 1;
if( a <
b )
begin
c = 3;
x = 5;
end
else
begin
c = 7;
x = 2;
end
end
endmodule
////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Conditional Class
(if/else)
/// Conditional - if /
else
//
//:Syntax: if( COND ) IFPART
//:Syntax: if( COND ) IFPART else
ELSEPART;
//
// Hardware:
//
// Synthesize hardware for IFPART and
ELSEPART.
//
// Synthesize hardware to evaluate
COND, call the output cond.
//
// Determine the union of variables
modified in IFPART and
// ELSEPART(taking all
variables from if and else part).
// For each variable in the
union:
//
// Synthesize a two-input
multiplexor.
//
//
// Connect one
input to the latest value in IFPART, or if the
// variable isn't
updated in IFPART, the latest value before the
// "if".
//
// Connect the
other input to the latest value in ELSEPART, or if
// the variable
isn't updated in ELSEPART, the latest value
// before the
"if".
//
// Connect cond to
the control input.
//
// The multiplexor
output is the updated value.
//
// A multiplexor
might be eliminated in an optimization step,
// see FormEnd
below.
//
// Updated Values
//
// All variables modified in "if" or
"else" parts.
/// FormEnd Class Form 1,
Conditional
// (The synthesis program will decide
whether to put a latch
// or not here.)
// (FormEnd is not an explicit code;
it is only for synthesis program.)
// Updated Variables
//
// Those which may be unchanged
due to an if
// or case condition(appearing
only in either if part or else part).
// (Such as y in the example
below; module cond_form_1_example2.)
//
// Hardware
//
// For each possibly unchanged
variable:
//
// A
level-triggered flip-flop (latch).
//
//
Condition(cond) is the clock(or enable) to the flip-flop
input
//
// The latest
value connects to the data (d) input.
//
// Optimization
//
// In many cases multiplexors
can be eliminated. (See y in
// the example
below.)
/// FormEnd Class Form 2,
Conditional
//
// Updated Variables
//
// All assigned(updated)
variables.
//
// Hardware
//
// For each
variable:
//
// An
edge-triggered flip-flop.
//
// CLK (see
Form 2 syntax) connects to the clock input.
//
// Logic that
determines whether the variable will change(update),
// that logic
connects to the flip-flop enable input
//
(enable is conditon or cond).
// The latest
value connects to the data (d) input.
// :Example:
//
// Very simple module to illustrate synthesis
of if statement
// in Form 1 code.
module
cond_form_1_example1(x,a,b,c);
input a, b,c;
output x;
reg
x;
always @( a or b or c )
begin
// x = 5; latch does not work; Mux always works.
if(
a ) x = b | c; //
SStatement1
end
// FormEnd
// See Fig.7.
//
endmodule
// Here is how the module above should
// be parsed(explained in detailed
steps):
// SStatement1 -> Conditional -> if(
COND ) IFPART
// COND -> a
// IFPART -> x = b |
c;
//
// :Example:
//
// Simple module to illustrate synthesis of
if/else statements in
// Form 1 code.
// Level-Triggered Registers: y, enabled by
a.
module
cond_form_1_example2(x,y,a,b,c);
input a,b,c;
output x,y;
wire [7:0] b, c;
reg [8:0] x,
y;
always @( a or b or c ) begin
if( a )
begin
x = b + c;
y = b - c;
end else
begin
x = b - c;
end
end
endmodule
//See fig.8.
// :Example:
//
// Simple module to illustrate synthesis of
if/else statements in
// Form 2 code.
// Edge-Triggered Registers: x and
y.
// The hardware for module below will consist
of two multiplexors
// one for x and one for y(before optimization; after
optimization,
// the multiplexor will be replaced with a
flip-flop with
// enable signal(a)).
// and two edge triggered flip
flops(registers);
// the register for y has enable signal(a)
and d input(b-c);
// the register for x does not have enable
input and d input which is
// output of a
multiplexor.
module
cond_form_2_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
// See Fig.9.
// :Example:
//
// Example of an if/else if/else
chain.
// Registers: None. (x assigned on all
paths.)
//
module anotherif(x,a);
input [7:0] a;
output
x;
reg [7:0]
x;
always @( a )
begin
if(
a < 10 )
x = 1; //
IFPART1
else
// ELSEPART1
if ( a < 50 )
x = 2; //
IFPART2
else
// ELSEPART2
if ( a < 200 ) x = 3;
else x = 4;
end
endmodule
// See Fig.10.
// :Example:
//
// Example of an if/else if/else
chain.
// Level-Triggered Registers:
x.
//
//
module
yetanotherif(x,a);
input [7:0] a;
output
x;
reg [7:0]
x;
always @( a )
begin
if(
a & 2 ) x = 6;
if(
a < 10 ) x = 1;
else
if ( a < 50 ) x = 2;
end
endmodule
// in the above example if a = 65, a&2 is
false, a< 10 is false,
// a < 50 false so x is never updated. We
need a latch.
// See Fig.11.
// :Example:
//
// An example with lots of
if's.
// Registers: None. (x is always
updated.)
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
//See Fig.12.
// :Example:
//
// Another ALU.
// Registers: None
module
form1_alu(result,a,b,op);
input [31:0] a, b;
input
op;
output
result;
reg [31:0]
result;
always @( a or b or op )
begin
if(op) result = a + b; else result = a - b;
end
endmodule
// :Example:
//
// An ALU with an overflow
output.
// Registers: None.
module
form1_alu_with_overflow(result,overflow,a,b,op);
input [31:0] a, b;
input
op;
output
result;
output
overflow;
reg
overflow;
reg [31:0]
result;
always @( a or b or op )
begin
if(
op ) result = a + b; else result = a - b;
overflow = a[31] == b[31] && a[31] !=
result[31];
end
endmodule
//See Fig.13.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Conditional Class (case,
if/else chains)
/// Conditional - if/else chains and
case.
//
// General Conditions: (See also Sequential
Conditions)
//
// :Syntax: if( C1 )
ST1;
//
else if ( C2 ) ST2;
//
else if ( C3 ) ST3;
//
...
//
else STD; //
Optional
//
// :Syntax: case ( EXPR )
// CEXP1:ST1;
//
CEXP2:ST2;
//
CEXP3:ST3;
//
...
//
default:STD; //
Optional
//
endcase
//
// Hardware:
//
// Synthesize hardware for ST1, ST2,
..., STD
//
// Synthesize hardware to evaluate
either:
// C1, C2,
...; call respective outputs c1,
// c2,...(We
called them "cond" before)
// EXPR ==
CEXP1, EXPR == CEXP2, ...
// call
respective outputs c1, c2,...
//
// Determine the union of
variables(taking all variables)
//
modified in ST1, ST2, ..., STD
// For each variable in the
union:
//
// Synthesize a
selector with one input per STx.
//
// For each
STx:
//
Connect the latest value of the variable in STx to
a
//
selector input, or if the variable isn't updated in
STx,
//
the latest value before the "case" or "if".
//
//
Connect cx to the corresponding control input.
//
// The selector
output is the updated value.
//
//
// Sequential Conditions:
//
// :Syntax: if( EXPR == 0 )
ST0;
//
else if ( EXPR == 1 ) ST1;
//
else if ( EXPR == 2 ) ST2;
//
...
//
// :Syntax: case ( EXPR )
//
0:ST0;
//
1:ST1;
//
2:ST2;
//
...
//
endcase
//
// Hardware:
//
// Synthesize hardware for ST0, ST1,
...
//
// Synthesize hardware to evaluate
EXPR, call the output expr.
//
// Determine the union of variables
modified in ST0, ST1, ...
// For each variable in the
union:
//
// Synthesize a
multiplexor with one input per STx.
//
// Connect expr to
the control input.
//
// For each
STx:
//
Connect the latest value of the variable in STx to
a
//
multiplexor input, or if the variable isn't updated in
STx,
//
the latest value before the "case" or "if".
//
// The multiplexor
output is the updated value.
//
/// More
Information
//
// The synthesis program may be smart enough
to use a multiplexor
// instead of a selector.
// Multiplexor is simpler than
selector.
// :Example:
//
// An up/down counter.
// This fall under "General Conditions"
above.
// Edge-triggered registers:
count.
//
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
//See Fig.14.
// :Example:
//
// A mux, the hard way, but look at how the
if/else chain works.
// Because the if conditions check for
consecutive constants (0,1,2)
// instead of using three two-input mux, the
synthesis
// program uses one four-input
multiplexor.
// This falls under "Sequential Conditions"
above.
// Registers: None.
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
//See Fig.15.
//
// :Example:
//
// It looks like a selector but it's
not. The synthesized
hardware
// will make use of a selector, but the
entire module is not a
// selector. How is it not a
selector?
module
not_exactly_a_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;
endcase
end
endmodule
// Variable x is not always assigned, so the
selector output
// goes to a level-triggered flip-flop. When none of the
// control inputs are set the module
output(x)
// remains at old
value.
//
// Level-Triggered Register:
x
// See Fig.16.
////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Iteration Class (for, while,
repeat)
/// Iteration - for, while,
repeat
//
//
:Syntax: for( INIT_ASSIGN; CONDITION; STEP_ASSIGN )
BODY
//
:Syntax: while( CONDITION ) BODY
//
:Syntax: repeat( COUNT ) BODY
//
// Remember
//
// The number of iterations must be
determinable(known in advance)
// by the synthesis program at analysis time(sort of synthesis
// or compile; when the synthesis
program reads the verilog code,
//
it should know the number of
iterations without performing
// any computation).
//
// Hardware:
//
// Let n denote number of
iterations.
//
// Synthesize and cascade
(connect in series) n copies of BODY.
//
// For a "for" loop, determine
value of iteration variable (e.g., i)
// at each iteration, and use
that as an input into the hardware
// for the corresponding
iteration.
//
// Updated Variables:
//
// Variables updated in the
last iteration.
// :Example:
//
// Simple repeat
example.
module
times_five(five_a,a);
input [7:0] a;
output [10:0] five_a;
reg [10:0]
five_a;
always @( a ) begin
five_a =
0;
repeat( 5 )
five_a = five_a + a;
end
endmodule
// See Fig.17.
//
// :Example:
//
// Simple for example.
module add_mult(sum,a);
input [7:0] a;
output sum;
reg [15:0] sum;
integer
i;
always @( a ) begin
sum =
a;
for(i = 0; i < 5; i = i + 1 ) sum = a + sum *
i;
end
endmodule
//See Fig.18.
// :Example:
//
// Simple for example.
module
times_five_f(five_a,a);
input [7:0] a;
output [10:0] five_a;
reg [10:0]
five_a;
integer
i;
always @( a ) begin
five_a =
0;
for(i = 0; i < 5; i = i + 1 ) five_a = five_a +
a;
end
endmodule
//
// Note: synthesized hardware identical to
version with repeat loop.
// Same as Fig.17.
// :Example:
//
// population count
module.
module
pop_combinational_syn(p,a);
input [4:0] a;
output
p;
reg [2:0]
p;
integer
i;
// Form 1
always @( a )
begin
// ST1 -> Assignment -> p =
0;
p = 0;
// ST2 -> Iteration -> for(
INIT_ASSIGN; CONDITION; STEP_ASSIGN ) BODY
// INIT_ASSIGN ->
i=0
// CONDITION ->
i<5
// STEP_ASSIGN ->
i=i+1
// BODY ->
p=p+a[i];
for(i=0; i<5; i=i+1) p = p +
a[i];
end
// FormEnd
// A register is not
needed for p because it's always assigned.
// We need a wire for
p.
// A register is not
needed for i because
// it is not
referenced elsewhere(kind like an
// internal variable;
used inside for loop).
endmodule
// Note:
//
// Make five copies of body, p = p +
a[i]; (an
adder).
// In first copy set i -> 0, in
second set i -> 1, etc.
// See Fig.19.
// :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 a, b;
output gt, lt;
wire [2:0] a, b;
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
// See Fig.20.
// :Example:
//
// Non-synthesizable loop. The loop cannot be synthesized because
the
// number of iterations in not a constant
(not known in advance;
//
it depends on the module input, a).
// For this particular case one could set the
sum to
// a(a+1)/2(if your intention is just adding
numbers starting from 0 to a;
// 0 + 1+ 2 + ...+ a = a(a+1)/2; don't use loop,
// just use simple equation; save
time).
module
not_synthesizable_sum(sum,a);
input [7:0] a;
output [10:0] sum;
reg [10:0]
sum;
integer
i;
always @( a ) begin
sum =
0;
for(i=0;
i<=a; i=i+1) sum = sum + i;
end
endmodule
//
// :Example:
//
// The code below is synthesizable but
requires 256 copies of the loop
// body and so is probably impractical. Computing a(a+1)/2 is
much
// easier; 0 + 1+ 2 + ...+ a = a(a+1)/2;
module
synthesizable_sum_but_impractical(sum,a);
input [7:0] a;
output [10:0] sum;
reg [10:0]
sum;
integer
i;
always @( a ) begin
sum =
0;
for(i=0;
i<256; i=i+1) if( i <= a ) sum = sum + i;
end
endmodule
//