Verilog: combinando lógica secuencial con lógica combinacional

2

Estoyintentandoimplementaruncambiosecuencialyagregarunmultiplicadorde4bitscomosemuestraenlaimagen.

Tengounmóduloseparadoparaelsumadordeacarreoderizadode4bits.Heprobadoelmódulosumadoryfuncionabien.

ahoranecesitoactivarlodesdeelmódulomultiplicador.paraquesedispareenlaseñal'agregar'.Porfavor,ayudeamodificarelcódigodelsumadorderipplecarry.Heincluidoelcódigodereferencia

códigodelmóduloprincipalquenosecompilayaqueheincluidoelmódulorca4bitdentrodelbloquesiempresecuencial

'include"rca4bit.v"
module seq_mult_4bit(output [7:0]product,input [3:0]a,b,input clock,input reset,input start);
    //reg prod[7:0];
    reg multiplicand[3:0];

    parameter WAIT_STATE = 0, LOAD_STATE = 1, ADD_STATE = 2,SHIFT_STATE = 3;

    always @ (posedge clock) 
    begin
        if (reset)
            state <= WAIT_STATE;
        else
            case (state)
                WAIT_STATE:
                    if(start)
                        state = LOAD_STATE;
                    else
                        state = WAIT_STATE;

                LOAD_STATE:
                    //load data into registers
                    product[3:0] = 4'h0;//load accumulator with zeros
                    multiplicand[3:0] = a[3:0];
                    product[7:4] = b[3:0];
                    //read lsb
                    if(product[7] == 0)
                        state = ADD_STATE;//only add if there's a 1 in the multiplicand
                    else
                        state = SHIFT_STATE;//else move to shift state directly

                ADD_STATE:
                    //add the partial product
                    rca_4bit adder(product[3:0],c_out,multiplicand[3:0],product[3:0], 0);//adder block

                SHIFT_STATE:
                    product = {c_out,product[7:1]};
                    count = count + 1;
                    if(count == 3)//wrap around
                        count = 0;
            endcase
    end 
end module

// máquina de estados

código de módulo para el ondulador que lleva el sumador

'include "fulladder.v"

module rca_4bit(output [3:0]sum,output c_out,input [3:0]a,b,input c_in);

wire c1,c2,c3;

full_adder fa1(.in_x(a[0]),.in_y(b[0]),.c_out(c1),.sum_out(sum[0]),.c_in(c_in));
full_adder fa2(.in_x(a[1]),.in_y(b[1]),.c_out(c2),.sum_out(sum[1]),.c_in(c1));
full_adder fa3(.in_x(a[2]),.in_y(b[2]),.c_out(c3),.sum_out(sum[2]),.c_in(c2));
full_adder fa4(.in_x(a[3]),.in_y(b[3]),.c_out(c_out),.sum_out(sum[3]),.c_in(c3));
endmodule

por favor ayuda! PD: soy nuevo en verilog, así que disculpen mi noobness :)

    
pregunta user7994

2 respuestas

2

En lugar de abordar los muchos problemas en su código fuente, permítame mostrarle cómo implementaría el módulo que describe.

Primero, no usaría un submódulo para construir el sumador; Las herramientas de síntesis son perfectamente capaces de crear sumadores a partir de código de comportamiento. En segundo lugar, no se requiere una máquina de estados elaborada; el módulo puede simplemente producir un resultado final cuatro relojes después de cada activación de la señal start . He añadido una señal done a la interfaz del módulo para hacerlo explícito.

module seq_mult_4bit (
  output  [7:0] product,
  output        done,
  input   [3:0] a,
  input   [3:0] b,
  input         clock,
  input         start
);

  reg     [7:0] product;
  reg     [3:0] multiplicand;
  reg     [3:0] delay;

  wire    [4:0] sum = {1'b0, product[7:4]} + {1'b0, multiplicand};

  assign done = delay[0];

  always @(posedge clock) begin
    if (start) begin
      delay = 4'b1000;
      multiplicand = a;
      if (b[0]) begin
        product <= {1'b0, a, b[3:1]};
      end else begin
        product <= {1'b0, 4'b0, b[3:1]};
      end
    end else begin
      delay = {1'b0, delay[3:1]};
      if (product[0]) begin
        product <= {sum, product[3:1]};
      end else begin
        product <= {1'b0, product[7:1]};
      end
    end
  end

endmodule

Si realmente desea utilizar un módulo externo para el sumador (que es realmente el punto de su pregunta), simplemente sustituya la declaración de cableado anterior con el siguiente bloque de código:

  wire   [4:0] sum;

  rca_4bit adder (
    .sum        (sum[3:0]),
    .c_out      (sum[4]),
    .a          (multiplicand),
    .b          (product[7:4]),
    .c_in       (0)
  );

Avíseme si tiene alguna pregunta específica sobre cómo funciona esta implementación.

    
respondido por el Dave Tweed
2

Primero, en Verilog, un módulo instanciado siempre se considera lógica "combinatoria" incluso si contiene lógica secuencial dentro de él. Para los fines del módulo que lo contiene, es solo una caja negra con entradas y salidas, por lo que el módulo que lo contiene lo considera combinatorio. Eso significa que las salidas de una instancia se declaran como wire s.

En segundo lugar, en la lógica secuencial Verilog sucede dentro de bloques siempre. Todo lo que se asigne dentro de un bloque siempre se declarará como reg . La única manera de que la lógica secuencial (físicamente) ocurra dentro de un bloque siempre es en el lado derecho de una declaración de asignación.

Por lo tanto, solo necesitas mover tu instancia fuera del bloque siempre.

Aquí hay un fragmento mucho más simplificado:

module demo(clk, in, out)
   input clk;
   input in;
   output out;

   wire some_result;
   reg some_state;

   always @(posedge clk) begin
       case (some_state) 
           1'b0: begin
               out <= 1'b0;
               some_state <= /* calculate next state */
           1'b1: begin
               out <= some_result;
               some_state <= /* calculate next state */
        endcase
   end

   my_module inst0 ( .IN(in), .OUT(some_result) );
endmodule

Con esta estructura, la salida de la instancia está disponible para la máquina de estado, pero la instancia en sí misma se crea fuera del bloque siempre.

Si está tratando de ahorrar energía al hacer que la instancia solo opere cuando es necesario, puede asignar al módulo de nivel inferior una entrada HABILITAR y generar una señal en la máquina de estado para controlar esa entrada. Sin embargo, no recomendaría hacer esto a menos que realmente sepa que necesita ahorrar energía y que deshabilitar el módulo de nivel inferior reducirá significativamente el consumo de energía.

    
respondido por el The Photon

Lea otras preguntas en las etiquetas