Merge branch 'master' of ssh://git.joppeb.nl:222/joppe/fpga_modem
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
`ifndef CONV_VH
|
||||
`define CONV_VH
|
||||
|
||||
// =============================================================================
|
||||
// Convert Q1.15 to a biased UQ0.16 signal
|
||||
// =============================================================================
|
||||
@@ -8,4 +11,6 @@ begin
|
||||
biased = q15 + 17'sd32768;
|
||||
q15_to_uq16 = biased[15:0];
|
||||
end
|
||||
endfunction
|
||||
endfunction
|
||||
|
||||
`endif
|
||||
91
rtl/util/rc_alpha_q15.vh
Normal file
91
rtl/util/rc_alpha_q15.vh
Normal file
@@ -0,0 +1,91 @@
|
||||
// rc_alpha_q15.vh
|
||||
// Plain Verilog-2001 constant function: R(ohm), C(pF), Fs(Hz) -> alpha_q15 (Q1.15)
|
||||
// Uses fixed-point approximation: 1 - exp(-x) ≈ x - x^2/2 + x^3/6, where x = 1/(Fs*R*C)
|
||||
// All integer math; suitable for elaboration-time constant folding (e.g., XST).
|
||||
|
||||
`ifndef RC_ALPHA_Q15_VH
|
||||
`define RC_ALPHA_Q15_VH
|
||||
|
||||
function integer alpha_q15_from_rc;
|
||||
input integer R_OHM; // ohms
|
||||
input integer C_PF; // picofarads
|
||||
input integer FS_HZ; // Hz
|
||||
|
||||
// Choose QN for x. N=24 is a good balance for accuracy/width.
|
||||
integer N;
|
||||
|
||||
// We'll keep everything as unsigned vectors; inputs copied into vectors first.
|
||||
reg [63:0] R_u, C_u, FS_u;
|
||||
|
||||
// x = 1 / (Fs * R * C) with C in pF -> x = 1e12 / (Fs*R*C_pf)
|
||||
// x_qN = round( x * 2^N ) = round( (1e12 << N) / denom )
|
||||
reg [127:0] NUM_1E12_SLLN; // big enough for 1e12 << N
|
||||
reg [127:0] DENOM; // Fs*R*C
|
||||
reg [127:0] X_qN; // x in QN
|
||||
|
||||
// Powers
|
||||
reg [255:0] X2; // x^2 in Q(2N)
|
||||
reg [383:0] X3; // x^3 in Q(3N)
|
||||
|
||||
integer term1_q15;
|
||||
integer term2_q15;
|
||||
integer term3_q15;
|
||||
integer acc;
|
||||
|
||||
begin
|
||||
N = 24;
|
||||
|
||||
// Copy integer inputs into 64-bit vectors (no bit-slicing of integers)
|
||||
R_u = R_OHM[31:0];
|
||||
C_u = C_PF[31:0];
|
||||
FS_u = FS_HZ[31:0];
|
||||
|
||||
// Denominator = Fs * R * C_pf (fits in < 2^64 for typical values)
|
||||
DENOM = 128'd0;
|
||||
DENOM = FS_u;
|
||||
DENOM = DENOM * R_u;
|
||||
DENOM = DENOM * C_u;
|
||||
|
||||
// // Guard: avoid divide by zero
|
||||
// if (DENOM == 0) begin
|
||||
// alpha_q15_from_rc = 0;
|
||||
// disable alpha_q15_from_rc;
|
||||
// end
|
||||
|
||||
// Numerator = (1e12 << N). 1e12 * 2^24 ≈ 1.6777e19 (fits in 2^64..2^65),
|
||||
// so use 128 bits to be safe.
|
||||
NUM_1E12_SLLN = 128'd1000000000000 << N;
|
||||
|
||||
// x_qN = rounded division
|
||||
X_qN = (NUM_1E12_SLLN + (DENOM >> 1)) / DENOM;
|
||||
|
||||
// Powers
|
||||
X2 = X_qN * X_qN;
|
||||
X3 = X2 * X_qN;
|
||||
|
||||
// Convert terms to Q1.15:
|
||||
// term1 = x -> shift from QN to Q15
|
||||
term1_q15 = (X_qN >> (N - 15)) & 16'hFFFF;
|
||||
|
||||
// term2 = x^2 / 2 -> Q(2N) to Q15 and /2
|
||||
term2_q15 = (X2 >> (2*N - 15 + 1)) & 16'hFFFF;
|
||||
|
||||
// term3 = x^3 / 6 -> Q(3N) to Q15, then /6 with rounding
|
||||
begin : gen_t3
|
||||
reg [383:0] tmp_q15_wide;
|
||||
reg [383:0] tmp_div6;
|
||||
tmp_q15_wide = (X3 >> (3*N - 15));
|
||||
tmp_div6 = (tmp_q15_wide + 6'd3) / 6;
|
||||
term3_q15 = tmp_div6[15:0];
|
||||
end
|
||||
|
||||
// Combine and clamp
|
||||
acc = term1_q15 - term2_q15 + term3_q15;
|
||||
if (acc < 0) acc = 0;
|
||||
else if (acc > 16'h7FFF) acc = 16'h7FFF;
|
||||
|
||||
alpha_q15_from_rc = acc;
|
||||
end
|
||||
endfunction
|
||||
|
||||
`endif
|
||||
Reference in New Issue
Block a user