@@ -49,7 +49,6 @@ module axi_dac_interpolate_filter #(
49
49
output reg [15 :0 ] dac_int_data,
50
50
output dma_ready,
51
51
output dac_valid_out,
52
- input sync_stop_channels,
53
52
output underflow,
54
53
55
54
input [ 2 :0 ] filter_mask,
@@ -58,6 +57,10 @@ module axi_dac_interpolate_filter #(
58
57
input dac_correction_enable,
59
58
input dma_transfer_suspend,
60
59
input start_sync_channels,
60
+ input sync_stop_channels,
61
+ input flush_dma_in,
62
+ input raw_transfer_en,
63
+ input [15 :0 ] dac_raw_ch_data,
61
64
input trigger,
62
65
input trigger_active,
63
66
input en_start_trigger,
@@ -66,7 +69,14 @@ module axi_dac_interpolate_filter #(
66
69
input dma_valid_adjacent
67
70
);
68
71
69
- // internal signals
72
+ // local parameters
73
+
74
+ localparam [1 :0 ] IDLE = 0 ;
75
+ localparam [1 :0 ] WAIT = 1 ;
76
+ localparam [1 :0 ] TRANSFER = 2 ;
77
+ localparam [1 :0 ] FLUSHING = 3 ;
78
+
79
+ // internal registers
70
80
71
81
reg dac_int_ready;
72
82
reg dac_filt_int_valid;
@@ -75,15 +85,20 @@ module axi_dac_interpolate_filter #(
75
85
reg cic_change_rate;
76
86
reg [31 :0 ] interpolation_counter;
77
87
78
- reg transmit_ready = 1'b0 ;
79
88
reg dma_data_valid = 1'b0 ;
80
89
reg dma_data_valid_adjacent = 1'b0 ;
81
90
82
91
reg filter_enable = 1'b0 ;
83
- reg transfer = 1'b0 ;
84
92
reg [15 :0 ] dma_valid_m = 16'd0 ;
85
93
reg stop_transfer = 1'd0 ;
86
94
95
+ reg transfer = 1'd0 ;
96
+ reg [ 1 :0 ] transfer_sm = 2'd0 ;
97
+ reg [ 1 :0 ] transfer_sm_next = 2'd0 ;
98
+ reg raw_dma_n = 1'd0 ;
99
+
100
+ // internal signals
101
+
87
102
wire dac_valid_corrected;
88
103
wire [15 :0 ] dac_data_corrected;
89
104
wire dac_fir_valid;
@@ -94,15 +109,37 @@ module axi_dac_interpolate_filter #(
94
109
95
110
wire dma_valid_ch_sync;
96
111
wire dma_valid_ch;
112
+ wire flush_dma;
113
+
114
+ wire [15 :0 ] iqcor_data_in;
115
+ wire iqcor_valid_in;
116
+
117
+ wire transfer_start;
118
+ wire transfer_ready;
119
+
120
+ // Once enabled the raw value will be selected until the DMA has valid data.
121
+ // This is a workaround for when DAC channels are start/stopped independent
122
+ // of each other and working in cyclic mode at a lower samplerate. It is
123
+ // used to solve a system limitation(delay) between the application and
124
+ // Linux kernel, which resulted in a pulse at the beginning of a new buffer
125
+ // consisting in the last sample on the DMA bus.
126
+ always @(posedge dac_clk) begin
127
+ raw_dma_n <= raw_transfer_en | flush_dma ? 1'b1 : raw_dma_n & ! dma_valid;
128
+ end
129
+
130
+ assign reset_filt = ! raw_dma_n & dma_transfer_suspend;
131
+
132
+ assign iqcor_data_in = raw_dma_n ? dac_raw_ch_data : dac_data;
133
+ assign iqcor_valid_in = raw_dma_n ? 1'b1 : dac_valid;
97
134
98
135
ad_iqcor #(
99
136
.Q_OR_I_N (0 ),
100
137
.DISABLE(CORRECTION_DISABLE),
101
138
.SCALE_ONLY(1 )
102
139
) i_ad_iqcor (
103
140
.clk (dac_clk),
104
- .valid (dac_valid ),
105
- .data_in (dac_data ),
141
+ .valid (iqcor_valid_in ),
142
+ .data_in (iqcor_data_in ),
106
143
.data_iq (16'h0 ),
107
144
.valid_out (dac_valid_corrected),
108
145
.data_out (dac_data_corrected),
@@ -113,36 +150,21 @@ module axi_dac_interpolate_filter #(
113
150
fir_interp fir_interpolation (
114
151
.clk (dac_clk),
115
152
.clk_enable (dac_cic_valid),
116
- .reset (dac_rst | dma_transfer_suspend ),
153
+ .reset (dac_rst | reset_filt ),
117
154
.filter_in (dac_data_corrected),
118
155
.filter_out (dac_fir_data),
119
156
.ce_out (dac_fir_valid));
120
157
121
158
cic_interp cic_interpolation (
122
159
.clk (dac_clk),
123
160
.clk_enable (dac_valid_corrected),
124
- .reset (dac_rst | cic_change_rate | dma_transfer_suspend ),
161
+ .reset (dac_rst | cic_change_rate | reset_filt ),
125
162
.rate (interp_rate_cic),
126
163
.load_rate (1'b0 ),
127
164
.filter_in (dac_fir_data[30 :0 ]),
128
165
.filter_out (dac_cic_data),
129
166
.ce_out (dac_cic_valid));
130
167
131
- assign dma_valid_ch_sync = sync_stop_channels ?
132
- dma_valid & dma_valid_adjacent & ! dma_transfer_suspend :
133
- dma_valid & ! dma_transfer_suspend;
134
-
135
- assign dma_valid_ch = dma_valid_ch_sync & ! stop_transfer;
136
- always @(posedge dac_clk) begin
137
- if (dac_rst == 1'b1 ) begin
138
- dma_valid_m <= 'd0;
139
- end else begin
140
- dma_valid_m <= {dma_valid_m[14 :0 ], dma_valid_ch};
141
- end
142
- end
143
-
144
- assign dac_valid_out = dma_valid_m[4'h5 ];
145
-
146
168
always @(posedge dac_clk) begin
147
169
filter_mask_d1 <= filter_mask;
148
170
if (filter_mask_d1 != filter_mask) begin
@@ -157,9 +179,7 @@ module axi_dac_interpolate_filter #(
157
179
// paths randomly ready, only when using data buffers
158
180
159
181
always @(posedge dac_clk) begin
160
- if (dac_filt_int_valid &
161
- (! start_sync_channels & dma_valid |
162
- (dma_valid & dma_valid_adjacent))) begin
182
+ if (dac_filt_int_valid & transfer_ready) begin
163
183
if (interpolation_counter == interpolation_ratio) begin
164
184
interpolation_counter <= 0 ;
165
185
dac_int_ready <= 1'b1 ;
@@ -173,26 +193,71 @@ module axi_dac_interpolate_filter #(
173
193
end
174
194
end
175
195
196
+ assign transfer_ready = start_sync_channels ?
197
+ dma_valid & dma_valid_adjacent :
198
+ dma_valid;
199
+ assign transfer_start = ! (en_start_trigger ^ trigger) & transfer_ready;
200
+
176
201
always @(posedge dac_clk) begin
177
- if (dma_transfer_suspend == 1'b0 ) begin
178
- transfer <= trigger ? 1'b1 : transfer | ! (trigger_active & en_start_trigger);
179
- end else begin
180
- transfer <= 1'b0 ;
181
- end
182
- if (start_sync_channels == 1'b0 ) begin
183
- transmit_ready <= dma_valid & transfer;
184
- end else begin
185
- transmit_ready <= dma_valid & dma_valid_adjacent & transfer;
186
- end
202
+ stop_transfer <= transfer_sm == IDLE ? 1'b0 :
203
+ stop_transfer |
204
+ dma_transfer_suspend |
205
+ (en_stop_trigger & trigger) |
206
+ (sync_stop_channels & dma_valid & dma_valid_adjacent);
207
+ end
208
+
209
+ // transfer state machine
210
+ always @(posedge dac_clk) begin
211
+ case (transfer_sm)
212
+ IDLE: begin
213
+ transfer <= 1'b0 ;
214
+ if (dac_int_ready) begin
215
+ transfer_sm_next <= WAIT;
216
+ end
217
+ end
218
+ WAIT: begin
219
+ transfer <= 1'b0 ;
220
+ if (transfer_start) begin
221
+ transfer_sm_next <= TRANSFER;
222
+ end
223
+ end
224
+ TRANSFER: begin
225
+ transfer <= 1'b1 ;
226
+ if (stop_transfer) begin
227
+ if (flush_dma_in) begin
228
+ transfer_sm_next <= FLUSHING;
229
+ end else begin
230
+ transfer_sm_next <= WAIT;
231
+ end
232
+ end else if (dma_valid == 1'b0 ) begin
233
+ transfer_sm_next <= IDLE;
234
+ end
235
+ end
236
+ FLUSHING: begin
237
+ transfer <= 1'b1 ;
238
+ if (dma_valid == 1'b0 ) begin
239
+ transfer_sm_next <= IDLE;
240
+ end
241
+ end
242
+ endcase
243
+ transfer_sm <= transfer_sm_next;
187
244
end
188
245
246
+ assign flush_dma = transfer_sm_next == FLUSHING ? 1'b1 : raw_transfer_en & flush_dma_in;
247
+ assign dma_ready = transfer_sm_next == TRANSFER ? dac_int_ready : flush_dma;
248
+ assign underflow = dac_enable & dma_ready & ~ dma_valid & ! flush_dma;
249
+
250
+ assign dma_valid_ch = transfer | raw_transfer_en;
251
+
189
252
always @(posedge dac_clk) begin
190
- stop_transfer <= ! en_stop_trigger | dma_transfer_suspend ? 1'b0 :
191
- stop_transfer | (trigger_active & trigger & transfer);
253
+ if (dac_rst == 1'b1 ) begin
254
+ dma_valid_m <= 'd0;
255
+ end else begin
256
+ dma_valid_m <= {dma_valid_m[14 :0 ], dma_valid_ch};
257
+ end
192
258
end
193
259
194
- assign dma_ready = transmit_ready ? dac_int_ready : 1'b0 ;
195
- assign underflow = dac_enable & dma_ready & ~ dma_valid;
260
+ assign dac_valid_out = dma_valid_m[2 ];
196
261
197
262
always @(posedge dac_clk) begin
198
263
case (filter_mask)
0 commit comments