I am currently working on a design of an algorithm for signal processing. I created a model in software that appears to work fine and I am now trying to translate it to verilog. Below is what I do in the software.
I get a 16 bit input, I do the following
a. convert the hex to decimal
b. subtract 32768 from the above
c. divide the result with 32768
d. convert the result to a signed number in the Q(4,20) format (4 bits for integer, 20 bits fractional)
For example,
case 1: value is 0x803f (ie, value > 0x8000)
a. Convert 0x803f to decimal, ie, 32831
b. 32831 - 32768 = 63
c. 63/32768 = 0.001922
d. convert to signed Q(4,20) 0x0007C8
case 2: value is 0x79fc (ie, value < 0x8000)
a. Convert 0x79fc to decimal, ie, 31228
b. 32668 - 32768 = -100
c. -100/32768 = -0.003051
d. convert to signed Q(4,20) 0xFFF3B7
I started with the following code to translate the software model to verilog and obtained result don't match what I expected. For Case 1 and Case 2, observed value for Y_DIV
in simulation is
0x1
. But I expect value that is close to Y (Ox003f
for case 1 and 0xff9c
for case 2) as 1/32768
is relatively small.
With regards to converting 0x003f
and 0xff9c
to Q(4,20), if I sign extend 0x003f
, how do we achieve the target value of 0x0007C8
?
I am not sure if the following is the right way to translate my algorithm
module test(
input clk,
input rst,
input [15:0] a,
input [15:0] b,
output reg signed [15:0] y,
output reg signed [15:0] y_div
);
always @(posedge clk) begin
if (rst) begin
y <= 0;
y_div <= 0;
end else begin
y <= (a-b);
// since (1/32768 = 0.000030) are we better off using a multiply instead of divide ?
y_div <= (a-b)/b; // returns wrong value, ie doesn't match expected value
// Q(4,20) is yet to be done. First need to get the above working
end
end
endmodule
Below is my test bench
module tb_test();
reg CLK, RST;
reg [15:0] A, B;
wire [15:0] Y, Y_DIV;
initial begin
CLK = 0;
forever #1 CLK = ~CLK;
end
initial begin
RST = 1;
#10;
RST = 0;
end
initial begin
A = 16'b0;
B = 16'b0;
#10;
A = 16'h803f; // case 1
B = 16'h8000;
#10;
A = 16'h7f9c; // case 2
B = 16'h8000;
end
test dut (.clk(CLK), .rst(RST), .a(A), .b(B), .y(Y), .y_div(Y_DIV));
endmodule