I am trying to implement a multiplication 32x32 Mealy machine using a 16x8 multiplicator in Verilog. I wrote the arithmetic part and the FSM part + a code to connect both and a test bench, but when I am trying to run it in Modelsim, it seems like nothing happened -- only the initial values. I am new to Verilog and can't find my mistake.
I have a b_sel of 16, 16, a_sel of 8,8,8,8, shifter with 6 positions, a_msb_is_0 to check if a's most significant bite is 0 and b_msw_is_0 to check if b's most significant word is zero. the machine should run only after start = 0 and to store the value in the register until the next start happens.
Here is my code:
mult32x32_fast_fsm.sv:
// 32X32 Multiplier FSM
module mult32x32_fast_fsm (
input logic clk, // Clock
input logic reset, // Reset
input logic start, // Start signal
input logic a_msb_is_0, // Indicates MSB of operand A is 0
input logic b_msw_is_0, // Indicates MSW of operand B is 0
output logic busy, // Multiplier busy indication
output logic [1:0] a_sel, // Select one byte from A
output logic b_sel, // Select one 2-byte word from B
output logic [2:0] shift_sel, // Select output from shifters
output logic upd_prod, // Update the product register
output logic clr_prod // Clear the product register
);
typedef enum { start_st, mult1x1_st, mult2x1_st,mult3x1_st,mult4x1_st,mult1x2_st,mult2x2_st,mult3x2_st,mult4x2_st} sm_type;
//signals for curr and next state
sm_type current_state;
sm_type next_state;
always_comb begin
// Defining defaults
next_state = current_state;
busy = 1'b0;
a_sel = 2'b00;
b_sel = 1'b0;
shift_sel = 3'b000;
upd_prod = 1'b0;
clr_prod = 1'b0;
case (current_state)
start_st: begin
if(start == 1'b1) begin
next_state = mult1x1_st;
upd_prod = 1'b1;
end
end
mult1x1_st: begin
next_state = mult2x1_st;
busy = 1'b1;
upd_prod = 1'b1;
a_sel = 2'b01;
shift_sel = 3'b001;
end
mult2x1_st: begin
next_state = mult3x1_st;
busy = 1'b1;
a_sel = 2'b10;
b_sel = 1'b0;
shift_sel = 3'b010;
upd_prod = 1'b1;
end
mult3x1_st: begin
busy = 1'b1;
if(a_msb_is_0 == 1 && b_msw_is_0 == 1) begin
next_state = start_st;
end
else if(a_msb_is_0 == 1 && b_msw_is_0 == 0) begin
next_state = mult1x2_st;
a_sel = 2'b00;
b_sel = 1'b1;
shift_sel = 3'b100;
upd_prod = 1'b1;
end
else begin
next_state = mult4x1_st;
a_sel = 2'b11;
b_sel = 1'b0;
shift_sel = 3'b011;
upd_prod = 1'b1;
end
end
mult4x1_st: begin
busy = 1'b1;
if(b_msw_is_0 == 1) begin
next_state = start_st;
end
else begin
next_state = mult1x2_st;
a_sel = 2'b00;
b_sel = 1'b1;
shift_sel = 3'b100;
upd_prod = 1'b1;
end
end
mult1x2_st: begin
next_state = mult2x2_st;
busy = 1'b1;
a_sel = 2'b01;
b_sel = 1'b1;
shift_sel = 3'b101;
upd_prod = 1'b1;
end
mult2x2_st: begin
next_state = mult3x2_st;
busy = 1'b1;
a_sel = 2'b10;
b_sel = 1'b1;
shift_sel = 3'b110;
upd_prod = 1'b1;
end
mult3x2_st: begin
busy = 1'b1;
if(a_msb_is_0 == 1) begin
next_state = start_st;
end
else begin
next_state = mult4x2_st;
a_sel = 2'b11;
b_sel = 1'b1;
shift_sel = 3'b111;
upd_prod = 1'b1;
end
end
mult4x2_st: begin
if(start == 1'b1) begin
next_state = start_st;
clr_prod = 1'b1;
end
next_state = mult4x2_st;
busy = 1'b1;
end
endcase
end
endmodule
mult32x32_fast_arith.sv:
// 32X32 Multiplier arithmetic unit template
module mult32x32_fast_arith (
input logic clk, // Clock
input logic reset, // Reset
input logic [31:0] a, // Input a
input logic [31:0] b, // Input b
input logic [1:0] a_sel, // Select one byte from A
input logic b_sel, // Select one 2-byte word from B
input logic [2:0] shift_sel, // Select output from shifters
input logic upd_prod, // Update the product register
input logic clr_prod, // Clear the product register
output logic a_msb_is_0, // Indicates MSB of operand A is 0
output logic b_msw_is_0, // Indicates MSW of operand B is 0
output logic [63:0] product // Miltiplication product
);
//Logics
logic[7:0] A_2_MULT;
logic[15:0] B_2_MULT;
logic[23:0] MULT_2_SHIFTER;
logic[63:0] SHIFTER_2_ADDER;
logic[63:0] ADDER_2_PROD;
logic[63:0] PROD_2_ADDER;
// FSM synchronous procedural block for storing product.
always_ff @(posedge clk, posedge reset) begin
if (reset == 1'b1 || clr_prod == 1'b1) begin
product <= 64'b0;
end
else if (upd_prod == 1'b1 ) begin
product <= ADDER_2_PROD;
end
end
always_comb begin
assign a_msb_is_0 = a[31:24] == 0; // Outputs for FSM
assign b_msw_is_0 = b[31:16] == 0;
if (b_sel == 0) begin // MUX 2->1 For b operand
assign B_2_MULT = b[15:0];
end
else begin
assign B_2_MULT = b[31:16];
end
case (a_sel) // MUX 4->1 For a operand
2'b00 : begin
assign A_2_MULT = a[7:0];
end
2'b01 : begin
assign A_2_MULT = a[15:8];
end
2'b10 : begin
assign A_2_MULT = a[23:16];
end
2'b11 : begin
assign A_2_MULT = a[31:24];
end
endcase
PROD_2_ADDER = product; // Connect Wire to product output
assign MULT_2_SHIFTER = A_2_MULT * B_2_MULT; // 16X8 Multiplier
assign SHIFTER_2_ADDER = MULT_2_SHIFTER << shift_sel; // Shifter
assign ADDER_2_PROD = SHIFTER_2_ADDER + PROD_2_ADDER ; // Adder
end
endmodule
mult32x32_fast.sv:
// 32X32 Iterative Multiplier template
module mult32x32_fast (
input logic clk, // Clock
input logic reset, // Reset
input logic start, // Start signal
input logic [31:0] a, // Input a
input logic [31:0] b, // Input b
output logic busy, // Multiplier busy indication
output logic [63:0] product // Miltiplication product
);
//Logics
logic [1:0] a_sel;
logic b_sel;
logic [2:0] shift_sel;
logic upd_prod;
logic clr_prod ;
logic a_msb_is_0;
logic b_msw_is_0;
mult32x32_fast_fsm FSM (.clk(clk), .reset(reset), .start(start),.a_sel(a_sel),.b_sel(b_sel),.shift_sel(shift_sel),.upd_prod(upd_prod),.clr_prod(clr_prod),.busy(busy),.a_msb_is_0(a_msb_is_0),.b_msw_is_0(b_msw_is_0));
mult32x32_fast_arith ARIC (.clk(clk), .reset(reset),.a(a),.b(b), .a_sel(a_sel),.b_sel(b_sel),.shift_sel(shift_sel),.upd_prod(upd_prod),.clr_prod(clr_prod),.a_msb_is_0(a_msb_is_0),.b_msw_is_0(b_msw_is_0), .product(product));
endmodule
and mult32x32_fast_test.sv:
// 32X32 Multiplier test template
module mult32x32_fast_test;
logic clk; // Clock
logic reset; // Reset
logic start; // Start signal
logic [31:0] a; // Input a
logic [31:0] b; // Input b
logic busy; // Multiplier busy indication
logic [63:0] product; // Miltiplication product
mult32x32_fast uut(.clk(clk), .reset(reset), .start(start), .a(a), .b(b), .busy(busy), .product(product));
always begin
#4 clk =~clk;
end
initial begin
clk = 1'b1;
reset = 1'b1;
start = 1'b0;
repeat(4) begin
@(posedge clk);
end
reset = 1'b0;
a = 321332983;
b = 206777104;
@(posedge clk);
start=1'b1;
@(posedge clk);
start=1'b0;
@(negedge busy);
@(posedge clk);
a = 9975;
b = 11024;
@(posedge clk);
start=1'b1;
@(posedge clk);
start=1'b0;
@(negedge busy);
end
endmodule