diff options
Diffstat (limited to 'fpga/usrp3/lib/dsp/hb47_int.v')
-rw-r--r-- | fpga/usrp3/lib/dsp/hb47_int.v | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/dsp/hb47_int.v b/fpga/usrp3/lib/dsp/hb47_int.v new file mode 100644 index 000000000..3f69952cc --- /dev/null +++ b/fpga/usrp3/lib/dsp/hb47_int.v @@ -0,0 +1,180 @@ +// +// Copyright 2011-2014 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// 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 3 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, see <http://www.gnu.org/licenses/>. +// + +module hb47_int + #(parameter WIDTH=18, + parameter DEVICE="7SERIES") + (input clk, + input rst, + input bypass, + input stb_in, + input [WIDTH-1:0] data_in, + input [7:0] output_rate, + input stb_out, + output reg [WIDTH-1:0] data_out); + + // Input data Pipeline + reg [WIDTH-1:0] data_in_pipe[0:23]; + + reg stb_pipe0, stb_pipe1, stb_pipe2, stb_pipe3, stb_pipe4 ; + reg stb_pipe5, stb_pipe6, stb_pipe7, stb_pipe8, stb_pipe9 ; + wire [WIDTH-1:0] sample_a[0:5], sample_b[0:5]; + wire [17:0] coeff[0:5]; + wire [47:0] accumulator_out[0:5]; + reg [47:0] partial_result_a, partial_result_b; + reg [47:0] result; + + + // Implicit coeff23 of 131071 + wire [17:0] coeff_a[0:5]; + wire [17:0] coeff_b[0:5]; + + assign coeff_a[0] = -62; + assign coeff_b[0] = 194; + assign coeff_a[1] = -440; + assign coeff_b[1] = 855; + assign coeff_a[2] = -1505; + assign coeff_b[2] = 2478; + assign coeff_a[3] = -3900; + assign coeff_b[3] = 5990; + assign coeff_a[4] = -9187; + assign coeff_b[4] = 14632; + assign coeff_a[5] = -26536; + assign coeff_b[5] = 83009; + + genvar i; + + always @(posedge clk) + if (rst) + data_in_pipe[0] <= 18'h0; + else if (stb_in) + data_in_pipe[0] <= data_in; + + generate + for (i=0; i<23; i=i+1) begin: sample_pipeline + always @(posedge clk) if (rst) + data_in_pipe[i+1] <= 0; + else if (stb_in) + data_in_pipe[i+1] <= data_in_pipe[i]; + end + endgenerate + + generate + for (i=0; i<6; i=i+1) begin: filter_core + + assign sample_a[i] = stb_pipe0 ? data_in_pipe[(i*2)] : data_in_pipe[(2*i)+1]; + assign sample_b[i] = stb_pipe0 ? data_in_pipe[23-(i*2)] : data_in_pipe[23-(2*i)-1]; + // Coeffs are 1 pipeline downstream of sample input + assign coeff[i] = stb_pipe1 ? coeff_a[i] : coeff_b[i]; + + add_then_mac + #(.DEVICE(DEVICE)) + add_then_mac_i + ( + .acc(accumulator_out[i]), + .carryin(1'b0), + .ce(1'b1), + .clk(clk), + .b(coeff[i]), + .load(stb_pipe2), + .c(48'h0), + .a(sample_a[i]), + .d(sample_b[i]), + .rst(rst) + ); + + end // block: filter_core + endgenerate + + // + // Dual 3:1 compressors + // + always @(posedge clk) if (stb_pipe5) begin + partial_result_a[47:0] <= accumulator_out[0] + accumulator_out[1] + accumulator_out[2]; + partial_result_b[47:0] <= accumulator_out[3] + accumulator_out[4] + accumulator_out[5]; + end + + // + // Final Result Adder + // + always @(posedge clk) if (stb_pipe6) begin + result[47:0] <= partial_result_a[47:0] + partial_result_b[47:0]; + end + + // + // Now round unneed precision from accumulator result, and clip the unused dynamic range + // + wire [47:17] result_rnd; + round_reg #(.bits_in(48),.bits_out(31)) + final_round (.clk(clk),.in(result[47:0]),.out(result_rnd[47:17]),.err()); + + wire [34:17] result_clip; + clip_reg #(.bits_in(31),.bits_out(18)) final_clip + (.clk(clk),.in(result_rnd[47:17]),.strobe_in(1'b1), .out(result_clip[34:17]), .strobe_out()); + + // + // Data enters the sample pipeline when stb_in is asserted. + // The clock cycle after is phase=0 with pipeline delay=0 + // + always @(posedge clk) + if (rst) begin + stb_pipe0 <= 1'b0; // New sample loaded into sample pipeline, setup on reg a + stb_pipe1 <= 1'b0; // Sample n+0 presented to pre-adder, result to reg ad, coeff_a setup on input reg b + stb_pipe2 <= 1'b0; // Sample n+1 presented to pre-adder, product of sample n+0 and coeff_a setup on reg m + stb_pipe3 <= 1'b0; // product of sample n+1 and coeff_b setup on reg m, previous product loaded into accumulator. + stb_pipe4 <= 1'b0; // Add both products into accumulator + stb_pipe5 <= 1'b0; // Add 3 accumulator values into one partial result + stb_pipe6 <= 1'b0; // Add both partial results into final full precision result. + stb_pipe7 <= 1'b0; // Round result + stb_pipe8 <= 1'b0; // Clip Result + stb_pipe9 <= 1'b0; + + end else begin + stb_pipe0 <= stb_in; // New sample loaded into sample pipeline, setup on reg a + stb_pipe1 <= stb_pipe0; // Sample n+0 presented to pre-adder, result to reg ad, coeff_a setup on input reg b + stb_pipe2 <= stb_pipe1; // Sample n+1 presented to pre-adder, product of sample n+0 and coeff_a setup on reg m + stb_pipe3 <= stb_pipe2; // product of sample n+1 and coeff_b setup on reg m, previous product loaded into accumulator. + stb_pipe4 <= stb_pipe3; // Add both products into accumulator + stb_pipe5 <= stb_pipe4; // Add 3 accumulator values into one partial result + stb_pipe6 <= stb_pipe5; // Add both partial results into final result. + stb_pipe7 <= stb_pipe6; // Round result + stb_pipe8 <= stb_pipe7; // Clip Result + stb_pipe9 <= stb_pipe8; + + end // else: !if(rst) + + // + // Interleave newly interpolated samples (odd taps) with raw input samples (even taps - All zero except center tap) + // Account for differences caused by various CPO settings and the pipeline advancing. + // + always @(posedge clk) + if (bypass) + data_out <= data_in; + else if (stb_in & stb_out) + data_out <= result_clip[34:17]; + else if(stb_out) + case(output_rate) + 1: data_out <= data_in_pipe[16]; // Four input pipeline shifts since we calculated odd taps + 2: data_out <= data_in_pipe[14]; // Three input pipeline shifts since we calculated odd taps + 3,4: data_out <= data_in_pipe[13]; // Two input pipeline shifts since we calculated odd taps + default: data_out <= data_in_pipe[12]; // One input pipeline shift since we calculated odd taps + endcase // case(output_rate) + +endmodule // hb47_int |