2016-10-19 67 views
1

這是我編寫的簡單代碼。從'outt'我得到了122116.但是如果我將'outt'寬度更改爲33位([32:0]),那麼代碼似乎工作並給出正確答案-140028。這種行爲的原因是什麼?如何正確確定寄存器位寬?

`timescale 1ns/1ps 

module valu_parser(clk,outt); 

input clk; 
reg signed [31:0] r_1; 
reg signed [31:0] r_2; 
output reg signed [31:0] outt; 

initial begin 
    r_1 = -47938; 
    r_2 = -150096; 
end 

always @ (posedge clk) begin 
    outt <= ((r_1 + r_2)* 11585 + 8192)>>>14; 
end 
endmodule 

回答

-1

當您在11585乘以-198034(R1 + R1)你有結果最高位爲0(OUTT [31]),那麼如果你有32位有符號價值的開始是積極的,在回答你積極的結果。當你改變33bit時,你的最高位是1(outt [32]),結果是負值,你有正確的答案。

1

您正在執行的操作需要至少33位(右移之前的臨時結果使用33位),理論上它可能需要32+「被乘數常量的大小」,假設r_1和r_2不是常量。

如果您想到代碼將生成的硬件,則需要將這些位臨時存儲在某處,以便硬件先執行乘法,然後再進行加法,然後進行右移。

這將做到這一點,但也會產生比您想要的更多的寄存器。如果你使用這個模塊來生成一個常量,我會建議對這個常量進行硬編碼。

module valu_parser(clk,outt); 

input clk; 
reg signed [31:0] r_1; 
reg signed [31:0] r_2; 
reg signed [32:0] temp; 
output reg signed [31:0] outt; 

initial begin 
    r_1 = -47938; 
    r_2 = -150096; 
end 

always @ (posedge clk) begin 
    temp <= ((r_1 + r_2)* 11585 + 8192); 
end 

assign outt = temp>>>14; 

endmodule 

這個概念可以在這裏看到:https://www.edaplayground.com/x/3BXy

+0

非常感謝您的回答! – RONEY

1

在表達式中Verilog需要決定在計算中使用多少位。

+*運營商造成所謂上下文確定表達式。使用表達式F = A + B;,使用的位數是F,AB的最大值。這通常工作正常,因爲通常你會確保F足夠寬以存儲添加AB的結果。同樣,F = A * B;的表達式通常也可以正常工作,因爲通常您會確保F的寬度足以存儲乘以AB的結果。

但是,通過添加右移運算符,您可以使變量被指定得比計算移位運算符左側表達式實際所需的位數更窄。 Verilog在計算中使用的位數是outtr_1r_2115858192的寬度的最大值。所有這些都是32位寬(包括115858192),所以在計算中使用了32位。正如你所發現的,32位是不夠的,但是,對於你選擇的值,33位是。對於其他值,33位也不夠。對於一個完全靈活的解決方案,您應該使用66位(32 + 32 + 1 + 1) - 32位+32位進行乘法運算,再加上另外1位。

解決您的問題的方法是使r_1和/或r_2更寬或使用中間值(如Hida的答案所示)。

+0

非常感謝您的回答!它清除了這一點! :) – RONEY