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
181
182
183
184
185
186
187
188
189
|
/*
* f15_wf_agg.v
*
* Watefall Aggregation
*
* Copyright (C) 2016 Ettus Corporation LLC
*
* vim: ts=4 sw=4
*/
`ifdef SIM
`default_nettype none
`endif
module f15_wf_agg #(
parameter integer Y_WIDTH = 12,
parameter integer X_WIDTH = 16,
parameter integer DECIM_WIDTH = 8
)(
input wire [Y_WIDTH-1:0] yin_0,
input wire [X_WIDTH-1:0] x_0,
input wire valid_0,
input wire last_0,
input wire [15:0] rng_0,
output wire [Y_WIDTH-1:0] yout_3,
output wire [7:0] zout_3,
output wire zvalid_3,
input wire [1:0] cfg_div,
input wire cfg_mode, // 0=MaxHold, 1=Average
input wire [DECIM_WIDTH-1:0] cfg_decim,
input wire cfg_decim_changed,
input wire clk,
input wire rst
);
localparam integer R_WIDTH = X_WIDTH + 9;
// Signals
// Data pah
reg [R_WIDTH-1:0] xe_1;
reg [R_WIDTH-1:0] ye_1;
wire over_2;
reg [R_WIDTH-1:0] r_2;
reg [Y_WIDTH-1:0] x_2;
reg [Y_WIDTH-1:0] y_2;
reg [Y_WIDTH-1:0] y_3;
// Control
reg [DECIM_WIDTH:0] decim_cnt;
reg init_0;
wire init_2;
reg init_force_0;
reg flush_0;
reg zvalid_1;
// Datapath
// --------
// X predivision mux
always @(posedge clk)
begin
case (cfg_div)
2'b00:
xe_1 <= { 1'd0, x_0, 8'd0 }; // 1:1
2'b01:
xe_1 <= { 4'd0, x_0, 5'd0 }; // 1:8
2'b10:
xe_1 <= { 7'd0, x_0, 2'd0 }; // 1:64
2'b11:
xe_1 <= { 9'd0, x_0 }; // 1:256
endcase
end
// Y register
always @(posedge clk)
begin
if (cfg_mode)
// Average
ye_1 <= { 1'b0, yin_0, rng_0[R_WIDTH-Y_WIDTH-2:0] };
else
// Max Hold
ye_1 <= { 1'b0, yin_0, {(R_WIDTH-Y_WIDTH-1){1'b0}} };
end
// Adder / Substractor
always @(posedge clk)
begin
if (cfg_mode)
// Average
r_2 <= ye_1 + xe_1;
else
// Max-Hold
r_2 <= ye_1 - xe_1;
end
assign over_2 = r_2[R_WIDTH-1];
// Registers for the two branches.
always @(posedge clk)
begin
x_2 <= xe_1[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
y_2 <= ye_1[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
end
// Output mux
always @(posedge clk)
begin
// If first : take x_2
// If average :
// - If overflow = 0 -> take r_2
// - If overflow = 1 -> sature to all 1's
// If max-hold
// - If overflow = 0 -> take y_2
// - If overflow = 1 -> take x_2
if (init_2)
y_3 <= x_2;
else if (cfg_mode)
y_3 <= over_2 ? { (Y_WIDTH){1'b1} } : r_2[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
else
y_3 <= over_2 ? x_2 : y_2;
end
assign yout_3 = y_3;
assign zout_3 = y_3[Y_WIDTH-1:Y_WIDTH-8];
// Control
// -------
// 1-in-N decimation counter
always @(posedge clk)
begin
if (rst)
decim_cnt <= 0;
else if (cfg_decim_changed)
// Force Reload
decim_cnt <= { 1'b0, cfg_decim };
else if (valid_0 & last_0)
if (decim_cnt[DECIM_WIDTH])
// Reload
decim_cnt <= { 1'b0, cfg_decim };
else
// Just decrement
decim_cnt <= decim_cnt - 1;
end
// Decimation flush & init states
always @(posedge clk)
begin
if (rst) begin
// Initial state
flush_0 <= 1'b0;
init_0 <= 1'b1;
init_force_0 <= 1'b0;
end else begin
if (valid_0 & last_0) begin
// Flushing
flush_0 <= decim_cnt[DECIM_WIDTH];
// Init after flush or if forced
init_0 <= flush_0 | init_force_0;
end
// Init forcing after a decim change
if (cfg_decim_changed)
init_force_0 <= 1'b1;
else if (valid_0 & last_0)
init_force_0 <= 1'b0;
end
end
delay_bit #(2) dl_init(init_0, init_2, clk);
// Z-output valid
always @(posedge clk)
zvalid_1 <= valid_0 & flush_0;
delay_bit #(2) dl_zvalid(zvalid_1, zvalid_3, clk);
endmodule // f15_wf_agg
|