Verilog: combinación de lógica secuencial con lógica combinacional

Multiplicador secuencial

Estoy tratando de implementar un cambio secuencial y agregar un multiplicador de 4 bits como se muestra en la imagen.

Tengo un módulo separado para el sumador de acarreo de ondulación de 4 bits. He probado el módulo sumador y funciona bien.

ahora necesito activarlo desde el módulo multiplicador. para que se dispare en la señal 'agregar'. por favor, ayuda para modificar el código del sumador de acarreo de ondulación. He incluido el código como referencia.

código del módulo principal que no se compila ya que he incluido el módulo rca4bit dentro del bloque secuencial siempre

    `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 estatal

código de módulo para sumador de acarreo de ondulación

`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 disculpe mi novato :)

¿Qué error obtienes?

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 estado elaborada; el módulo puede simplemente producir un resultado final cuatro relojes después de cada activación de la startseñal. He agregado una doneseñal a la interfaz del módulo para hacer esto 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 usar un módulo externo para el sumador (que es realmente el punto de su pregunta), simplemente sustituya la declaración de cable 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.

Primero, en Verilog, un módulo instanciado siempre se considera lógica "combinatoria", incluso si contiene lógica secuencial en su interior. A los efectos 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 wires.

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

Entonces solo necesita mover su 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 misma se instancia fuera del bloque siempre.

Si está tratando de ahorrar energía haciendo que la instancia solo funcione cuando lo necesita, puede darle al módulo de nivel inferior una entrada ENABLE 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.