Created
March 10, 2026 17:21
-
-
Save LIMPIX31/72856860be253a0625ddd3804cd7eeb2 to your computer and use it in GitHub Desktop.
Piecewise Linear Reciprocal function Approximation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module reciprocal # | |
| ( parameter int I = 16 | |
| , parameter int O = I + 2 | |
| , parameter int S = 8 | |
| ) | |
| ( input logic clk | |
| , input logic i_ce | |
| // Q0.I Demoninator in range 0.5 .. 1 | |
| , input logic [I-1:0] i_den | |
| // Q2.I Reciprocal in range 1 .. 2 | |
| , output logic [O-1:0] o_rec | |
| ); | |
| wire _unused = i_den[I-1]; | |
| wire [S-1:0] addr_0 = i_den[I-2-:S]; | |
| wire [I-S-2:0] dx_0 = i_den[I-S-2:0]; | |
| // 1: Access ROM | |
| logic [O*2-1:0] rom_1 [2 ** S]; | |
| logic [O-1:0] slope_1, rec_1; | |
| logic [I-S-2:0] dx_1; | |
| always_ff @(posedge clk) begin | |
| if (i_ce) begin | |
| {rec_1, slope_1} <= rom_1[addr_0]; | |
| dx_1 <= dx_0; | |
| end | |
| end | |
| initial begin | |
| localparam int SEG = 2 ** S; | |
| localparam real DX = 0.5 / real'(SEG); | |
| var automatic int i; | |
| for (i = 0; i < SEG; i++) begin | |
| var automatic real x0, x1, y0, y1, slope; | |
| var automatic int slope_fixed, rec_fixed; | |
| x0 = 0.5 + real'(i) * DX; | |
| x1 = x0 + DX; | |
| y0 = 1.0 / x0; | |
| y1 = 1.0 / x1; | |
| slope = (y1 - y0) / DX; | |
| slope_fixed = $rtoi($floor(-slope * (2.0 ** I) + 0.5)); | |
| rec_fixed = $rtoi($floor(y0 * (2.0 ** I) + 0.5)); | |
| rom_1[i] = {rec_fixed[O-1:0], slope_fixed[O-1:0]}; | |
| end | |
| end | |
| // 2: Compute fine adjustment | |
| logic [O+S-2:0] fine_2; | |
| logic [O-1:0] rec_2; | |
| always_ff @(posedge clk) begin | |
| if (i_ce) begin | |
| fine_2 <= (O+S-1)'(slope_1 * dx_1 + (1 << I - 1)); | |
| rec_2 <= rec_1; | |
| end | |
| end | |
| // 3: Refine | |
| always_ff @(posedge clk) begin | |
| if (i_ce) begin | |
| o_rec <= O'(rec_2 - (fine_2 >> I)); | |
| end | |
| end | |
| initial begin | |
| $dumpfile("wave.fst"); | |
| $dumpvars(0, magic_reciprocal); | |
| end | |
| endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment