Saturday, 12 April 2014

chapter 10



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