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
|