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
|
//
// Copyright 2016 Ettus Research
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
module cic_interpolate #(
parameter WIDTH = 16,
parameter N = 4,
parameter MAX_RATE = 128
)(
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 [WIDTH-1:0] signal_in,
output reg [WIDTH-1:0] signal_out
);
wire [WIDTH+$clog2(MAX_RATE**(N-1))-1:0] signal_in_ext;
reg [WIDTH+$clog2(MAX_RATE**(N-1))-1:0] integrator [0:N-1];
reg [WIDTH+$clog2(MAX_RATE**(N-1))-1:0] differentiator [0:N-1];
reg [WIDTH+$clog2(MAX_RATE**(N-1))-1:0] pipeline [0:N-1];
reg [WIDTH+$clog2(MAX_RATE**(N-1))-1:0] sampler;
reg [N-1:0] strobe_diff;
reg [N-1:0] strobe_integ;
reg strobe_sampler;
integer i;
sign_extend #(WIDTH,WIDTH+$clog2(MAX_RATE**(N-1))) ext_input (.in(signal_in),.out(signal_in_ext));
// Differentiate
always @(posedge clk) begin
if (reset) begin
strobe_diff <= 'd0;
for (i = 0; i < N; i = i + 1) begin
differentiator[i] <= 0;
pipeline[i] <= 0;
end
end else begin
strobe_diff <= {strobe_diff[N-2:0], strobe_in};
if (strobe_in) begin
differentiator[0] <= signal_in_ext;
pipeline[0] <= signal_in_ext - differentiator[0];
end
for (i = 1; i < N; i = i + 1) begin
if (strobe_diff[i-1]) begin
differentiator[i] <= pipeline[i-1];
pipeline[i] <= pipeline[i-1] - differentiator[i];
end
end
end
end
// Strober
reg [$clog2(MAX_RATE+1)-1:0] counter;
wire strobe_out_int;
always @(posedge clk) begin
if (reset | rate_stb) begin
counter <= rate;
end else if (strobe_diff[N-1]) begin
counter <= rate - 1;
end else begin
if (counter == 0) begin
counter <= rate;
end else if (counter < rate) begin
counter <= counter - 1;
end
end
end
assign strobe_out_int = (counter < rate) & ~rate_stb;
// Integrate
always @(posedge clk) begin
if (reset) begin
strobe_sampler <= 1'b0;
strobe_integ <= 'd0;
for (i = 0; i < N; i = i + 1) begin
integrator[i] <= 0;
end
end else begin
strobe_sampler <= strobe_diff[N-1];
if (strobe_diff[N-1]) begin
sampler <= pipeline[N-1];
end
strobe_integ <= {strobe_integ[N-2:0],strobe_out_int};
if (strobe_sampler) begin
integrator[0] <= integrator[0] + sampler;
end
for (i = 1; i < N; i = i + 1) begin
if (strobe_integ[i-1]) begin
integrator[i] <= integrator[i] + integrator[i-1];
end
end
end
end
genvar l;
wire [WIDTH-1:0] signal_out_shifted[0:MAX_RATE];
wire signal_out_shifted_strobe[0:MAX_RATE];
generate
for (l = 0; l <= MAX_RATE; l = l + 1) begin
axi_round #(
.WIDTH_IN((l == 0 || l == 1) ? WIDTH : $clog2(l**(N-1))+WIDTH),
.WIDTH_OUT(WIDTH))
axi_round (
.clk(clk), .reset(reset),
.i_tdata((l == 0 || l == 1) ? integrator[N-1][WIDTH-1:0] : integrator[N-1][$clog2(l**(N-1))+WIDTH-1:0]),
.i_tlast(1'b0), .i_tvalid(strobe_integ[N-1]), .i_tready(),
.o_tdata(signal_out_shifted[l]), .o_tlast(), .o_tvalid(signal_out_shifted_strobe[l]), .o_tready(1'b1));
end
endgenerate
// Output register
always @(posedge clk) begin
if (reset) begin
strobe_out <= 1'b0;
signal_out <= 'd0;
end else begin
strobe_out <= signal_out_shifted_strobe[0]; // Any of the strobes will work here
signal_out <= signal_out_shifted[rate];
end
end
endmodule
|