0
votes

I have a 32x32 multiplier in system-verilog with an fsm style machine that basically does long multiplication like in school.

I tested it 2 days ago, and it worked out fine. But, suddenly without even changing the code, one of the outputs just stays put at 0 for no reason. Here is the code:

// 32X32 Multiplier arithmetic unit template
module mult32x32_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 a_sel,           // Select one byte from A
    input logic b_sel,           // Select one 2-byte word from B
    input logic [1:0] shift_sel, // Select output from shifter
    input logic upd_prod,        // Update the product register
    input logic clr_prod,        // Clear the product register
    output logic [63:0] product  // Miltiplication product
);

// Put your code here
// ------------------
logic [15:0] mux2to1a;
logic [15:0] mux2to1b;
logic [31:0] mul;
logic [63:0] shift0;
logic [63:0] shift16;
logic [63:0] shift32;
logic [63:0] mux4to1;
logic [63:0] adder;
always_comb begin
    if(a_sel==1'b1)begin
         mux2to1a=a[31:16];
    end
    else begin
         mux2to1a=a[15:0];
    end
    
    if(b_sel==1'b1)begin
         mux2to1b=b[31:16];
    end
    else begin
         mux2to1b=b[15:0];
    end
    
    mul=mux2to1a*mux2to1b;
    
    shift0=mul;
    
    shift16= mul << 16;
    shift32= mul << 32;
    
    if(shift_sel[0]==1'b0&&shift_sel[1]==1'b0)begin
        mux4to1=shift0;
    end
    else if(shift_sel[0]==1'b1&&shift_sel[1]==1'b0)begin
        mux4to1=shift16;
    end
    else if(shift_sel[0]==1'b0&&shift_sel[1]==1'b1)begin
        mux4to1=shift32;
    end
    else begin
        mux4to1=0;
    end
    
    adder=mux4to1+product;
    
end

always_ff @(posedge clk, posedge reset)begin
                if(reset)begin
                    product<=0;
                end
                
                else begin
                    if(upd_prod==1'b1)begin
                        product<=adder;
                    end
                    else begin
                        product<=product;
                    end     
                    
                    if(clr_prod==1'b1)begin
                        product<=0;
                    end
                    else begin
                        product<=product;
                    end
                end
    end
// End of your code

endmodule

For some reason the product output stays at 0 although you can see that the adder value changes.

enter image description here

EDIT: the rest of the code (fsm and tb)

FSM part:

// 32X32 Multiplier FSM
module mult32x32_fsm (
    input logic clk,              // Clock
    input logic reset,            // Reset
    input logic start,            // Start signal
    output logic busy,            // Multiplier busy indication
    output logic a_sel,           // Select one byte from A
    output logic b_sel,           // Select one 2-byte word from B
    output logic [1:0] shift_sel, // Select output from shifter
    output logic upd_prod,        // Update the product register
    output logic clr_prod         // Clear the product register
);

// Put your code here
// ------------------
typedef enum {idle, a0b0,a0b1,a1b0,a1b1} sm_type;

sm_type current, next;

always_ff @(posedge clk, posedge reset) begin
    if(reset) begin
        current<=idle;
    end
    else begin
        current<=next;
    end
end

always_comb begin
    next=idle;
    busy=1'b1;
    a_sel=1'b0;
    b_sel=1'b0;
    shift_sel={1'b0,1'b1};
    upd_prod=1'b1;
    clr_prod=1'b0;
    case(current)
        idle: if(start==1'b1) begin
                next=a0b0;
                busy=1'b0;
                upd_prod=1'b0;
                clr_prod=1'b1;
            end 
            else begin
                next=idle;
                busy=1'b0;
                upd_prod=1'b0;
            end
        a0b0: begin 
            next=a0b1;
            shift_sel={1'b0,1'b0};
            end
        
        a0b1: begin
            next=a1b0;
            b_sel=1'b1;
            end
        a1b0: begin
            next=a1b1;
            a_sel=1'b1;
            end
        a1b1: begin
            a_sel=1'b1;
            b_sel=1'b1;
            shift_sel={1'b1,1'b0};
            end
    endcase
end
// End of your code

endmodule

Combined Machine:

// 32X32 Iterative Multiplier template
module mult32x32 (
    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
);
// Put your code here
// ------------------
        
 logic a_sel;       
 logic b_sel;         
 logic [1:0] shift_sel; 
 logic upd_prod;      
 logic clr_prod; 
 
mult32x32_fsm fsm(
    .busy(busy),
    .a_sel(a_sel),
    .b_sel(b_sel),
    .shift_sel(shift_sel),
    .upd_prod(upd_prod),
    .clr_prod(clr_prod),
    .clk(clk),
    .reset(reset),
    .start(start)
    );
mult32x32_arith arith(
    .product(product),
    .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)
);

// End of your code
endmodule

Test Bench:

// 32X32 Multiplier test template
module mult32x32_tb;

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

// Put your code here
// ------------------

mult32x32 uut(
    .busy(busy),
    .product(product),
    .clk(clk),
    .reset(reset),
    .start(start),
    .a(a),
    .b(b)
);

initial begin
    clk=1'b1;
end
always begin
    #1 clk=~clk;
end

initial begin
    reset=1'b1;
    a=0;
    b=0;
    start=1'b0;
    repeat (4) begin
        @(posedge clk);
    end
    reset=1'b0;
    @(posedge clk);
    a=32'd211578794;
    b=32'd212209639;
    start=1'b1;
    #2;
    start=1'b0;
    @(negedge busy);
end
// End of your code

endmodule
1
yeah but its just code to copy paste so you can run the tb the only thing that could be a coding error and not a bug is in the first part, but 100% i think its some sort of bug caus it ran just fine like 2 days ago, its extremly wierdShalev rissin

1 Answers

1
votes

You have a bug in your logic. Your code always executes at least one of your 2 product<=product; lines because they are in separate if/else statements.

This works:

always_ff @(posedge clk, posedge reset) begin
    if (reset) begin
        product<=0;
    end else if (upd_prod) begin
        product<=adder;
    end else if (clr_prod) begin
        product<=0;
    end
end

This prioritizes upd over clr (if that is your intent).