Síntesis de un diseño multiplicador

1

He escrito un código verilog para un multiplicador que da resultados correctos después de la simulación. Pero, el código generado después de la síntesis del código mencionado anteriormente no da resultados correctos. De hecho, no da resultados. El archivo de registro creado después de la síntesis dice que podría haber posibles errores de sincronización con mi diseño, aunque he intentado sincronizar todo en el borde positivo del reloj. Además, también genera una advertencia que dice:

  

La variable o señal se controla en más de un proceso o bloque. Esto puede causar desajustes de simulación entre los diseños originales y sintetizados. [CDFG2G-622]           : 'qq [1]' en el módulo 'ab_mac' en el archivo '/ugassignments/ma3ps139/cadence/abacus8_syn/abacus8_chk.v' en la línea 59, columna 22.

No sé cómo rectificar esto. Por favor ayuda. Aquí está el código:

      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

Además, aquí están los códigos para las otras instancias en caso de que desee verificar:

    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
    
pregunta titan

1 respuesta

4

Supongo que estás sintetizando para un FPGA o CPLD. El simulador simulará con éxito muchas construcciones de lenguaje que son Verilog técnicamente válidas, pero son muy difíciles de traducir a hardware lógico programable real.

No puedo sintetizar el bloqueo, ya que no tengo los módulos part_prod_gen1, count_one y shift disponibles, pero los problemas que puedo ver al leer el código son:

  • El uso de posicionamiento y negación siempre en bloques @ para señales distintas del reloj y las líneas de reinicio no es sintetizable (consulte esta respuesta ). Creo que el uso de registros de desplazamiento (explícitamente o con un registro signal_old) es un enfoque mucho más confiable que las pruebas para determinar el número de cuenta [0].
  • Los elementos qq de la matriz de registro se asignan en varios procesados separados (siempre bloques). Esto no es sintetizable ya que los bloques de proceso se ejecutan en paralelo y el registro flip-flop no se puede configurar desde dos fuentes diferentes. Puede rectificar esto combinando gran parte del código en un solo proceso secuencial (que es feo y más difícil de depurar) o utilizando cables intermedios que se combinan en un solo proceso. Consulte esta respuesta para obtener un problema similar.

    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
    
respondido por el Xcodo

Lea otras preguntas en las etiquetas