diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/cic_decimate.v')
| -rw-r--r-- | fpga/usrp3/lib/rfnoc/cic_decimate.v | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/cic_decimate.v b/fpga/usrp3/lib/rfnoc/cic_decimate.v new file mode 100644 index 000000000..6a723d88e --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/cic_decimate.v @@ -0,0 +1,148 @@ +// +// Copyright 2016 Ettus Research +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +module cic_decimate #( + parameter WIDTH = 16, + parameter N = 4, + parameter MAX_RATE = 256 +)( + input clk, + input reset, + input rate_stb, + input [$clog2(MAX_RATE+1)-1:0] rate, // +1 due to $clog2() rounding + input strobe_in, + output reg strobe_out, + input last_in, + output reg last_out, + input [WIDTH-1:0] signal_in, + output reg [WIDTH-1:0] signal_out +); + + wire [WIDTH+(N*$clog2(MAX_RATE+1))-1:0] signal_in_ext; + reg [WIDTH+(N*$clog2(MAX_RATE+1))-1:0] integrator [0:N-1]; + reg [WIDTH+(N*$clog2(MAX_RATE+1))-1:0] differentiator [0:N-1]; + reg [WIDTH+(N*$clog2(MAX_RATE+1))-1:0] pipeline [0:N-1]; + reg [WIDTH+(N*$clog2(MAX_RATE+1))-1:0] sampler; + reg [N-1:0] last_integ; + reg last_integ_hold; + reg [N-1:0] last_diff; + reg last_sampler; + reg [N-1:0] strobe_integ; + reg strobe_sampler; + reg [N-1:0] strobe_diff; + + integer i; + + sign_extend #(WIDTH,WIDTH+(N*$clog2(MAX_RATE+1))) ext_input (.in(signal_in),.out(signal_in_ext)); + + // Integrate + always @(posedge clk) begin + if (reset) begin + last_integ <= 0; + last_integ_hold <= 0; + for (i = 0; i < N; i = i + 1) begin + integrator[i] <= 0; + strobe_integ[i] <= 0; + end + end else begin + strobe_integ <= {strobe_integ[N-2:0],strobe_in}; + if (strobe_in) begin + last_integ[0] <= last_in; + integrator[0] <= integrator[0] + signal_in_ext; + end + for (i = 1; i < N; i = i + 1) begin + if (strobe_integ[i-1]) begin + last_integ[i] <= last_integ[i-1]; + integrator[i] <= integrator[i] + integrator[i-1]; + end + end + if (last_integ[N-1] & ~strobe_sampler) begin + last_integ_hold <= 1'b1; + end else if (strobe_sampler) begin + last_integ_hold <= 1'b0; + end + end + end + + // Sampler strobe + reg [$clog2(MAX_RATE+1)-1:0] counter; + always @(posedge clk) begin + if (reset) begin + counter <= rate; + strobe_sampler <= 1'b0; + last_sampler <= 1'b0; + sampler <= 'd0; + end else begin + strobe_sampler <= 1'b0; + last_sampler <= 1'b0; + if (rate_stb) begin + counter <= rate; + end else if (strobe_integ[N-1]) begin + if (counter <= 1) begin + counter <= rate; + strobe_sampler <= 1'b1; + last_sampler <= last_integ[N-1] | last_integ_hold; + sampler <= integrator[N-1]; + end else begin + counter <= counter - 1; + end + end + end + end + + // Differentiate + always @(posedge clk) begin + if (reset) begin + last_diff <= 0; + for (i = 0; i < N; i = i + 1) begin + pipeline[i] <= 0; + differentiator[i] <= 0; + strobe_diff <= 0; + end + end else begin + strobe_diff <= {strobe_diff[N-2:0], strobe_sampler}; + if (strobe_sampler) begin + last_diff[0] <= last_sampler; + differentiator[0] <= sampler; + pipeline[0] <= sampler - differentiator[0]; + end + for (i = 1; i < N; i = i + 1) begin + if (strobe_diff[i-1]) begin + last_diff[i] <= last_diff[i-1]; + differentiator[i] <= pipeline[i-1]; + pipeline[i] <= pipeline[i-1] - differentiator[i]; + end + end + end + end + + genvar l; + wire [WIDTH-1:0] signal_out_shifted[0:MAX_RATE]; + generate + for (l = 1; l <= MAX_RATE; l = l + 1) begin + // N*log2(rate), $clog2(rate) = ceil(log2(rate)) which rounds to nearest shift without overflow + assign signal_out_shifted[l] = pipeline[N-1][$clog2(l**N)+WIDTH-1:$clog2(l**N)]; + end + endgenerate + assign signal_out_shifted[0] = pipeline[N-1][WIDTH-1:0]; + + // Output register + always @(posedge clk) begin + if (reset) begin + last_out <= 1'b0; + strobe_out <= 1'b0; + signal_out <= 'd0; + end else begin + strobe_out <= strobe_diff[N-1]; + if (strobe_diff[N-1]) begin + last_out <= last_diff[N-1]; + signal_out <= signal_out_shifted[rate]; + end + end + end + +endmodule |
