fpga/usrp3: Fix DC truncation bias by adding rounding to DDC chain.

A digital DC bias caused by various truncations in the DDC chain was
previously noticable with small signal levels, especially with high
decimation rates. This patch eliminates the bias by replacing the
truncation with rounding or simply keeping more bits for longer where it
makes sense.

This is essentially a forward port of a similar prior fix to the usrp2
DDC chain: https://github.com/EttusResearch/fpga/pull/4.

Signed-off-by: Ryan Volz <ryan.volz@gmail.com>


Original-commit: a57c162a0d11ab82a83c911a94272ceb6f7ff70a
This commit is contained in:
Ryan Volz
2024-06-11 10:20:08 +02:00
committed by Joerg Hofrichter
parent 523212fa04
commit 1451ae066b
3 changed files with 88 additions and 29 deletions
+20 -10
View File
@@ -26,7 +26,7 @@ module hb_dec
output reg [WIDTH-1:0] data_out);
localparam INTWIDTH = 17;
localparam ACCWIDTH = WIDTH + 3;
localparam ACCWIDTH = 36;
// Round off inputs to 17 bits because of 18 bit multipliers
wire [INTWIDTH-1:0] data_rnd;
@@ -174,20 +174,30 @@ module hb_dec
always @(posedge clk) sum_of_prod <= prod1 + prod2; // Can't overflow
wire [ACCWIDTH-1:0] acc_out;
acc #(.IWIDTH(ACCWIDTH-2),.OWIDTH(ACCWIDTH))
acc (.clk(clk),.clear(clear),.acc(do_acc),.in(sum_of_prod[35:38-ACCWIDTH]),.out(acc_out));
acc #(.IWIDTH(36),.OWIDTH(ACCWIDTH))
acc (.clk(clk),.clear(clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out));
wire [ACCWIDTH-1:0] data_even_signext;
wire [WIDTH:0] acc_out_rnd;
round #(
.bits_in(ACCWIDTH),
.bits_out(WIDTH+1)
) round_acc (
.in(acc_out),
.out(acc_out_rnd)
);
localparam SHIFT_FACTOR = 6;
wire [WIDTH:0] data_even_signext;
sign_extend #(.bits_in(INTWIDTH),.bits_out(ACCWIDTH-SHIFT_FACTOR)) signext_data_even
(.in(data_even),.out(data_even_signext[ACCWIDTH-1:SHIFT_FACTOR]));
assign data_even_signext[SHIFT_FACTOR-1:0] = 0;
localparam SHIFT_FACTOR = 17 - (ACCWIDTH - (WIDTH+1));
always @(posedge clk) final_sum <= acc_out + data_even_signext;
sign_extend #(.bits_in(INTWIDTH),.bits_out(WIDTH+1-SHIFT_FACTOR)) signext_data_even
(.in(data_even),.out(data_even_signext[WIDTH:SHIFT_FACTOR]));
assign data_even_signext[SHIFT_FACTOR-1:0] = 0;
clip #(.bits_in(WIDTH+1), .bits_out(WIDTH)) clip (.in(final_sum), .out(final_sum_clip));
always @(posedge clk) final_sum <= acc_out_rnd + data_even_signext;
clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip_finalsum
(.in(final_sum), .out(final_sum_clip));
// Output MUX to allow for bypass
wire selected_stb = bypass ? stb_in : stb_out_pre[8];