Electronic – Synthesis of a multiplier design

multiplierverilog

I have written a verilog code for a multiplier which gives correct results after simulation. But, the code generated after synthesis of the above mentioned code does not give correct results. In fact, it gives no results. The log file created after synthesis says that there could be possible timing errors with my design, although I have tried to synchronize everything at the positive edge of the clock. Besides, it also generates a warning which says:

Variable or signal is driven in more than one process or block. This may cause simulation mismatches between the original and synthesized designs. [CDFG2G-622]
: 'qq[1]' in module 'ab_mac' in file '/ugassignments/ma3ps139/cadence/abacus8_syn/abacus8_chk.v' on line 59, column 22.

I don't know how to rectify this. Please help. Here is the code:

      module ab_mac (result, a, b, clk, reset, zero);
      output [16:1] result;
      input [8:1] a, b;
      input [11:0] zero;
      reg [8:1] A, B;
      input clk, reset;
      wire [16:1] p0, p1, p2, p3, p4, p5, p6, p7;
      reg [9:0] qq [16:1];
      reg [9:0] rr [16:1];
      wire [9:0] q [16:1];
      wire [3:0] ones [16:1];
      genvar j, i,  k, m;
      reg [4:0] count;

      part_prod_gen1 ppg (p0, p1, p2, p3, p4, p5, p6, p7, a, b);

     //load the partial products
     generate
 for (j=1; j<=16; j=j+1)
 begin: loop1
  always @ (posedge clk)
  begin
  if (!reset)
  begin
    if (count == 5'b00000)
    begin
    qq[j][9] <= p7[j];
    qq[j][8] <= p6[j];
    qq[j][7] <= p5[j];
    qq[j][6] <= p4[j];
    qq[j][5] <= p3[j];
    qq[j][4] <= p2[j];
    qq[j][3] <= p1[j];
    qq[j][2] <= p0[j];
    qq[j][1] <= 1'b0;
    qq[j][0] <= 1'b0;
    end

  else if (count[0] == 1)
    begin
      qq[j] <= q[j];
    end

  else 
    begin
      case (ones[j])
      4'b0010 : 
      begin {qq[j][9], qq[j][8]} <= 2'b0;
          if (j<16) qq[j+1][9-ones[j+1]] <= 1'b1; end

      4'b0011 : 
      begin {qq[j][9], qq[j][8]} <= 2'b0;
          if (j<16) qq[j+1][9-ones[j+1]] <= 1'b1; end

      4'b0100 : 
      begin {qq[j][9], qq[j][8], qq[j][7],qq[j][6]} <= 4'b0;
          if (j<15) qq[j+2][8-ones[j+2]] <= 1'b1; end

      4'b0101 : 
      begin {qq[j][9], qq[j][8], qq[j][7],qq[j][6]} <= 4'b0;
          if (j<15) qq[j+2][8-ones[j+2]] <= 1'b1; end

      4'b0110 : 
      begin {qq[j][9], qq[j][8], qq[j][7],qq[j][6]} <= 4'b0;
          if (j<15) qq[j+2][8-ones[j+2]] <= 1'b1; end

      4'b0111 : 
      begin {qq[j][9], qq[j][8], qq[j][7],qq[j][6]} <= 4'b0;
          if (j<15) qq[j+2][8-ones[j+2]] <= 1'b1; end

      4'b1000 : 
      begin {qq[j][9],qq[j][8],qq[j][7],qq[j][6],qq[j][5],qq[j][4],qq[j][3],qq[j][2]} <= 8'b0; 
          if (j<14) qq[j+3][7-ones[j+3]] <= 1'b1; end
      endcase
    end
end
end
end
   endgenerate

    //compress the partial products
      generate
      for (i=1; i<=16; i=i+1)
      begin: loop2
      count_one con (ones[i], qq[i]);
      shift sft (q[i], qq[i]);
      end
      endgenerate

assign result[1] = qq[1][9] & (!reset) ,
       result[2] = qq[2][9] & (!reset) ,
       result[3] = qq[3][9] & (!reset) ,
       result[4] = qq[4][9] & (!reset) ,
       result[5] = qq[5][9] & (!reset) ,
       result[6] = qq[6][9] & (!reset) ,
       result[7] = qq[7][9] & (!reset) ,
       result[8] = qq[8][9] & (!reset) ,
       result[9] = qq[9][9] & (!reset) ,
       result[10] = qq[10][9] & (!reset) ,
       result[11] = qq[11][9] & (!reset) ,
       result[12] = qq[12][9] & (!reset) ,
       result[13] = qq[13][9] & (!reset) ,
       result[14] = qq[14][9] & (!reset) ,
       result[15] = qq[15][9] & (!reset) ,
       result[16] = qq[16][9] & (!reset) ;

      always @ (posedge clk)
      if (reset)
      count <= 5'b00000;
      else
      begin
      count <= count + 1'b1;
      if(count == 5'b10001)
     count <= 5'b00000;
     end  

     endmodule

Also, here are the codes for the other instances in case you would like to verify:

    module shift (out, in);
    output[9:0] out;
    input [9:0] in;
    wire [3:0] ones;
    genvar i;
    count_one coon (ones, in);
    generate
    for (i=9; i>=0; i=i-1)
    begin: loop
    assign out[i] = (i > (9-ones)? 1 : 0);
    end
    endgenerate
    endmodule  

   module count_one (ones, column);
   output [3:0] ones;
   input [9:0] column;
   assign ones =    column[9]+column[8]+column[7]+column[6]+column[5]+column[4]+column[3]+column[2]+column[1]+column[0];
  endmodule

  module part_prod_gen (p0, p1, p2, p3, p4, p5, p6, p7, in1, in2);
  output [15:1] p0, p1, p2, p3, p4, p5, p6, p7;
  input [7:0] in1, in2;
  wire [7:0] pp [7:0];
  genvar i, j;

  generate
  for (i=0; i<=7; i=i+1)
  begin: loop1
   for (j=0; j<=7; j=j+1)
   begin: loop2
   assign pp[i][j] = in1[j] & in2[i];
 end
 end
 endgenerate

 assign p0 = {7'b0, pp[0][7], 7'b0};
 assign p1 = {6'b0, pp[1][7], pp[1][6], pp[0][6], 6'b0};
 assign p2 = {5'b0, pp[2][7:5],pp[1][5],pp[0][5],5'b0};
 assign p3 = {4'b0, pp[3][7:4],pp[2][4],pp[1][4],pp[0][4],4'b0};
 assign p4 = {3'b0, pp[4][7:3],pp[3][3],pp[2][3],pp[1][3],pp[0][3],3'b0};
 assign p5 = {2'b0, pp[5][7:2],pp[4][2],pp[3][2],pp[2][2],pp[1][2],pp[0][2],2'b0};
 assign p6 = {1'b0, pp[6][7:1],pp[5][1],pp[4][1],pp[3][1],pp[2][1],pp[1][1],pp[0]   [1],1'b0};
 assign p7 = {pp[7][7:0],pp[6][0],pp[5][0],pp[4][0],pp[3][0],pp[2][0],pp[1][0],pp[0][0]};
 endmodule

Best Answer

I presume that you are synthesising for an FPGA or CPLD. The simulator will successfully simulate many language constructs which are technically valid Verilog, but are very hard to translate to real programmable logic hardware.

I can't synthesise your block myself as I don't have the part_prod_gen1, count_one and shift modules available, but the problems I can see from reading the code are:

  • Using posedge and negedge always@ blocks for signals other than clock and reset lines often isn't synthesisable (see this answer). I think that using shift registers (explicitly or with a signal_old register) is a much more reliable approach than testing for posedge of count[0].
  • Register array qq elements are assigned in multiple separate processed (always blocks). This is not synthesisable as the process blocks run in parallel and the register flip-flop cannot be set from two different sources. You can rectify this by combining much of the code into a single sequential process (which is ugly and harder to debug) or using intermediate wires which are combined together in a single process. See this answer for a similar problem.

    genvar j, i,  k, m;
    // ... other code
    //load the partial products
    generate
      for (j=1; j<=16; j=j+1)
      begin: loop1
        always @ (posedge clk)
        begin
          if (!reset) begin
          // ... qq assignments
          end
        end
      end
    endgenerate
    
    /* should be */
    
    genvar i,  k, m;
    integer j; // j as integer not genvar
    // ... other code
    //load the partial products
    //generate // comment out or remove
    always @ (posedge clk)
    begin
      for (j=1; j<=16; j=j+1) // <- for-loop inside always block
      begin: loop1
        if (!reset) begin
        // ... qq assignments
        end
      end
    end
    //endgenerate // comment out or remove