fix(fpga): widen AGC gain arithmetic to 6-bit to prevent wraparound
5-bit signed subtraction in clamp_gain wrapped for agc_attack >= 10 or
agc_decay >= 9 when |agc_gain| + step > 16, inverting gain polarity
instead of clamping — e.g. gain=-7, attack=10 produced +7 (max amplify)
rather than -7 (max attenuate), causing ADC saturation on strong returns.
Widen clamp_gain input to [5:0] and sign-extend both operands to 6 bits
({agc_gain[3],agc_gain[3],agc_gain} and {2'b00,agc_attack/decay}),
covering the full [-22,+22] range before clamping. Default attack/decay
values (1-4) are unaffected; behaviour changes only for values >= 10/9.
This commit is contained in:
@@ -169,11 +169,11 @@ endfunction
|
||||
// =========================================================================
|
||||
// Clamp a wider signed value to [-7, +7]
|
||||
function signed [3:0] clamp_gain;
|
||||
input signed [4:0] val; // 5-bit to handle overflow from add
|
||||
input signed [5:0] val; // 6-bit: covers [-22,+22] (max |gain|+step = 7+15)
|
||||
begin
|
||||
if (val > 5'sd7)
|
||||
if (val > 6'sd7)
|
||||
clamp_gain = 4'sd7;
|
||||
else if (val < -5'sd7)
|
||||
else if (val < -6'sd7)
|
||||
clamp_gain = -4'sd7;
|
||||
else
|
||||
clamp_gain = val[3:0];
|
||||
@@ -246,15 +246,15 @@ always @(posedge clk or negedge reset_n) begin
|
||||
// Use inclusive counts/peaks (accounting for simultaneous valid_in)
|
||||
if (wire_frame_sat_incr || frame_sat_count > 8'd0) begin
|
||||
// Clipping detected: reduce gain immediately (attack)
|
||||
agc_gain <= clamp_gain($signed({agc_gain[3], agc_gain}) -
|
||||
$signed({1'b0, agc_attack}));
|
||||
agc_gain <= clamp_gain($signed({agc_gain[3], agc_gain[3], agc_gain}) -
|
||||
$signed({2'b00, agc_attack}));
|
||||
holdoff_counter <= agc_holdoff; // Reset holdoff
|
||||
end else if ((wire_frame_peak_update ? max_iq[14:7] : frame_peak[14:7])
|
||||
< agc_target) begin
|
||||
// Signal too weak: increase gain after holdoff expires
|
||||
if (holdoff_counter == 4'd0) begin
|
||||
agc_gain <= clamp_gain($signed({agc_gain[3], agc_gain}) +
|
||||
$signed({1'b0, agc_decay}));
|
||||
agc_gain <= clamp_gain($signed({agc_gain[3], agc_gain[3], agc_gain}) +
|
||||
$signed({2'b00, agc_decay}));
|
||||
end else begin
|
||||
holdoff_counter <= holdoff_counter - 4'd1;
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user