Verilog中的指数衰减

时间:2016-06-21 18:59:12

标签: verilog fpga

我是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为零)?有谁知道这里出了什么问题?

1 个答案:

答案 0 :(得分:1)

签名号码应使用>>>签署延期。不确定为什么需要执行* -1>>>可能会解决问题。在转换之前还要考虑乘法以保持更好的精度。

也在做:

tmp = {in,10'd0};
tmp = $signed(tmp) >> 10;

没有太多意义你用0填充LSB然后将零移出。

签名扩展(相当于>>>)这可能是MSB复制10次:

tmp = { {10{in[32-1]}}, in};

我会避免重复使用像tmp这样的变量,并为每个部分使用命名和大小的变量,这不会影响合成的大小。