File size: 1,427 Bytes
2166d7e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | // EXP_APPROX: exp(-delta/256) in Q0.16 (65536 == 1.0) for delta >= 0.
// y = delta * log2(e); n = integer part, f = fraction
// 2^-f ~ 16-segment LUT with linear interpolation; result = 2^-f >> n
// One cycle of latency.
module fa_exp_approx
import fa_pkg::*;
(
input logic clk,
input logic rst_n,
input logic in_valid,
input logic [31:0] delta, // non-negative, logit units (1/256)
output logic out_valid,
output logic [16:0] result
);
logic [11:0] dcl;
logic [23:0] y8;
logic [4:0] n;
logic [7:0] f;
logic [16:0] t0, t1, diff, base;
logic [20:0] interp;
logic [16:0] res_c;
always_comb begin
dcl = (delta > 32'd4095) ? 12'd4095 : delta[11:0];
y8 = 24'(dcl) * 24'd369 >> 8;
n = y8[12:8];
f = y8[7:0];
t0 = exp_lut({1'b0, f[7:4]});
t1 = exp_lut({1'b0, f[7:4]} + 5'd1);
diff = t0 - t1;
interp = diff * f[3:0];
base = t0 - 17'(interp >> 4);
res_c = (y8[23:8] >= 16'd16) ? 17'd0 : (base >> n);
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
out_valid <= 1'b0;
result <= '0;
end else begin
out_valid <= in_valid;
result <= res_c;
end
end
endmodule : fa_exp_approx
|