我是Verilog的新手,我需要一点帮助。
我有一个寄存器数组reg [32-1:0] out
,它代表一个有符号整数。
较小的数组包含0到1000 reg [14-1:0] d
之间的数字。我想做这样的事情(在每个时钟周期阻尼):
always @(posedge clk_i) begin
out <= $signed(out) * $unsigned(d)/1000;
end
我听说使用/是可合成代码的不良做法。谁能告诉我如何实现这种指数衰减?
编辑: 我改为除以1000除以1024,因为它更容易处理。我的代码现在看起来像这样:
reg [32-1:0] out;
reg [32-1:0] in;
reg [42-1:0] tmp;
reg [14-1:0] d;
always @(posedge clk_i) begin
tmp = {in,10'd0};
if(tmp[41]==1) begin
tmp = $signed(tmp) * -1;
tmp = $signed(tmp) >> 10;
tmp = $signed(tmp) * $unsigned(d);
tmp = $signed(tmp) * -1;
end
else begin
tmp = $signed(tmp) >> 10;
tmp = $signed(tmp) * $unsigned(d);
end
out <= tmp[42-1:10];
end
代码在模拟中运行良好,但在fpga上它似乎是乘以零(out为零)?有谁知道这里出了什么问题?
答案 0 :(得分:1)
签名号码应使用>>>
签署延期。不确定为什么需要执行* -1
,>>>
可能会解决问题。在转换之前还要考虑乘法以保持更好的精度。
也在做:
tmp = {in,10'd0};
tmp = $signed(tmp) >> 10;
没有太多意义你用0填充LSB然后将零移出。
签名扩展(相当于>>>
)这可能是MSB复制10次:
tmp = { {10{in[32-1]}}, in};
我会避免重复使用像tmp
这样的变量,并为每个部分使用命名和大小的变量,这不会影响合成的大小。