fpga: Fix overflows in quarterrate downconverter
The 1/4-rate downconverter naively negated the input signals (y = -x) which doesn't work when the signal is at full scale. In particular, signals that are at full negative scale get converted to zeros (even though 2's complement would be to return the same number, although that would also be incorrect). This fix changes it such that the smallest negative value gets converted to the largest positive value. This is not a mathematical correction inversion, but a minor amplitude distortion. However, since we're already at full scale, and thus probably clipping, this is preferable to the incorrect resolution of the regular inversion. Put differently, there is no better value in this case. Original-commit: 8bd982745e6247cf3cf3da52925c65126287428a
This commit is contained in:
committed by
michael-west
parent
ddcc0b1211
commit
4e2da5912b
@@ -43,6 +43,17 @@ module quarter_rate_downconverter #(
|
|||||||
reg [WIDTH-1:0] tmp_i = {WIDTH{1'b0}};
|
reg [WIDTH-1:0] tmp_i = {WIDTH{1'b0}};
|
||||||
reg [WIDTH-1:0] tmp_q = {WIDTH{1'b0}};
|
reg [WIDTH-1:0] tmp_q = {WIDTH{1'b0}};
|
||||||
|
|
||||||
|
localparam [WIDTH-1:0] MAX_NEG_VAL = -2**(WIDTH-1);
|
||||||
|
localparam [WIDTH-1:0] MAX_POS_VAL = 2**(WIDTH-1)-1;
|
||||||
|
|
||||||
|
function [WIDTH-1:0] invert_sig(
|
||||||
|
input [WIDTH-1:0] x
|
||||||
|
);
|
||||||
|
begin
|
||||||
|
invert_sig = x == MAX_NEG_VAL ? MAX_POS_VAL : -x;
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
// State machine types and reg
|
// State machine types and reg
|
||||||
localparam S0=0, S1=1, S2=2, S3=3;
|
localparam S0=0, S1=1, S2=2, S3=3;
|
||||||
reg[1:0] cur_state;
|
reg[1:0] cur_state;
|
||||||
@@ -108,18 +119,18 @@ module quarter_rate_downconverter #(
|
|||||||
end
|
end
|
||||||
S1: begin
|
S1: begin
|
||||||
// S(t) * i = -Q(t) + iI(t):
|
// S(t) * i = -Q(t) + iI(t):
|
||||||
tmp_i = -q_in;
|
tmp_i = invert_sig(q_in);
|
||||||
tmp_q = i_in;
|
tmp_q = i_in;
|
||||||
end
|
end
|
||||||
S2: begin
|
S2: begin
|
||||||
// S(t) * -1 = -I(t) - iQ(t):
|
// S(t) * -1 = -I(t) - iQ(t):
|
||||||
tmp_i = -i_in;
|
tmp_i = invert_sig(i_in);
|
||||||
tmp_q = -q_in;
|
tmp_q = invert_sig(q_in);
|
||||||
end
|
end
|
||||||
S3: begin
|
S3: begin
|
||||||
// S(t) * -i = Q(t) - iI(t):
|
// S(t) * -i = Q(t) - iI(t):
|
||||||
tmp_i = q_in;
|
tmp_i = q_in;
|
||||||
tmp_q = -i_in;
|
tmp_q = invert_sig(i_in);
|
||||||
end
|
end
|
||||||
default: begin
|
default: begin
|
||||||
tmp_i = i_in;
|
tmp_i = i_in;
|
||||||
|
|||||||
Reference in New Issue
Block a user