Saturday, 12 April 2014

CHAPTER 14




Computer Arithmetic
and
Verilog HDL Fundamentals

Chapter 14

Floating-Point Multiplication

Verilog Code Figures


































Page 619, Figure 14.4

//behavioral floating-point multiplication
module mul_flp (flp_a, flp_b, sign, exponent,
                  exp_unbiased, exp_sum, prod);

input [31:0] flp_a, flp_b;
output sign;
output [7:0] exponent, exp_unbiased;
output [8:0] exp_sum;
output [22:0] prod;

//variables used in an always block are declared as registers
reg sign_a, sign_b;
reg [7:0] exp_a, exp_b;
reg [7:0] exp_a_bias, exp_b_bias;
reg [8:0] exp_sum;
reg [22:0] fract_a, fract_b;
reg [45:0] prod_dbl;
reg [22:0] prod;
reg sign;
reg [7:0] exponent, exp_unbiased;

//define sign, exponent, and fraction
always @ (flp_a or flp_b)
begin
   sign_a = flp_a[31];
   sign_b = flp_b[31];

   exp_a = flp_a[30:23];
   exp_b = flp_b[30:23];

   fract_a = flp_a[22:0];
   fract_b = flp_b[22:0];

//bias exponents
      exp_a_bias = exp_a + 8'b0111_1111;
      exp_b_bias = exp_b + 8'b0111_1111;

//add exponents
      exp_sum = exp_a_bias + exp_b_bias;

//remove one bias
      exponent = exp_sum - 8'b0111_1111;

      exp_unbiased = exponent - 8'b0111_1111;

//multiply fractions
      prod_dbl = fract_a * fract_b;
      prod = prod_dbl[45:23];

//postnormalize product
      while (prod[22] == 0)
         begin
            prod = prod << 1;
            exp_unbiased = exp_unbiased - 1;
         end
      sign = sign_a ^ sign_b;
end
endmodule
//test bench for floating-point multiplication
module mul_flp_tb;

reg [31:0] flp_a, flp_b;
wire sign;
wire [7:0] exponent, exp_unbiased;
wire [8:0] exp_sum;
wire [22:0] prod;

//display variables
initial
$monitor ("sign = %b, exp_biased = %b, exp_unbiased = %b,
            prod = %b",
            sign, exp_sum, exp_unbiased, prod);

//apply input vectors
initial
begin
         //+5 x +3 = +15
         //          s ----e---- --------------f-------------
   #0    flp_a = 32'b0_0000_0011_1010_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0010_1100_0000_0000_0000_0000_000;

         //+6 x +4 = +24
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0011_1100_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0011_1000_0000_0000_0000_0000_000;

         //-5 x +5 = -25
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b1_0000_0011_1010_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0011_1010_0000_0000_0000_0000_000;

         //+7 x -5 = -35
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0011_1110_0000_0000_0000_0000_000;
         flp_b = 32'b1_0000_0011_1010_0000_0000_0000_0000_000;

         //+25 x +25 = +625
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0101_1100_1000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0101_1100_1000_0000_0000_0000_000;

         //+76 x +55 = +4180
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0111_1001_1000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0110_1101_1100_0000_0000_0000_000;

         //-48 x -17 = +816
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b1_0000_0110_1100_0000_0000_0000_0000_000;
         flp_b = 32'b1_0000_0101_1000_1000_0000_0000_0000_000;

       //+3724 x +853 = +3,176,572
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_1100_1110_1000_1100_0000_0000_000;
         flp_b = 32'b0_0000_1010_1101_0101_0100_0000_0000_000;

   #10   $stop;
end

//instantiate the module into the test bench
mul_flp inst1 (
      .flp_a(flp_a),
      .flp_b(flp_b),
      .sign(sign),
      .exponent(exponent),
      .exp_unbiased(exp_unbiased),
      .exp_sum(exp_sum),
      .prod(prod)
      );

endmodule
















































Page 624, Figure 14.8

//behavioral floating-point multiplication
module mul_flp3 (flp_a, flp_b, start, sign, exponent,
                     exp_unbiased, cout, prod);


input [31:0] flp_a, flp_b;
input start;

output sign;
output [7:0] exponent, exp_unbiased;
output cout;
output [45:0] prod;

//variables used in an always block are declared as registers
reg sign_a, sign_b;
reg [7:0] exp_a, exp_b;
reg [7:0] exp_a_bias, exp_b_bias;
reg [7:0] exp_sum;
reg [22:0] fract_a, fract_b;
reg [22:0] fract_b_reg;
reg sign;
reg [7:0] exponent, exp_unbiased;
reg cout;
reg [45:0] prod;
reg [22:0] product;
reg [4:0] count;

//define sign, exponent, and fraction
always @ (flp_a or flp_b)
begin
      sign_a = flp_a[31];
      sign_b = flp_b[31];

      exp_a = flp_a[30:23];
      exp_b = flp_b[30:23];

      fract_a = flp_a[22:0];
      fract_b = flp_b[22:0];

//bias exponents
      exp_a_bias = exp_a + 8'b0111_1111;
      exp_b_bias = exp_b + 8'b0111_1111;

//add exponents
      exp_sum = exp_a_bias + exp_b_bias;

//remove one bias
      exponent = exp_sum - 8'b0111_1111;

      exp_unbiased = exponent - 8'b0111_1111;
end







//multiply fractions
always @ (posedge start)
      begin
         fract_b_reg = fract_b;
         prod = 0;
         count = 5'b10111;

       if ((fract_a != 0) && (fract_b != 0))
            while (count)
               begin
                  {cout, prod[45:23]} = (({23{fract_b_reg[0]}} &
                                       fract_a) + prod[45:23]);
                  prod = {cout, prod[45:23], prod[22:1]};
                  fract_b_reg = fract_b_reg >> 1;
                  count = count - 1;
               end

         else
            begin
               sign = 1'b0;
               exp_unbiased = 8’h00;
               prod = 0;
            end

//postnormalize result
      if (prod != 0)
         while (prod[45] == 0)
            begin
               prod = prod << 1;
               exp_unbiased = exp_unbiased - 1;
            end

      sign = sign_a ^ sign_b;
end

endmodule
























//test bench for floating-point multiplication
module mul_flp3_tb;

reg [31:0] flp_a, flp_b;
reg start;
wire sign;
wire [7:0] exponent, exp_unbiased;
wire [8:0] exp_sum;
wire [45:0] prod;

initial                 //display variables
$monitor ("sign = %b, exp_unbiased = %b, prod = %b",
               sign, exp_unbiased, prod);

//apply input vectors
initial
begin
   #0    start = 1'b0;
         //+5 x +3 = +15
         //          s ----e---- --------------f-------------
         flp_a = 32'b0_0000_0011_1010_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0010_1100_0000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //+6 x +4 = +24
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0011_1100_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0011_1000_0000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //-5 x +5 = -25
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b1_0000_0011_1010_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0011_1010_0000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //+7 x -5 = -35
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0011_1110_0000_0000_0000_0000_000;
         flp_b = 32'b1_0000_0011_1010_0000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //+25 x +25 = +625
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0101_1100_1000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0101_1100_1000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;



       //+76 x +55 = +4180
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_0111_1001_1000_0000_0000_0000_000;
         flp_b = 32'b0_0000_0110_1101_1100_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //-48 x -17 = +816
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b1_0000_0110_1100_0000_0000_0000_0000_000;
         flp_b = 32'b1_0000_0101_1000_1000_0000_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //+3724 x +853 = +3,176,572
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_1100_1110_1000_1100_0000_0000_000;
         flp_b = 32'b0_0000_1010_1101_0101_0100_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;


         //0 x +853 = +0
         //          s ----e---- --------------f-------------
   #10   flp_a = 32'b0_0000_1100_0000_0000_0000_0000_0000_000;
         flp_b = 32'b0_0000_1010_1101_0101_0100_0000_0000_000;
   #10   start = 1'b1;
   #10   start = 1'b0;

   #20   $stop;

end

//instantiate the module into the test bench
mul_flp3 inst1 (
      .flp_a(flp_a),
      .flp_b(flp_b),
      .start(start),
      .sign(sign),
      .exponent(exponent),
      .exp_unbiased(exp_unbiased),
      .prod(prod)
      );

endmodule






No comments:

Post a Comment