1
\$\begingroup\$

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

This is what I get when I try to run it: enter image description here

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

To debug Verilog simulations, you need to look at waveforms of internal signals. When I look at your FSM, I notice current_state never changes (it remains in its default state, start_st). You are missing logic to update the state register:

    always_ff @(posedge clk, posedge reset) begin
        if (reset) begin
            current_state <= start_st;
        end else begin
            current_state <= next_state;
        end
    end

With this change, I see the current state changing.

This shows you where to put the code:

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_ff @(posedge clk, posedge reset) begin
        if (reset) begin
            current_state <= start_st;
        end else begin
            current_state <= next_state;
        end
    end

fsm

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.