1
votes

I am writing a code which uses a multiplier module which returns weird answers when one of the inputs is a negative number. I am guessing this has to do with how Verilog treats signed numbers and the module is not storing the result properly in the 'reg signed out' decleration. All my input/output/wire/reg declarations are signed, so I am not sure what I am missing and what else I need to do to tell Verilog to take care of this. Sorry for the beginner question!

For example,

When X[0] is 1610 and Theta1[1] is -123, the result I am getting from the multiplier module is: 6914897148530

Here are the relevant parts of my code:

module mult(in1, in2, out, mult_start); // multiplication module

input signed    [32-1:0]    in1, in2;
input               mult_start;

output      signed [64-1:0] out;
reg         signed [64-1:0] out;

always @(in1 or in2 or mult_start)
begin
    if (mult_start)
    begin
        out <= (in1 * in2) & {64{1'b1}};
    end
    else
        out <= out;
end
endmodule



module child_one (clk, rst_b, sig_start, Input_X, Input_Theta1)

// Internal Variables Memory
reg signed [`REG_LENGTH-1:0] Theta1 [0:217-1];
reg signed [`REG_LENGTH-1:0] X [0:216-1];
wire signed [`OUT_LENGTH-1:0] prod_1 [0:217-1];
reg signed [`OUT_LENGTH-1:0] prod_sum;
wire signed [`OUT_LENGTH-1:0] sig_result;

mult mult_001 (X[0], Theta1[1], prod_1[1], mult_start); 
mult mult_002 (X[1], Theta1[2], prod_1[2], mult_start); 
mult mult_003 (X[2], Theta1[3], prod_1[3], mult_start); 
mult mult_004 (X[3], Theta1[4], prod_1[4], mult_start); 

always @(posedge clk or negedge rst_b)
begin
    if (sig_start == 1) 
    begin
        if (state == 4'b0000)
        begin
            state <= 4'b0001; // initialize state variable to zero
            k <= 0;
            result_done <= 0;
            index <= 0;
        end
        else if (state == 4'b0001) // Start Multiplication Operation
        begin
            k               <= result_done ?      0     : k + 1;
            result_done     <= result_done ?      1     : (k == 10);
            state       <= result_done ?      4'b0010   : 4'b0001;
            mult_start  <= result_done ?      1'b1  : 1'b0; 
        //mult_start <= 1'b1;
        //state <= 4'b0010;
        end
        else if (state == 4'b0010) // Stop Multiplication Operation
        begin
            k <= 0;
            result_done <= 0;
            mult_start <= 0;
            state <= 4'b0011;
        end
    end
end

endmodule

Thanks,

Faisal.

1
I don't know Verilog at all and I don't know why this question is tagged VHDL, but I cannot see how assigning to Theta1[0] affects any of the multiplier modules at all.user_1818839
sorry about both those things. The Theta1[0] example was something I added at the end to show the problem I was having n I didn't paste it properly. As for the vhdl tag, that was cos I thought the problem I am having is a hardware language issue and someone who knew HDLs could let me know what I am missing with regards to signed, two's complement, sign extend, or something like that...Faisal Rasool
That's OK. I hear enough odd things about Verilog that I decided to avoid it - including that it does unsigned arithmetic by default; and signed and unsigned multiplication are somewhat different processes. All I can suggest is to create a testbench for the multiplier module and work on it in isolation - simplify it to "out <= (in1 * in2)", add assert/report to see its internals, or additional output ports for intermediate signals, until you understand it and it does what you expect - then add back in any other functionality you need. In VHDL, numeric_std.signed would make this module easy.user_1818839
thanks for the suggestion about writing a testbench for the multiplier module. i tried a bunch of cases in the testbench and it worked through some trial and error! it was an issue of sign extension.Faisal Rasool
If you solved your problem, consider posting your solution as an answer and ticking the 'accept' checkbox. Then we know it's been solved. Thanks!Tim

1 Answers

5
votes

Thanks for all the help and suggestions. Writing a separate testbench for the mult module helped arrive at a solution.

My issue was in the mult module. Since my inputs are 32 bits long, the mult output would be 32*2+1 = 65 bits long. My output port 'out' was only assigned to be 64 bits long which resulted in a sign issue when the answer was a negative number. Assigning it to be 65 bits long took care of my problem.