1

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

toolic
  • 5,637
  • 5
  • 20
  • 33

1 Answers1

1

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

toolic
  • 5,637
  • 5
  • 20
  • 33