Geek-9pm
First of all, what language is this?
What experience do you have?
This is VHDL - verilog.
I am a highschool student programming a DAQ to filter nuclear spectrometer data in real time (before you ask, there's no teacher in my school that knows anything about HDL or FPGAs). I have moderate experience with verilog and have a decent understanding of FPGAs. I've written the entire filter consisting of this logic:
aK,L[n] = x[n] − x[n − K] − x[n − L] + x[n − K − L]
b[n] = b[n − 1] + aK,L[n], n ≥ 0
c[n] = b[n] + MaK,L[n]
y[n] = y[n − 1] + c[n], n ≥ 0
Where x[n] is digitized input and y[n] is output. k, l, and M are user defined variables.
This equation outputs a y[n] that is m*(l or k +1) times larger than x[n]'s peak. I need to reduce y[n] by dividing it by m*(l+1). Because M and L are changing variables, I can't simply hard code a multiplication + bitshift into the FPGA.
I don't necessary need a dynamic variable to control a loop, here is a slightly altered version (Note, 7 iterations of the loop is the minimum number to ensure the correct value (truncated) being outputted given output is 14 bits unsigned or 15 bits signed):
module dividez (clk, num, den, out);
parameter bit = 64;
input clk;
input [bit-1:0] den, num;
output [13:0] out;
reg signed [bit-1:0] x, y;
reg [24:0] count;
assign out = $signed(count);
integer i;
always @ (posedge clk) begin
x = $signed(num);
count = 0;
y = den;
for (i = 0; i <= 6; i = i+1) begin
if (x >= 0) begin
if (x > (y*4096)) begin
x = x - (y*4096);
count = count + 4096;
end
if (x >= (y*1024)) begin
x = x - (y*1024);
count = count + 1024;
end
if (x >= (y*256)) begin
x = x - (y*256);
count = count + 256;
end
if (x >= (y*64)) begin
x = x - (y*64);
count = count + 64;
end
if (x >= (y*16)) begin
x = x - (y*16);
count = count + 16;
end
if (x >= (y*4)) begin
x = x - (y*4);
count = count + 4;
end
if (x >= (y)) begin
x = x - (y);
count = count + 1;
end
end
if (x < 0) begin
if (x <= -y*4096) begin
x = x + (y*4096);
count = count - 4096;
end
if (x <= -y*1024) begin
x = x + (y*1024);
count = count - 1024;
end
if (x <= -y*256) begin
x = x + (y*256);
count = count - 256;
end
if (x <= -y*64) begin
x = x + (y*64);
count = count - 64;
end
if (x <= -y*16) begin
x = x + (y*16);
count = count - 16;
end
if (x <= -y*4) begin
x = x + (y*4);
count = count - 4;
end
if (x <= -y) begin
x = x + (y);
count = count - 1;
end
end
end
end
endmoduleThis works logically and can be synthesized, although it takes up quite a bit of LUTs (over 10000). The entire loop also takes more than 0.5 clock cycles (4ns) to run, I need it under that for the rest of the hardware logic to function. The FPGA I currently have access to is the one on the Zynq-7000 SOC. I have 17,000 LUTs to work with and 4ns between pos-neg edges of clock.
The goal is to have a module that can do division of very large numbers very quickly. The first version can not be synthesized, this version above is too resource heavy and too slow. In case you aren't familiar with verilog, division is not possible natively. This is my attempt at division that I threw together in 20 minutes; the code won't be very organized. If you know of any other methods to do division using only +, -, * by integers, <<, >>, or logic, please let me know. Thanks!