1
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ @Xcodo, I have posted the remaining parts of the code. Please have a look at it. \$\endgroup\$ – titan May 23 '14 at 10:15
  • 1
    \$\begingroup\$ You can use for loops inside a process in Verilog (or VHDL), the syntax is the same as in C. However it's only synthesisable if the loop condition is constant at compile time, that is that the loop variable is being incremented up on down to a fixed value, either a numeric constant or a module parameter. In hardware this is equivalent to multiple copies of the circuit in parallel (like generates). Just be careful to ensure that none of the iterations rely on the result of another iteration in the same clock cycle or you will get a chain of the circuits rather than a parallel set. \$\endgroup\$ – Xcodo May 23 '14 at 12:32
4
\$\begingroup\$

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
    
\$\endgroup\$
  • 1
    \$\begingroup\$ I've found the source of that. In the case statement based on ones[j] you assign values to qq[j+1]. In the simulator or on paper try to step through that logic to find out what you're actually assigning each time. Make sure for any condition each qq[][] bit is only assigned once per clock cycle. I'm afraid I have to go do some work so won't be able to look again until tonight. Let me know how you get on! \$\endgroup\$ – Xcodo May 23 '14 at 13:35
  • 1
    \$\begingroup\$ Sorry - I missed that j was still in a generate statement (I'm not doing badly since I haven't used Verilog in about five years, only VHDL!) Move the j to a for loop INSIDE the always block and it will at least synthesise. \$\endgroup\$ – Xcodo May 23 '14 at 17:54
  • 1
    \$\begingroup\$ For clarification - the generate statement is just a convenient shorthand for writing the always@ process 16 times. In each of those blocks there is a possibility (the synthesiser isn't too smart) that the process could write to a given qq register, so it is given as a driver. All of these generated processes then have a claim on driving the output, which isn't synthesisable. \$\endgroup\$ – Xcodo May 23 '14 at 17:57
  • 2
    \$\begingroup\$ @Xcodo, good debug. I added a code example of second bullet to be more specific. \$\endgroup\$ – Greg May 23 '14 at 18:06
  • 1
    \$\begingroup\$ @titan, It will be all done in one clock cycle. There are no delay elements in the always block. The for-loop will execute in zero time. \$\endgroup\$ – Greg May 23 '14 at 22:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.