Reputation: 2304
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
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