1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 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
|