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