Search code examples
verilogvivado

carry look ahead adder verilog


I am designing GATE LEVEL MODELING 6BIT CARRY LOOK AHEAD ADDER. All INPUT OUTPUTs are fixed to D-FF and only up to 4 INPUT GATE can be used. I run the test code, and out and c_out keep returning only 0, which causes a problem and leaves me a question.

module DFF(input wire D, input wire clk, input wire rst, output reg Q);
  always @(posedge clk or negedge rst)
    if (!rst)
      Q <= 1'b0;
    else
      Q <= D;
endmodule


module CLA6(output [5:0] out, output c_out, input [5:0] in_A, in_B, input wire c_in, input wire clk, rst);
  wire [5:0] A, B;
  wire cin;
  DFF dff_in_A[5:0](
    .D(in_A),
    .clk(clk),
    .rst(rst),
    .Q(A)
  );
  
  DFF dff_in_B[5:0](
    .D(in_B),
    .clk(clk),
    .rst(rst),
    .Q(B)
  );
  DFF dff_c_in(.D(c_in), .clk(clk), .rst(rst), .Q(cin));

  wire [5:0] g, p;
  wire [26:0] e;
  wire [8:0] c;
  wire [5:0] sum;
//0
  and(g[0],A[0], B[0]);
  
  or (p[0], A[0], B[0]);

  and (e[0], p[0], cin);
  or (c[0], g[0], e[0]);

  xor (sum[0], A[0], B[0], cin);
//1  
  and(g[1], A[1], B[1]);
  
  or (p[1], A[1], B[1]);

  and (e[1], p[1], g[0]);
  and (e[2], p[1], p[0], cin);
  or (c[1], g[1], e[1], e[2]);

  xor (sum[1], A[1], B[1], c[0]);
 //2 
  and(g[2], A[2], B[2]);
  
  or (p[2], A[2], B[2]);

  and (e[3], p[2], g[1]);
  and (e[4], p[2], p[1], g[0]);
  and (e[5], p[2], p[1], p[0], cin); 
  or (c[2], g[2], e[3], e[4], e[5]);

  xor (sum[2], A[2], B[2], c[1]);
//3
  and(g[3], A[3], B[3]);
  
  or (p[3], A[3], B[3]);

  and (e[6], p[3], g[2]);
  and (e[7], p[3], p[2], g[1]);
  and (e[8], p[3], p[2], p[1], g[0]);
  and (e[9], p[0], cin);
  and (e[10], p[3], p[2], p[1], e[9]);
  or (c[3], e[8], e[10]);
  or (c[4], g[3], e[6], e[7], c[3]);

  xor (sum[3], A[3], B[3], c[2]);
  
//4 
  and(g[4], A[4], B[4]);
  
  or (p[4], A[4], B[4]);

  and (e[11], p[4], g[3]);
  and (e[12], p[4], p[3], g[2]);
  and (e[13], p[4], p[3], p[2], g[1]);
  and (e[14], p[1], g[0]);
  and (e[15], p[4], p[3], p[2], e[14]);
  and (e[16], p[1], p[0], cin);
  and (e[17], p[4], p[3], p[2], e[16]);
  or (c[5], e[13], e[15], e[17]);
  or (c[6], g[4], e[11], e[12], c[5]);

  xor (sum[4], A[4], B[4], c[4]);
//5
  and(g[5], A[5], B[5]);
  
  or (p[5], A[5], B[5]);

  and (e[18], p[5], g[4]);
  and (e[19], p[5], p[4], g[3]);
  and (e[20], p[5], p[4], p[3], g[2]);
  and (e[21], p[2], g[1]);
  and (e[22], p[5], p[4], p[3], e[21]);
  and (e[23], p[2], p[1], g[0]);
  and (e[24], p[5], p[4], p[3], e[23]);
  and (e[25], p[2], p[1], p[0], cin);
  and (e[26], p[5], p[4], p[3], e[25]);
  or (c[7], e[20], e[22], e[24], e[26]);
  or (c[8], g[5], e[18], e[19], c[7]);

  xor (sum[5], A[5], B[5], c[6]);
 
  DFF dff_out[5:0](
    .D(sum),
    .clk(clk),
    .rst(rst),
    .Q(out)
  );

  DFF dff_c_out(.D(c[8]), .clk(clk), .rst(rst), .Q(c_out));
endmodule

this is test bench code

`timescale 1ns/1ps

module tb_CLA6;

  // Inputs
  reg [5:0] in_A, in_B;
  reg c_in, clk, rst;

  // Outputs
  wire [5:0] out;
  wire c_out;

  // Instantiate CLA6 module
  CLA6 uut(
    .out(out),
    .c_out(c_out),
    .in_A(in_A),
    .in_B(in_B),
    .c_in(c_in),
    .clk(clk),
    .rst(rst)
  );

  // Clock generation
  initial begin
    clk = 0;
    forever #5 clk = ~clk;
  end

  // Initial stimulus
  initial begin
    // Initialize inputs
    in_A = 6'd30;
    in_B = 6'd15;
    c_in = 0;
    rst = 1;

    // Apply reset
    #10 rst = 0;

    // Wait for a few clock cycles
    
    // Apply new inputs
    in_A = 6'd15;
    in_B = 6'd17;
    c_in = 1;
    
    #10 rst = 0;
    
    in_A= 6'd10;
    in_B= 6'd11;
    c_in = 0;

    #10 $finish;
  end

endmodule 

enter image description here

enter image description here The carry equations are summarized as follows and expressed using wire. The last c[8] is c_out of the carry look ahead adder, and I want each sum[5:0] of the code to be output as out[5:0], but the result continues to be 0.

conditons The input of the design module goes through FF and is then applied to the 6-bit CLA of combinational logic. The output of combinational logic will be output as the output of the design module after going through FF. Combinational logic should be designed using gate level modeling using only logic gates with four or fewer inputs. FF is designed using behavioral modeling (positive edge triggered, negative edge asynchronous reset, D-FF) Can be configured with hierarchical design CLA6 is designed using gate level modeling


Solution

  • The basic problem is that the design reset is active low, and the teststbench is active high, so the design is held in reset forever. Maybe you intended for them both to be active low. If that is the case then they were just not sequenced properly. You are attempting to reset the design between application of the two vectors which does not seem to be necessary and was confusing you. If you want to reset between vectors, wait for the data for the first vector to appear at the ouput prior to resetting.

    Changing the reset to active low in the testbench and improving way that stimulus is applied brings the design to life. I reset only one time at t = 0, then apply a vector and wait, repeating the apply/wait pattern.

    Change the testbench main initial block to be:

      // Initial stimulus
      initial begin
        // reset
        rst = 0;
        repeat(2) @(posedge clk)
        rst = 1;
        repeat(1) @(posedge clk)
        
        // first vector
        in_A = 6'd30;
        in_B = 6'd15;
        c_in = 0;
    
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)
        
        // next vector
        in_A = 6'd15;
        in_B = 6'd17;
        c_in = 1;
        
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)
          
        in_A= 6'd10;
        in_B= 6'd11;
        c_in = 0;
        
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)    
    
        #10 $finish;
      end
    

    The waves look like this for me now: enter image description here

    You can improve the synchronization between testbench and DUT by using non-blocking assignments. Its the same strategy you used to model the dff ( combination of @(posedge clk) and non-blocking assignments <=.) This approach allows the testbench and DUT to behave as a synchronous system.

      // Initial stimulus
      initial begin
        // reset
        rst <= 0;
        repeat(2) @(posedge clk)
        rst <= 1;
        repeat(1) @(posedge clk)
        
        // first vector
        in_A <= 6'd30;
        in_B <= 6'd15;
        c_in <= 0;
    
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)
        
        // next vector
        in_A <= 6'd15;
        in_B <= 6'd17;
        c_in <= 1;
        
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)
        
        // next vector
        in_A<= 6'd10;
        in_B<= 6'd11;
        c_in <= 0;
        
       // Wait for a few clock cycles
        repeat(2) @(posedge clk)    
    
        #10 $finish;
      end
    

    Produces
    enter image description here Which makes sense (you can see 15 = hex F + 30 = hex 1e, adds to be 2d hex = 45 after two clock cycles, and you have a 2 clock pipe)