diff options
-rw-r--r-- | usrp2/sdr_lib/round.v | 22 | ||||
-rw-r--r-- | usrp2/sdr_lib/round_tb.v | 61 |
2 files changed, 80 insertions, 3 deletions
diff --git a/usrp2/sdr_lib/round.v b/usrp2/sdr_lib/round.v index 7a137d702..5b83981c6 100644 --- a/usrp2/sdr_lib/round.v +++ b/usrp2/sdr_lib/round.v @@ -2,7 +2,7 @@ // // USRP - Universal Software Radio Peripheral // -// Copyright (C) 2007 Matt Ettus +// Copyright (C) 2011 Matt Ettus // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -24,12 +24,28 @@ module round #(parameter bits_in=0, - parameter bits_out=0) + parameter bits_out=0, + parameter round_to_zero=0, // original behavior + parameter round_to_nearest=1, // lowest noise + parameter trunc=0) // round to negative infinity (input [bits_in-1:0] in, output [bits_out-1:0] out, output [bits_in-bits_out:0] err); - assign out = in[bits_in-1:bits_in-bits_out] + (in[bits_in-1] & |in[bits_in-bits_out-1:0]); + wire round_corr; + wire round_corr_trunc = 0; + wire round_corr_rtz = (in[bits_in-1] & |in[bits_in-bits_out-1:0]); + wire round_corr_nearest = in[bits_in-bits_out-1]; + wire round_corr_nearest_safe = (~in[bits_in-1] & (&in[bits_in-2:bits_out])) ? 0 : + round_corr_nearest; + + assign round_corr = round_to_nearest ? round_corr_nearest_safe : + trunc ? round_corr_trunc : + round_to_zero ? round_corr_rtz : + 0; // default to trunc + + assign out = in[bits_in-1:bits_in-bits_out] + round_corr; + assign err = in - {out,{(bits_in-bits_out){1'b0}}}; endmodule // round diff --git a/usrp2/sdr_lib/round_tb.v b/usrp2/sdr_lib/round_tb.v new file mode 100644 index 000000000..ddc464f4a --- /dev/null +++ b/usrp2/sdr_lib/round_tb.v @@ -0,0 +1,61 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2011 Matt Ettus +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA +// + +// Rounding "macro" +// Keeps the topmost bits, does proper 2s comp round to zero (unbiased truncation) + +module round_tb(); + + localparam IW=8; + localparam OW=4; + localparam EW=IW-OW+1; + + reg signed [IW-1:0] in; + wire signed [OW-1:0] out; + wire signed [EW-1:0] err; + + round #(.bits_in(IW), + .bits_out(OW), + .round_to_zero(0), // original behavior + .round_to_nearest(1), // lowest noise + .trunc(0)) // round to negative infinity + round (.in(in),.out(out),.err(err)); + + initial $dumpfile("round_tb.vcd"); + initial $dumpvars(0,round_tb); + + wire signed [IW-1:0] out_round = {out,{IW-OW{1'b0}}}; + + initial + begin + in <= -129; + #1; + repeat (260) + begin + in <= in + 1; + #1; + $display("In %d, out %d, out_rnd %d, err %d, real err %d",in,out,out_round,-err,out_round-in); + #1; + end + $finish; + end + +endmodule // round |