Saturday, 12 April 2014









Computer Arithmetic
and
Verilog HDL Fundamentals

By Joseph Carnaugh


Chapter 3

Introduction to Verilog HDL

Verilog Code Figures





























Page 96, Figure 3.3  

//built-in primitives for a pos equation
module log_eqn_pos_nor2 (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;

nor      inst1 (net1, x1, ~x2),
         inst2 (net2, x2, x3, ~x4),
         inst3 (net3, ~x1, ~x3, x4);

nor      inst4 (z1, net1, net2, net3);

endmodule


//test bench for pos equation
module log_eqn_pos_nor2_tb;

//inputs are reg for test bench
reg x1, x2, x3, x4;

//outputs are wire for test bench
wire z1;

//apply input vectors
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
log_eqn_pos_nor2 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule










Page 99, Figure 3.9

//built-in primitive number range
module num_range3 (x1, x2, x3, x4, z1);

//list inputs and output
input x1, x2, x3, x4;
output z1;

//design the logic using built-in primitives
nand        inst1 (net1, ~x1, x2),
         inst2 (net2, x2, ~x3),
         inst3 (net3, x1, ~x4),
         inst4 (net4, x1, ~x2, x3);
nand        inst5 (z1, net1, net2, net3, net4);
endmodule


//test bench for number range module
module num_range3_tb;

//inputs are reg outputs are wire for test bench
reg x1, x2, x3, x4;
wire z1;

//apply input vectors
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
num_range3 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule











Page 102, Figure 3.14

//built-in primitive 3:8 decoder
module decoder_3to8_bip (x1, x2, x3, enable, z);

input x1, x2, x3, enable;
output [7:0] z;

and      inst0 (z[0], ~x1, ~x2, ~x3, enable),
         inst1 (z[1], ~x1, ~x2, x3, enable),
         inst2 (z[2], ~x1, x2, ~x3, enable),
         inst3 (z[3], ~x1, x2, x3, enable),
         inst4 (z[4], x1, ~x2, ~x3, enable),
         inst5 (z[5], x1, ~x2, x3, enable),
         inst6 (z[6], x1, x2, ~x3, enable),
         inst7 (z[7], x1, x2, x3, enable);

endmodule


//test bench for the 3:8 decoder
module decoder_3to8_bip_tb;

reg x1, x2, x3, enable;
wire [7:0] z;

//display variables
initial
$monitor ("x1 x2 x3 = %b, z = %b", {x1, x2, x3}, z);

//apply input vectors
initial
begin
      #0       enable = 1'b1;
               x1=1'b0;          x2=1'b0;             x3=1'b0;

     #10      x1=1'b0;          x2=1'b0;             x3=1'b1;
      #10      x1=1'b0;          x2=1'b1;             x3=1'b0;
      #10      x1=1'b0;          x2=1'b1;             x3=1'b1;
      #10      x1=1'b1;          x2=1'b0;             x3=1'b0;
      #10      x1=1'b1;          x2=1'b0;             x3=1'b1;
      #10      x1=1'b1;          x2=1'b1;             x3=1'b0;
      #10      x1=1'b1;          x2=1'b1;             x3=1'b1;
      #10      $stop;
end

//instantiate the module into the test bench
decoder_3to8_bip inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .enable(enable),
      .z(z)
      );
endmodule




Page 105, Figure 3.19

//built-in primitives for 3-bit comparator
module comparator3_bip (a2, a1, a0, b2, b1, b0,
                           a_lt_b, a_eq_b, a_gt_b);

input a2, a1, a0, b2, b1, b0;
output a_lt_b, a_eq_b, a_gt_b;

and         inst1 (net1, ~a2, b2);
xnor        inst2 (net2, a2, b2);
xnor        inst3 (net3, a1, b1);
xnor        inst4 (net4, a0, b0);
and         inst5 (net5, a2, ~b2);
and         inst6 (net6, net2, ~a1, b1);
and         inst7 (net7, net2, net3, ~a0, b0);
and         inst9 (net9, net2, a1, ~b1);
and         inst10   (net10, net2, net3, a0, ~b0);

and         inst8 (a_eq_b, net2, net3, net4);
or       inst11   (a_lt_b, net1, net6, net7);
or       inst12   (a_gt_b, net5, net9, net10);

endmodule


//test bench for 3-bit comparator
module comparator3_bip_tb;

reg a2, a1, a0, b2, b1, b0;
wire a_lt_b, a_eq_b, a_gt_b;

//apply input vectors
initial
begin: apply_stimulus
      reg [6:0] invect;
      for (invect=0; invect<64; invect=invect+1)
         begin
            {a2, a1, a0, b2, b1, b0} = invect [6:0];
            #10 $display ("a2 a1 a0 = %b, b2 b1 b0 = %b,
                        a_lt_b = %b, a_eq_b = %b, a_gt_b = %b",
                        {a2, a1, a0}, {b2, b1, b0},
                        a_lt_b, a_eq_b, a_gt_b);
         end
end

//instantiate the module into the test bench
comparator3_bip inst1 (
      .a2(a2),
      .a1(a1),
      .a0(a0),
      .b2(b2),
      .b1(b1),
      .b0(b0),
      .a_lt_b(a_lt_b),
      .a_eq_b(a_eq_b),
      .a_gt_b(a_gt_b)
      );
 endmodule
Page 110, Figure 3.24

//five-input majority circuit as a udp.  Save as a .v file
primitive udp_maj5 (z1, x1, x2, x3, x4, x5);

output z1;
input x1, x2, x3, x4, x5;

table
   //inputs are in same order as input list
   // x1 x2 x3 x4 x5 :  z1;
      0  0  0  ?  ?  :  0;
      0  0  ?  0  ?  :  0;
      0  0  ?  ?  0  :  0;
      0  ?  0  0  ?  :  0;
      0  ?  ?  0  0  :  0;
      0  ?  0  ?  0  :  0;
      ?  0  0  0  ?  :  0;
      ?  ?  0  0  0  :  0;
      ?  0  0  ?  0  :  0;
      ?  0  ?  0  0  :  0;
      ?  ?  0  0  0  :  0;

      1  1  1  ?  ?  :  1;
      1  1  ?  1  ?  :  1;
      1  1  ?  ?  1  :  1;
      1  ?  1  1  ?  :  1;
      1  ?  ?  1  1  :  1;
      1  ?  1  ?  1  :  1;
      ?  1  1  1  ?  :  1;
      ?  ?  1  1  1  :  1;
      ?  1  1  ?  1  :  1;
      ?  1  ?  1  1  :  1;
      ?  ?  1  1  1  :  1;
endtable

endprimitive


//udp_maj5 test bench
module udp_maj5_tb;
reg x1, x2, x3, x4, x5;             //inputs are reg for tb
wire z1;                            //outputs are wire

//udp_maj5 test bench
module udp_maj5_tb;
reg x1, x2, x3, x4, x5;                               //inputs are reg for tb
wire z1;                            //outputs are wire

//Declare a vector that has 1 more bit than the # of inputs.
//This allows the for statement count to go 1 higher than the
//... maximum count of the input combinations and prevents
//... looping forever.  If only 5 bits were used as the input
//... vector, then the count would always be < 32 (the maximum
//... count for 5 bits).

initial
begin: name             //a name is required for this method
      reg [5:0] invect;
      for (invect = 0; invect < 32; invect = invect + 1)
         begin
            {x1, x2, x3, x4, x5} = invect [4:0];
            #10 $display ("x1x2x3x4x5 = %b%b%b%b%b, z1=%b",
                              x1, x2, x3, x4, x5, z1);
         end
end

//instantiation must be done by position, not by name.
udp_maj5 inst1 (z1, x1, x2, x3, x4, x5);

endmodule


Page 112, Figure 3.28

//a positive-edge-sensitive D flip-flop
primitive udp_dff_edge1 (q, d, clk, rst_n);

input d, clk, rst_n;
output q;

reg q;               //q is internal storage

//initialize q to 0
initial
      q = 0;

//initialize q to 0
initial
      q = 0;

//define state table
table
//inputs are in the same order as the input list
//    d     clk      rst_n    :  q  :  q+;      q+ is the next state
      0     (01)     1     :  ?  :  0;    //(01) is rising edge
      1     (01)     1     :  ?  :  1;    //rst_n = 1 means no rst
      1     (0x)     1     :  1  :  1;    //(0x) is no change
      0     (0x)     1     :  0  :  0;   
      ?     (?0)     1     :  ?  :  -;    //ignore negative edge
//reset case when rst_n is 0 and clk has any transition
      ?     (??)     0     :  ?  :  0;    //rst_n = 0 means reset
//reset case when rst_n is 0.  d & clk can be anything, q+=0
      ?     ?     0     :  ?  :  0;
//reset case when 0 --> 1 transition on rst_n.  Hold q+ state
      ?     ?     (01)     :  ?  :  -;
//non-reset case when d has any trans, but clk has no trans            
      (??)     ?     1     :  ?  :  -;    //clk = ?, means no edge
endtable
endprimitive









//udp for a 4-bit johnson counter
module ctr_johnson4 (rst_n, clk, y1, y2, y3, y4);
input rst_n, clk;
output y1, y2, y3, y4;

//instantiate D flip-flop for y1
udp_dff_edge1 inst1 (y1, ~y4, clk, rst_n);

//instantiate D flip-flop for y2
udp_dff_edge1 inst2 (y2, y1, clk, rst_n);

//instantiate D flip-flop for y3
udp_dff_edge1 inst3 (y3, y2, clk, rst_n);

//instantiate D flip-flop for y4
udp_dff_edge1 inst4 (y4, y3, clk, rst_n);
endmodule


Page 114, Figure 3.30

//test bench for the 4-bit johnson counter
module ctr_johnson4_tb;

reg clk, rst_n;                           //inputs are reg for tb
wire y1, y2, y3, y4;                         //outputs are wire for tb

initial
$monitor ("count = %b", {y1, y2, y3, y4});

initial                          //define clk
begin
      clk = 1'b0;
      forever
         #10   clk = ~clk;
end

initial                          //define reset
begin
      #0 rst_n = 1'b0;
      #5 rst_n = 1'b1;
      #200     $stop;
end

ctr_johnson4 inst1 (             //instantiate the module
      .rst_n(rst_n),
      .clk(clk),
      .y1(y1),
      .y2(y2),
      .y3(y3),
      .y4(y4)
      );
endmodule







Page 116, Figure 3.34

//2-input NOR gate as a user-defined primitive
primitive udp_nor2 (z1, x1, x2);

input x1, x2;
output z1;

//define state table
table
   //inputs are in the same order as the input list
   // x1 x2 :  z1;      comment is for readability
      0  0  :  1;
      0  1  :  0;
      1  0  :  0;
      1  1  :  0;
endtable
endprimitive


Page 116, Figure 3.35

//module for logic diagram using NOR logic
//user-defined primitives
module log_diag_eqn5 (x1, x2, z1);

input x1, x2;
output z1;

//instantiate the udps
udp_nor2 inst1 (net1, x1, ~x2);
udp_nor2 inst2 (net2, x1, net1);
udp_nor2 inst3 (net3, net1, ~x2);
udp_nor2 inst4 (z1, net2, net3);
endmodule


//test bench for logic diagram equation 5
module log_diag_eqn5_tb;

reg x1, x2;
wire z1;

//test bench for logic diagram equation 5
module log_diag_eqn5_tb;

reg x1, x2;
wire z1;

//display variables
initial
$monitor ("x1 x2 = %b %b, z1 = %b", x1, x2, z1);

//apply input vectors
initial
begin
      #0    x1 = 1'b0;  x2 = 1'b0;
      #10      x1 = 1'b0;  x2 = 1'b1;
      #10      x1 = 1'b1;  x2 = 1'b0;
      #10      x1 = 1'b1;  x2 = 1'b1;
  
      #10      $stop;
end

//instantiate the module into the test bench
log_diag_eqn5 inst1 (
      .x1(x1),
      .x2(x2),
      .z1(z1)
      );
endmodule


Page 120, Figure 3.41

//dataflow for a sum-of-products equation
module sop_eqn_df2 (x1, x2, x3, x4, z1);

//define inputs and output
input x1, x2, x3, x4;
output z1;

//define internal nets
wire net1, net2, net3;

//design logic
assign      net1 = ~x2 & ~x3 & ~x4,
            net2 = ~x1 & ~x3 & x4,
            net3 = x2 & x3;

assign      z1 = net1 | net2 | net3;

endmodule


//test bench for the dataflow sop
module sop_eqn_df2_tb;

reg x1, x2, x3, x4;
wire z1;

initial           //apply input vectors and display variables
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end
sop_eqn_df2 inst1 (              //instantiate the module
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );
endmodule


Page 122, Figure 3.46

//dataflow for a product-of-sums equation
module pos_eqn_df (x1, x2, x3, x4, z1);

//define inputs and output
input x1, x2, x3, x4;
output z1;

//define internal nets
wire net1, net2, net3, net4;

//design the logic using continuous assignment
assign            net1 = (x2 | ~x3),
            net2 = (~x2 | x3 | x4),
            net3 = (~x1 | x3 | ~x4),
            net4 = ~(net1 & net2 & net3);

assign      z1 = (~net4 | ~net4);

endmodule


//test bench for product-of-sums equation
module pos_eqn_df_tb;

reg x1, x2, x3, x4;
wire z1;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
pos_eqn_df inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule









Page 125, Figure 3.52

//dataflow to activate segment a
module seg_a_df (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;
wire net1;

assign            net1 = ~(x2 ^ x4);                                    //exclusive-NOR
assign            z1 = (net1 | x1 | x3);
endmodule


//test bench for segment a dataflow module
module seg_a_df_tb;

reg x1, x2, x3, x4;
wire z1;

initial              //apply input vectors and display variables
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end

seg_a_df inst1 (           //instantiate the module into the test bench
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );
endmodule



















Page 127, Figure 3.56

//dataflow pos for segment a
module pos_eqn_df2 (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;

wire net1, net2;

assign            net1 = ~(~x2 | x3 | x4),
            net2 = ~(x1 | x2 | x3 | ~x4);

assign            z1 = (~net1 & ~net2);

endmodule


//test bench for pos for segment a
module pos_eqn_df2_tb;

reg x1, x2, x3, x4;
wire z1;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect=0; invect<16; invect=invect+1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                           {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
pos_eqn_df2 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule














Page 131, Figure 3.60

//behavioral 5-input majority circuit
module maj5_bh (x1, x2, x3, x4, x5, z1);

input x1, x2, x3, x4, x5;
output z1;

wire x1, x2, x3, x4, x5;
reg z1;

always @ (x1 or x2 or x3 or x4 or x5)
      z1 = #5 (x3 & x4 & x5) | (x2 & x3 & x5) | (x2 & x4 & x5) |
              (x1 & x3 & x5) | (x1 & x4 & x5) | (x1 & x2 & x3) |
              (x1 & x2 & x4) | (x2 & x3 & x4) | (x1 & x3 & x4) |
              (x1 & x2 & x5);
endmodule


//test bench for the 5-input majority circuit
module maj5_bh_tb;

reg x1, x2, x3, x4, x5;
wire z1;

initial              //apply vectors and display variables
begin: apply_stimulus
      reg [5:0] invect;
      for (invect=0; invect<32; invect=invect+1)
         begin
            {x1, x2, x3, x4, x5} = invect [5:0];
            #7 $display ($time, "input = %b, z1 = %b",
                        {x1, x2, x3, x4, x5}, z1);
         end
end

//instantiate the module into the test bench
maj5_bh inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .x5(x5),
      .z1(z1)
      );
endmodule














Page 134, Figure 3.64

//behavioral blocking assignment using
// intrastatement and interstatement delays
module blocking6 (x1, x2, x3, z1, z2, z3, z4);

input x1, x2, x3;
output z1, z2, z3, z4;

reg z1, z2, z3, z4;

always @ (x1 or x2 or x3)
begin
      z1 = #2 (x1 ^ x2) & x3;
      z2 = #2 ~(x1 ^ x2) | x3;
end

always @ (x1 or x2 or x3)
begin
      #2 z3 = x1 & x2 & x3;
      #2 z4 = x1 ^ x2 ^ x3;
end

endmodule


//test bench for blocking assignment using
//intrastatement and interstatement delays
module blocking6_tb;

reg x1, x2, x3;
wire z1, z2, z3, z4;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [3:0] invect;
      for (invect=0; invect<8; invect=invect+1)
         begin
            {x1, x2, x3} = invect [3:0];
            #10 $display ("x1 x2 x3 = %b, z1 z2 z3 z4 = %b",
                           {x1, x2, x3}, {z1, z2, z3, z4});
         end
end

//instantiate the module into the test bench
blocking6 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .z1(z1),
      .z2(z2),
      .z3(z3),
      .z4(z4)
      );
endmodule




Page 137, Figure 3.68

//behavioral to illustrate blocking
//and nonblocking assignments
module block_nonblock (data_reg_a, data_reg_b, data_reg_c);

output [7:0] data_reg_a, data_reg_b, data_reg_c;
reg [7:0] data_reg_a, data_reg_b, data_reg_c;

initial
begin
      data_reg_a = 8'b0111_1100;
      data_reg_b = 8'b1111_0000;
      data_reg_c = 8'b1111_1111;

      data_reg_a [2:0] <= #5 3'b111;
      data_reg_b [7:0] <= #10 {data_reg_b [7:4], 4'b1111};
      data_reg_c [7:0] <= #15 {2'b11, data_reg_a [5:0]};
end

endmodule


page 139, Figure 3.70

//behavioral modulo-10 counter with logic gating
module ctr_mod10_logic (rst_n, clk, q, z1, z2, z3);

input rst_n, clk;
output [3:0] q;
output z1, z2, z3;

wire rst_n, clk;
reg [3:0] q;
wire z1, z2, z3;

//define counting sequence
always @ (posedge clk or negedge rst_n)
begin
      if (rst_n == 0)
         q = 4'b0000;
      else
         q = (q + 1) % 10;
end

//define outputs
assign            z1 = q[2] & q[1],
            z2 = q[2] ^ q[1] ^ q[0],
            z3 = q[3] | q[0];

endmodule









//test bench for modulo-10 counter
module ctr_mod10_logic_tb;

reg rst_n, clk;
wire [3:0] q;
wire z1, z2, z3;

//display outputs
initial
$monitor ("count = %b, z1 z2 z3 = %b", q, {z1, z2, z3});

//define reset
initial
begin
      #0 rst_n = 1'b0;
      #5 rst_n = 1'b1;
end

//define clock
initial
begin
      clk = 1'b0;
      forever
         #10   clk = ~clk;
end

//define length of simulation
initial
begin
      #200     $finish;
end

//instantiate the module into the test bench
ctr_mod10_logic inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .q(q),
      .z1(z1),
      .z2(z2),
      .z3(z3)
      );

endmodule

















Page 142, Figure 3.74

//behavioral counter using the case statement
module ctr_triangle (rst_n, clk, count);

input rst_n, clk;
output [15:0] count;

wire rst_n, clk;
reg [15:0] count, next_count;

always @ (posedge clk or negedge rst_n)
begin
      if (~rst_n)             //if the reset = 0
         count = 16'h0000;
      else
         count = next_count;
end

//define the counting sequence
always @ (count)
begin
      case (count)
         16'h0000 : next_count = 16'h8000;
         16'h8000 : next_count = 16'hc000;
         16'hc000 : next_count = 16'he000;
         16'he000 : next_count = 16'hf000;
         16'hf000 : next_count = 16'hf800;
         16'hf800 : next_count = 16'hfc00;
         16'hfc00 : next_count = 16'hfe00;
         16'hfe00 : next_count = 16'hff00;
         16'hff00 : next_count = 16'hff80;
         16'hff80 : next_count = 16'hffc0;
         16'hffc0 : next_count = 16'hffe0;
         16'hffe0 : next_count = 16'hfff0;
         16'hfff0 : next_count = 16'hfff8;
         16'hfff8 : next_count = 16'hfffc;
         16'hfffc : next_count = 16'hfffe;
         16'hfffe : next_count = 16'hffff;
         default  : next_count = 16'h0000;
      endcase
end

endmodule
















//test bench for counter triangle
module ctr_triangle_tb;

reg rst_n, clk;
wire [15:0] count;

//display count
initial
$monitor ("count = %b", count);

//define clock
initial
begin
      clk = 1'b0;
      forever
         #10 clk = ~clk;
end

//define reset
initial
begin
      #0 rst_n = 1'b0;
      #5 rst_n = 1'b1;
end

//define length of simulation
initial
begin
      #320 $finish;
end

//instantiate the module into the test bench
ctr_triangle inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .count(count)
      );

endmodule





















Page 146, Figure 3.79

//behavioral moore ssm
module moore_ssm23 (rst_n, clk, x1, x2, y, z1, z2, z3);

input rst_n, clk, x1, x2;
output [1:3] y;
output z1, z2, z3;

reg [1:3] y, next_state;
wire z1, z2, z3;

//assign state codes
parameter               state_a = 3'b000,
               state_b = 3'b011,
               state_c = 3'b101,
               state_d = 3'b110,
               state_e = 3'b100;

//set next state
always @ (posedge clk)
begin
      if (~rst_n)
         y <= state_a;
      else
         y <= next_state;
end

assign      z1 = (~y[1] & ~y[2] & ~y[3]),                              
            z2 = (y[1] & ~y[2] & y[3]),
            z3 = (y[1] & y[2] & ~y[3]);

//determine the next state
always @ (x1 or x2 or y)
begin
      case (y)
         state_a:
            if (x1==0)
               next_state = state_a;
            else
               next_state = state_b;

         state_b:
            if (x2==0)
               next_state = state_d;
            else
               next_state = state_c;

         state_c: next_state = state_e;
         state_d: next_state = state_e;
         state_e: next_state = state_a;
         default: next_state = state_a;
      endcase
end
endmodule




//test bench for moore ssm
module moore_ssm23_tb;

reg rst_n, clk, x1, x2;
wire [1:3] y;
wire z1, z2, z3;

//display variables
initial
$monitor ("x1 x2 = %b, state = %b, z1 z2 z3 = %b",
            {x1, x2}, y, {z1, z2, z3});

//define clock
initial
begin
      clk = 1'b0;
      forever
         #10 clk = ~clk;
end

//define input sequence
initial
begin
      #0    rst_n = 1'b0;
            x1 = 1'b0;
            x2 = 1'b0;

      #5    rst_n = 1'b1;
  
            x1 = 1'b0;              x2 = $random;
            @ (posedge clk)         //go to state_a (000); assert z1
  
            x1 = 1'b1;              x2 = $random;
            @ (posedge clk)         //go to state_b (011)
  
            x1 = $random;           x2 = 1'b0;
            @ (posedge clk)         //go to state_d (110); assert z3
  
            x1 = $random;           x2 = $random;
            @ (posedge clk)         //go to state_e (100)
  
            x1 = $random;           x2 = $random;
            @ (posedge clk)         //go to state_a (000); assert z1
  
            x1 = 1'b1;              x2 = $random;
            @ (posedge clk)         //go to state_b (011)

            x1 = $random;           x2 = 1'b1;
            @ (posedge clk)         //go to state_c (101); assert z2

            x1 = $random;           x2 = $random;
            @ (posedge clk)         //go to state_e (100)

          x1 = $random;           x2 = $random;
            @ (posedge clk)         //go to state_a (000); assert z1

            x1 = 1'b0;              x2 = $random;
            @ (posedge clk)         //go to state_a (000); assert z1

      #10      $stop;

end


//instantiate the module into the test bench
moore_ssm23 inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .x1(x1),
      .x2(x2),
      .y(y),
      .z1(z1),
      .z2(z2),
      .z3(z3)
      );


endmodule










































Page 152, Figure 3.83

//example of a while loop
//determine the value of a register
module reg_value;

integer value;

initial
begin: determine_value
      reg [7:0] reg_a;
      value = 0;
      reg_a = 8'b0001_1011;

      while (reg_a > 0)
         begin
            value = value + 1;
            reg_a = reg_a - 1;
            $display ("value = %d", value);
         end
end

endmodule


Page 153, Figure 3.85

//example of the repeat keyword
module add_regs_repeat;

reg [7:0] reg_a, reg_b, sum;

initial
begin
      reg_a = 8'b0000_1000;
      reg_b = 8'b0000_0010;

      repeat (8)
      begin
         sum = reg_a + reg_b;
         $display ("reg_a=%b, reg_b=%b, sum=%b",
                     reg_a, reg_b, sum);
         reg_b = reg_b + 1;
      end
end

endmodule





















Page 157, Figure 3.89

//dataflow 2-input and gate
module and2_df (x1, x2, z1);

input x1, x2;                    //list inputs and output
output z1;

wire x1, x2;                     //define signals as wire for dataflow
wire z1;

assign z1 = x1 & x2;             //continuous assign for dataflow

endmodule


//dataflow 3-input and gate
module and3_df (x1, x2, x3, z1);

input x1, x2, x3;                //list inputs and output
output z1;

wire x1, x2, x3;                 //define signals as wire for dataflow
wire z1;

assign z1 = x1 & x2 & x3;        //continuous assign for dataflow

endmodule


//or4 dataflow
module or4_df (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;

wire x1, x2, x3, x4;
wire z1;

assign z1 = x1 | x2 | x3 | x4;

endmodule



















Page 158, Figure 3.92

//structural sum of products 2 < z1 <= 6; 10 <= z1 < 15
module sop_struc2 (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;

wire x1, x2, x3, x4;
wire z1;

//define internal wires
wire net1, net2, net3, net4;

//instantiate the logic
and2_df inst1 (
      .x1(x2),
      .x2(~x3),
      .z1(net1)
      );

and2_df inst2 (
      .x1(x2),
      .x2(~x4),
      .z1(net2)
      );

and3_df inst3 (
      .x1(x1),
      .x2(~x2),
      .x3(x3),
      .z1(net3)
      );

and3_df inst4 (
      .x1(~x2),
      .x2(x3),
      .x3(x4),
      .z1(net4)
      );

or4_df inst5 (
      .x1(net1),
      .x2(net2),
      .x3(net3),
      .x4(net4),
      .z1(z1)
      );
endmodule












//test bench for sop_struc2
module sop_struc2_tb;

//define inputs and output
reg x1, x2, x3, x4;
wire z1;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect = 0; invect < 16; invect = invect + 1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                        {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
sop_struc2 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule































Page 161, Figure 3.97

//dataflow 3-input nor gate
module nor3_df (x1, x2, x3, z1);

input x1, x2, x3;
output z1;

wire x1, x2;
wire z1;

assign z1 = ~(x1 | x2 | x3);
endmodule


//structural product of sums 2 < z1 <= 6; 10 <= z1 < 15
module pos_struc2 (x1, x2, x3, x4, z1);

input x1, x2, x3, x4;
output z1;

//define internal nets
wire net1, net2, net3;

//instantiate the logic gates
nor2_df inst1 (
      .x1(x2),
      .x2(x3),
      .z1(net1)
      );

nor3_df inst2 (
      .x1(~x2),
      .x2(~x3),
      .x3(~x4),
      .z1(net2)
      );

nor3_df inst3 (
      .x1(x2),
      .x2(x1),
      .x3(x4),
      .z1(net3)
      );

nor3_df inst4 (
   .x1(net1),
   .x2(net2),
   .x3(net3),
   .z1(z1)
   );

endmodule







//test bench for sop_struc2
module pos_struc2_tb;

//define inputs and output
reg x1, x2, x3, x4;
wire z1;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [4:0] invect;
      for (invect = 0; invect < 16; invect = invect + 1)
         begin
            {x1, x2, x3, x4} = invect [4:0];
            #10 $display ("x1 x2 x3 x4 = %b, z1 = %b",
                        {x1, x2, x3, x4}, z1);
         end
end

//instantiate the module into the test bench
pos_struc2 inst1 (
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .x4(x4),
      .z1(z1)
      );

endmodule































Page 166, Figure 3.103

//dataflow or4
module or4_df (x1, x2, x3, x4, z1);
input x1, x2, x3, x4;
output z1;

wire x1, x2, x3, x4;
wire z1;
assign z1 = x1 | x2 | x3 | x4;
endmodule


//dataflow xor2_df
module xor2_df (x1, x2, z1);
input x1, x2;
output z1;
wire x1, x2;
wire z1;
assign z1 = x1 ^ x2;
endmodule


//behavioral D flip-flop
module d_ff_bh (rst_n, clk, d, q, q_n);

input rst_n, clk, d;
output q, q_n;

wire rst_n, clk, d;
reg q;

assign q_n = ~q;

always @ (rst_n or posedge clk)
begin
      if (rst_n == 0)
           q <= 1'b0;
      else q <= d;
end
endmodule


//structural odd even counter
module ctr_odd_evn2 (rst_n, clk, y);

input rst_n, clk;
output [1:4] y;

wire rst_n, clk;
wire [1:4] y;

//define internal wires
wire        net1, net2, net3, net4, net6,
         net8, net9, net10, net11,
         net13, net14, net15, net16;


//instantiate the logic for flip-flop y[1]
and2_df inst1 (
      .x1(y[1]),
      .x2(~y[3]),
      .z1(net1)
      );

and2_df inst2 (
      .x1(y[1]),
      .x2(~y[2]),
      .z1(net2)
      );

and3_df inst3 (
      .x1(~y[1]),
      .x2(y[2]),
      .x3(y[3]),
      .z1(net3)
      );

or3_df inst4 (
      .x1(net1),
      .x2(net2),
      .x3(net3),
      .z1(net4)
      );

d_ff_bh inst5 (
      .rst_n(rst_n),
      .clk(clk),
      .d(net4),
      .q(y[1])
      );

//instantiate the logic for flip-flop y[2]
xor2_df inst6 (
   .x1(y[2]),
   .x2(y[3]),
   .z1(net6)
   );

d_ff_bh inst7 (
   .rst_n(rst_n),
   .clk(clk),
   .d(net6),
   .q(y[2])
   );

//instantiate the logic for flip-flop y[3]
and2_df inst8 (
      .x1(y[2]),
      .x2(~y[3]),
      .z1(net8)
      );

and2_df inst9 (
      .x1(~y[3]),
      .x2(y[4]),
      .z1(net9)
      );



and3_df inst10 (
      .x1(y[1]),
      .x2(y[2]),
      .x3(y[4]),
      .z1(net10)
      );

or4_df inst11 (
      .x1(net1),
      .x2(net8),
      .x3(net9),
      .x4(net10),
      .z1(net11)
      );

d_ff_bh inst12 (
      .rst_n(rst_n),
      .clk(clk),
      .d(net11),
      .q(y[3])
      );

//instantiate the logic for flip-flop y[4]
and2_df inst13 (
      .x1(~y[1]),
      .x2(y[4]),
      .z1(net13)
      );

and2_df inst14 (
      .x1(~y[2]),
      .x2(y[4]),
      .z1(net14)
      );

and3_df inst15 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .z1(net15)
      );

or4_df inst16 (
      .x1(net9),
      .x2(net13),
      .x3(net14),
      .x4(net15),
      .z1(net16)
      );

d_ff_bh inst17 (
      .rst_n(rst_n),
      .clk(clk),
      .d(net16),
      .q(y[4])
      );
endmodule




//test bench for odd even counter
module ctr_odd_evn2_tb;

reg rst_n, clk;
wire [1:4] y;

//display count
initial
$monitor ("count = %b", y);

//generate reset
initial
begin
      #0    rst_n = 1'b0;
      #2    rst_n = 1'b1;
end

//generate clock
initial
begin
      clk = 1'b0;
      forever
         #12      clk = ~clk;
end

//determine length of simulation
initial
      #370     $stop;

//instantiate the module into the test bench
ctr_odd_evn2 inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .y(y)
      );

endmodule












Page 174, Figure 3.113

//structural moore ssm
module moore_ssm22 (rst_n, clk, x1, x2, x3, y,
                        z1, z2, z3, z4, z5);

//define inputs and outputs
input rst_n, clk, x1, x2, x3;
output [1:3] y;
output z1, z2, z3, z4, z5;

//define internal wires
wire net1, net3, net5, net6, net7;

//instantiate the logic for flip-flop y[1]
and5_df inst1 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .x4(x1),
      .x5(~x2),
      .z1(net1)
      );

d_ff_bh inst2 (
      .rst_n(rst_n),
      .clk(clk),
      .d(net1),
      .q(y[1])
      );

//instantiate the logic for flip-flop y[2]
and5_df inst3 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .x4(~x1),
      .x5(x2),
      .z1(net3)
      );


//continued on next page
d_ff_bh inst4 (
   .rst_n(rst_n),
   .clk(clk),
   .d(net3),
   .q(y[2])
   );

//instantiate the logic for flip-flop y[3]
and5_df inst5 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .x4(~x1),
      .x5(x3),
      .z1(net5)
      );


and5_df inst6 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .x4(~x2),
      .x5(x3),
      .z1(net6)
      );

or2_df inst7 (
      .x1(net5),
      .x2(net6),
      .z1(net7)
      );

d_ff_bh inst8 (
      .rst_n(rst_n),
      .clk(clk),
      .d(net7),
      .q(y[3])
      );
//instantiate the logic outputs z1, z2, z3, z4, and z5
and4_df inst9 (
      .x1(~y[1]),
      .x2(~y[2]),
      .x3(y[3]),
      .x4(~clk),
      .z1(z1)
      );

and4_df inst10 (
      .x1(~y[1]),
      .x2(y[2]),
      .x3(~y[3]),
      .x4(~clk),
      .z1(z2)
      );
and4_df inst11 (
      .x1(~y[1]),
      .x2(y[2]),
      .x3(y[3]),
      .x4(~clk),
      .z1(z3)
      );

and4_df inst12 (
      .x1(y[1]),
      .x2(~y[2]),
      .x3(~y[3]),
      .x4(~clk),
      .z1(z4)
      );
and4_df inst13 (
      .x1(y[1]),
      .x2(~y[2]),
      .x3(y[3]),
      .x4(~clk),
      .z1(z5)
      );
endmodule

Page 176, Figure 3.114

//test bench for moore ssm22
module moore_ssm22_tb;

reg rst_n, clk, x1, x2, x3;

wire [1:3] y;
wire z1, z2, z3, z4, z5;

//display inputs and outputs
initial
$monitor ("x1 x2 x3 = %b, state = %b, z1 z2 z3 z4 z5 = %b",
            {x1, x2, x3}, y, {z1, z2, z3, z4, z5});

//define clock
initial
begin
      clk = 1'b0;
      forever
         #10      clk = ~clk;
end

//define input sequence
initial
begin
      #0    rst_n = 1'b0;              //reset to state_a (000)
            x1=1'b0;       x2=1'b0;       x3=1'b0;
      #5    rst_n = 1'b1;

      x1=1'b0;          x2=1'b0;          x3=1'b1;
      @ (posedge  clk)                //go to state_b (001); assert z1

      x1=$random;          x2=$random;          x3=$random;
      @ (posedge clk)                     //go to state_a (000)

      x1=1'b0;          x2=1'b1;          x3=1'b0;
      @ (posedge clk)                  //go to state_c (010); assert z2

      x1=$random;          x2=$random;          x3=$random;
      @ (posedge clk)                  //go to state_a (000)

      x1=1'b0;          x2=1'b1;          x3=1'b1;
      @ (posedge clk)                  //go to state_d (011); assert z3

      x1=$random;          x2=$random;          x3=$random;
      @ (posedge clk)                  //go to state_a (000)

      x1=1'b1;          x2=1'b0;          x3=1'b0;
      @ (posedge clk)                  //go to state_e (100); assert z4

      x1=$random;          x2=$random;          x3=$random;
      @ (posedge clk)                  //go to state_a (000)

      x1=1'b1;          x2=1'b0;          x3=1'b1;
      @ (posedge clk)                  //go to state_f (101); assert z5

      x1=$random;    x2=$random;    x3=$random;
      @ (posedge clk)                  //go to state_a (000)

   #10      $stop;
end

//instantiate the module into the test bench
moore_ssm22 inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .x1(x1),
      .x2(x2),
      .x3(x3),
      .y(y),
      .z1(z1),
      .z2(z2),
      .z3(z3),
      .z4(z4),
      .z5(z5)
      );

endmodule




Computer Arithmetic
and
Verilog HDL Fundamentals

Chapter 4

Fixed-Point Addition

Verilog Code Figures


























Page 188, Figure 4.7

//dataflow full adder
module full_adder (a, b, cin, sum, cout);

//list all inputs and outputs
input a, b, cin;
output sum, cout;

//define wires
wire a, b, cin;
wire sum, cout;

//continuous assign
assign sum = (a ^ b) ^ cin;
assign cout = cin & (a ^ b) | (a & b);

endmodule

Page 188, figure 4.8

//structural 4_bit ripple-carry counter
module adder_ripple4_struc2 (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;
wire [3:0] sum;
wire cout;

wire [3:0] c;                       //define internal nets for carries

assign cout = c[3];

full_adder inst0 (
      .a(a[0]),
      .b(b[0]),
      .cin(cin),
      .sum(sum[0]),
      .cout(c[0])
      );

full_adder inst1 (
      .a(a[1]),
      .b(b[1]),
      .cin(c[0]),
      .sum(sum[1]),
      .cout(c[1])
      );

full_adder inst2 (
      .a(a[2]),
      .b(b[2]),
      .cin(c[1]),
      .sum(sum[2]),
      .cout(c[2])
      );

full_adder inst3 (
      .a(a[3]),
      .b(b[3]),
      .cin(c[2]),
      .sum(sum[3]),
      .cout(c[3])
      );

endmodule


Page 189, Figure 4.9

//test bench for 4-bit ripple-carry adder
module adder_ripple4_struc2_tb;

//define inputs
reg [3:0] a, b;
reg cin;

//define outputs
wire [3:0] sum;
wire cout;

initial
$monitor ("a=%b, b=%b, cin=%b, cout=%b, sum=%b",
               a, b, cin, cout, sum);

initial
begin
      #0    a = 4'b0000;   b = 4'b0001;   cin = 1'b0;
      #10   a = 4'b0011;   b = 4'b0100;   cin = 1'b1;
      #10   a = 4'b0111;   b = 4'b0101;   cin = 1'b0;
      #10   a = 4'b1011;   b = 4'b1100;   cin = 1'b1;
      #10   a = 4'b0110;   b = 4'b0100;   cin = 1'b0;
      #10   a = 4'b0101;   b = 4'b0100;   cin = 1'b1;
      #10   a = 4'b1111;   b = 4'b1111;   cin = 1'b1;
      #10   a = 4'b1000;   b = 4'b1000;   cin = 1'b1;
      #10   a = 4'b1100;   b = 4'b1100;   cin = 1'b0;
      #10   a = 4'b1001;   b = 4'b0101;   cin = 1'b1;
      #10   a = 4'b0111;   b = 4'b0111;   cin = 1'b0;

      #10      $stop;
end

//instantiate the module into the test bench
adder_ripple4_struc2 inst1 (
      .a(a),
      .b(b),
      .cin(cin),
      .sum(sum),
      .cout(cout)
      );

endmodule


Page 196, Figure 4.16

//dataflow 8-bit carry lookahead adder
module adder_cla8 (a, b, cin, sum, cout);

input [7:0] a, b;             //input/output port declaration
input cin;
output [7:0] sum;
output cout;

wire g7, g6, g5, g4, g3, g2, g1, g0;                                                            //define internal wires
wire p7, p6, p5, p4, p3, p2, p1, p0;
wire c7, c6, c5, c4, c3, c2, c1, c0;
//continued on next page


//define internal wires
wire g7, g6, g5, g4, g3, g2, g1, g0;
wire p7, p6, p5, p4, p3, p2, p1, p0;
wire c7, c6, c5, c4, c3, c2, c1, c0;

//dataflow 8-bit carry lookahead adder
module adder_cla8 (a, b, cin, sum, cout);

//input/output port declaration
input [7:0] a, b;
input cin;
output [7:0] sum;
output cout;

//define generate functions
//multiple statements using 1 assign
assign      g7 = a[7] & b[7],
            g6 = a[6] & b[6],
            g5 = a[5] & b[5],
            g4 = a[4] & b[4],
            g3 = a[3] & b[3],
            g2 = a[2] & b[2],
            g1 = a[1] & b[1],
            g0 = a[0] & b[0];


//define propagate functions
//multiple statements using 1 assign
assign      p7 = a[7] ^ b[7],
            p6 = a[6] ^ b[6],
            p5 = a[5] ^ b[5],
            p4 = a[4] ^ b[4],
            p3 = a[3] ^ b[3],
            p2 = a[2] ^ b[2],
            p1 = a[1] ^ b[1],
            p0 = a[0] ^ b[0];


//obtain the carry equations for low order
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 carry equations for high order
assign      c4 = g4 | (p4 & c3),
            c5 = g5 | (p5 & g4) | (p5 & p4 & c3),
            c6 = g6 | (p6 & g5) | (p6 & p5 & g4) |
                  (p6 & p5 & p4 & c3),
            c7 = g7 | (p7 & g6) | (p7 & p6 & g5) |
                  (p7 & p6 & p5 & g4) |
                  (p7 & p6 & p5 & p4 & c3);

//obtain the sum equations
assign      sum[0] = p0 ^ cin,
            sum[1] = p1 ^ c0,
            sum[2] = p2 ^ c1,
            sum[3] = p3 ^ c2,
            sum[4] = p4 ^ c3,
            sum[5] = p5 ^ c4,
            sum[6] = p6 ^ c5,
            sum[7] = p7 ^ c6;

//obtain cout
assign      cout = c7;

endmodule


//test bench for dataflow 8-bit carry lookahead adder
module adder_cla8_tb;

reg [7:0] a, b;
reg cin;

wire [7:0] sum;
wire cout;

//display signals
initial
$monitor ("a = %d, b = %d, cin = %b, cout = %b, sum = %d",
               a, b, cin, cout, sum);

//apply stimulus
initial
begin
      #0    a = 8'b0000_0000;
            b = 8'b0000_0000;
            cin = 1'b0;             //cout = 0, sum = 0000_0000

      #10   a = 8'b0000_0001;
            b = 8'b0000_0010;
            cin = 1'b0;             //cout = 0, sum = 0000_0011

//apply stimulus
initial
begin
      #0    a = 8'b0000_0000;
            b = 8'b0000_0000;
            cin = 1'b0;             //cout = 0, sum = 0000_0000

      #10   a = 8'b0000_0001;
            b = 8'b0000_0010;
            cin = 1'b0;             //cout = 0, sum = 0000_0011

      #10   a = 8'b0000_0010;
            b = 8'b0000_0110;
            cin = 1'b0;             //cout = 0, sum = 0000_1000

      #10   a = 8'b0000_0111;
            b = 8'b0000_0111;
            cin = 1'b0;             //cout = 0, sum = 0000_1110

      #10   a = 8'b0000_1001;
            b = 8'b0000_0110;
            cin = 1'b0;             //cout = 0, sum = 0000_1111

      #10   a = 8'b0000_1100;
            b = 8'b0000_1100;
            cin = 1'b0;             //cout = 0, sum = 0001_1000

      #10   a = 8'b0000_1111;
            b = 8'b0000_1110;
            cin = 1'b0;             //cout = 0, sum = 0001_1101

      #10   a = 8'b0000_1110;
            b = 8'b0000_1110;
            cin = 1'b1;             //cout = 0, sum = 0001_1101

      #10   a = 8'b0000_1111;
            b = 8'b0000_1111;
            cin = 1'b1;             //cout = 0, sum = 0001_1111

      #10   a = 8'b1111_0000;
            b = 8'b0000_1111;
            cin = 1'b1;             //cout = 1, sum = 0000_0000

      #10   a = 8'b0111_0000;
            b = 8'b0000_1111;
            cin = 1'b1;             //cout = 0, sum = 1000_0000

      #10   a = 8'b1011_1000;
            b = 8'b0100_1111;
            cin = 1'b1;             //cout = 1, sum = 0000_1000

      #10      $stop;
end

adder_cla8 inst1 (                  //instantiate the module
      .a(a),
      .b(b),
      .cin(cin),
      .sum(sum),
      .cout(cout)
      );

endmodule



Page 202, Figure 4.21

//dataflow carry-save full adder
module csa_full_adder (a, b, c, sum, cout);

input a, b, c;                      //list all inputs and outputs
output sum, cout;

wire a, b, c;                       //define wires
wire sum, cout;

assign sum = (a ^ b) ^ c;           //continuous assign
assign cout = c & (a ^ b) | (a & b);

endmodule


//test bench for carry-save full adder
module csa_full_adder_tb;

reg a, b, c;
wire sum, cout;

//apply input vectors
initial
begin: apply_stimulus
      reg [3:0] invect;
      for (invect = 0; invect < 8; invect = invect + 1)
         begin
            {a, b, c} = invect [3:0];
            #10 $display ("a b c = %b, cout = %b, sum = %b",
                           {a, b, c}, cout, sum);
         end
end

//instantiate the module into the test bench
csa_full_adder inst1 (
      .a(a),
      .b(b),
      .c(c),
      .sum(sum),
      .cout(cout)
      );

endmodule















Page 204, Figure 4.25

//structural 5-input wallace tree
module wallace_tree_5_inputs (in, sum_w);

input [4:0] in;
output [2:0] sum_w;

wire [4:0] in;
wire [2:0] sum_w;

//define internal nets
wire net1, net2, net3;

//instantiate the carry-save full adders
csa_full_adder inst1 (
      .a(in[2]),
      .b(in[1]),
      .c(in[0]),
      .sum(net1),
      .cout(net2)
      );

csa_full_adder inst2 (
      .a(in[4]),
      .b(in[3]),
      .c(net1),
      .sum(sum_w[0]),
      .cout(net3)
      );

csa_full_adder inst3 (
      .a(1'b0),
      .b(net2),
      .c(net3),
      .sum(sum_w[1]),
      .cout(sum_w[2])
      );

endmodule


//test bench for 5-input wallace tree
module wallace_tree_5_inputs_tb;

reg [4:0] in;                    //define inputs and outputs
wire [2:0] sum_w;

//apply input vectors and display variables
initial
begin: apply_stimulus
      reg [5:0] invect;
      for (invect = 0; invect < 32; invect = invect + 1)
         begin
            in = invect [5:0];
            #10 $display ("inputs = %b, sum = %b",
                           in, sum_w);
         end
end

//instantiate the module
wallace_tree_5_inputs nst1 (                                           
      .in(in),
      .sum_w(sum_w)
      );

endmodule



Page 207, Figure 4.30

//structural wallace tree for 5 operands
module wallace_tree_5_opnds (a, b, c, d, e, sum_w);

input [3:0] a, b, c, d, e;
output [6:0] sum_w;

wire [3:0] a, b, c, d, e;
wire [6:0] sum_w;

//define internal nets
wire     net1, net2, net3, net4, net5, net6,
         net7, net8, net9, net10, net11,
         net12, net13, net14, net15, net16,
         net17, net18, net19, net20, net21;

//instantiate the 5-input wallace tree
wallace_tree_5_inputs inst1 (
      .in({a[0], b[0], c[0], d[0], e[0]}),
      .sum_w({net2, net1, sum_w[0]})
      );

wallace_tree_5_inputs inst2 (
      .in({a[1], b[1], c[1], d[1], e[1]}),
      .sum_w({net5, net4, net3})
      );

wallace_tree_5_inputs inst3 (
      .in({a[2], b[2], c[2], d[2], e[2]}),
      .sum_w({net8, net7, net6})
      );

wallace_tree_5_inputs inst4 (
      .in({a[3], b[3], c[3], d[3], e[3]}),
      .sum_w({net11, net10, net9})
      );

//instantiate the carry-save full adder
csa_full_adder inst5 (
      .a(1'b0),
      .b(net1),
      .c(net3),
      .sum(sum_w[1]),
      .cout(net12)
      );



csa_full_adder inst6 (
      .a(net2),
      .b(net4),
      .c(net6),
      .sum(net13),
      .cout(net14)
      );

csa_full_adder inst7 (
      .a(net5),
      .b(net7),
      .c(net9),
      .sum(net15),
      .cout(net16)
      );

csa_full_adder inst8 (
      .a(net8),
      .b(net10),
      .c(1'b0),
      .sum(net17),
      .cout(net18)
      );

csa_full_adder inst9 (
      .a(net12),
      .b(1'b0),
      .c(net13),
      .sum(sum_w[2]),
      .cout(net19)
      );

csa_full_adder inst10 (
      .a(net19),
      .b(net14),
      .c(net15),
      .sum(sum_w[3]),
      .cout(net20)
      );

csa_full_adder inst11 (
      .a(net20),
      .b(net16),
      .c(net17),
      .sum(sum_w[4]),
      .cout(net21)
      );

csa_full_adder inst12 (
      .a(net21),
      .b(net18),
      .c(net11),
      .sum(sum_w[5]),
      .cout(sum_w[6])
      );

endmodule




//test bench for 5-operand wallace tree
module wallace_tree_5_opnds_tb;

//define inputs and outputs
reg [3:0] a, b, c, d, e;
wire [6:0] sum_w;

//display outputs
initial
$monitor ("a=%b, b=%b, c=%b, d=%b, e=%b, sum=%b",
               a, b, c, d, e, sum_w);

//apply input vectors
initial
begin
      #0    a = 4'b0001;
            b = 4'b0001;
            c = 4'b0001;
            d = 4'b0001;
            e = 4'b0001;               //sum = 000 0101

      #10   a = 4'b0111;
            b = 4'b1010;
            c = 4'b0101;
            d = 4'b1001;
            e = 4'b0011;               //sum = 010 0010

      #10   a = 4'b1111;
            b = 4'b1010;
            c = 4'b1101;
            d = 4'b1001;
            e = 4'b1011;               //sum = 011 1010

      #10   a = 4'b0110;
            b = 4'b1110;
            c = 4'b1111;
            d = 4'b1000;
            e = 4'b1001;               //sum = 011 0100

      #10   a = 4'b1111;
            b = 4'b1111;
            c = 4'b1111;
            d = 4'b1111;
            e = 4'b1111;               //sum = 100 1011

     #10   a = 4'b1000;
            b = 4'b1000;
            c = 4'b1000;
            d = 4'b1000;
            e = 4'b1000;               //sum = 010 1000

      #10   a = 4'b1100;
            b = 4'b1100;
            c = 4'b1100;
            d = 4'b1100;
            e = 4'b1100;               //sum = 011 1100

      #10      $stop;
end

//instantiate the module into the test bench
wallace_tree_5_opnds inst1 (
      .a(a),
      .b(b),
      .c(c),
      .d(d),
      .e(e),
      .sum_w(sum_w)
      );

endmodule


Page 214, Figure 4.35

//behavioral to add two operands
module mem_sum (opnds, sum);

input [5:0] opnds;                  //list inputs and outputs
output [3:0] sum;

wire [5:0] opnds;                   //augend and addend to address 64 words
reg [3:0] sum;

//define memory size
//mem_add is an array of 64 four-bit registers
reg [3:0] mem_add [0:63];

//define memory contents
//load mem_add from file opnds.add
initial
begin
      $readmemb ("opnds.add", mem_add);
end

//use the operands to access the memory
always @ (opnds)
begin
      sum = mem_add [opnds];
end
endmodule


//test bench for mem_sum module
module mem_sum_tb;

reg [5:0] opnds;
wire [3:0] sum;

//display variables
initial
$monitor ("augend_addend = %b, sum = %b", opnds, sum);

//apply input vectors for augend and addend
initial
begin
      #0    opnds = 6'b000_011;                       //augend_addend
      #10      opnds = 6'b001_100;
      #10      opnds = 6'b010_100;
      #10      opnds = 6'b011_110;
      #10      opnds = 6'b100_100;
      #10      opnds = 6'b101_101;
      #10      opnds = 6'b110_101;
      #10      opnds = 6'b100_110;
      #10      opnds = 6'b111_010;
      #10      opnds = 6'b111_100;
      #10      opnds = 6'b111_110;
      #10      opnds = 6'b111_111;
      #10      $stop;
end

//instantiate the module into the test bench
mem_sum inst1 (
      .opnds(opnds),
      .sum(sum)
      );

endmodule


Page 218, Figure 4.39

//behavioral model for a 4-bit adder
module adder4 (a, b, cin, sum, cout);

//define inputs and outputs
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
//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

//dataflow 2-input and gate
module and2_df (x1, x2, z1);

input x1, x2;
output z1;

wire x1, x2;
wire z1;

//continuous assign for dataflow
assign z1 = x1 & x2;
endmodule


//and3 dataflow
module and3_df (x1, x2, x3, z1);

input x1, x2, x3;             //list inputs and output
output z1;

wire x1, x2, x3;              //define signals as wire for dataflow
wire z1;

assign z1 = x1 & x2 & x3;     //continuous assign for dataflow

endmodule


//dataflow or2
module or2_df (x1, x2, z1);

input x1, x2;                 //list inputs and output
output z1;

wire x1, x2;                  //define signals as wire for dataflow
wire z1;

assign z1 = x1 | x2;          //continuous assign for dataflow

endmodule


//or3 dataflow
module or3_df (x1, x2, x3, z1);

input x1, x2, x3;
output z1;

wire x1, x2, x3;
wire z1;

assign z1 = x1 | x2 | x3;

endmodule






Page 221, Figure 4.45

//structural carry-select adder
module adder_carry_sel (a, b, sum, sel_nxt_mux);

input [11:0] a, b;
output [11:0] sum;
output sel_nxt_mux;

wire [11:0] a, b;
wire [11:0] sum;
wire sel_nxt_mux;

//define internal nets
wire     sum2_7, sum2_6, sum2_5, sum2_4, cout2, cout1,
         sum3_7, sum3_6, sum3_5, sum3_4, cout3, net8,
         net9, sum10_11, sum10_10, sum10_9, sum10_8, cout10,
         sum11_11, sum11_10, sum11_9, sum11_8, cout11,
         net16, net17;

//instantiate the 4-bit adder for a[3:0] and b[3:0]
adder4 inst1 (
      .a(a[3:0]),
      .b(b[3:0]),
      .cin(1'b0),
      .sum(sum[3:0]),
      .cout(cout1)
      );

//instantiate the 4-bit adder for a[7:4] and b[7:4]
adder4 inst2 (
      .a(a[7:4]),
      .b(b[7:4]),
      .cin(1'b0),
      .sum({sum2_7, sum2_6, sum2_5, sum2_4}),
      .cout(cout2)
      );

adder4 inst3 (
   .a(a[7:4]),
   .b(b[7:4]),
   .cin(1'b1),
   .sum({sum3_7, sum3_6, sum3_5, sum3_4}),
   .cout(cout3)
   );

//instantiate the 2:1 muxs for sum[7:4]
mux2_df inst4 (
      .sel(cout1),
      .data({sum3_4, sum2_4}),
      .z1(sum[4])
      );

mux2_df inst5 (
      .sel(cout1),
      .data({sum3_5, sum2_5}),
      .z1(sum[5])
      );

mux2_df inst6 (
      .sel(cout1),
      .data({sum3_6, sum2_6}),
      .z1(sum[6])
      );

mux2_df inst7 (
      .sel(cout1),
      .data({sum3_7, sum2_7}),
      .z1(sum[7])
      );

//instantiate the logic to select muxs for sum[11] thru sum[8]
and2_df inst8 (
      .x1(cout1),
      .x2(cout3),
      .z1(net8)
      );

or2_df inst9 (
      .x1(cout2),
      .x2(net8),
      .z1(net9)
      );

//instantiate the 4-bit adder for a[11:8] and b[11:8]
adder4 inst10 (
      .a(a[11:8]),
      .b(b[11:8]),
      .cin(1'b0),
      .sum({sum10_11, sum10_10, sum10_9, sum10_8}),
      .cout(cout10)
      );

adder4 inst11 (
      .a(a[11:8]),
      .b(b[11:8]),
      .cin(1'b1),
      .sum({sum11_11, sum11_10, sum11_9, sum11_8}),
      .cout(cout11)
      );

//instantiate the 2:1 muxs for sum[11:8]
mux2_df inst12 (
      .sel(net9),
      .data({sum11_8, sum10_8}),
      .z1(sum[8])
      );

mux2_df inst13 (
      .sel(net9),
      .data({sum11_9, sum10_9}),
      .z1(sum[9])
      );

mux2_df inst14 (
      .sel(net9),
      .data({sum11_10, sum10_10}),
      .z1(sum[10])
      );

mux2_df inst15 (
      .sel(net9),
      .data({sum11_11, sum10_11}),
      .z1(sum[11])
      );

and2_df inst16 (
   .x1(cout2),
   .x2(cout11),
   .z1(net16)
   );

and3_df inst17 (
   .x1(cout1),
   .x2(cout3),
   .x3(cout11),
   .z1(net17)
   );

or3_df inst18 (
   .x1(cout10),
   .x2(net16),
   .x3(net17),
   .z1(sel_nxt_mux)
   );

endmodule


//test bench for carry-select adder
module adder_carry_sel_tb;

//define inputs and outputs
reg [11:0] a, b;
wire [11:0] sum;
wire sel_nxt_mux;

//display outputs
initial
$monitor ("a = %b, b = %b, sum = %b, sel_nxt_mux = %b",
               a, b, sum, sel_nxt_mux);

//apply input vectors
initial
begin
      #0    a = 12'b0000_0000_0001;
            b = 12'b0000_0000_0010;

      #10   a = 12'b0000_0001_0010;
            b = 12'b0000_0000_0011;

     #10   a = 12'b0001_0001_0010;
            b = 12'b0000_0000_0011;

      #10   a = 12'b0011_0011_0010;
            b = 12'b0001_0100_0011;

      #10   a = 12'b1111_0000_0111;
            b = 12'b1000_1101_1000;

      #10   a = 12'b1111_1111_1111;
            b = 12'b1111_1111_1111;

      #10   a = 12'b1010_1010_1010;
            b = 12'b0101_0101_0101;

      #10   a = 12'b0111_1011_1010;
            b = 12'b0011_0110_1101;

      #10   a = 12'b1111_0111_0110;
            b = 12'b0011_1100_0111;

      #10   a = 12'b1100_1010_0111;
            b = 12'b0101_0011_0101;

      #10   a = 12'b0011_0111_1011;
            b = 12'b1011_0011_0111;

      #10   a = 12'b1011_0111_1100;
            b = 12'b0100_1000_0110;

      #10   $stop;
end

//instantiate the module into the test bench
adder_carry_sel inst1 (
      .a(a),
      .b(b),
      .sum(sum),
      .sel_nxt_mux(sel_nxt_mux)
      );

endmodule




























Page 228, Figure 4.50

//behavioral parallel-in, serial-out shift register
module shift_reg_piso8 (rst_n, clk, load, x, y, z1);
input rst_n, clk, load;
input [7:0] x;
output [7:0] y;
output z1;
reg [7:0] y;
assign z1 = y[0];
always @ (rst_n)
begin
      if (rst_n == 0)
         y <= 8'b0000_0000;
end
always @ (posedge clk)
begin
      y[7] <= ((load && x[7]) || (~load && 1'b0));
      y[6] <= ((load && x[6]) || (~load && y[7]));
      y[5] <= ((load && x[5]) || (~load && y[6]));
      y[4] <= ((load && x[4]) || (~load && y[5]));
      y[3] <= ((load && x[3]) || (~load && y[4]));
      y[2] <= ((load && x[2]) || (~load && y[3]));
      y[1] <= ((load && x[1]) || (~load && y[2]));
      y[0] <= ((load && x[0]) || (~load && y[1]));
end
endmodule


//behavioral serial-in parallel-out shift register
module shift_reg_sipo (rst_n, clk, ser_in, shift_reg);

input rst_n, clk, ser_in;
output [7:0] shift_reg;

reg [7:0] shift_reg;

always @ (rst_n)
begin
      if (rst_n == 0)
         shift_reg <= 8'b0000_0000;
end

always @ (posedge clk)
begin
      shift_reg [7] <= ser_in;
      shift_reg [6] <= shift_reg [7];
      shift_reg [5] <= shift_reg [6];
      shift_reg [4] <= shift_reg [5];
      shift_reg [3] <= shift_reg [4];
      shift_reg [2] <= shift_reg [3];
      shift_reg [1] <= shift_reg [2];
      shift_reg [0] <= shift_reg [1];
end
endmodule





//dataflow full adder
module full_adder (a, b, cin, sum, cout);

//list all inputs and outputs
input a, b, cin;
output sum, cout;

//define wires
wire a, b, cin;
wire sum, cout;

//continuous assign
assign sum = (a ^ b) ^ cin;
assign cout = cin & (a ^ b) | (a & b);

endmodule


//behavioral D flip-flop
module d_ff_bh (rst_n, clk, d, q, q_n);

input rst_n, clk, d;
output q, q_n;

wire rst_n, clk, d;
reg q;

assign q_n = ~q;

always @ (rst_n or posedge clk)
begin
      if (rst_n == 0)
          q <= 1'b0;
      else q <= d;
end
endmodule


//structural for serial adder
module adder_serial (rst_n, clk, load, a, b, sum);

input rst_n, clk, load;
input [7:0] a, b;
output [7:0] sum;

//define internal nets
wire     a_reg_out, b_reg_out, fa_sum, fa_cout,
         net4, d_ff_out;

//instantiate the parallel-in, serial-out shift registers
shift_reg_piso8 inst1 (
      .rst_n(rst_n),
      .clk(clk),
      .load(load),
      .x(a),
      .z1(a_reg_out)
      );

shift_reg_piso8 inst2 (
      .rst_n(rst_n),
      .clk(clk),
      .load(load),
      .x(b),
      .z1(b_reg_out)
      );
//instantiate the full adder
full_adder inst3 (
      .a(a_reg_out),
      .b(b_reg_out),
      .cin(d_ff_out),
      .sum(fa_sum),
      .cout(fa_out)
      );
//instantiate the d flip-flop and logic
and2_df inst4 (
      .x1(clk),
      .x2(~load),
      .z1(net4)
      );
d_ff_bh inst5 (
      .rst_n(rst_n),
      .clk(clk),
      .d(fa_out),
      .q(d_ff_out)
      );
//instantiate the serial-in, parallel-out shift register
shift_reg_sipo inst6 (
      .rst_n(rst_n),
      .clk(clk),
      .ser_in(fa_sum),
      .shift_reg(sum)
      );

endmodule


//test bench for the serial adder
module adder_serial_tb;

reg rst_n, clk, load;
reg [7:0] a, b;
wire [7:0] sum;

//define clock
initial
begin
      clk = 1'b0;
      forever
         #10 clk = ~clk;
end

//display variables
initial
$monitor ("a = %b, b = %b, sum = %b", a, b, sum);

//apply input vectors
initial
begin
      #0    rst_n = 1'b0;
      #2    rst_n = 1'b1;

      #3    a = 8'b0000_0011;
            b = 8'b0000_1000;

            load = 1'b1;
      #15   load = 1'b0;
//------------------------------
      #165  rst_n = 1'b0;
      #2    rst_n = 1'b1;

      #2    a = 8'b0001_1001;
            b = 8'b0010_0010;

            load = 1'b1;
      #15   load = 1'b0;
end

//determine length of simulation
initial
begin
      #370     $stop;
end

//instantiate the module into the test bench
adder_serial inst1 (
   .rst_n(rst_n),
   .clk(clk),
   .load(load),
   .a(a),
   .b(b),
   .sum(sum)
   );

endmodule













No comments:

Post a Comment