user2224350
user2224350

Reputation: 2304

Exponential decay in Verilog

I'm new to Verilog and I need a little help here. I have a register array reg [32-1:0] out which represents a signed integer. A smaller array holds a number between 0 and 1000 reg [14-1:0] d. I would like to do something like this (damping out on every clock cycle):

always @(posedge clk_i) begin
    out <= $signed(out) * $unsigned(d)/1000;
end

I heared that using / is bad practice for synthesizable code. Can anyone show me how to implement such an exponential decay?

EDIT: I changed dividing by 1000 to dividing by 1024, because it's much easier to handle. My code looks now like this:

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

The code works well in simulation but on the fpga it seems like in is multiplied by zero (out is zero)? Does anyone know what is going wrong here?

Upvotes: 0

Views: 337

Answers (1)

Morgan
Morgan

Reputation: 20514

Signed number should use >>> to sign extend. Not sure why you need to do the * -1 maybe the >>> will solve the issue. Also consider multiplying before shifting to maintain better precision.

Also doing :

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

does not make too much sense you have padded the LSBs with 0's then shift the zeros out.

Sign extending (equivalent to >>>) this could be MSB replicated 10 times:

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

I would avoid reusing variables like tmp and use named and sized variables for each section, this will not effect the synthesised size.

Upvotes: 1

Related Questions