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 :)
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 start
señal. He agregado una done
señ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 wire
s.
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.
martin thompson