2015-12-05 256 views
0

我正在设计一个Verilog处理器。我正在研究ALU,特别是ALU的乘数。在用小的正数进行乘法运算时,我可以得到正确的结果,但如果我尝试乘以有符号数,我会遇到问题。当一个正数乘以一个负数时,结果将不会一直扩展到64位,如果两个负数相乘,那么这个数字是完全不正确的(符号和数值)。任何人都可以看到问题在哪里?我认为我没有进行算术转换,但我调整了这一点,但仍然得到了错误的结果。有符号乘数Verilog

module multiplier(
     input[31:0] operand1, 
     input[31:0] operand2, 
     output reg [63:0] product 
    ); 

reg [64:0] prod; 
reg [31:0] mcand; 
reg [31:0] sum; 
integer i = 0; 


always @* begin 


    prod = {32'b0,operand1}; 
    mcand = operand2; 

    for(i=0;i<32;i=i+1) begin 

     //test 0 bit of product 
     case(prod[0]) 
      1'b0:begin  //if prod[0] == 0, arithmetic shift right 
        prod = prod>>>1; 
      end 

      1'b1:begin //if prod[0] == 1, add multiplicand to upper 32 
          //bits and arithmetic shift right 
        prod = {(prod[63:32]+mcand[31:0]),prod[31:0]}; 
        prod = prod>>>1; 
       end 
     endcase 
    end 

product = prod[63:0]; 

end 


endmodule 
+0

任何不在RTL中使用'*'的理由? – Morgan

回答

0

对于>>>执行带符号移位的变量必须声明为signed。

reg signed [64:0] prod; 

简短示例on eda playground

另请注意,prod = {32'b0,operand1};不是符号扩展名。你应该使用:

prod = { {32{operand[31]}}, operand1 }; 
+0

谢谢,经过签名的声明会使代码返回正确的值,但该符号仍然不正确。该算法要求我填充变量'prod'的高32位,因此对于这个实现 'prod = {32'b0,operand1}'是正确的 – tcas271