Computer
Arithmetic
and
Verilog HDL
Fundamentals
By Joseph Carnaugh
Chapter 3
Introduction to
Verilog HDL
Verilog Code
Figures
Page
96, Figure 3.3
//built-in
primitives for a pos equation
module
log_eqn_pos_nor2 (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
nor inst1
(net1, x1, ~x2),
inst2 (net2, x2, x3, ~x4),
inst3 (net3, ~x1, ~x3, x4);
nor inst4 (z1, net1, net2, net3);
endmodule
//test
bench for pos equation
module
log_eqn_pos_nor2_tb;
//inputs
are reg for test bench
reg x1,
x2, x3, x4;
//outputs
are wire for test bench
wire z1;
//apply
input vectors
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
//instantiate
the module into the test bench
log_eqn_pos_nor2
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page
99, Figure 3.9
//built-in
primitive number range
module
num_range3 (x1, x2, x3, x4, z1);
//list
inputs and output
input x1,
x2, x3, x4;
output z1;
//design
the logic using built-in primitives
nand inst1
(net1, ~x1, x2),
inst2 (net2, x2, ~x3),
inst3 (net3, x1, ~x4),
inst4 (net4, x1, ~x2, x3);
nand inst5
(z1, net1, net2, net3, net4);
endmodule
//test
bench for number range module
module
num_range3_tb;
//inputs
are reg outputs are wire for test bench
reg x1,
x2, x3, x4;
wire z1;
//apply
input vectors
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
//instantiate
the module into the test bench
num_range3
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page
102, Figure 3.14
//built-in
primitive 3:8 decoder
module
decoder_3to8_bip (x1, x2, x3, enable, z);
input x1,
x2, x3, enable;
output [7:0]
z;
and inst0
(z[0], ~x1, ~x2, ~x3, enable),
inst1 (z[1], ~x1, ~x2, x3, enable),
inst2 (z[2], ~x1, x2, ~x3, enable),
inst3 (z[3], ~x1, x2, x3, enable),
inst4 (z[4], x1, ~x2, ~x3, enable),
inst5 (z[5], x1, ~x2, x3, enable),
inst6 (z[6], x1, x2, ~x3, enable),
inst7 (z[7], x1, x2, x3, enable);
endmodule
//test
bench for the 3:8 decoder
module
decoder_3to8_bip_tb;
reg x1,
x2, x3, enable;
wire [7:0]
z;
//display
variables
initial
$monitor
("x1 x2 x3 = %b, z = %b", {x1, x2, x3}, z);
//apply
input vectors
initial
begin
#0 enable = 1'b1;
x1=1'b0; x2=1'b0; x3=1'b0;
#10 x1=1'b0; x2=1'b0; x3=1'b1;
#10 x1=1'b0; x2=1'b1; x3=1'b0;
#10 x1=1'b0; x2=1'b1; x3=1'b1;
#10 x1=1'b1; x2=1'b0; x3=1'b0;
#10 x1=1'b1; x2=1'b0; x3=1'b1;
#10 x1=1'b1; x2=1'b1; x3=1'b0;
#10 x1=1'b1; x2=1'b1; x3=1'b1;
#10 $stop;
end
//instantiate
the module into the test bench
decoder_3to8_bip
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.enable(enable),
.z(z)
);
endmodule
Page
105, Figure 3.19
//built-in
primitives for 3-bit comparator
module
comparator3_bip (a2, a1, a0, b2, b1, b0,
a_lt_b, a_eq_b,
a_gt_b);
input a2,
a1, a0, b2, b1, b0;
output
a_lt_b, a_eq_b, a_gt_b;
and inst1 (net1, ~a2, b2);
xnor inst2 (net2, a2, b2);
xnor inst3 (net3, a1, b1);
xnor inst4 (net4, a0, b0);
and inst5 (net5, a2, ~b2);
and inst6 (net6, net2, ~a1, b1);
and inst7 (net7, net2, net3, ~a0, b0);
and inst9 (net9, net2, a1, ~b1);
and inst10 (net10, net2, net3, a0, ~b0);
and inst8 (a_eq_b, net2, net3, net4);
or inst11 (a_lt_b, net1, net6, net7);
or inst12 (a_gt_b, net5, net9, net10);
endmodule
//test
bench for 3-bit comparator
module
comparator3_bip_tb;
reg a2,
a1, a0, b2, b1, b0;
wire
a_lt_b, a_eq_b, a_gt_b;
//apply
input vectors
initial
begin:
apply_stimulus
reg
[6:0] invect;
for
(invect=0; invect<64; invect=invect+1)
begin
{a2,
a1, a0, b2, b1, b0} = invect [6:0];
#10 $display ("a2 a1 a0 = %b, b2 b1
b0 = %b,
a_lt_b = %b, a_eq_b =
%b, a_gt_b = %b",
{a2, a1, a0}, {b2, b1,
b0},
a_lt_b, a_eq_b, a_gt_b);
end
end
//instantiate
the module into the test bench
comparator3_bip
inst1 (
.a2(a2),
.a1(a1),
.a0(a0),
.b2(b2),
.b1(b1),
.b0(b0),
.a_lt_b(a_lt_b),
.a_eq_b(a_eq_b),
.a_gt_b(a_gt_b)
);
endmodule
Page 110, Figure 3.24
//five-input
majority circuit as a udp. Save as a .v
file
primitive
udp_maj5 (z1, x1, x2, x3, x4, x5);
output z1;
input x1,
x2, x3, x4, x5;
table
//inputs
are in same order as input list
// x1 x2 x3 x4 x5 : z1;
0 0 0 ? ? : 0;
0 0 ? 0 ? : 0;
0 0 ? ? 0 : 0;
0 ? 0 0 ? : 0;
0 ? ? 0 0 : 0;
0 ? 0 ? 0 : 0;
? 0 0 0 ? : 0;
? ? 0 0 0 : 0;
? 0 0 ? 0 : 0;
? 0 ? 0 0 : 0;
? ? 0 0 0 : 0;
1 1 1 ? ? : 1;
1 1 ? 1 ? : 1;
1 1 ? ? 1 : 1;
1 ? 1 1 ? : 1;
1 ? ? 1 1 : 1;
1 ? 1 ? 1 : 1;
? 1 1 1 ? : 1;
? ? 1 1 1 : 1;
? 1 1 ? 1 : 1;
? 1 ? 1 1 : 1;
? ? 1 1 1 : 1;
endtable
endprimitive
//udp_maj5
test bench
module
udp_maj5_tb;
reg x1,
x2, x3, x4, x5; //inputs are
reg for tb
wire z1; //outputs are wire
//udp_maj5
test bench
module
udp_maj5_tb;
reg x1,
x2, x3, x4, x5; //inputs
are reg for tb
wire z1; //outputs are wire
//Declare
a vector that has 1 more bit than the # of inputs.
//This
allows the for statement count to go 1 higher than the
//...
maximum count of the input combinations and prevents
//...
looping forever. If only 5 bits were
used as the input
//...
vector, then the count would always be < 32 (the maximum
//...
count for 5 bits).
initial
begin: name //a name is required for this
method
reg
[5:0] invect;
for
(invect = 0; invect < 32; invect = invect + 1)
begin
{x1,
x2, x3, x4, x5} = invect [4:0];
#10 $display ("x1x2x3x4x5 =
%b%b%b%b%b, z1=%b",
x1, x2, x3, x4,
x5, z1);
end
end
//instantiation
must be done by position, not by name.
udp_maj5
inst1 (z1, x1, x2, x3, x4, x5);
endmodule
Page 112, Figure 3.28
//a
positive-edge-sensitive D flip-flop
primitive
udp_dff_edge1 (q, d, clk, rst_n);
input d,
clk, rst_n;
output q;
reg q; //q is internal storage
//initialize
q to 0
initial
q
= 0;
//initialize
q to 0
initial
q
= 0;
//define
state table
table
//inputs
are in the same order as the input list
// d clk rst_n : q : q+; q+
is the next state
0 (01) 1 : ? : 0; //(01)
is rising edge
1 (01) 1 : ? : 1; //rst_n
= 1 means no rst
1 (0x) 1 : 1 : 1; //(0x)
is no change
0 (0x) 1 : 0 : 0;
? (?0) 1 : ? : -; //ignore
negative edge
//reset
case when rst_n is 0 and clk has any transition
? (??) 0 : ? : 0; //rst_n
= 0 means reset
//reset
case when rst_n is 0. d & clk can be
anything, q+=0
? ? 0 : ? : 0;
//reset
case when 0 --> 1 transition on rst_n.
Hold q+ state
? ? (01) : ? : -;
//non-reset
case when d has any trans, but clk has no trans
(??) ? 1 : ? : -; //clk
= ?, means no edge
endtable
endprimitive
//udp
for a 4-bit johnson counter
module
ctr_johnson4 (rst_n, clk, y1, y2, y3, y4);
input
rst_n, clk;
output y1,
y2, y3, y4;
//instantiate
D flip-flop for y1
udp_dff_edge1
inst1 (y1, ~y4, clk, rst_n);
//instantiate
D flip-flop for y2
udp_dff_edge1
inst2 (y2, y1, clk, rst_n);
//instantiate
D flip-flop for y3
udp_dff_edge1
inst3 (y3, y2, clk, rst_n);
//instantiate
D flip-flop for y4
udp_dff_edge1
inst4 (y4, y3, clk, rst_n);
endmodule
Page 114, Figure 3.30
//test
bench for the 4-bit johnson counter
module
ctr_johnson4_tb;
reg clk,
rst_n; //inputs
are reg for tb
wire y1,
y2, y3, y4; //outputs
are wire for tb
initial
$monitor
("count = %b", {y1, y2, y3, y4});
initial //define
clk
begin
clk = 1'b0;
forever
#10 clk = ~clk;
end
initial //define
reset
begin
#0 rst_n
= 1'b0;
#5 rst_n
= 1'b1;
#200 $stop;
end
ctr_johnson4
inst1 ( //instantiate the module
.rst_n(rst_n),
.clk(clk),
.y1(y1),
.y2(y2),
.y3(y3),
.y4(y4)
);
endmodule
Page 116, Figure 3.34
//2-input
NOR gate as a user-defined primitive
primitive
udp_nor2 (z1, x1, x2);
input x1,
x2;
output z1;
//define
state table
table
//inputs
are in the same order as the input list
// x1 x2 : z1; comment
is for readability
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 0;
endtable
endprimitive
Page 116, Figure 3.35
//module
for logic diagram using NOR logic
//user-defined
primitives
module
log_diag_eqn5 (x1, x2, z1);
input x1,
x2;
output z1;
//instantiate
the udps
udp_nor2
inst1 (net1, x1, ~x2);
udp_nor2
inst2 (net2, x1, net1);
udp_nor2
inst3 (net3, net1, ~x2);
udp_nor2
inst4 (z1, net2, net3);
endmodule
//test
bench for logic diagram equation 5
module
log_diag_eqn5_tb;
reg x1,
x2;
wire z1;
//test
bench for logic diagram equation 5
module
log_diag_eqn5_tb;
reg x1,
x2;
wire z1;
//display
variables
initial
$monitor
("x1 x2 = %b %b, z1 = %b", x1, x2, z1);
//apply
input vectors
initial
begin
#0 x1 = 1'b0; x2
= 1'b0;
#10 x1
= 1'b0; x2 = 1'b1;
#10 x1
= 1'b1; x2 = 1'b0;
#10 x1
= 1'b1; x2 = 1'b1;
#10 $stop;
end
//instantiate
the module into the test bench
log_diag_eqn5
inst1 (
.x1(x1),
.x2(x2),
.z1(z1)
);
endmodule
Page 120, Figure 3.41
//dataflow
for a sum-of-products equation
module
sop_eqn_df2 (x1, x2, x3, x4, z1);
//define
inputs and output
input x1,
x2, x3, x4;
output z1;
//define
internal nets
wire net1,
net2, net3;
//design
logic
assign net1
= ~x2 & ~x3 & ~x4,
net2 = ~x1 & ~x3 & x4,
net3 = x2 & x3;
assign z1
= net1 | net2 | net3;
endmodule
//test
bench for the dataflow sop
module
sop_eqn_df2_tb;
reg x1,
x2, x3, x4;
wire z1;
initial //apply
input vectors and display variables
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
sop_eqn_df2
inst1 ( //instantiate the
module
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 122, Figure 3.46
//dataflow
for a product-of-sums equation
module
pos_eqn_df (x1, x2, x3, x4, z1);
//define
inputs and output
input x1,
x2, x3, x4;
output z1;
//define
internal nets
wire net1,
net2, net3, net4;
//design
the logic using continuous assignment
assign net1
= (x2 | ~x3),
net2 = (~x2 | x3 | x4),
net3 = (~x1 | x3 | ~x4),
net4 = ~(net1 & net2 &
net3);
assign z1
= (~net4 | ~net4);
endmodule
//test
bench for product-of-sums equation
module
pos_eqn_df_tb;
reg x1,
x2, x3, x4;
wire z1;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
//instantiate
the module into the test bench
pos_eqn_df
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 125, Figure 3.52
//dataflow
to activate segment a
module
seg_a_df (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
wire net1;
assign net1
= ~(x2 ^ x4); //exclusive-NOR
assign z1
= (net1 | x1 | x3);
endmodule
//test
bench for segment a dataflow module
module
seg_a_df_tb;
reg x1,
x2, x3, x4;
wire z1;
initial //apply
input vectors and display variables
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
seg_a_df
inst1 ( //instantiate the module
into the test bench
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 127, Figure 3.56
//dataflow
pos for segment a
module
pos_eqn_df2 (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
wire net1,
net2;
assign net1
= ~(~x2 | x3 | x4),
net2 = ~(x1 | x2 | x3 | ~x4);
assign z1
= (~net1 & ~net2);
endmodule
//test
bench for pos for segment a
module
pos_eqn_df2_tb;
reg x1,
x2, x3, x4;
wire z1;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect=0; invect<16; invect=invect+1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4},
z1);
end
end
//instantiate
the module into the test bench
pos_eqn_df2
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 131, Figure 3.60
//behavioral
5-input majority circuit
module
maj5_bh (x1, x2, x3, x4, x5, z1);
input x1,
x2, x3, x4, x5;
output z1;
wire x1,
x2, x3, x4, x5;
reg z1;
always @ (x1
or x2 or x3 or x4 or x5)
z1 = #5 (x3 & x4 & x5) | (x2 &
x3 & x5) | (x2 & x4 & x5) |
(x1 & x3 & x5) | (x1 & x4 & x5) | (x1 & x2 & x3)
|
(x1 & x2 & x4) | (x2 & x3 & x4) | (x1 & x3 & x4)
|
(x1 & x2 & x5);
endmodule
//test
bench for the 5-input majority circuit
module
maj5_bh_tb;
reg x1,
x2, x3, x4, x5;
wire z1;
initial //apply
vectors and display variables
begin:
apply_stimulus
reg
[5:0] invect;
for
(invect=0; invect<32; invect=invect+1)
begin
{x1,
x2, x3, x4, x5} = invect [5:0];
#7 $display ($time, "input = %b, z1 = %b",
{x1, x2, x3, x4, x5},
z1);
end
end
//instantiate
the module into the test bench
maj5_bh
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.x5(x5),
.z1(z1)
);
endmodule
Page 134, Figure 3.64
//behavioral
blocking assignment using
//
intrastatement and interstatement delays
module
blocking6 (x1, x2, x3, z1, z2, z3, z4);
input x1,
x2, x3;
output z1,
z2, z3, z4;
reg z1,
z2, z3, z4;
always @ (x1
or x2 or x3)
begin
z1
= #2 (x1 ^ x2) & x3;
z2 = #2 ~(x1 ^ x2) | x3;
end
always @ (x1
or x2 or x3)
begin
#2
z3 = x1 & x2 & x3;
#2 z4 = x1 ^ x2 ^ x3;
end
endmodule
//test
bench for blocking assignment using
//intrastatement
and interstatement delays
module
blocking6_tb;
reg x1,
x2, x3;
wire z1,
z2, z3, z4;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[3:0] invect;
for
(invect=0; invect<8; invect=invect+1)
begin
{x1,
x2, x3} = invect [3:0];
#10 $display ("x1 x2 x3 = %b, z1 z2
z3 z4 = %b",
{x1, x2, x3}, {z1,
z2, z3, z4});
end
end
//instantiate
the module into the test bench
blocking6
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.z1(z1),
.z2(z2),
.z3(z3),
.z4(z4)
);
endmodule
Page 137, Figure 3.68
//behavioral
to illustrate blocking
//and
nonblocking assignments
module
block_nonblock (data_reg_a, data_reg_b, data_reg_c);
output [7:0]
data_reg_a, data_reg_b, data_reg_c;
reg [7:0]
data_reg_a, data_reg_b, data_reg_c;
initial
begin
data_reg_a
= 8'b0111_1100;
data_reg_b = 8'b1111_0000;
data_reg_c = 8'b1111_1111;
data_reg_a [2:0] <= #5 3'b111;
data_reg_b [7:0] <= #10 {data_reg_b
[7:4], 4'b1111};
data_reg_c [7:0] <= #15 {2'b11,
data_reg_a [5:0]};
end
endmodule
page 139, Figure 3.70
//behavioral
modulo-10 counter with logic gating
module
ctr_mod10_logic (rst_n, clk, q, z1, z2, z3);
input
rst_n, clk;
output [3:0]
q;
output z1,
z2, z3;
wire
rst_n, clk;
reg [3:0]
q;
wire z1,
z2, z3;
//define
counting sequence
always @ (posedge clk or negedge rst_n)
begin
if
(rst_n == 0)
q = 4'b0000;
else
q
= (q + 1) % 10;
end
//define
outputs
assign z1
= q[2] & q[1],
z2 = q[2] ^ q[1] ^ q[0],
z3 = q[3] | q[0];
endmodule
//test
bench for modulo-10 counter
module
ctr_mod10_logic_tb;
reg
rst_n, clk;
wire [3:0]
q;
wire z1,
z2, z3;
//display
outputs
initial
$monitor
("count = %b, z1 z2 z3 = %b", q, {z1, z2, z3});
//define
reset
initial
begin
#0 rst_n = 1'b0;
#5 rst_n
= 1'b1;
end
//define
clock
initial
begin
clk
= 1'b0;
forever
#10 clk = ~clk;
end
//define
length of simulation
initial
begin
#200 $finish;
end
//instantiate
the module into the test bench
ctr_mod10_logic
inst1 (
.rst_n(rst_n),
.clk(clk),
.q(q),
.z1(z1),
.z2(z2),
.z3(z3)
);
endmodule
Page 142, Figure 3.74
//behavioral
counter using the case statement
module
ctr_triangle (rst_n, clk, count);
input
rst_n, clk;
output
[15:0] count;
wire
rst_n, clk;
reg
[15:0] count, next_count;
always @ (posedge clk or negedge rst_n)
begin
if
(~rst_n) //if the reset = 0
count = 16'h0000;
else
count
= next_count;
end
//define
the counting sequence
always @
(count)
begin
case
(count)
16'h0000 : next_count = 16'h8000;
16'h8000 : next_count = 16'hc000;
16'hc000 : next_count = 16'he000;
16'he000 : next_count = 16'hf000;
16'hf000 : next_count = 16'hf800;
16'hf800 : next_count = 16'hfc00;
16'hfc00 : next_count = 16'hfe00;
16'hfe00 : next_count = 16'hff00;
16'hff00 : next_count = 16'hff80;
16'hff80 : next_count = 16'hffc0;
16'hffc0 : next_count = 16'hffe0;
16'hffe0 : next_count = 16'hfff0;
16'hfff0 : next_count = 16'hfff8;
16'hfff8 : next_count = 16'hfffc;
16'hfffc : next_count = 16'hfffe;
16'hfffe : next_count = 16'hffff;
default
: next_count = 16'h0000;
endcase
end
endmodule
//test
bench for counter triangle
module
ctr_triangle_tb;
reg
rst_n, clk;
wire
[15:0] count;
//display
count
initial
$monitor
("count = %b", count);
//define
clock
initial
begin
clk
= 1'b0;
forever
#10
clk = ~clk;
end
//define
reset
initial
begin
#0 rst_n = 1'b0;
#5 rst_n
= 1'b1;
end
//define
length of simulation
initial
begin
#320
$finish;
end
//instantiate
the module into the test bench
ctr_triangle
inst1 (
.rst_n(rst_n),
.clk(clk),
.count(count)
);
endmodule
Page 146, Figure 3.79
//behavioral
moore ssm
module
moore_ssm23 (rst_n, clk, x1, x2, y, z1, z2, z3);
input
rst_n, clk, x1, x2;
output [1:3]
y;
output z1,
z2, z3;
reg [1:3]
y, next_state;
wire z1,
z2, z3;
//assign
state codes
parameter state_a = 3'b000,
state_b = 3'b011,
state_c = 3'b101,
state_d = 3'b110,
state_e = 3'b100;
//set
next state
always @ (posedge clk)
begin
if
(~rst_n)
y <= state_a;
else
y
<= next_state;
end
assign z1
= (~y[1] & ~y[2] & ~y[3]),
z2 = (y[1] & ~y[2] & y[3]),
z3 = (y[1] & y[2] & ~y[3]);
//determine
the next state
always @ (x1
or x2 or y)
begin
case
(y)
state_a:
if
(x1==0)
next_state = state_a;
else
next_state
= state_b;
state_b:
if
(x2==0)
next_state = state_d;
else
next_state
= state_c;
state_c:
next_state = state_e;
state_d:
next_state = state_e;
state_e:
next_state = state_a;
default:
next_state = state_a;
endcase
end
endmodule
//test
bench for moore ssm
module
moore_ssm23_tb;
reg
rst_n, clk, x1, x2;
wire [1:3]
y;
wire z1,
z2, z3;
//display
variables
initial
$monitor
("x1 x2 = %b, state = %b, z1 z2 z3 = %b",
{x1, x2}, y, {z1, z2, z3});
//define
clock
initial
begin
clk
= 1'b0;
forever
#10
clk = ~clk;
end
//define
input sequence
initial
begin
#0 rst_n = 1'b0;
x1 = 1'b0;
x2 = 1'b0;
#5 rst_n
= 1'b1;
x1 = 1'b0; x2 = $random;
@ (posedge clk) //go to
state_a (000); assert z1
x1 = 1'b1; x2 = $random;
@ (posedge clk) //go to
state_b (011)
x1 = $random; x2 = 1'b0;
@ (posedge clk) //go to
state_d (110); assert z3
x1 = $random; x2 = $random;
@ (posedge clk) //go to
state_e (100)
x1 = $random; x2 = $random;
@ (posedge clk) //go to
state_a (000); assert z1
x1 = 1'b1; x2 = $random;
@ (posedge clk) //go to
state_b (011)
x1 = $random; x2 = 1'b1;
@ (posedge clk) //go to
state_c (101); assert z2
x1 = $random; x2 = $random;
@ (posedge clk) //go to
state_e (100)
x1
= $random; x2 = $random;
@ (posedge clk) //go to
state_a (000); assert z1
x1 = 1'b0; x2 = $random;
@ (posedge clk) //go to
state_a (000); assert z1
#10 $stop;
end
//instantiate
the module into the test bench
moore_ssm23
inst1 (
.rst_n(rst_n),
.clk(clk),
.x1(x1),
.x2(x2),
.y(y),
.z1(z1),
.z2(z2),
.z3(z3)
);
endmodule
Page 152, Figure 3.83
//example
of a while loop
//determine
the value of a register
module
reg_value;
integer
value;
initial
begin:
determine_value
reg
[7:0] reg_a;
value = 0;
reg_a = 8'b0001_1011;
while
(reg_a > 0)
begin
value
= value + 1;
reg_a
= reg_a - 1;
$display
("value = %d", value);
end
end
endmodule
Page 153, Figure 3.85
//example
of the repeat keyword
module
add_regs_repeat;
reg [7:0]
reg_a, reg_b, sum;
initial
begin
reg_a
= 8'b0000_1000;
reg_b = 8'b0000_0010;
repeat
(8)
begin
sum
= reg_a + reg_b;
$display
("reg_a=%b, reg_b=%b, sum=%b",
reg_a, reg_b, sum);
reg_b = reg_b + 1;
end
end
endmodule
Page 157, Figure 3.89
//dataflow
2-input and gate
module
and2_df (x1, x2, z1);
input x1,
x2; //list inputs and
output
output z1;
wire x1,
x2; //define signals
as wire for dataflow
wire z1;
assign z1 =
x1 & x2; //continuous
assign for dataflow
endmodule
//dataflow
3-input and gate
module
and3_df (x1, x2, x3, z1);
input x1,
x2, x3; //list inputs and
output
output z1;
wire x1,
x2, x3; //define signals
as wire for dataflow
wire z1;
assign z1 =
x1 & x2 & x3; //continuous
assign for dataflow
endmodule
//or4
dataflow
module
or4_df (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
wire x1,
x2, x3, x4;
wire z1;
assign z1 =
x1 | x2 | x3 | x4;
endmodule
Page 158, Figure 3.92
//structural
sum of products 2 < z1 <= 6; 10 <= z1 < 15
module
sop_struc2 (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
wire x1,
x2, x3, x4;
wire z1;
//define
internal wires
wire net1,
net2, net3, net4;
//instantiate
the logic
and2_df
inst1 (
.x1(x2),
.x2(~x3),
.z1(net1)
);
and2_df
inst2 (
.x1(x2),
.x2(~x4),
.z1(net2)
);
and3_df
inst3 (
.x1(x1),
.x2(~x2),
.x3(x3),
.z1(net3)
);
and3_df
inst4 (
.x1(~x2),
.x2(x3),
.x3(x4),
.z1(net4)
);
or4_df
inst5 (
.x1(net1),
.x2(net2),
.x3(net3),
.x4(net4),
.z1(z1)
);
endmodule
//test
bench for sop_struc2
module
sop_struc2_tb;
//define
inputs and output
reg x1,
x2, x3, x4;
wire z1;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect = 0; invect < 16; invect = invect + 1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4}, z1);
end
end
//instantiate
the module into the test bench
sop_struc2
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 161, Figure 3.97
//dataflow
3-input nor gate
module
nor3_df (x1, x2, x3, z1);
input x1,
x2, x3;
output z1;
wire x1,
x2;
wire z1;
assign z1 =
~(x1 | x2 | x3);
endmodule
//structural
product of sums 2 < z1 <= 6; 10 <= z1 < 15
module
pos_struc2 (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
//define
internal nets
wire net1,
net2, net3;
//instantiate
the logic gates
nor2_df
inst1 (
.x1(x2),
.x2(x3),
.z1(net1)
);
nor3_df
inst2 (
.x1(~x2),
.x2(~x3),
.x3(~x4),
.z1(net2)
);
nor3_df
inst3 (
.x1(x2),
.x2(x1),
.x3(x4),
.z1(net3)
);
nor3_df
inst4 (
.x1(net1),
.x2(net2),
.x3(net3),
.z1(z1)
);
endmodule
//test
bench for sop_struc2
module
pos_struc2_tb;
//define
inputs and output
reg x1,
x2, x3, x4;
wire z1;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect = 0; invect < 16; invect = invect + 1)
begin
{x1,
x2, x3, x4} = invect [4:0];
#10 $display ("x1 x2 x3 x4 = %b, z1 =
%b",
{x1, x2, x3, x4}, z1);
end
end
//instantiate
the module into the test bench
pos_struc2
inst1 (
.x1(x1),
.x2(x2),
.x3(x3),
.x4(x4),
.z1(z1)
);
endmodule
Page 166, Figure 3.103
//dataflow
or4
module
or4_df (x1, x2, x3, x4, z1);
input x1,
x2, x3, x4;
output z1;
wire x1,
x2, x3, x4;
wire z1;
assign z1 =
x1 | x2 | x3 | x4;
endmodule
//dataflow
xor2_df
module
xor2_df (x1, x2, z1);
input x1,
x2;
output z1;
wire x1,
x2;
wire z1;
assign z1 =
x1 ^ x2;
endmodule
//behavioral
D flip-flop
module
d_ff_bh (rst_n, clk, d, q, q_n);
input
rst_n, clk, d;
output q,
q_n;
wire
rst_n, clk, d;
reg q;
assign q_n =
~q;
always @
(rst_n or posedge clk)
begin
if
(rst_n == 0)
q <= 1'b0;
else
q <= d;
end
endmodule
//structural
odd even counter
module
ctr_odd_evn2 (rst_n, clk, y);
input
rst_n, clk;
output [1:4]
y;
wire
rst_n, clk;
wire [1:4]
y;
//define
internal wires
wire net1,
net2, net3, net4, net6,
net8, net9, net10, net11,
net13, net14, net15, net16;
//instantiate
the logic for flip-flop y[1]
and2_df
inst1 (
.x1(y[1]),
.x2(~y[3]),
.z1(net1)
);
and2_df
inst2 (
.x1(y[1]),
.x2(~y[2]),
.z1(net2)
);
and3_df
inst3 (
.x1(~y[1]),
.x2(y[2]),
.x3(y[3]),
.z1(net3)
);
or3_df
inst4 (
.x1(net1),
.x2(net2),
.x3(net3),
.z1(net4)
);
d_ff_bh
inst5 (
.rst_n(rst_n),
.clk(clk),
.d(net4),
.q(y[1])
);
//instantiate
the logic for flip-flop y[2]
xor2_df
inst6 (
.x1(y[2]),
.x2(y[3]),
.z1(net6)
);
d_ff_bh
inst7 (
.rst_n(rst_n),
.clk(clk),
.d(net6),
.q(y[2])
);
//instantiate
the logic for flip-flop y[3]
and2_df
inst8 (
.x1(y[2]),
.x2(~y[3]),
.z1(net8)
);
and2_df
inst9 (
.x1(~y[3]),
.x2(y[4]),
.z1(net9)
);
and3_df
inst10 (
.x1(y[1]),
.x2(y[2]),
.x3(y[4]),
.z1(net10)
);
or4_df
inst11 (
.x1(net1),
.x2(net8),
.x3(net9),
.x4(net10),
.z1(net11)
);
d_ff_bh
inst12 (
.rst_n(rst_n),
.clk(clk),
.d(net11),
.q(y[3])
);
//instantiate
the logic for flip-flop y[4]
and2_df
inst13 (
.x1(~y[1]),
.x2(y[4]),
.z1(net13)
);
and2_df
inst14 (
.x1(~y[2]),
.x2(y[4]),
.z1(net14)
);
and3_df
inst15 (
.x1(~y[1]),
.x2(~y[2]),
.x3(~y[3]),
.z1(net15)
);
or4_df
inst16 (
.x1(net9),
.x2(net13),
.x3(net14),
.x4(net15),
.z1(net16)
);
d_ff_bh
inst17 (
.rst_n(rst_n),
.clk(clk),
.d(net16),
.q(y[4])
);
endmodule
//test
bench for odd even counter
module
ctr_odd_evn2_tb;
reg
rst_n, clk;
wire [1:4]
y;
//display
count
initial
$monitor
("count = %b", y);
//generate
reset
initial
begin
#0 rst_n = 1'b0;
#2 rst_n
= 1'b1;
end
//generate
clock
initial
begin
clk
= 1'b0;
forever
#12 clk
= ~clk;
end
//determine
length of simulation
initial
#370 $stop;
//instantiate
the module into the test bench
ctr_odd_evn2
inst1 (
.rst_n(rst_n),
.clk(clk),
.y(y)
);
endmodule
Page 174, Figure 3.113
//structural
moore ssm
module
moore_ssm22 (rst_n, clk, x1, x2, x3, y,
z1, z2, z3, z4, z5);
//define
inputs and outputs
input
rst_n, clk, x1, x2, x3;
output [1:3]
y;
output z1,
z2, z3, z4, z5;
//define
internal wires
wire net1,
net3, net5, net6, net7;
//instantiate
the logic for flip-flop y[1]
and5_df
inst1 (
.x1(~y[1]),
.x2(~y[2]),
.x3(~y[3]),
.x4(x1),
.x5(~x2),
.z1(net1)
);
d_ff_bh
inst2 (
.rst_n(rst_n),
.clk(clk),
.d(net1),
.q(y[1])
);
//instantiate
the logic for flip-flop y[2]
and5_df
inst3 (
.x1(~y[1]),
.x2(~y[2]),
.x3(~y[3]),
.x4(~x1),
.x5(x2),
.z1(net3)
);
//continued
on next page
d_ff_bh
inst4 (
.rst_n(rst_n),
.clk(clk),
.d(net3),
.q(y[2])
);
//instantiate
the logic for flip-flop y[3]
and5_df
inst5 (
.x1(~y[1]),
.x2(~y[2]),
.x3(~y[3]),
.x4(~x1),
.x5(x3),
.z1(net5)
);
and5_df
inst6 (
.x1(~y[1]),
.x2(~y[2]),
.x3(~y[3]),
.x4(~x2),
.x5(x3),
.z1(net6)
);
or2_df
inst7 (
.x1(net5),
.x2(net6),
.z1(net7)
);
d_ff_bh
inst8 (
.rst_n(rst_n),
.clk(clk),
.d(net7),
.q(y[3])
);
//instantiate
the logic outputs z1, z2, z3, z4, and z5
and4_df
inst9 (
.x1(~y[1]),
.x2(~y[2]),
.x3(y[3]),
.x4(~clk),
.z1(z1)
);
and4_df
inst10 (
.x1(~y[1]),
.x2(y[2]),
.x3(~y[3]),
.x4(~clk),
.z1(z2)
);
and4_df
inst11 (
.x1(~y[1]),
.x2(y[2]),
.x3(y[3]),
.x4(~clk),
.z1(z3)
);
and4_df
inst12 (
.x1(y[1]),
.x2(~y[2]),
.x3(~y[3]),
.x4(~clk),
.z1(z4)
);
and4_df
inst13 (
.x1(y[1]),
.x2(~y[2]),
.x3(y[3]),
.x4(~clk),
.z1(z5)
);
endmodule
Page 176, Figure 3.114
//test
bench for moore ssm22
module
moore_ssm22_tb;
reg
rst_n, clk, x1, x2, x3;
wire [1:3]
y;
wire z1,
z2, z3, z4, z5;
//display
inputs and outputs
initial
$monitor
("x1 x2 x3 = %b, state = %b, z1 z2 z3 z4 z5 = %b",
{x1, x2, x3}, y, {z1, z2, z3, z4,
z5});
//define
clock
initial
begin
clk
= 1'b0;
forever
#10 clk = ~clk;
end
//define
input sequence
initial
begin
#0 rst_n = 1'b0; //reset to state_a (000)
x1=1'b0; x2=1'b0; x3=1'b0;
#5 rst_n
= 1'b1;
x1=1'b0; x2=1'b0; x3=1'b1;
@ (posedge clk) //go
to state_b (001); assert z1
x1=$random; x2=$random; x3=$random;
@ (posedge
clk) //go to state_a
(000)
x1=1'b0; x2=1'b1; x3=1'b0;
@ (posedge
clk) //go to state_c
(010); assert z2
x1=$random; x2=$random; x3=$random;
@ (posedge
clk) //go to state_a
(000)
x1=1'b0; x2=1'b1; x3=1'b1;
@ (posedge
clk) //go to state_d
(011); assert z3
x1=$random; x2=$random; x3=$random;
@ (posedge
clk) //go to state_a
(000)
x1=1'b1; x2=1'b0; x3=1'b0;
@ (posedge
clk) //go to state_e
(100); assert z4
x1=$random; x2=$random; x3=$random;
@ (posedge
clk) //go to state_a
(000)
x1=1'b1; x2=1'b0; x3=1'b1;
@ (posedge
clk) //go to state_f
(101); assert z5
x1=$random; x2=$random; x3=$random;
@ (posedge
clk) //go to state_a
(000)
#10 $stop;
end
//instantiate
the module into the test bench
moore_ssm22
inst1 (
.rst_n(rst_n),
.clk(clk),
.x1(x1),
.x2(x2),
.x3(x3),
.y(y),
.z1(z1),
.z2(z2),
.z3(z3),
.z4(z4),
.z5(z5)
);
endmodule
Computer
Arithmetic
and
Verilog HDL
Fundamentals
Chapter 4
Fixed-Point
Addition
Verilog Code
Figures
Page 188, Figure 4.7
//dataflow
full adder
module
full_adder (a, b, cin, sum, cout);
//list
all inputs and outputs
input a, b,
cin;
output sum,
cout;
//define
wires
wire a, b,
cin;
wire sum,
cout;
//continuous
assign
assign sum =
(a ^ b) ^ cin;
assign cout
= cin & (a ^ b) | (a & b);
endmodule
Page 188, figure 4.8
//structural
4_bit ripple-carry counter
module
adder_ripple4_struc2 (a, b, cin, sum, cout);
input [3:0]
a, b;
input cin;
output [3:0]
sum;
output cout;
wire [3:0]
a, b;
wire cin;
wire [3:0]
sum;
wire cout;
wire [3:0]
c; //define internal
nets for carries
assign cout
= c[3];
full_adder
inst0 (
.a(a[0]),
.b(b[0]),
.cin(cin),
.sum(sum[0]),
.cout(c[0])
);
full_adder
inst1 (
.a(a[1]),
.b(b[1]),
.cin(c[0]),
.sum(sum[1]),
.cout(c[1])
);
full_adder
inst2 (
.a(a[2]),
.b(b[2]),
.cin(c[1]),
.sum(sum[2]),
.cout(c[2])
);
full_adder
inst3 (
.a(a[3]),
.b(b[3]),
.cin(c[2]),
.sum(sum[3]),
.cout(c[3])
);
endmodule
Page 189, Figure 4.9
//test
bench for 4-bit ripple-carry adder
module
adder_ripple4_struc2_tb;
//define
inputs
reg [3:0]
a, b;
reg cin;
//define
outputs
wire [3:0]
sum;
wire cout;
initial
$monitor
("a=%b, b=%b, cin=%b, cout=%b, sum=%b",
a, b, cin, cout, sum);
initial
begin
#0 a = 4'b0000; b
= 4'b0001; cin = 1'b0;
#10 a
= 4'b0011; b = 4'b0100; cin = 1'b1;
#10 a
= 4'b0111; b = 4'b0101; cin = 1'b0;
#10 a
= 4'b1011; b = 4'b1100; cin = 1'b1;
#10 a
= 4'b0110; b = 4'b0100; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0100; cin = 1'b1;
#10 a
= 4'b1111; b = 4'b1111; cin = 1'b1;
#10 a
= 4'b1000; b = 4'b1000; cin = 1'b1;
#10 a
= 4'b1100; b = 4'b1100; cin = 1'b0;
#10 a
= 4'b1001; b = 4'b0101; cin = 1'b1;
#10 a
= 4'b0111; b = 4'b0111; cin = 1'b0;
#10 $stop;
end
//instantiate
the module into the test bench
adder_ripple4_struc2
inst1 (
.a(a),
.b(b),
.cin(cin),
.sum(sum),
.cout(cout)
);
endmodule
Page 196, Figure 4.16
//dataflow
8-bit carry lookahead adder
module
adder_cla8 (a, b, cin, sum, cout);
input [7:0]
a, b; //input/output port
declaration
input cin;
output [7:0]
sum;
output cout;
wire g7,
g6, g5, g4, g3, g2, g1, g0; //define internal wires
wire p7,
p6, p5, p4, p3, p2, p1, p0;
wire c7,
c6, c5, c4, c3, c2, c1, c0;
//continued
on next page
//define
internal wires
wire g7,
g6, g5, g4, g3, g2, g1, g0;
wire p7,
p6, p5, p4, p3, p2, p1, p0;
wire c7,
c6, c5, c4, c3, c2, c1, c0;
//dataflow
8-bit carry lookahead adder
module
adder_cla8 (a, b, cin, sum, cout);
//input/output
port declaration
input [7:0]
a, b;
input cin;
output [7:0]
sum;
output cout;
//define
generate functions
//multiple
statements using 1 assign
assign g7
= a[7] & b[7],
g6 = a[6] & b[6],
g5 = a[5] & b[5],
g4 = a[4] & b[4],
g3 = a[3] & b[3],
g2 = a[2] & b[2],
g1 = a[1] & b[1],
g0 = a[0] & b[0];
//define
propagate functions
//multiple
statements using 1 assign
assign p7
= a[7] ^ b[7],
p6 = a[6] ^ b[6],
p5 = a[5] ^ b[5],
p4 = a[4] ^ b[4],
p3 = a[3] ^ b[3],
p2 = a[2] ^ b[2],
p1 = a[1] ^ b[1],
p0 = a[0] ^ b[0];
//obtain
the carry equations for low order
assign c0
= g0 | (p0 & cin),
c1 = g1 | (p1 & g0) | (p1 &
p0 & cin),
c2 = g2 | (p2 & g1) | (p2 &
p1 & g0) |
(p2 & p1 & p0 &
cin),
c3 = g3 | (p3 & g2) | (p3 &
p2 & g1) |
(p3 & p2 & p1 &
g0) |
(p3 & p2 & p1 & p0
& cin);
//obtain
the carry equations for high order
assign c4
= g4 | (p4 & c3),
c5 = g5 | (p5 & g4) | (p5 &
p4 & c3),
c6 = g6 | (p6 & g5) | (p6 &
p5 & g4) |
(p6 & p5 & p4 &
c3),
c7 = g7 | (p7 & g6) | (p7 &
p6 & g5) |
(p7 & p6 & p5 &
g4) |
(p7 & p6 & p5 & p4
& c3);
//obtain
the sum equations
assign sum[0]
= p0 ^ cin,
sum[1] = p1 ^ c0,
sum[2] = p2 ^ c1,
sum[3] = p3 ^ c2,
sum[4] = p4 ^ c3,
sum[5] = p5 ^ c4,
sum[6] = p6 ^ c5,
sum[7] = p7 ^ c6;
//obtain
cout
assign cout
= c7;
endmodule
//test
bench for dataflow 8-bit carry lookahead adder
module
adder_cla8_tb;
reg [7:0]
a, b;
reg cin;
wire [7:0]
sum;
wire cout;
//display
signals
initial
$monitor
("a = %d, b = %d, cin = %b, cout = %b, sum = %d",
a, b, cin, cout, sum);
//apply
stimulus
initial
begin
#0 a = 8'b0000_0000;
b = 8'b0000_0000;
cin = 1'b0; //cout = 0, sum = 0000_0000
#10 a
= 8'b0000_0001;
b = 8'b0000_0010;
cin = 1'b0; //cout = 0, sum = 0000_0011
//apply
stimulus
initial
begin
#0 a = 8'b0000_0000;
b = 8'b0000_0000;
cin = 1'b0; //cout = 0, sum = 0000_0000
#10 a
= 8'b0000_0001;
b = 8'b0000_0010;
cin = 1'b0; //cout = 0, sum = 0000_0011
#10 a
= 8'b0000_0010;
b = 8'b0000_0110;
cin = 1'b0; //cout = 0, sum = 0000_1000
#10 a
= 8'b0000_0111;
b = 8'b0000_0111;
cin = 1'b0; //cout = 0, sum = 0000_1110
#10 a
= 8'b0000_1001;
b = 8'b0000_0110;
cin = 1'b0; //cout = 0, sum = 0000_1111
#10 a
= 8'b0000_1100;
b = 8'b0000_1100;
cin = 1'b0; //cout = 0, sum = 0001_1000
#10 a
= 8'b0000_1111;
b = 8'b0000_1110;
cin = 1'b0; //cout = 0, sum = 0001_1101
#10 a
= 8'b0000_1110;
b = 8'b0000_1110;
cin = 1'b1; //cout = 0, sum = 0001_1101
#10 a
= 8'b0000_1111;
b = 8'b0000_1111;
cin = 1'b1; //cout = 0, sum = 0001_1111
#10 a
= 8'b1111_0000;
b = 8'b0000_1111;
cin = 1'b1; //cout = 1, sum = 0000_0000
#10 a
= 8'b0111_0000;
b = 8'b0000_1111;
cin = 1'b1; //cout = 0, sum = 1000_0000
#10 a
= 8'b1011_1000;
b = 8'b0100_1111;
cin = 1'b1; //cout = 1, sum = 0000_1000
#10 $stop;
end
adder_cla8
inst1 ( //instantiate the
module
.a(a),
.b(b),
.cin(cin),
.sum(sum),
.cout(cout)
);
endmodule
Page 202, Figure 4.21
//dataflow
carry-save full adder
module
csa_full_adder (a, b, c, sum, cout);
input a, b,
c; //list all inputs
and outputs
output sum,
cout;
wire a, b,
c; //define wires
wire sum,
cout;
assign sum =
(a ^ b) ^ c; //continuous assign
assign cout
= c & (a ^ b) | (a & b);
endmodule
//test
bench for carry-save full adder
module
csa_full_adder_tb;
reg a, b,
c;
wire sum,
cout;
//apply
input vectors
initial
begin:
apply_stimulus
reg
[3:0] invect;
for
(invect = 0; invect < 8; invect = invect + 1)
begin
{a,
b, c} = invect [3:0];
#10 $display ("a b c = %b, cout = %b,
sum = %b",
{a, b, c}, cout,
sum);
end
end
//instantiate
the module into the test bench
csa_full_adder
inst1 (
.a(a),
.b(b),
.c(c),
.sum(sum),
.cout(cout)
);
endmodule
Page 204, Figure 4.25
//structural
5-input wallace tree
module
wallace_tree_5_inputs (in, sum_w);
input [4:0]
in;
output [2:0]
sum_w;
wire [4:0]
in;
wire [2:0]
sum_w;
//define
internal nets
wire net1,
net2, net3;
//instantiate
the carry-save full adders
csa_full_adder
inst1 (
.a(in[2]),
.b(in[1]),
.c(in[0]),
.sum(net1),
.cout(net2)
);
csa_full_adder
inst2 (
.a(in[4]),
.b(in[3]),
.c(net1),
.sum(sum_w[0]),
.cout(net3)
);
csa_full_adder
inst3 (
.a(1'b0),
.b(net2),
.c(net3),
.sum(sum_w[1]),
.cout(sum_w[2])
);
endmodule
//test
bench for 5-input wallace tree
module
wallace_tree_5_inputs_tb;
reg [4:0]
in; //define inputs and
outputs
wire [2:0]
sum_w;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[5:0] invect;
for
(invect = 0; invect < 32; invect = invect + 1)
begin
in
= invect [5:0];
#10 $display ("inputs = %b, sum =
%b",
in, sum_w);
end
end
//instantiate
the module
wallace_tree_5_inputs
nst1 (
.in(in),
.sum_w(sum_w)
);
endmodule
Page 207, Figure 4.30
//structural
wallace tree for 5 operands
module
wallace_tree_5_opnds (a, b, c, d, e, sum_w);
input [3:0]
a, b, c, d, e;
output [6:0]
sum_w;
wire [3:0]
a, b, c, d, e;
wire [6:0]
sum_w;
//define
internal nets
wire net1,
net2, net3, net4, net5, net6,
net7, net8, net9, net10, net11,
net12, net13, net14, net15, net16,
net17, net18, net19, net20, net21;
//instantiate
the 5-input wallace tree
wallace_tree_5_inputs
inst1 (
.in({a[0], b[0], c[0], d[0], e[0]}),
.sum_w({net2, net1, sum_w[0]})
);
wallace_tree_5_inputs
inst2 (
.in({a[1], b[1], c[1], d[1], e[1]}),
.sum_w({net5, net4, net3})
);
wallace_tree_5_inputs
inst3 (
.in({a[2], b[2], c[2], d[2], e[2]}),
.sum_w({net8, net7, net6})
);
wallace_tree_5_inputs
inst4 (
.in({a[3], b[3], c[3], d[3], e[3]}),
.sum_w({net11, net10, net9})
);
//instantiate
the carry-save full adder
csa_full_adder
inst5 (
.a(1'b0),
.b(net1),
.c(net3),
.sum(sum_w[1]),
.cout(net12)
);
csa_full_adder
inst6 (
.a(net2),
.b(net4),
.c(net6),
.sum(net13),
.cout(net14)
);
csa_full_adder
inst7 (
.a(net5),
.b(net7),
.c(net9),
.sum(net15),
.cout(net16)
);
csa_full_adder
inst8 (
.a(net8),
.b(net10),
.c(1'b0),
.sum(net17),
.cout(net18)
);
csa_full_adder
inst9 (
.a(net12),
.b(1'b0),
.c(net13),
.sum(sum_w[2]),
.cout(net19)
);
csa_full_adder
inst10 (
.a(net19),
.b(net14),
.c(net15),
.sum(sum_w[3]),
.cout(net20)
);
csa_full_adder
inst11 (
.a(net20),
.b(net16),
.c(net17),
.sum(sum_w[4]),
.cout(net21)
);
csa_full_adder
inst12 (
.a(net21),
.b(net18),
.c(net11),
.sum(sum_w[5]),
.cout(sum_w[6])
);
endmodule
//test
bench for 5-operand wallace tree
module
wallace_tree_5_opnds_tb;
//define
inputs and outputs
reg [3:0]
a, b, c, d, e;
wire [6:0]
sum_w;
//display
outputs
initial
$monitor
("a=%b, b=%b, c=%b, d=%b, e=%b, sum=%b",
a, b, c, d, e, sum_w);
//apply
input vectors
initial
begin
#0 a = 4'b0001;
b = 4'b0001;
c = 4'b0001;
d = 4'b0001;
e = 4'b0001; //sum = 000 0101
#10 a
= 4'b0111;
b = 4'b1010;
c = 4'b0101;
d = 4'b1001;
e = 4'b0011; //sum = 010 0010
#10 a
= 4'b1111;
b = 4'b1010;
c = 4'b1101;
d = 4'b1001;
e = 4'b1011; //sum = 011 1010
#10 a
= 4'b0110;
b = 4'b1110;
c = 4'b1111;
d = 4'b1000;
e = 4'b1001; //sum = 011 0100
#10 a
= 4'b1111;
b = 4'b1111;
c = 4'b1111;
d = 4'b1111;
e = 4'b1111; //sum = 100 1011
#10 a = 4'b1000;
b = 4'b1000;
c = 4'b1000;
d = 4'b1000;
e = 4'b1000; //sum = 010 1000
#10 a
= 4'b1100;
b = 4'b1100;
c = 4'b1100;
d = 4'b1100;
e = 4'b1100; //sum = 011 1100
#10 $stop;
end
//instantiate
the module into the test bench
wallace_tree_5_opnds
inst1 (
.a(a),
.b(b),
.c(c),
.d(d),
.e(e),
.sum_w(sum_w)
);
endmodule
Page 214, Figure 4.35
//behavioral
to add two operands
module
mem_sum (opnds, sum);
input [5:0]
opnds; //list inputs and
outputs
output [3:0]
sum;
wire [5:0]
opnds; //augend and
addend to address 64 words
reg [3:0]
sum;
//define
memory size
//mem_add
is an array of 64 four-bit registers
reg [3:0]
mem_add [0:63];
//define
memory contents
//load
mem_add from file opnds.add
initial
begin
$readmemb
("opnds.add", mem_add);
end
//use
the operands to access the memory
always @
(opnds)
begin
sum
= mem_add [opnds];
end
endmodule
//test
bench for mem_sum module
module
mem_sum_tb;
reg [5:0]
opnds;
wire [3:0]
sum;
//display
variables
initial
$monitor
("augend_addend = %b, sum = %b", opnds, sum);
//apply
input vectors for augend and addend
initial
begin
#0 opnds = 6'b000_011; //augend_addend
#10 opnds
= 6'b001_100;
#10 opnds
= 6'b010_100;
#10 opnds
= 6'b011_110;
#10 opnds
= 6'b100_100;
#10 opnds
= 6'b101_101;
#10 opnds
= 6'b110_101;
#10 opnds
= 6'b100_110;
#10 opnds
= 6'b111_010;
#10 opnds
= 6'b111_100;
#10 opnds
= 6'b111_110;
#10 opnds
= 6'b111_111;
#10 $stop;
end
//instantiate
the module into the test bench
mem_sum
inst1 (
.opnds(opnds),
.sum(sum)
);
endmodule
Page 218, Figure 4.39
//behavioral
model for a 4-bit adder
module
adder4 (a, b, cin, sum, cout);
//define
inputs and outputs
input [3:0]
a, b;
input cin;
output [3:0]
sum;
output cout;
wire [3:0]
a, b;
wire cin;
reg [3:0]
sum;
reg cout;
always @ (a
or b or cin)
begin
sum = a + b + cin;
cout = (a[3] & b[3]) |
((a[3] | b[3]) & (a[2] & b[2])) |
((a[3] | b[3]) & (a[2] | b[2]) & (a[1]
& b[1])) |
((a[3] | b[3]) & (a[2] | b[2]) & (a[1]
|
b[1]) & (a[0] & b[0])) |
((a[3] | b[3]) & (a[2] | b[2]) & (a[1]
|
b[1]) & (a[0] | b[0]) & cin);
end
endmodule
//dataflow
2:1 multiplexer
module
mux2_df (sel, data, z1);
//define
inputs and output
input sel;
input [1:0]
data;
output z1;
assign z1 =
(~sel & data[0]) | (sel & data[1]);
endmodule
//dataflow
2-input and gate
module
and2_df (x1, x2, z1);
input x1,
x2;
output z1;
wire x1,
x2;
wire z1;
//continuous
assign for dataflow
assign z1 =
x1 & x2;
endmodule
//and3
dataflow
module
and3_df (x1, x2, x3, z1);
input x1,
x2, x3; //list inputs and
output
output z1;
wire x1,
x2, x3; //define signals as
wire for dataflow
wire z1;
assign z1 =
x1 & x2 & x3; //continuous
assign for dataflow
endmodule
//dataflow
or2
module
or2_df (x1, x2, z1);
input x1,
x2; //list inputs and
output
output z1;
wire x1,
x2; //define signals as
wire for dataflow
wire z1;
assign z1 =
x1 | x2; //continuous assign for
dataflow
endmodule
//or3
dataflow
module
or3_df (x1, x2, x3, z1);
input x1,
x2, x3;
output z1;
wire x1,
x2, x3;
wire z1;
assign z1 =
x1 | x2 | x3;
endmodule
Page 221, Figure 4.45
//structural
carry-select adder
module
adder_carry_sel (a, b, sum, sel_nxt_mux);
input
[11:0] a, b;
output
[11:0] sum;
output
sel_nxt_mux;
wire
[11:0] a, b;
wire
[11:0] sum;
wire
sel_nxt_mux;
//define
internal nets
wire sum2_7,
sum2_6, sum2_5, sum2_4, cout2, cout1,
sum3_7, sum3_6, sum3_5, sum3_4, cout3,
net8,
net9, sum10_11, sum10_10, sum10_9,
sum10_8, cout10,
sum11_11, sum11_10, sum11_9, sum11_8,
cout11,
net16, net17;
//instantiate
the 4-bit adder for a[3:0] and b[3:0]
adder4
inst1 (
.a(a[3:0]),
.b(b[3:0]),
.cin(1'b0),
.sum(sum[3:0]),
.cout(cout1)
);
//instantiate
the 4-bit adder for a[7:4] and b[7:4]
adder4
inst2 (
.a(a[7:4]),
.b(b[7:4]),
.cin(1'b0),
.sum({sum2_7, sum2_6, sum2_5, sum2_4}),
.cout(cout2)
);
adder4
inst3 (
.a(a[7:4]),
.b(b[7:4]),
.cin(1'b1),
.sum({sum3_7, sum3_6, sum3_5, sum3_4}),
.cout(cout3)
);
//instantiate
the 2:1 muxs for sum[7:4]
mux2_df
inst4 (
.sel(cout1),
.data({sum3_4, sum2_4}),
.z1(sum[4])
);
mux2_df
inst5 (
.sel(cout1),
.data({sum3_5, sum2_5}),
.z1(sum[5])
);
mux2_df
inst6 (
.sel(cout1),
.data({sum3_6, sum2_6}),
.z1(sum[6])
);
mux2_df
inst7 (
.sel(cout1),
.data({sum3_7, sum2_7}),
.z1(sum[7])
);
//instantiate
the logic to select muxs for sum[11] thru sum[8]
and2_df
inst8 (
.x1(cout1),
.x2(cout3),
.z1(net8)
);
or2_df
inst9 (
.x1(cout2),
.x2(net8),
.z1(net9)
);
//instantiate
the 4-bit adder for a[11:8] and b[11:8]
adder4
inst10 (
.a(a[11:8]),
.b(b[11:8]),
.cin(1'b0),
.sum({sum10_11, sum10_10, sum10_9, sum10_8}),
.cout(cout10)
);
adder4
inst11 (
.a(a[11:8]),
.b(b[11:8]),
.cin(1'b1),
.sum({sum11_11, sum11_10, sum11_9,
sum11_8}),
.cout(cout11)
);
//instantiate
the 2:1 muxs for sum[11:8]
mux2_df
inst12 (
.sel(net9),
.data({sum11_8, sum10_8}),
.z1(sum[8])
);
mux2_df
inst13 (
.sel(net9),
.data({sum11_9, sum10_9}),
.z1(sum[9])
);
mux2_df
inst14 (
.sel(net9),
.data({sum11_10, sum10_10}),
.z1(sum[10])
);
mux2_df
inst15 (
.sel(net9),
.data({sum11_11, sum10_11}),
.z1(sum[11])
);
and2_df
inst16 (
.x1(cout2),
.x2(cout11),
.z1(net16)
);
and3_df
inst17 (
.x1(cout1),
.x2(cout3),
.x3(cout11),
.z1(net17)
);
or3_df
inst18 (
.x1(cout10),
.x2(net16),
.x3(net17),
.z1(sel_nxt_mux)
);
endmodule
//test
bench for carry-select adder
module
adder_carry_sel_tb;
//define
inputs and outputs
reg
[11:0] a, b;
wire
[11:0] sum;
wire
sel_nxt_mux;
//display
outputs
initial
$monitor
("a = %b, b = %b, sum = %b, sel_nxt_mux = %b",
a, b, sum, sel_nxt_mux);
//apply
input vectors
initial
begin
#0 a = 12'b0000_0000_0001;
b = 12'b0000_0000_0010;
#10 a = 12'b0000_0001_0010;
b
= 12'b0000_0000_0011;
#10 a = 12'b0001_0001_0010;
b = 12'b0000_0000_0011;
#10 a
= 12'b0011_0011_0010;
b = 12'b0001_0100_0011;
#10 a
= 12'b1111_0000_0111;
b = 12'b1000_1101_1000;
#10 a
= 12'b1111_1111_1111;
b = 12'b1111_1111_1111;
#10 a
= 12'b1010_1010_1010;
b = 12'b0101_0101_0101;
#10 a
= 12'b0111_1011_1010;
b = 12'b0011_0110_1101;
#10 a
= 12'b1111_0111_0110;
b = 12'b0011_1100_0111;
#10 a
= 12'b1100_1010_0111;
b = 12'b0101_0011_0101;
#10 a
= 12'b0011_0111_1011;
b = 12'b1011_0011_0111;
#10 a
= 12'b1011_0111_1100;
b = 12'b0100_1000_0110;
#10 $stop;
end
//instantiate
the module into the test bench
adder_carry_sel
inst1 (
.a(a),
.b(b),
.sum(sum),
.sel_nxt_mux(sel_nxt_mux)
);
endmodule
Page 228, Figure 4.50
//behavioral
parallel-in, serial-out shift register
module
shift_reg_piso8 (rst_n, clk, load, x, y, z1);
input
rst_n, clk, load;
input [7:0]
x;
output [7:0]
y;
output z1;
reg [7:0]
y;
assign z1 =
y[0];
always @
(rst_n)
begin
if
(rst_n == 0)
y <= 8'b0000_0000;
end
always @ (posedge clk)
begin
y[7]
<= ((load && x[7]) || (~load && 1'b0));
y[6] <= ((load && x[6]) ||
(~load && y[7]));
y[5] <= ((load && x[5]) ||
(~load && y[6]));
y[4] <= ((load && x[4]) ||
(~load && y[5]));
y[3] <= ((load && x[3]) ||
(~load && y[4]));
y[2] <= ((load && x[2]) ||
(~load && y[3]));
y[1] <= ((load && x[1]) ||
(~load && y[2]));
y[0] <= ((load && x[0]) ||
(~load && y[1]));
end
endmodule
//behavioral
serial-in parallel-out shift register
module
shift_reg_sipo (rst_n, clk, ser_in, shift_reg);
input
rst_n, clk, ser_in;
output [7:0]
shift_reg;
reg [7:0]
shift_reg;
always @
(rst_n)
begin
if
(rst_n == 0)
shift_reg <= 8'b0000_0000;
end
always @ (posedge clk)
begin
shift_reg
[7] <= ser_in;
shift_reg [6] <= shift_reg [7];
shift_reg [5] <= shift_reg [6];
shift_reg [4] <= shift_reg [5];
shift_reg [3] <= shift_reg [4];
shift_reg [2] <= shift_reg [3];
shift_reg [1] <= shift_reg [2];
shift_reg [0] <= shift_reg [1];
end
endmodule
//dataflow
full adder
module
full_adder (a, b, cin, sum, cout);
//list
all inputs and outputs
input a, b,
cin;
output sum,
cout;
//define
wires
wire a, b,
cin;
wire sum,
cout;
//continuous
assign
assign sum =
(a ^ b) ^ cin;
assign cout
= cin & (a ^ b) | (a & b);
endmodule
//behavioral
D flip-flop
module
d_ff_bh (rst_n, clk, d, q, q_n);
input
rst_n, clk, d;
output q,
q_n;
wire
rst_n, clk, d;
reg q;
assign q_n =
~q;
always @
(rst_n or posedge clk)
begin
if
(rst_n == 0)
q <= 1'b0;
else
q <= d;
end
endmodule
//structural
for serial adder
module
adder_serial (rst_n, clk, load, a, b, sum);
input
rst_n, clk, load;
input [7:0]
a, b;
output [7:0]
sum;
//define
internal nets
wire a_reg_out,
b_reg_out, fa_sum, fa_cout,
net4, d_ff_out;
//instantiate
the parallel-in, serial-out shift registers
shift_reg_piso8
inst1 (
.rst_n(rst_n),
.clk(clk),
.load(load),
.x(a),
.z1(a_reg_out)
);
shift_reg_piso8
inst2 (
.rst_n(rst_n),
.clk(clk),
.load(load),
.x(b),
.z1(b_reg_out)
);
//instantiate
the full adder
full_adder
inst3 (
.a(a_reg_out),
.b(b_reg_out),
.cin(d_ff_out),
.sum(fa_sum),
.cout(fa_out)
);
//instantiate
the d flip-flop and logic
and2_df
inst4 (
.x1(clk),
.x2(~load),
.z1(net4)
);
d_ff_bh
inst5 (
.rst_n(rst_n),
.clk(clk),
.d(fa_out),
.q(d_ff_out)
);
//instantiate
the serial-in, parallel-out shift register
shift_reg_sipo
inst6 (
.rst_n(rst_n),
.clk(clk),
.ser_in(fa_sum),
.shift_reg(sum)
);
endmodule
//test
bench for the serial adder
module
adder_serial_tb;
reg
rst_n, clk, load;
reg [7:0]
a, b;
wire [7:0]
sum;
//define
clock
initial
begin
clk
= 1'b0;
forever
#10
clk = ~clk;
end
//display
variables
initial
$monitor
("a = %b, b = %b, sum = %b", a, b, sum);
//apply
input vectors
initial
begin
#0 rst_n = 1'b0;
#2 rst_n
= 1'b1;
#3 a
= 8'b0000_0011;
b = 8'b0000_1000;
load = 1'b1;
#15 load
= 1'b0;
//------------------------------
#165 rst_n
= 1'b0;
#2 rst_n
= 1'b1;
#2 a
= 8'b0001_1001;
b = 8'b0010_0010;
load = 1'b1;
#15 load
= 1'b0;
end
//determine
length of simulation
initial
begin
#370 $stop;
end
//instantiate
the module into the test bench
adder_serial
inst1 (
.rst_n(rst_n),
.clk(clk),
.load(load),
.a(a),
.b(b),
.sum(sum)
);
endmodule
No comments:
Post a Comment