com
Digital Design Using Verilog
assign pcinc = pc + 4;
for (i=0; i < 31; i = i+1) begin
1>
5:2
: <2
Rc EL
2S
RA
on 1> 1
ILLP JT cti 5:1 0
tru : <1
dOr Ins emory Rb
WERF
XA 1
0
M 2 WD
A 6> RA
FaaDoOEngineers.com
2 0:1 WE
3 00
D
: <2 ter
L4 Ra gis RD
2
SE L Re ile
PC PC SE RA
1 F
WA
AA
WW 1
1 RD
X5P:21> 0 JT EL
+4 BS
+ : <2
Rc >) 1
0
Z 15:0 Wr
XT(<
S
C: R/W
)
0 WD
(C 1 ory
XT EL em
4*S AS ta M
+4+ Z
B Da
PC RD
IRQ U Ad
r
gic AL
Lo A
ol
ntr
Co L
SE UF
N
PC SEL AL
2
RA L
E
AS
EL
BS SEL
WD FN EL
+4 WDS
AL
U PC 2
Wr 01
RF
WE EL
S
WA
,
t,irq
se Inpu
lk,re t [3 1
c ( :0] m
beta em_
e l data
odu ;
m
If (done) $finish; e
dul
o
ndm
e
FaaDoOEngineers.com
In the beginning designs involved just a few
FaaDoOEngineers.com
FaaDoOEngineers.com
FaaDoOEngineers.com
FaaDoOEngineers.com
FaaDoOEngineers.com
FaaDoOEngineers.com
Processor Processor Processor
A B C
Network
Memory Memory
Bank Bank
A B
VHDL
Verilog
ADA-like verbose syntax, lots C-like concise syntax
of redundancy
Extensible types and Built-in types and logic
simulation engine representations
FaaDoOEngineers.com
Design is composed of entities
Design is composed of modules
each of which can have which have just one
multiple architectures implementation
Gate-level, dataflow, and Gate-level, dataflow, and
behavioral modeling. behavioral modeling.
Synthesizable subset. Synthesizable subset.
Harder to learn and use, DoD Easy to learn and use, fast
mandate simulation
Advantages
Choice of many US design teams
Most of us are familiar with C-like syntax
Simple module/port syntax is familiar way to organize
hierarchical building blocks and manage complexity
With care it is well-suited for both verification
FaaDoOEngineers.com
and synthesis
Disadvantages
Some comma gotchas which catch beginners everytime
C syntax can cause beginners to assume C semantics
Easy to create very ugly code, good and consistent
FaaDoOEngineers.com
Language with syntactic and semantic support for modeling the
temporal behavior and spatial structure of hardware
module foo(clk,xi,yi,done);
input [15:0] xi,yi;
output done;
FaaDoOEngineers.com
A B
FaaDoOEngineers.com
A B
module adder( input [3:0] A, B,
output cout,
output [3:0] sum );
FaaDoOEngineers.com
a b module FA( input a, b, cin
output cout, sum );
cin
// HDL modeling of 1 bit
cout FA // adder functionality
endmodule
c
FaaDoOEngineers.com
A B
module adder( input [3:0] A, B,
output cout,
adder output [3:0] S );
cout S
FA fa0( ... );
FA fa1( ... );
FA fa2( ... );
FA fa3( ... );
FA FA FA FA endmodule
FaaDoOEngineers.com
A B
module adder( input [3:0] A, B,
output cout,
adder output [3:0] S );
cout S
wire c0, c1, c2;
FA FA FA FA
endmodule
Carry Chain
FaaDoOEngineers.com
A B
module adder( input [3:0] A, B,
output cout,
adder output [3:0] S );
cout S
wire c0, c1, c2;
FA fa0( .a(A[0]), .b(B[0]),
.cin(0), .cout(c0),
.sum(S[0] );
endmodule
4b10_11
0 1 Underscores
FaaDoOEngineers.com
X Z
are ignored
Base format
(d,b,o,h)
Decimal number
representing size in bits
32h8XXX_XXA3
Module is implemented by
FaaDoOEngineers.com
Dataflow specifying how data flows
between registers
FaaDoOEngineers.com
and and1( n1, a,
and and2( n2, d,
and and3( n3, b,
sel_b[1]
sel[1]
sel_b[1]
);
);
);
sel[0]
sel[1]
a
out
wire y0, y1; d
or or0( y0, x0, sel[0] );
or or1( y1, x1, sel_b[0] ); b
endmodule
FaaDoOEngineers.com
assign out = ~( (t0 | sel[0]) & (t1 | ~sel[0]) );
endmodule
endmodule
FaaDoOEngineers.com
// Simple four bit adder
module adder( input [3:0] op1, op2,
output [3:0] sum );
endmodule
FaaDoOEngineers.com
A wide variety of operators are available including:
Arithmetic: + - * / % **
Concatenation: { }
Conditional: ?:
FaaDoOEngineers.com
A wide variety of operators are available including:
Arithmetic: + - * / % **
Logical: ! && ||
assign signal[3:0]
Conditional:
?:
reg out;
always @( a or b or c or d or sel )
begin
out = a;
else if ( sel == 1 )
block which contains a list of
out = b
expressions which are (usually)
else if ( sel == 2 )
evaluated sequentially
out = c
else if ( sel == 3 )
The code in an always block can
out = d
be very abstract (similar to C
end code) here we implement a mux
with an if/else statement
endmodule
reg out;
always @( a or b or c or d or sel )
begin
FaaDoOEngineers.com
if ( sel == 0 )
out = a;
An always block can include a
else if ( sel == 1 )
out = b
else if ( sel == 2 )
sensitivity list if any of these
out = c
signals change then the always
else if ( sel == 3 )
block is executed
out = d
end
endmodule
reg out;
always @( a, b, c, d, sel )
begin
FaaDoOEngineers.com
if ( sel == 0
out = a;
else if ( sel
)
== 1 )
out = b In Verilog-2001 we can use a
else if ( sel == 2 ) comma instead of the or
out = c
else if ( sel == 3 )
out = d
end
endmodule
FaaDoOEngineers.com
if ( sel == 0
out = a;
else if ( sel
)
The always block will not
execute if just d changes so if
== 1 )
out = b sel == 3 and d changes then
else if ( sel == 2 ) out will not be updated
out = c
else if ( sel == 3 )
out = d This will cause discrepancies
end between simulated and
synthesized hardware there
endmodule are no sensitivity lists in real
hardware so it would work fine!
reg out;
always @( * )
begin
FaaDoOEngineers.com
if ( sel == 0
out = a;
else if ( sel
)
== 1 )
out = b In Verilog-2001 we can use the
else if ( sel == 2 ) @(*) construct which creates a
out = c sensitivity list for all signals
else if ( sel == 3 )
read in the always block
out = d
end
endmodule
reg out;
always @( * )
begin
FaaDoOEngineers.com
case ( sel )
end
endmodule
FaaDoOEngineers.com
case ( sel )
0 : out = a;
1 : out = b;
2 : out = c;
3 : out = d;
endcase
end
endmodule
reg out;
In Verilog a reg is just a variable
always @( * ) when you see reg think variable not
begin hardware register!
FaaDoOEngineers.com
case ( sel )
0 : out = a;Any assignments in an always block
1 : out = b; must assign to a reg variable the
reg variable may or may not actually
2 : out = c;
3 : out = d;
endcase represent a hardware register
end
If the always block assigns a value to
endmodule the reg variable for all possible
executions then the reg variable is
not actually a hardware register
FaaDoOEngineers.com
case ( sel )
0 : out = a;
1 : out = b;
2 : out = c;
3 : out = d;
endcase
end
endmodule
FaaDoOEngineers.com
case ( sel )
0 : out = a;
1 : out = b;
2 : out = c;
3 : out = d;
endcase
end
endmodule
FaaDoOEngineers.com
case ( sel )
default : out = 1bx;
0 : out = a;
1 : out = b;
2 : out = c;
3 : out = d;
endcase
end
endmodule
next_x D Q X next_x D Q X
clk clk
FaaDoOEngineers.com
always @( posedge clk ) always @( posedge clk )
begin begin
x = next_x; x <= next_x;
y = x; y <= x;
end end
X X
next_x D Q Y next_x D Q D Q Y
clk clk clk
X Y
D Q X
FaaDoOEngineers.com clk
FaaDoOEngineers.com
Behaviora
l
Gat Dataflow
e-L
eve
l
FaaDoOEngineers.com
Dataflow The problem though, is
that it is very hard to
predict what the generated
hardware will look like
This makes it difficult to
Gate-Level perform rational design
space exploration
Gate-Level
FaaDoOEngineers.com
// Specify parameters at instantiation time
mux4 #( .width(32) )
alu_mux( .a(op1), .b(bypass), .c(32b0), .d(32b1),
.sel(alu_mux_sel), .out(alu_mux_out) );
genvar i;
FaaDoOEngineers.com
Generate blocks can
use parameters to
generate
for ( i = 0; i < width; i = i+1 )
begin : ripple instantiate a variable
FA fa( op1[i], op2[i],
number of sub-modules
carry[i], carry[i+1] );
or to create a variable
end
number of nets
endgenerate
endmodule
Model
Static Elaboration
FaaDoOEngineers.com
Elaborated Model
Synthesis
Gate-Level
www.jntuworld.com
Larger Examples
FaaDoOEngineers.com
GCD Beta
integer done;
begin
done = 0;
A = A_in; B = B_in;
while ( !done )
FaaDoOEngineers.com
begin
if ( A < B )
begin
swap = A;
A = A - B;
else
done = 1;
end
Y = A;
end
endmodule
Test Harness
reg [width-1:0] A_in, B_in;
wire [width-1:0] Y;
gcd_behavioral #( .width(width) )
initial
begin
B_in = 15;
go done
Control Unit
zero? lt out
A_in
FaaDoOEngineers.com
A
sub
B_in
Design
Design Strategy
Strategy
Partition
Partition into
into control
control and
and datapath
datapath
Keep
Keep all
all functional
functional code
code in
in the
the leaf
leaf modules
modules
reg [width-1:0] A, B;
assign Y = A;
// Datapath logic
wire [width-1:0] out = ( out_mux_sel ) ? B : A - B;
FaaDoOEngineers.com
wire [width-1:0] A_next = ( A_mux_sel ) ? out : A_in;
wire [width-1:0] B_next = ( B_mux_sel ) ? A : B_in;
flip-flops with
if ( A_en ) enables
A <= A_next;
if ( B_en )
B <= B_next;
end
endmodule
// The running bit is one after go goes high and until done goes high
reg running = 0;
begin
if ( go ) running <= 1;
FaaDoOEngineers.com
end
always @(*)
begin
if ( !running ) ctrl_sig = 6'b11_00x_0; // Latch in A and B values
else if ( A_lt_B ) ctrl_sig = 6'b11_111_0; // A <= B and B <= A
else if ( !B_zero ) ctrl_sig = 6'b10_1x0_0; // A <= A - B and B <= B
else ctrl_sig = 6'b00_xxx_1; // Done
end
endmodule
Test Inputs
FaaDoOEngineers.com
Behavioral RTL
Model Model
Identical
Outputs?
XAdr OP JT
PCSEL 4 3 2 1 0
PC 00
A Instruction
Memory
+4 D
XP
RA1 Register RA2
1
WD
Rc: <25:21> WA
WA
File
FaaDoOEngineers.com
0
RD1 RD2 WE WERF
Z Figure by MIT OCW.
JT
C: SXT(<15:0>)
PC+4+4*SXT(C)
IRQ Z
ASEL 1 0 1 0 BSEL
Control Logic
PCSEL
RA2SEL A B
ASEL ALU WD R/W Wr
ALUFN
BSEL
WDSEL Data Memory
ALUFN Adr RD
Wr
WERF
WASEL
PC+4
0 1 2 WDSEL
FaaDoOEngineers.com
themselves, just a few base cells to design & verify.
Think about physical partition since wires that cross boundaries can take
lots of area and blocks have to fit into the floorplan without wasteful
gaps.
2 + WASEL
XP 1
RA1 Register RA2
WD
1
PC
Rc: <25:21> WA
WA
FaaDoOEngineers.com
0 File WERF
RD1 RD2 WE
Z
JT
C: SXT(<15:0>)
PC+4+4*SXT(C)
IRQ Z
ASEL 1 0 1 0 BSEL
Control Logic
PCSEL
RA2SEL A B
ASEL ALU WD R/W Wr
ALUFN
BSEL
WDSEL Data Memory
ALUFN Adr RD
Wr
WERF
WASEL
PC+4 1
0 1 2 WDSEL
2
Main Datapath
6.884 Spring 2005 02/04/05 L02 Verilog 58
www.jntuworld.com
Take Away Points
FaaDoOEngineers.com
3. Try out the GCD Verilog example
(or on any MIT server/Linux machine)
% setup 6.884
% cp r /mit/6.884/examples/gcd .
% cat gcd/README