Saturday, 12 April 2014

vlsi book next chapter



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