Computer
Arithmetic
and
Verilog HDL
Fundamentals
Chapter 7
Fixed-Point
Division
Verilog Code
Figures
Page 365, Figure
7.5
//mixed-design
for restoring division
module
div_restoring (a, b, start, rslt);
input [7:0]
a;
input [3:0]
b;
input
start;
output [7:0]
rslt;
wire [3:0]
b_bar;
//define
internal registers
reg [3:0]
b_neg;
reg [7:0]
rslt;
reg [3:0]
count;
assign b_bar
= ~b;
always @
(b_bar)
b_neg = b_bar + 1;
always @ (posedge start)
begin
rslt
= a;
count = 4'b0100;
if
((a!=0) && (b!=0)) //if
a or b = 0, exit
while
(count) //else do while
loop
begin
rslt
= rslt << 1;
rslt = {(rslt[7:4] + b_neg),
rslt[3:0]};
if
(rslt[7] == 1)
begin
rslt
= {(rslt[7:4] + b), rslt[3:1], 1'b0};
count = count - 1;
end
else
begin
rslt
= {rslt[7:1], 1'b1};
count = count - 1;
end
end
end
endmodule
//test
bench for restoring division
module
div_restoring_tb;
reg [7:0]
a;
reg [3:0]
b;
reg
start;
wire [7:0]
rslt;
initial //display
variables
$monitor
("a = %b, b = %b, quot = %b, rem = %b",
a, b, rslt[3:0], rslt[7:4]);
initial //apply
input vectors
begin
#0 start = 1'b0;
a = 8'b0000_1101; b = 4'b0101;
#10 start = 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1100; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0101_0010; b =
4'b0110;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1000; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_0100; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_1110; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 $stop;
end
div_restoring
inst1 ( //instantiate the
module
.a(a),
.b(b),
.start(start),
.rslt(rslt)
);
endmodule
Page 371, Figure
7.11
//behavioral/dataflow
restoring division using a multiplexor
module
div_restoring_vers2 (a, b, start, rslt);
input [7:0]
a; //dividend
input [3:0]
b; //divisor
input
start;
output [7:0]
rslt; //rslt[7:4] is rem;
rslt[3:0] is quot
wire [3:0]
b_bar;
//define
internal registers
reg [3:0]
b_neg;
reg [7:0]
rslt;
reg [3:0]
count;
reg [4:0]
sum;
reg cout;
assign b_bar
= ~b; //1s complement of
divisor
always
@ (b_bar)
b_neg = b_bar + 1; //2s complement of divisor
always @ (posedge start)
begin
rslt
= a;
count = 4'b0100;
if
((a!=0) && (b!=0)) //if a or b =
0, exit
while
(count) //else do while loop
begin
rslt
= rslt << 1;
sum = rslt[7:4] + b_neg;
cout = sum[4];
if (cout
== 0)
begin
rslt[0]
= cout; //q0 = cout
rslt[7:4] = rslt[7:4];
count = count -1;
end
else
begin
rslt[0]
= cout; //q0 = cout
rslt[7:4] = sum[3:0];
count = count - 1;
end
end
end
endmodule
//test
bench for restoring division version 2
module
div_restoring_vers2_tb;
reg [7:0]
a;
reg [3:0]
b;
reg
start;
wire [7:0]
rslt;
//display
variables
initial
$monitor
("a = %b, b = %b, quot = %b, rem = %b",
a, b, rslt[3:0], rslt[7:4]);
//apply
input vectors
initial
begin
#0 start = 1'b0;
a = 8'b0000_1101; b = 4'b0101;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1100; b = 4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a = 8'b0101_0010; b = 4'b0110;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1000; b = 4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_0100; b = 4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_1110; b = 4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 $stop;
end
//instantiate
the module into the test bench
div_restoring_vers2
inst1 (
.a(a),
.b(b),
.start(start),
.rslt(rslt)
);
endmodule
Page 377, Figure
7.17
//behavioral/dataflow
nonrestoring division
module
div_nonrestoring (a, b, start, rslt);
input [7:0]
a;
input [3:0]
b;
input start
;
output [7:0]
rslt;
wire [3:0]
b_bar;
//define
internal registers
reg [3:0]
b_neg;
reg [7:0]
rslt;
reg [3:0]
count;
reg
part_rem_7;
assign b_bar
= ~b;
always @
(b_bar)
b_neg = b_bar + 1;
always @ (posedge start)
begin
rslt
= a;
count = 4'b0100;
part_rem_7 = 1'b0;
if
((a!=0) && (b!=0))
begin
rslt
= rslt << 1;
rslt = {(rslt[7:4] + b_neg),
rslt[3:0]}; //2A–B
if
(rslt[7] == 1)
begin
rslt
= {rslt[7:1], 1'b0};
part_rem_7 = 1'b1;
count = count - 1;
end
else
begin
rslt
= {rslt[7:1], 1'b1};
part_rem_7 = 1'b0;
count = count - 1;
end
end
while
(count)
begin
rslt
= rslt << 1;
if
(part_rem_7 == 1)
begin
rslt = {(rslt[7:4] + b),
rslt[3:0]}; //2A+B
if (rslt[7] == 1)
begin
rslt
= {rslt[7:1], 1'b0};
part_rem_7 = 1'b1;
count
= count - 1;
end
else
begin
rslt
= {rslt[7:1], 1'b1};
part_rem_7 = 1'b0;
count = count - 1;
end
end
else
begin
rslt
= {(rslt[7:4] + b_neg), rslt[3:0]}; //2A–B
if
(rslt[7] == 1)
begin
rslt
= {rslt[7:1], 1'b0};
part_rem_7 = 1'b1;
count = count - 1;
end
else
begin
rslt
= {rslt[7:1], 1'b1};
part_rem_7 = 1'b0;
count = count - 1;
end
end
end
if
(rslt[7] == 1)
rslt = {(rslt[7:4] + b), rslt[3:0]};
end
endmodule
//test
bench for nonrestoring division
module
div_nonrestoring_tb;
//define
inputs
reg [7:0]
a;
reg [3:0]
b;
reg
start;
//define
output
wire [7:0]
rslt;
//display
variables
initial
$monitor
("a = %b, b = %b, quot = %b, rem = %b",
a, b, rslt[3:0], rslt[7:4]);
//apply
input vectors
initial
begin
#0 start = 1'b0;
a = 8'b0000_0111; b = 4'b0011;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0000_1101; b =
4'b0101;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1100; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0101_0010; b =
4'b0110;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0011_1000; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_0100; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 a
= 8'b0110_1110; b =
4'b0111;
#10 start
= 1'b1;
#10 start
= 1'b0;
#10 $stop;
end
//instantiate
the module into the test bench
div_nonrestoring
inst1 (
.a(a),
.b(b),
.start(start),
.rslt(rslt)
);
endmodule
Page 394, Figure
7.23
//behavioral
srt division using table lookup
module
srt_div_tbl_lookup (opnds, quot_rem, ovfl);
input [8:0]
opnds; //dvdnd 6
bits; dvsr 3 bits
output [5:0]
quot_rem;
output ovfl;
wire [8:0]
opnds;
reg [5:0]
quot_rem;
reg ovfl;
//check
for overflow
always @
(opnds)
begin
if
(opnds[8:6] >= opnds[2:0])
ovfl = 1'b1;
else
ovfl
= 1'b0;
end
//define
memory size
//mem_srt
is an array of 512 six-bit registers
reg [5:0]
mem_srt[0:511];
//define
memory contents
//load
mem_srt from file opnds.srt
initial
begin
$readmemb
("opnds.srt", mem_srt);
end
//use
the operands to access memory
always @
(opnds)
begin
quot_rem
= mem_srt [opnds];
end
endmodule
//test
bench for srt division using table lookup
module
srt_div_tbl_lookup_tb;
reg [8:0]
opnds;
wire [5:0]
quot_rem;
wire ovfl;
//display
variables
initial
$monitor
("dvdnd=%b, dvsr=%b, quot=%b, rem=%b, ovfl=%b",
opnds[8:3], opnds[2:0],
quot_rem[5:3], quot_rem[2:0],
ovfl);
//apply
stimulus
initial
begin
#0 opnds = 9'b000110001;
#10 opnds
= 9'b000111010;
#10 opnds
= 9'b010001011;
#10 opnds
= 9'b011101100;
#10 opnds
= 9'b010100011;
#10 opnds
= 9'b100111101;
#10 opnds
= 9'b110011111;
#10 opnds
= 9'b101010110;
#10 opnds
= 9'b110001101; //overflow
#10 opnds
= 9'b101000101; //overflow
#10 $stop;
end
//instantiate
the module into the test bench
srt_div_tbl_lookup
inst1 (
.opnds(opnds),
.quot_rem(quot_rem),
.ovfl(ovfl)
);
endmodule
Page 398, Figure
7.27
//behavioral
srt division using the case statement
module
srt_div_case2 (opnds, quot, rem, ovfl);
input
[11:0] opnds; //dividend 8
bits; divisor 4 bits
output [3:0]
quot, rem;
output ovfl;
wire
[11:0] opnds;
reg [3:0]
quot, rem;
reg ovfl;
//check
for overflow
always @
(opnds)
begin
if
(opnds[11:8] >= opnds[3:0])
ovfl = 1'b1;
else
ovfl
= 1'b0;
end
always @
(opnds)
begin
case
(opnds)
//dvdnd = +6; dvsr = +1; quot = 6; rem = 0
12'b000001100001 : begin
quot = 4'b0110;
rem = 4'b0000;
end
//dvdnd
= +7; dvsr = +2; quot = 3; rem = 1
12'b000001110010 : begin
quot = 4'b0011;
rem = 4'b0001;
end
//dvdnd = +17; dvsr = +3; quot = 5; rem = 2
12'b000100010011
: begin
quot = 4'b0101;
rem = 4'b0010;
end
//dvdnd = +41; dvsr = +3; quot = 13; rem = 2
12'b001010010011 : begin
quot = 4'b1101;
rem = 4'b0010;
end
//dvdnd
= +51; dvsr = +8; quot = 6; rem = 3
12'b001100111000 : begin
quot = 4'b0110;
rem = 4'b0011;
end
//dvdnd
= +72; dvsr = +5; quot = 14; rem = 2
12'b010010000101 : begin
quot = 4'b1110;
rem = 4'b0010;
end
//dvdnd
= +76; dvsr = +6; quot = 12; rem = 4
12'b010011000110 : begin
quot = 4'b1100;
rem = 4'b0100;
end
//dvdnd
= +110; dvsr = +7; quot = 15; rem
= 5
12'b011011100111 : begin
quot = 4'b1111;
rem = 4'b0101;
end
//dvdnd
= +97; dvsr = +5; quot = 19; rem = 2
//overflow occurs
12'b011000010101 : begin
quot = 4'bxxxx;
rem = 4'bxxxx;
end
//dvdnd
= +70; dvsr = +4; quot = 17; rem = 2
//overflow occurs
12'b010001100100 : begin
quot = 4'bxxxx;
rem = 4'bxxxx;
end
default : begin
quot = 4'b0000;
rem = 4'b0000;
end
endcase
end
endmodule
//test
bench for srt division using the case statement
module
srt_div_case_tb;
reg
[11:0] opnds;
wire [3:0]
quot, rem;
wire ovfl;
//display
variables
initial
$monitor
("opnds= %b, quot = %b, rem = %b, ovfl = %b",
opnds, quot, rem, ovfl);
//apply
stimulus
initial
begin
//dvdnd
= +6; dvsr = +1; quot = 6; rem = 0
#0 opnds
= 12'b000001100001;
//dvdnd
= +7; dvsr = +2; quot = 3; rem = 1
#10 opnds
= 12'b000001110010;
//dvdnd = +17; dvsr = +3; quot
= 5; rem = 2
#10 opnds
= 12'b000100010011;
//dvdnd = +41; dvsr = +3; quot
= 13; rem = 2
#10 opnds
= 12'b001010010011;
//dvdnd = +51; dvsr = +8; quot
= 6; rem = 3
#10 opnds
= 12'b001100111000;
//dvdnd = +72; dvsr = +5; quot
= 14; rem = 2
#10 opnds
= 12'b010010000101;
//dvdnd = +76; dvsr = +6; quot
= 12; rem = 4
#10 opnds
= 12'b010011000110;
//dvdnd = +110; dvsr = +7; quot
= 15; rem = 5
#10 opnds
= 12'b011011100111;
//dvdnd = +97; dvsr = +5; quot
= 19; rem = 2
//overflow occurs
#10 opnds
= 12'b011000010101;
//dvdnd = +70; dvsr = +4; quot
= 17; rem = 2
//overflow occurs
#10 opnds
= 12'b010001100100;
#10 $stop;
end
//instantiate
the module into the test bench
srt_div_case2
inst1 (
.opnds(opnds),
.quot(quot),
.rem(rem),
.ovfl(ovfl)
);
endmodule
Page 413, Figure
7.35
//dataflow
full adder
module
full_adder (a, b, cin, sum, cout);
input a, b,
cin;
output sum,
cout;
assign sum =
(a ^ b) ^ cin;
assign cout
= cin & (a ^ b) | (a & b);
endmodule
//structural
full adder for an array divide
module
full_adder_div_array (a, bin, cin, modein,
sum, cout,
bout, modeout);
input a,
bin, cin, modein;
output sum,
cout, bout, modeout;
wire net1; //define internal net
//instantiate
the logic
xor2_df
inst1 (
.x1(modein),
.x2(bin),
.z1(net1)
);
full_adder
inst2 (
.a(net1),
.b(a),
.cin(cin),
.sum(sum),
.cout(cout)
);
buf inst3
(modeout, modein);
buf inst4
(bout, bin);
endmodule
//test
bench for the full adder cell used in the array divider
module
full_adder_div_array_tb;
reg a,
bin, cin, modein;
wire sum,
cout, bout, modeout;
initial //apply
stimulus
begin :
apply_stimulus
reg
[4:0] invect;
for
(invect = 0; invect < 16; invect = invect + 1)
begin
{a,
bin, cin, modein} = invect [4:0];
#10 $display ("a=%b, bin=%b, cin=%b, modein=%b,
sum=%b, cout=%b,
bout=%b, modeout=%b",
a, bin, cin, modein, sum,
cout, bout, modeout);
end
end
full_adder_div_array
inst1 ( //instantiate
the module
.a(a),
.bin(bin),
.cin(cin),
.modein(modein),
.sum(sum),
.cout(cout),
.bout(bout),
.modeout(modeout)
);
endmodule
//dataflow
for a 4-bit adder
module
adder4_df (a, b, cin, sum, cout);
//list
inputs and outputs
input [3:0]
a, b;
input cin;
output [3:0]
sum;
output cout;
//define
signals as wire for dataflow (or default to wire)
wire [3:0]
a, b;
wire cin,
cout;
wire [3:0]
sum;
//continuous
assignment for dataflow
//implement
the 4-bit adder as a logic equation
//...concatenating
cout and sum
assign
{cout, sum} = a + b + cin;
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
//structural
array divide
module
div_array2 (a, b, mode, q, r);
input [6:0]
a;
input [3:0]
b;
input mode;
output [3:0]
q, r;
wire [6:0]
a;
wire [3:0]
b;
wire mode;
wire [3:0]
q, r;
//define
internal nets
wire mode1,
mode2, mode3, mode4, mode5, mode6, mode7, mode8,
mode9, mode10, mode11, mode12, mode13,
mode14, mode15,
mode16,
cout1, cout2, cout3, cout4, cout5,
cout6, cout7, cout8,
cout9, cout10, cout11, cout12, cout13,
cout14, cout15,
cout16,
bout1, bout2, bout3, bout4, bout5,
bout6, bout7, bout8,
bout9, bout10, bout11, bout12, bout13,
bout14, bout15,
bout16,
sum2, sum3, sum4, sum6, sum7, sum8,
sum10,
sum11, sum12, sum13, sum14, sum15,
sum16,
sum17_0, sum17_1, sum17_2, sum17_3;
//instantiate
the logic for the array divider
//instantiate
the array of full adders
full_adder_div_array
inst1 (
.a(a[6]),
.bin(b[3]),
.cin(cout2),
.modein(mode),
.cout(cout1),
.bout(bout1),
.modeout(mode1)
);
full_adder_div_array
inst2 (
.a(a[5]),
.bin(b[2]),
.cin(cout3),
.modein(mode1),
.sum(sum2),
.cout(cout2),
.bout(bout2),
.modeout(mode2)
);
full_adder_div_array
inst3 (
.a(a[4]),
.bin(b[1]),
.cin(cout4),
.modein(mode2),
.sum(sum3),
.cout(cout3),
.bout(bout3),
.modeout(mode3)
);
full_adder_div_array
inst4 (
.a(a[3]),
.bin(b[0]),
.cin(mode4),
.modein(mode3),
.sum(sum4),
.cout(cout4),
.bout(bout4),
.modeout(mode4)
);
full_adder_div_array
inst5 (
.a(sum2),
.bin(bout1),
.cin(cout6),
.modein(cout1),
.cout(cout5),
.bout(bout5),
.modeout(mode5)
);
full_adder_div_array
inst6 (
.a(sum3),
.bin(bout2),
.cin(cout7),
.modein(mode5),
.sum(sum6),
.cout(cout6),
.bout(bout6),
.modeout(mode6)
);
full_adder_div_array
inst7 (
.a(sum4),
.bin(bout3),
.cin(cout8),
.modein(mode6),
.sum(sum7),
.cout(cout7),
.bout(bout7),
.modeout(mode7)
);
full_adder_div_array
inst8 (
.a(a[2]),
.bin(bout4),
.cin(mode8),
.modein(mode7),
.sum(sum8),
.cout(cout8),
.bout(bout8),
.modeout(mode8)
);
full_adder_div_array
inst9 (
.a(sum6),
.bin(bout5),
.cin(cout10),
.modein(cout5),
.cout(cout9),
.bout(bout9),
.modeout(mode9)
);
full_adder_div_array
inst10 (
.a(sum7),
.bin(bout6),
.cin(cout11),
.modein(mode9),
.sum(sum10),
.cout(cout10),
.bout(bout10),
.modeout(mode10)
);
full_adder_div_array
inst11 (
.a(sum8),
.bin(bout7),
.cin(cout12),
.modein(mode10),
.sum(sum11),
.cout(cout11),
.bout(bout11),
.modeout(mode11)
);
full_adder_div_array
inst12 (
.a(a[1]),
.bin(bout8),
.cin(mode12),
.modein(mode11),
.sum(sum12),
.cout(cout12),
.bout(bout12),
.modeout(mode12)
);
full_adder_div_array
inst13 (
.a(sum10),
.bin(bout9),
.cin(cout14),
.modein(cout9),
.sum(sum13),
.cout(cout13),
.bout(bout13),
.modeout(mode13)
);
full_adder_div_array
inst14 (
.a(sum11),
.bin(bout10),
.cin(cout15),
.modein(mode13),
.sum(sum14),
.cout(cout14),
.bout(bout14),
.modeout(mode14)
);
full_adder_div_array
inst15 (
.a(sum12),
.bin(bout11),
.cin(cout16),
.modein(mode14),
.sum(sum15),
.cout(cout15),
.bout(bout15),
.modeout(mode15)
);
full_adder_div_array
inst16 (
.a(a[0]),
.bin(bout12),
.cin(mode16),
.modein(mode15),
.sum(sum16),
.cout(cout16),
.bout(bout16),
.modeout(mode16)
);
//instantiate
the 4-input adder
adder4_df
inst17 (
.a({sum13, sum14, sum15, sum16}),
.b({bout13, bout14, bout15, bout16}),
.cin(1'b0),
.sum({sum17_3, sum17_2, sum17_1, sum17_0})
);
//instantiate
the 2:1 multiplexers
mux2_df
inst18 (
.sel(cout13),
.data({sum13, sum17_3}),
.z1(r[3])
);
mux2_df
inst19 (
.sel(cout13),
.data({sum14, sum17_2}),
.z1(r[2])
);
mux2_df
inst20 (
.sel(cout13),
.data({sum15, sum17_1}),
.z1(r[1])
);
mux2_df
inst21 (
.sel(cout13),
.data({sum16, sum17_0}),
.z1(r[0])
);
//assign
the quotient outputs
assign q[3]
= cout1,
q[2] = cout5,
q[1] = cout9,
q[0] = cout13;
endmodule
//test
bench for array divider
module
div_array2_tb;
reg [6:0]
a;
reg [3:0]
b;
reg mode;
wire [3:0]
q, r;
//display
inputs and outputs
initial
$monitor
("dvdnd = %b, dvsr = %b, quot = %b, rem = %b",
a, b, q, r);
//apply
input vectors
initial
begin
#0 a = 7'b1101110; b = 4'b0111; mode =
1'b1;
#10 a
= 7'b0001110; b = 4'b0011; mode = 1'b1;
#10 a
= 7'b0000111; b = 4'b0011; mode = 1'b1;
#10 a
= 7'b0110011; b = 4'b0111; mode = 1'b1;
#10 a
= 7'b0000110; b = 4'b0001; mode = 1'b1;
#10 a = 7'b0000111; b = 4'b0010; mode =
1'b1;
#10 a
= 7'b0010001; b = 4'b0011; mode = 1'b1;
#10 a
= 7'b0101001; b = 4'b0011; mode = 1'b1;
#10 a = 7'b1001100; b = 4'b0110; mode =
1'b1;
#10 a
= 7'b1101110; b = 4'b0111; mode = 1'b1;
#10 a
= 7'b0111111; b = 4'b0100; mode = 1'b1;
#10 a
= 7'b0100101; b = 4'b0101; mode = 1'b1;
#10 $stop;
end
//instantiate
the module into the test bench
div_array2
inst1 (
.a(a),
.b(b),
.mode(mode),
.q(q),
.r(r)
);
endmodule
Computer
Arithmetic
and
Verilog HDL
Fundamentals
Chapter 8
Decimal Addition
Verilog Code
Figures
Page 433, Figure
8.3
//mixed-design
bcd adder
module
add_bcd (a, b, cin, bcd, cout, invalid_inputs);
//define
inputs and outputs
input [3:0]
a, b;
input cin;
output [3:0]
bcd;
output cout,
invalid_inputs;
reg
invalid_inputs; //reg
if used in always statement
//define
internal nets
wire [3:0]
sum;
wire
cout3, net3, net4;
//check
for invalid inputs
always @ (a or b)
begin
if
((a > 4'b1001) || (b > 4'b1001)) //||
is logical or
invalid_inputs = 1'b1;
else
invalid_inputs
= 1'b0;
end
//instantiate
the logic for adder_1
adder4
inst1 (
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.sum(sum[3:0]),
.cout(cout3)
);
//instantiate
the logic for adder_2
adder4
inst2 (
.a(sum[3:0]),
.b({1'b0, cout, cout, 1'b0}),
.cin(1'b0),
.sum(bcd[3:0])
);
//instantiate
the logic for intermediate sum adjustment
and2_df
inst3 (
.x1(sum[3]),
.x2(sum[1]),
.z1(net3)
);
and2_df
inst4 (
.x1(sum[3]),
.x2(sum[2]),
.z1(net4)
);
or3_df
inst5 (
.x1(cout3),
.x2(net3),
.x3(net4),
.z1(cout)
);
endmodule
//test
bench for mixed-design add_bcd
module
add_bcd_tb;
reg [3:0]
a, b;
reg cin;
wire [3:0]
bcd;
wire cout,
invalid_inputs;
//display
variables
initial
$monitor
("a=%b, b=%b, cin=%b,
cout=%b, bcd=%b,
invalid_inputs=%b",
a, b, cin, cout, bcd,
invalid_inputs);
//apply
input vectors
initial
begin
#0 a = 4'b0011; b
= 4'b0011; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0110; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0100; cin = 1'b0;
#10 a
= 4'b0111; b = 4'b1000; cin = 1'b0;
#10 a
= 4'b0111; b = 4'b0111; cin = 1'b0;
#10 a
= 4'b1000; b = 4'b1001; cin = 1'b0;
#10 a
= 4'b1001; b = 4'b1001; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0110; cin = 1'b1;
#10 a
= 4'b0111; b = 4'b1000; cin = 1'b1;
#10 a
= 4'b1001; b = 4'b1001; cin = 1'b1;
#10 a
= 4'b1000; b = 4'b1000; cin = 1'b0;
#10 a
= 4'b1000; b = 4'b1000; cin = 1'b1;
#10 a
= 4'b1001; b = 4'b0111; cin = 1'b0;
#10 a
= 4'b0111; b = 4'b0010; cin = 1'b1;
#10 a
= 4'b0011; b = 4'b1000; cin = 1'b0;
//invalid inputs
#10 a
= 4'b1010; b = 4'b0001; cin = 1'b0;
//invalid inputs
#10 a
= 4'b0011; b = 4'b1100; cin = 1'b0;
//invalid inputs
#10 a
= 4'b1011; b = 4'b1110; cin = 1'b1;
#10 $stop;
end
//instantiate
the module into the test bench
add_bcd
inst1 (
.a(a),
.b(b),
.cin(cin),
.bcd(bcd),
.cout(cout),
.invalid_inputs(invalid_inputs)
);
endmodule
Page 439, Figure
8.9
//dataflow
carry lookahead adder
module
adder4_cla (a, b, cin, sum, cout);
//i/o
port declaration
input [3:0]
a, b;
input cin;
output [3:0]
sum;
output cout;
//define
internal wires
wire g3,
g2, g1, g0;
wire p3,
p2, p1, p0;
wire c3,
c2, c1, c0;
//define
generate functions
assign g0
= a[0] & b[0], //multiple
statements with 1 assign
g1 = a[1] & b[1],
g2 = a[2] & b[2],
g3 = a[3] & b[3];
//define
propagate functions
assign p0
= a[0] ^ b[0], //multiple statements
with 1 assign
p1 = a[1] ^ b[1],
p2 = a[2] ^ b[2],
p3 = a[3] ^ b[3];
//obtain
the carry equations
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 sum equations
assign sum[0]
= p0 ^ cin,
sum[1] = p1 ^ c0,
sum[2] = p2 ^ c1,
sum[3] = p3 ^ c2;
//obtain
cout
assign cout
= c3;
endmodule
//dataflow
2:1 multiplexer
module
mux2_df (sel, data, z1);
input sel; //define inputs and output
input [1:0]
data;
output z1;
assign z1 =
(~sel & data[0]) | (sel & data[1]);
endmodule
//mixed-design
bcd adder using multiplexers
module
add_bcd_mux3 (a, b, cin, bcd, cout, invalid_inputs);
//define
inputs and outputs
input [3:0]
a, b;
input cin;
output [3:0]
bcd;
output cout,
invalid_inputs;
//continued
on next page
reg
invalid_inputs; //reg
if used in always statement
//define
internal nets
wire [3:0]
adder_1, adder_2;
wire
cout3, cout8;
//check
for invalid inputs
always @ (a or b)
begin
if
((a > 4'b1001) || (b > 4'b1001))
invalid_inputs = 1'b1;
else
invalid_inputs
= 1'b0;
end
//instantiate
the adder for adder_1
adder4_cla
inst1 (
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.sum(adder_1),
.cout(cout3)
);
//instantiate
the adder for adder_2
adder4_cla
inst2 (
.a(adder_1),
.b({1'b0, 1'b1, 1'b1, 1'b0}),
.cin(1'b0),
.sum(adder_2),
.cout(cout8)
);
//instantiate
the multiplexer select logic
or2_df
inst3 (
.x1(cout8),
.x2(cout3),
.z1(cout)
);
//instantiate
the 2:1 multiplexers
mux2_df
inst4 (
.sel(cout),
.data({adder_2[0], adder_1[0]}),
.z1(bcd[0])
);
mux2_df
inst5 (
.sel(cout),
.data({adder_2[1], adder_1[1]}),
.z1(bcd[1])
);
mux2_df
inst6 (
.sel(cout),
.data({adder_2[2], adder_1[2]}),
.z1(bcd[2])
);
mux2_df
inst7 (
.sel(cout),
.data({adder_2[3], adder_1[3]}),
.z1(bcd[3])
);
endmodule
//test
bench mixed-design bcd adder using multiplexers
module
add_bcd_mux3_tb;
reg [3:0]
a, b;
reg cin;
wire [3:0]
bcd;
wire cout,
invalid_inputs;
initial //display variables
$monitor
("a=%b, b=%b, cin=%b,
cout=%b, bcd=%b,
invalid_inputs=%b",
a, b, cin, cout, bcd,
invalid_inputs);
initial //apply input vectors
begin
#0 a = 4'b0011; b
= 4'b0011; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0110; cin = 1'b0;
#10 a
= 4'b0111; b = 4'b1000; cin = 1'b0;
#10 a
= 4'b0111; b = 4'b0111; cin = 1'b0;
#10 a
= 4'b1000; b = 4'b1001; cin = 1'b0;
#10 a
= 4'b1001; b = 4'b1001; cin = 1'b0;
#10 a
= 4'b0101; b = 4'b0110; cin = 1'b1;
#10 a = 4'b0111; b
= 4'b1000; cin = 1'b1;
#10 a
= 4'b1001; b = 4'b1001; cin = 1'b1;
#10 a
= 4'b0111; b = 4'b1011; cin = 1'b0; //invalid inputs
#10 a
= 4'b1111; b = 4'b1000; cin = 1'b0; //invalid inputs
#10 a
= 4'b1101; b = 4'b1010; cin = 1'b1; //invalid inputs
#10 $stop;
end
//instantiate
the module into the test bench
add_bcd_mux3
inst1 (
.a(a),
.b(b),
.cin(cin),
.bcd(bcd),
.cout(cout),
.invalid_inputs(invalid_inputs)
);
endmodule
Page 449, Figure
8.16
//mixed-design
for bcd addition using memories
module
add_bcd_rom (a, b, cin, bcd_rslt, invalid_inputs);
input [7:0]
a, b;
input cin;
output [8:0]
bcd_rslt;
output
invalid_inputs;
wire [7:0]
a, b;
wire cin;
reg [8:0]
bcd_rslt;
reg
invalid_inputs;
//define
internal nets
wire [3:0]
adder_1, adder_2;
wire
cout1, cout4, cout5, cout8;
wire net2,
net3, net6, net7;
//check
for invalid inputs
always @ (a or b)
begin
if
((a[7:4] > 4'b1001) || (a[3:0] > 4'b1001) ||
(b[7:4] > 4'b1001) || (b[3:0] >
4'b1001))
invalid_inputs = 1'b1;
else
invalid_inputs
= 1'b0;
end
//instantiate
the 4-bit adder for the units decade
adder4_cla
inst1 (
.a(a[3:0]),
.b(b[3:0]),
.cin(1'b0),
.sum(adder_1),
.cout(cout1)
);
//instantiate
the logic for the carry-out from the units decade
and2_df
inst2 (
.x1(adder_1[3]),
.x2(adder_1[1]),
.z1(net2)
);
and2_df
inst3 (
.x1(adder_1[3]),
.x2(adder_1[2]),
.z1(net3)
);
or3_df
inst4 (
.x1(cout1),
.x2(net2),
.x3(net3),
.z1(cout4)
);
//instantiate
the 4-bit adder for the tens decade
adder4_cla
inst5 (
.a(a[7:4]),
.b(b[7:4]),
.cin(cout4),
.sum(adder_2),
.cout(cout5)
);
//instantiate
the logic for the carry-out from the tens decade
and2_df
inst6 (
.x1(adder_2[3]),
.x2(adder_2[1]),
.z1(net6)
);
and2_df
inst7 (
.x1(adder_2[3]),
.x2(adder_2[2]),
.z1(net7)
);
or3_df
inst8 (
.x1(cout5),
.x2(net6),
.x3(net7),
.z1(cout8)
);
//define
memory size for units decade
//mem_bcd01
is an array of 32 four-bit registers
reg [3:0]
mem_bcd01[0:31];
//define
memory size for tens decade
//mem_bcd10
is an array of 32 four-bit registers
reg [3:0]
mem_bcd10[0:31];
//define
memory contents for units decade
//load
mem_bcd01 from file addbcd.rom01
initial
begin
$readmemb
("addbcd.rom01", mem_bcd01);
end
//define
memory contents for tens decade
//load
mem_bcd10 from file addbcd.rom10
initial
begin
$readmemb
("addbcd.rom10", mem_bcd10);
end
//obtain
the bcd result
always @ (a or b)
begin
bcd_rslt[3:0]
= mem_bcd01[{cout4, adder_1}];
bcd_rslt[7:4] = mem_bcd10[{cout8,
adder_2}];
bcd_rslt[8] = cout8;
end
endmodule
//test
bench for bcd addition using memories
module
add_bcd_rom_tb;
reg [7:0]
a, b;
reg cin;
wire [8:0]
bcd_rslt;
wire
invalid_inputs;
//display
variables
initial
$monitor
("a=%b, b=%b, bcd_hun=%b, bcd_ten=%b, bcd_unit=%b,
invalid_inputs=%b",
a, b, {{3{1'b0}}, bcd_rslt[8]},
bcd_rslt[7:4],
bcd_rslt[3:0],
invalid_inputs);
//replication
operator {3{1'b0}} provides 4 bits for hundreds
initial //apply
input vectors
begin
#0 a
= 8'b1001_1000; b = 8'b1001_1000; //98 + 98 = 196
#10 a
= 8'b0111_0001; b = 8'b1000_0001; //71 + 81 = 152
#10 a
= 8'b0110_0010; b = 8'b0111_0100; //62 + 74 = 136
#10 a
= 8'b1001_0111; b = 8'b1001_1000; //97 + 98 = 195
#10 a
= 8'b0010_0011; b = 8'b0111_0101; //23 + 75 = 098
#10 a
= 8'b1001_1001; b = 8'b1001_1001; //99 + 99 = 198
#10 a
= 8'b0110_0101; b = 8'b0011_1000; //65 + 38 = 103
#10 a
= 8'b0101_0010; b = 8'b0011_0111; //52 + 37 = 089
#10 a
= 8'b0111_1011; b = 8'b1001_0011; //invalid inputs
#10 a
= 8'b1111_0110; b = 8'b1000_1010; //invalid inputs
#10 a
= 8'b1101_1100; b = 8'b1010_1100; //invalid inputs
#10 $stop;
end
//instantiate
the module into the test bench
add_bcd_rom
inst1 (
.a(a),
.b(b),
.cin(cin),
.bcd_rslt(bcd_rslt),
.invalid_inputs(invalid_inputs)
);
endmodule
Page 456, Figure
8.20
//behavioral
for a 2-digit bcd adder with biased augend
module
add_bcd_biased (a, b, cin, cout_tens, bcd);
input [7:0]
a, b;
input cin;
output [7:0]
bcd;
output
cout_tens;
//variables
are declared as reg if used in always
reg [7:0]
a_biased;
reg [4:0]
sum_units;
reg [8:4]
sum_tens;
reg
cout_units, cout_tens;
reg
bcd[7:0];
always @ (a or b)
begin
a_biased[3:0]
= (a[3:0] + 4'b0110); //add bias
sum_units = (a_biased[3:0] + b[3:0] +
cin);
cout_units = sum_units[4];
a_biased[7:4] = (a[7:4] + 4'b0110); //add bias
sum_tens = (a_biased[7:4] + b[7:4]+
cout_units);
cout_tens = sum_tens[8];
if
(cout_units == 1'b0)
bcd[3:0] = sum_units[3:0] + 4'b1010; //unbias
else
bcd[3:0]
= sum_units[3:0];
if
(cout_tens == 1'b0)
bcd[7:4] = sum_tens[7:4] + 4'b1010; //unbias
else
bcd[7:4]
= sum_tens[7:4];
end
endmodule
//test
bench for bcd addition using a biased augend
module
add_bcd_biased_tb;
reg [7:0]
a, b;
reg cin;
wire [7:0]
bcd;
wire
cout_tens;
//display
variables
initial
$monitor
("a_tens=%b, a_units=%b, b_tens=%b, b_units=%b,
cin=%b, cout=%b, bcd_tens=%b,
bcd_units=%b",
a[7:4], a[3:0], b[7:4], b[3:0],
cin, {{3{1'b0}}, cout_tens},
bcd[7:4], bcd[3:0]);
//apply
input vectors
initial
begin
//63
+ 36 + 0 = 099
#0 a
= 8'b0110_0011; b = 8'b0011_0110; cin = 1'b0;
//25 + 52 + 0 = 077
#10 a
= 8'b0010_0101; b = 8'b0101_0010; cin = 1'b0;
//63 + 75 + 1 = 139
#10 a
= 8'b0110_0011; b = 8'b0111_0101; cin = 1'b1;
//79 + 63 + 0 = 142
#10 a
= 8'b0111_1001; b = 8'b0110_0011; cin = 1'b0;
//99 + 99 + 1 = 199
#10 a
= 8'b1001_1001; b = 8'b1001_1001; cin = 1'b1;
//27 + 63 + 0 = 090
#10 a
= 8'b0010_0111; b = 8'b0110_0011; cin = 1'b0;
//63 + 27 + 1 = 091
#10 a
= 8'b0110_0011; b = 8'b0010_0111; cin = 1'b1;
//44 + 85 + 0 = 129
#10 a
= 8'b0100_0100; b = 8'b1000_0101; cin = 1'b0;
//86 + 88 + 0 = 174
#10 a
= 8'b1000_0110; b = 8'b1000_1000; cin = 1'b0;
#10 $stop;
end
//instantiate
the module into the test bench
add_bcd_biased
inst1 (
.a(a),
.b(b),
.cin(cin),
.cout_tens(cout_tens),
.bcd(bcd)
);
endmodule
No comments:
Post a Comment