Computer
Arithmetic
and
Verilog HDL
Fundamentals
Chapter 10
Decimal
Multiplication
Verilog Code
Figures
Page 496, Figure
10.2
//behavioral
bcd multiplier
module
mul_bcd_behav (a, b, bcd);
input [7:0]
a;
input [3:0]
b;
output
[11:0] bcd;
reg
[11:0] a_reg, b_reg;
reg
[23:0] shift_reg;
reg [3:0]
shift_ctr;
always @ (a or b)
begin
shift_ctr
= 4'b1011; //11 shift
sequences
a_reg = 12'b0000_0000_0000; //reset register a
b_reg = a * b; //register b contains product
shift_reg = {a_reg, b_reg};
while
(shift_ctr)
begin
shift_reg
= shift_reg << 1;
if
(shift_reg[15:12] > 4'b0100)
shift_reg[15:12] =
shift_reg[15:12] + 4'b0011;
if (shift_reg[19:16] > 4'b0100)
shift_reg[19:16] =
shift_reg[19:16] + 4'b0011;
if (shift_reg[23:20] > 4'b0100)
shift_reg[23:20] =
shift_reg[23:20] + 4'b0011;
shift_ctr = shift_ctr - 1;
end
shift_reg
= shift_reg << 1;
end
assign bcd =
shift_reg[23:12];
endmodule
//test
bench for bcd multiplier
module
mul_bcd_behav_tb;
reg [7:0]
a;
reg [3:0]
b;
wire
[11:0] bcd;
//display
variables
initial
$monitor
("a=%b, b=%b, bcd=%b", a, b, bcd);
//apply
input vectors
initial
begin
//99
x 9 = 891
#0 a
= 8'b0110_0011; b = 4'b1001;
//45 x 6 = 270
#10 a
= 8'b0010_1101; b = 4'b0110;
//77 x 7 = 539
#10 a
= 8'b0100_1101; b = 4'b0111;
//89 x 8 = 712
#10 a
= 8'b0101_1001; b = 4'b1000;
//37 x 6 = 222
#10 a
= 8'b0010_0101; b = 4'b0110;
//99 x 9 = 891
#10 a
= 8'd99; b = 4'd9;
//37 x 6 = 222
#10 a
= 8'd37; b = 4'd6;
#10 $stop;
end
//instantiate
the module into the test bench
mul_bcd_behav
inst1 (
.a(a),
.b(b),
.bcd(bcd)
);
endmodule
Page 501, Figure
10.8
//behavioral
8 bits times 4 bits
module
mul_8x4 (a, b, prod);
input [7:0]
a;
input [3:0]
b;
output
[11:0] prod;
reg
[11:0] prod;
always @ (a or b)
begin
prod
= a * b;
end
endmodule
//behavioral
parallel-in, serial-out left shift register
module
shift_left_reg_piso12 (rst_n, clk, ser_in,
load, data_in,
q);
input
rst_n, clk, ser_in, load;
input
[11:0] data_in;
output
[11:0] q;
reg
[11:0] q;
always @
(rst_n)
begin
if
(rst_n == 0)
q <= 12'h000;
end
always @ (posedge clk)
begin
q[11] <= ((load && data_in[11]) ||
(~load && q[10]));
q[10] <= ((load && data_in[10]) ||
(~load && q[9]));
q[9]
<= ((load && data_in[9])
|| (~load && q[8]));
q[8]
<= ((load && data_in[8])
|| (~load && q[7]));
q[7]
<= ((load && data_in[7])
|| (~load && q[6]));
q[6]
<= ((load && data_in[6])
|| (~load && q[5]));
q[5]
<= ((load && data_in[5])
|| (~load && q[4]));
q[4]
<= ((load && data_in[4])
|| (~load && q[3]));
q[3]
<= ((load && data_in[3])
|| (~load && q[2]));
q[2]
<= ((load && data_in[2])
|| (~load && q[1]));
q[1]
<= ((load && data_in[1])
|| (~load && q[0]));
q[0]
<= ((load && data_in[0])
|| (~load && ser_in));
end
endmodule
//dataflow
greater than four detector
module
gt_4_df (x, z);
input [3:0]
x;
output [3:0]
z;
wire [3:0]
x;
wire [3:0]
z;
assign z[3]
= 1'b0,
z[2] = 1'b0,
z[1] = x[3] | (x[2] & x[0]) |
(x[2] & x[1]),
z[0] = x[3] | (x[2] & x[0]) |
(x[2] & x[1]);
endmodule
//test
bench for greater than four detector
module
gt_4_df_tb;
reg [3:0]
x;
wire [3:0]
z;
//apply
input vectors and display variables
initial
begin:
apply_stimulus
reg
[4:0] invect;
for
(invect = 0; invect < 16; invect = invect + 1)
begin
x
= invect [4:0];
#10 $display ("x3 x2 x1 x0 = %b, z3 z2 z1 z0 = %b",
x, z);
end
end
//instantiate
the module into the test bench
gt_4_df
inst1 (
.x(x),
.z(z)
);
endmodule
//behavioral
model for a 4-bit adder
module
adder4 (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;
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
//structural
bcd multiplier
module
mul_bcd_struc (rst_n, clk_a, clk_b, load_a, load_b,
a, b);
input [7:0]
a;
input [3:0]
b;
input
rst_n, clk_a, clk_b, load_a, load_b;
//define
internal nets
wire
[11:0] prod;
wire [3:0]
a_reg_11_8, a_reg_7_4, a_reg_3_0;
wire [3:0]
net4, net5, net6, net7, net8, net9;
wire
[11:0] b_reg;
//define
internal register
reg
[11:0] a_reg;
assign
b_reg_11 = b_reg[11];
//instantiate
the multiplier
mul_8x4
inst1 (
.a(a),
.b(b),
.prod(prod)
);
//instantiate
the parallel-in, serial-out
//11-bit
left-shift register a_reg
shift_left_reg_piso12
inst2 (
.rst_n(rst_n),
.clk(clk_a),
.ser_in(b_reg_11),
.load(load_a),
.data_in({net9, net7, net5}),
.q({a_reg_11_8, a_reg_7_4, a_reg_3_0})
);
//instantiate
the parallel-in, serial-out
//11-bit
left-shift register b_reg
shift_left_reg_piso12
inst3 (
.rst_n(rst_n),
.clk(clk_b),
.ser_in(1'b0),
.load(load_b),
.data_in(prod),
.q(b_reg)
);
//instantiate
the greater-than-four detectors
//and
the 4-bit adders
gt_4_df
inst4 (
.x(a_reg_3_0),
.z(net4)
);
adder4
inst5 (
.a(a_reg_3_0),
.b(net4),
.cin(1'b0),
.sum(net5)
);
gt_4_df
inst6 (
.x(a_reg_7_4),
.z(net6)
);
adder4
inst7 (
.a(a_reg_7_4),
.b(net6),
.cin(1'b0),
.sum(net7)
);
gt_4_df
inst8 (
.x(a_reg_11_8),
.z(net8)
);
adder4
inst9 (
.a(a_reg_11_8),
.b(net8),
.cin(1'b0),
.sum(net9)
);
endmodule
//test
bench for structural bcd multiplier
module
mul_bcd_struc_tb;
reg [7:0]
a;
reg [3:0]
b;
reg
rst_n, clk_a, clk_b, load_a, load_b;
//apply
input vectors
initial
begin
#0 rst_n = 1'b0;
a = 8'b0000_0000; b = 8'b0000_0000;
clk_a = 1'b0; clk_b = 1'b0;
load_a = 1'b0; load_b = 1'b0;
#5 rst_n
= 1'b1; //#5
//99 x 9 = 891
a = 8'b0110_0011; b = 4'b1001;
#5 load_b
= 1'b1; //#10
#5 clk_b
= 1'b1; //#15, ld b_reg
with prod
#5 load_b
= 1'b0; //#20
#5 clk_b
= 1'b0; //#25
//sequence
1 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#35, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#45
#10 load_a
= 1'b1; //#55
#5 clk_a
= 1'b1; //#60, load
a_reg
#5 load_a
= 1'b0; //#65
#5 clk_a
= 1'b0; //#70
//sequence
2 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#80, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#90
#10 load_a
= 1'b1; //#100
#5 clk_a
= 1'b1; //#105, load
a_reg
#5 load_a
= 1'b0; //#110
#5 clk_a
= 1'b0; //#115
//sequence
3 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#35, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#45
#10 load_a
= 1'b1; //#55
#5 clk_a
= 1'b1; //#60, load
a_reg
#5 load_a
= 1'b0; //#65
#5 clk_a
= 1'b0; //#70
//sequence
4 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#80, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#90
#10 load_a
= 1'b1; //#100
#5 clk_a
= 1'b1; //#105, load
a_reg
#5 load_a
= 1'b0; //#110
#5 clk_a
= 1'b0; //#115
//sequence
5 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#125, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#135
#10 load_a
= 1'b1; //#145
#5 clk_a
= 1'b1; //#150, load
a_reg
#5 load_a
= 1'b0; //#155
#5 clk_a
= 1'b0; //#160
//sequence
6 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#170, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#180
#10 load_a
= 1'b1; //#190
#5 clk_a
= 1'b1; //#195, load
a_reg
#5 load_a
= 1'b0; //#200
#5 clk_a
= 1'b0; //#205
//sequence
7 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#215, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#225
#10 load_a
= 1'b1; //#235
#5 clk_a
= 1'b1; //#240, load
a_reg
#5 load_a
= 1'b0; //#245
#5 clk_a
= 1'b0; //#250
//sequence
8 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#260, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#270
#10 load_a
= 1'b1; //#280
#5 clk_a
= 1'b1; //#285, load
a_reg
#5 load_a
= 1'b0; //#290
#5 clk_a
= 1'b0; //#295
//sequence
9 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#305, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#315
#10 load_a
= 1'b1; //#325
#5 clk_a
= 1'b1; //#330, load
a_reg
#5 load_a
= 1'b0; //#335
#5 clk_a
= 1'b0; //#340
//sequence
10 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#350, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#360
#10 load_a
= 1'b1; //#370
#5 clk_a
= 1'b1; //#375, load
a_reg
#5 load_a
= 1'b0; //#380
#5 clk_a
= 1'b0; //#385
//sequence
11 -- shift a_reg & b_reg; load a_reg
#10 clk_a
= 1'b1; clk_b = 1'b1; //#395, shift registers
#10 clk_a
= 1'b0; clk_b = 1'b0; //#405
#10 load_a
= 1'b1; //#415
#5 clk_a
= 1'b1; //#420, load
a_reg
#5 load_a
= 1'b0; //#425
#5 clk_a
= 1'b0; //#430
//sequence
12 -- shift a_reg
#10 clk_a
= 1'b1;
#10 clk_a
= 1'b0;
#10 $stop;
end
//instantiate
the module into the test bench
mul_bcd_struc
inst1 (
.rst_n(rst_n),
.clk_a(clk_a),
.clk_b(clk_b),
.load_a(load_a),
.load_b(load_b),
.a(a),
.b(b)
);
endmodule
Page 519, Figure
10.22
//behavioral
for a bcd adder
module
add_bcd_behav (a, b, cin, bcd, cout);
input [3:0]
a, b;
input cin;
output [3:0]
bcd;
output cout;
reg [3:0]
sum, bcd;
reg
cout3, cout;
always @ (a or b)
begin
{cout3,
sum} = a + b + cin;
cout = (cout3 || (sum[3] &&
sum[1]) || (sum[3] && sum[2]));
bcd = sum + {1'b0, cout, cout, 1'b0};
end
endmodule
//mixed-design
for bcd multiplication using memory
module
mul_bcd_rom2 (a, b, bcd, invalid_inputs);
input [7:0]
a;
input [3:0]
b;
output
[11:0] bcd;
output
invalid_inputs;
wire [7:0]
a;
wire [3:0]
b;
wire
[11:0] bcd;
reg
invalid_inputs;
//define
internal nets
wire [3:0]
net1, net2, net3, net4;
wire
cout1;
//define
internal registers
reg [7:0]
units_reg, tens_reg;
//check
for invalid inputs
always @ (a or b)
begin
if
((a[7:4] > 4'b1001) || (a[3:0] > 4'b1001) ||
(b[3:0] > 4'b1001))
invalid_inputs = 1'b1;
else
invalid_inputs
= 1'b0;
end
//define
memory size for units decade
//mem_mul_bcd01
is an array of 160 eight-bit registers
reg [7:0]
mem_mul_bcd01 [0:159];
//define
memory contents for units decade
//load
file mulbcd.rom01 into memory mem_mul_bcd01
initial
begin
$readmemb
("mulbcd.rom01", mem_mul_bcd01);
end
//define
memory for tens decade
//mem_mul_bcd10
is an array of 160 eight-bit registers
reg [7:0]
mem_mul_bcd10 [0:159];
//define
memory contents for tens decade
//load
file mulbcd.rom10 into memory mem_mul_bcd10
initial
begin
$readmemb
("mulbcd.rom10", mem_mul_bcd10);
end
//load
units_reg and tens_reg
always @ (a or b)
begin
units_reg
= mem_mul_bcd01[{a[3:0], b[3:0]}];
tens_reg = mem_mul_bcd10[{a[7:4],
b[3:0]}];
end
assign net1
= units_reg[3:0],
net2 = units_reg[7:4],
net3 = tens_reg[3:0];
assign #2 net4 = tens_reg[7:4];
//instantiate
the bcd adder for the units decade
add_bcd_behav
inst1 (
.a(net2),
.b(net3),
.cin(1'b0),
.bcd(bcd[7:4]),
.cout(cout1)
);
//instantiate
the bcd adder for the tens decade
add_bcd_behav
inst2 (
.a(net4),
.b(4'b0000),
.cin(cout1),
.bcd(bcd[11:8])
);
assign bcd[3:0]
= net1;
endmodule
//test
bench for bcd multiplication using memory
module
mul_bcd_rom_tb;
reg [7:0]
a;
reg [3:0]
b;
wire
[11:0] bcd;
wire
invalid_inputs;
//display
variables
initial
$monitor
("a=%b, b=%b, bcd=%b, invalid_inputs=%b",
a, b, bcd, invalid_inputs);
//apply
input vectors
initial
begin
//99
x 9 = 891
#15 a
= 8'b1001_1001; b = 4'b1001;
//2 x 3 = 6
#15 a
= 8'b0000_0010; b = 4'b0011;
//77 x 6 = 442
#15 a
= 8'b0111_0111; b = 4'b0110;
//97 x 5 = 485
#15 a
= 8'b1001_0111; b = 4'b0101;
//46 x 7 = 322
#15 a
= 8'b0100_0110; b = 4'b0111;
//55 x 8 = 440
#15 a
= 8'b0101_0101; b = 4'b1000;
//55 x 6 = 330
#15 a = 8'b0101_0101; b = 4'b0110;
//56 x 9 = 504
#15 a
= 8'b0101_0110; b = 4'b1001;
#15 a
= 8'b1100_0011; b = 4'b1001;
#15 $stop;
end
//instantiate
the module into the test bench
mul_bcd_rom2
inst1 (
.a(a),
.b(b),
.bcd(bcd),
.invalid_inputs(invalid_inputs)
);
endmodule
No comments:
Post a Comment