芯片ADS9224R的FPGA驱动实现
ADS9224R这款芯片是德州仪器(TI)的一款SAR ADC,笔者写这芯片IP核大概有段时间了,这款ADC采集芯片挺复杂的。笔者当时对写axi4_lite的IP核还不是很熟悉,就接下了含有这款芯片的项目,当时看了手册觉得亚历山大。因为当时项目允许开发一款IP的时间就2周左右,不过笔者还是顶住了压力把芯片驱动的IP核写了出来。现在想想大概是有过了一些挑战之后,后面写IP核变得更加顺畅。
这款芯片的datasheet可自行查找,最大采样频率是3MSPS,16bit。说真的当时笔者想着的是尽量把该芯片的IP核写的通用些,看了手册才发现过于乐观,这款芯片的采样模式实在是太多了,笔者真有被吓到。由于开发时间很短,数据手册都是英文阅读需要不少时间,后面就只能尽可能把代码些通用些了,这次之后笔者获益匪浅。
这款芯片的大体框架如下:
根据当时项目的设计及调试结果,笔者设计的IP核是为了更多的适应项目需求,所以会对代码的接收SDI引脚加些延时。硬件上的限制,当时是设计最大采样率为1.5MSPS。笔者用的采样模式为下图模式:
笔者看到这时序图有点疑惑不知道是不是手册有问题,上图中的ADC采样过程中READY/STROBE为高电平,而下面对于采样时序的时序图分析中居然是拉低的,这让笔者很是疑惑,后面就根据实际情况来分析的,实际调试过程中这个信号应该是低的。
笔者根据手册共设计了SPI-00-S-SDR,SPI-10-S-SDR,SPI-01-S-SDR,SPI-11-S-SDR;SPI-00-D-SDR,SPI-10-D-SDR,SPI-01-D-SDR,SPI-11-D-SDR;SPI-00-Q-SDR,SPI-10-Q-SDR,SPI-01-Q-SDR,SPI-11-Q-SDR这12种模式,还有DDR等其他模式笔者没有设计。不过这么多模式笔者碍于时间紧迫,并没有一一调试,可能会多少存在些问题,笔者就把SPI-00-S-SDR,SPI-00-D-SDR,SPI-00-Q-SDR这三种最常用的模式调试了。
ADS9224R_IF.v:
1 //**************************************************************************
2 // *** file name : ADS9224R_IF.v
3 // *** version : 1.0
4 // *** Description : ADS9224R interface driver
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2020.04.21
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module ADS9224R_IF
12 #(
13 parameter SDI_WIDTH =4
14 )
15 (
16 input i_sys_clk ,
17 input i_sys_reset ,
18 input i_spi_enable ,
19 input [31:0] i_spi_sclk_ctrl ,
20 input [31:0] i_spi_sample_time ,
21 input [23:0] i_fre_sample ,
22
23 input i_spi_tx_valid ,
24 input [23:0] i_spi_tx_data ,
25 output reg o_spi_tx_ready ,
26 output [31:0] o_spi_rx_data ,
27 output o_spi_rx_single_valid ,
28 output o_spi_rx_valid ,
29 output o_time_sample_en ,
30 output o_spi_bus_busy ,
31 output o_spi_ready ,
32
33 input [1:0] i_spi_type ,
34 output o_spi_cnv ,
35 input i_spi_ready ,
36 output o_spi_cs ,
37 output reg o_spi_sclk ,
38 output o_spi_sdout ,
39 input [SDI_WIDTH-1:0] i_spi_sdina ,
40 input [SDI_WIDTH-1:0] i_spi_sdinb
41
42 );
43
44 parameter T_DRDY = 2;
45 localparam DEJITTER_LEVEL = 2;
46 localparam SPI_IDLE = 0,
47 SPI_START = 1,
48 SPI_READY = 2,
49 SPI_WAIT_READY = 3,
50 SPI_SCLKNEG = 4,
51 SPI_DEAL = 5,
52 SPI_CNVEND = 6;
53 parameter CH_DEJITTER = DEJITTER_LEVEL*SDI_WIDTH;
54 parameter BIT_SHIFT = SDI_WIDTH>>1;
55
56 reg [CH_DEJITTER-1:0] r_spi_sdina_s ;
57 reg [SDI_WIDTH-1:0] r_spi_sdina_temp ;
58 reg [CH_DEJITTER-1:0] r_spi_sdinb_s ;
59 reg [SDI_WIDTH-1:0] r_spi_sdinb_temp ;
60 reg r_spi_ready_s ;
61 wire w_spi_sclk_neg ;
62 wire w_spi_sclk_pos ;
63 reg [31:0] r_spi_sclk_ctrl_temp ;
64 reg [31:0] r_spi_sclk_cnt ;
65 reg r_spi_sclk_temp ;
66 reg [8:0] r_spi_state ;
67 reg [8:0] r_spi_state_next ;
68 wire w_spi_wait_over ;
69 wire w_spi_reset ;
70 reg [5:0] r_spi_bit_cnt ;
71 reg [23:0] r_tx_data_temp ;
72 reg [15:0] r_rx_data_tempa ;
73 reg [15:0] r_rx_data_tempb ;
74 reg [31:0] r_spi_sample_cnt ;
75 wire w_rx_data_en ;
76 wire w_rx_data_over ;
77 reg [DEJITTER_LEVEL-1+13:0] r_rx_data_en_s ;
78 reg [DEJITTER_LEVEL-1+13:0] r_rx_data_over_s ;
79 wire w_spi_clk_temp_00 ;
80 wire w_spi_clk_temp_01 ;
81 wire w_spi_clk_temp_10 ;
82 wire w_spi_clk_temp_11 ;
83 reg [15:0] r_run_time_cnt ;
84 reg [31:0] r_cnv_cnt ;
85 wire w_time_clr ;
86 wire w_wait_ready_cnt_over ;
87 wire [15:0] w_rx_data_tempa ;
88 wire [15:0] w_rx_data_tempb ;
89 reg r_sample_end ;
90 reg r_spi_bus_busy ;
91
92 /******************************************************************************\
93 输入i_spi_ready
94 \******************************************************************************/
95 always @ (posedge i_sys_clk)
96 begin
97 if(~i_sys_reset)
98 begin
99 r_spi_ready_s <= 1'b0;
100 end
101 else
102 begin
103 r_spi_ready_s <= i_spi_ready;
104 end
105 end
106 assign o_spi_ready = r_spi_ready_s ;
107 assign w_spi_ready_pos = ~r_spi_ready_s & i_spi_ready;
108
109 /******************************************************************************\
110 SPI时钟控制
111 \******************************************************************************/
112 always @ (posedge i_sys_clk)
113 begin
114 if(~i_sys_reset)
115 begin
116 r_spi_sclk_ctrl_temp <= 32'd0;
117 end
118 else
119 begin
120 r_spi_sclk_ctrl_temp <= i_spi_sclk_ctrl;
121 end
122 end
123
124 always @ (posedge i_sys_clk)
125 begin
126 if(~w_spi_reset)
127 begin
128 r_spi_sclk_cnt <= 32'd0;
129 end
130 else
131 begin
132 if(r_spi_state[SPI_CNVEND])
133 begin
134 r_spi_sclk_cnt <= 32'd0;
135 end
136 else
137 begin
138 r_spi_sclk_cnt <= r_spi_sclk_cnt + r_spi_sclk_ctrl_temp;
139 end
140 end
141 end
142
143 always @ (posedge i_sys_clk)
144 begin
145 if(~w_spi_reset)
146 begin
147 r_spi_sclk_temp <= 1'd0;
148 end
149 else
150 begin
151 r_spi_sclk_temp <= r_spi_sclk_cnt[31];
152 end
153 end
154
155 assign w_spi_sclk_neg = r_spi_sclk_temp & ~r_spi_sclk_cnt[31];
156 assign w_spi_sclk_pos = ~r_spi_sclk_temp & r_spi_sclk_cnt[31];
157
158 /******************************************************************************\
159 时间计数
160 \******************************************************************************/
161 always @(posedge i_sys_clk)
162 begin
163 if(~w_spi_reset | w_time_clr |r_spi_state[SPI_IDLE])
164 begin
165 r_run_time_cnt <= 16'd0;
166 end
167 else if(r_spi_state[SPI_READY])
168 begin
169 r_run_time_cnt <= r_run_time_cnt + 1'b1;
170 end
171 else
172 begin
173 r_run_time_cnt <= 16'd0;
174 end
175 end
176
177 assign w_wait_ready_cnt_over = r_spi_state[SPI_READY]&(r_run_time_cnt == T_DRDY);
178
179 assign w_time_clr = w_wait_ready_cnt_over;
180 /******************************************************************************\
181 SPI状态控制
182 \******************************************************************************/
183 assign w_spi_reset = i_spi_enable & i_sys_reset;
184
185 always @ (posedge i_sys_clk)
186 begin
187 if(~w_spi_reset)
188 begin
189 r_spi_state <= 'd0;
190 r_spi_state[SPI_IDLE] <= 1'b1;
191 end
192 else
193 begin
194 r_spi_state <= r_spi_state_next;
195 end
196 end
197
198 always @ (*)
199 begin
200 r_spi_state_next = 'd0;
201 case(1'b1)
202 r_spi_state[SPI_IDLE] : begin
203 if(i_spi_tx_valid & w_spi_sclk_neg )
204 begin
205 r_spi_state_next[SPI_START] = 1'b1;
206 end
207 else
208 begin
209 r_spi_state_next[SPI_IDLE] = 1'b1;
210 end
211 end
212
213 r_spi_state[SPI_START] : begin
214 if(~r_tx_data_temp[16])
215 begin
216 r_spi_state_next[SPI_SCLKNEG] = 1'b1;
217 end
218 else if(~i_spi_ready)//刚上电时i_spi_ready为高,0.9ms之后为低
219 begin
220 r_spi_state_next[SPI_READY] = 1'b1;
221 end
222 else
223 begin
224 r_spi_state_next[SPI_START] = 1'b1;
225 end
226 end
227 r_spi_state[SPI_READY] : begin
228 if(w_wait_ready_cnt_over)
229 begin
230 r_spi_state_next[SPI_WAIT_READY] = 1'b1;
231 end
232 else
233 begin
234 r_spi_state_next[SPI_READY] = 1'b1;
235 end
236 end
237 r_spi_state[SPI_WAIT_READY] :begin
238 if(w_spi_ready_pos)
239 begin
240 r_spi_state_next[SPI_SCLKNEG] = 1'b1;
241 end
242 else
243 begin
244 r_spi_state_next[SPI_WAIT_READY] = 1'b1;
245 end
246 end
247 r_spi_state[SPI_SCLKNEG]: begin
248 if(w_spi_sclk_neg)
249 r_spi_state_next[SPI_DEAL] = 1'b1;
250 else
251 r_spi_state_next[SPI_SCLKNEG] = 1'b1;
252 end
253 r_spi_state[SPI_DEAL] : begin
254 if(w_spi_sclk_neg & (r_spi_bit_cnt == 6'd15) & (~r_tx_data_temp[17]))
255 begin
256 r_spi_state_next[SPI_CNVEND] = 1'b1;
257 end
258 else if(w_spi_sclk_neg & (r_spi_bit_cnt == 6'd15>>BIT_SHIFT) & r_tx_data_temp[17])
259 begin
260 r_spi_state_next[SPI_CNVEND] = 1'b1;
261 end
262 else
263 begin
264 r_spi_state_next[SPI_DEAL] = 1'b1;
265 end
266 end
267 r_spi_state[SPI_CNVEND] : begin
268 if(~r_tx_data_temp[16])
269 begin
270 r_spi_state_next[SPI_IDLE] = 1'b1;
271 end
272 else if(r_cnv_cnt==i_fre_sample)
273 begin
274 if(r_tx_data_temp[19] & (~r_sample_end))
275 begin
276 r_spi_state_next[SPI_READY] = 1'b1;
277 end
278 else
279 begin
280 r_spi_state_next[SPI_IDLE] = 1'b1;
281 end
282 end
283 else
284 begin
285 r_spi_state_next[SPI_CNVEND] = 1'b1;
286 end
287 end
288 default : begin
289 r_spi_state_next[SPI_IDLE] = 1'b1;
290 end
291 endcase
292 end
293 /******************************************************************************\
294 获取数据
295 \******************************************************************************/
296 always @ (*)
297 begin
298 case(1'b1)
299 r_spi_state[SPI_IDLE] : begin
300 if(i_spi_tx_valid & w_spi_sclk_neg )
301 begin
302 o_spi_tx_ready = 1'b1;
303 end
304 else
305 begin
306 o_spi_tx_ready = 1'b0;
307 end
308 end
309 default : begin
310 o_spi_tx_ready = 1'b0;
311 end
312 endcase
313 end
314 /******************************************************************************\
315 bit计数
316 \******************************************************************************/
317 always @ (posedge i_sys_clk)
318 begin
319 if(~w_spi_reset | ~r_spi_state[SPI_DEAL])
320 begin
321 r_spi_bit_cnt <= 6'd0;
322 end
323 else if(w_spi_sclk_neg)
324 begin
325 if(r_spi_bit_cnt == 6'd15 && (~r_tx_data_temp[17]))
326 begin
327 r_spi_bit_cnt <= 6'd0;
328 end
329 else if(r_spi_bit_cnt == 6'd15>>BIT_SHIFT && r_tx_data_temp[17])
330 begin
331 r_spi_bit_cnt <= 6'd0;
332 end
333 else
334 begin
335 r_spi_bit_cnt <= r_spi_bit_cnt + 6'd1;
336 end
337 end
338 end
339 /******************************************************************************\
340 发送数据
341 \******************************************************************************/
342 always @ (posedge i_sys_clk)
343 begin
344 if(~w_spi_reset)
345 begin
346 r_tx_data_temp <= 24'd0;
347 end
348 else if(o_spi_tx_ready & i_spi_tx_valid)
349 begin
350 r_tx_data_temp <= i_spi_tx_data;
351 end
352 else if(w_spi_sclk_neg & r_spi_state[SPI_DEAL] & r_tx_data_temp[18])
353 begin
354 r_tx_data_temp[15:0] <= {r_tx_data_temp[14:0],1'b0};
355 end
356 end
357
358 assign o_spi_sdout = r_tx_data_temp[15];
359 assign o_time_sample_en = r_tx_data_temp[19];
360
361 /******************************************************************************\
362 输入去抖动
363 \******************************************************************************/
364 genvar ch_i;
365 generate
366 for(ch_i=0;ch_i<SDI_WIDTH;ch_i=ch_i+1)
367 begin:sdin_channel
368 always @ (posedge i_sys_clk)
369 begin
370 if(~i_sys_reset)
371 begin
372 r_spi_sdina_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i] <= {DEJITTER_LEVEL{1'b0}};
373 end
374 else
375 begin
376 r_spi_sdina_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i] <= {r_spi_sdina_s[DEJITTER_LEVEL*(ch_i+1)-2:DEJITTER_LEVEL*ch_i],i_spi_sdina[ch_i]};//去抖32ns
377 end
378 end
379
380 always @ (posedge i_sys_clk)
381 begin
382 if(~i_sys_reset)
383 begin
384 r_spi_sdina_temp[ch_i] <= 1'b0;
385 end
386 else if(&r_spi_sdina_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i])
387 begin
388 r_spi_sdina_temp[ch_i] <= 1'b1;
389 end
390 else if(~(|r_spi_sdina_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i]))
391 begin
392 r_spi_sdina_temp[ch_i] <= 1'b0;
393 end
394 end
395 always @ (posedge i_sys_clk)
396 begin
397 if(~i_sys_reset)
398 begin
399 r_spi_sdinb_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i] <= {DEJITTER_LEVEL{1'b0}};
400 end
401 else
402 begin
403 r_spi_sdinb_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i] <= {r_spi_sdinb_s[DEJITTER_LEVEL*(ch_i+1)-2:DEJITTER_LEVEL*ch_i],i_spi_sdinb[ch_i]};//去抖32ns
404 end
405 end
406
407 always @ (posedge i_sys_clk)
408 begin
409 if(~i_sys_reset)
410 begin
411 r_spi_sdinb_temp[ch_i] <= 1'b0;
412 end
413 else if(&r_spi_sdinb_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i])
414 begin
415 r_spi_sdinb_temp[ch_i] <= 1'b1;
416 end
417 else if(~(|r_spi_sdinb_s[DEJITTER_LEVEL*(ch_i+1)-1:DEJITTER_LEVEL*ch_i]))
418 begin
419 r_spi_sdinb_temp[ch_i] <= 1'b0;
420 end
421 end
422
423 always @ (posedge i_sys_clk)
424 begin
425 if(~w_spi_reset)
426 begin
427 {r_rx_data_tempa[(16>>BIT_SHIFT)*(ch_i+1)-1:(16>>BIT_SHIFT)*ch_i]} <= {(16>>BIT_SHIFT){1'b0}};
428 {r_rx_data_tempb[(16>>BIT_SHIFT)*(ch_i+1)-1:(16>>BIT_SHIFT)*ch_i]} <= {(16>>BIT_SHIFT){1'b0}};
429 end
430 else if(r_rx_data_en_s[DEJITTER_LEVEL-1+13])
431 begin
432 {r_rx_data_tempa[(16>>BIT_SHIFT)*(ch_i+1)-1:(16>>BIT_SHIFT)*ch_i]} <= {r_rx_data_tempa[(16>>BIT_SHIFT)*(ch_i+1)-2:(16>>BIT_SHIFT)*ch_i],r_spi_sdina_temp[ch_i]};
433 {r_rx_data_tempb[(16>>BIT_SHIFT)*(ch_i+1)-1:(16>>BIT_SHIFT)*ch_i]} <= {r_rx_data_tempb[(16>>BIT_SHIFT)*(ch_i+1)-2:(16>>BIT_SHIFT)*ch_i],r_spi_sdinb_temp[ch_i]};
434 end
435 end
436
437 end
438 endgenerate
439 /******************************************************************************\
440 接收数据
441 \******************************************************************************/
442 assign w_rx_data_en = w_spi_sclk_pos & r_spi_state[SPI_DEAL] & r_tx_data_temp[17];
443 assign w_rx_data_over = w_spi_sclk_neg & (r_spi_bit_cnt == 6'd15>>BIT_SHIFT) & r_spi_state[SPI_DEAL] & r_tx_data_temp[17];//17位是读操作
444
445 always @ (posedge i_sys_clk)
446 begin
447 if(~i_sys_reset)
448 begin
449 r_rx_data_en_s <= {(DEJITTER_LEVEL+13){1'b0}};
450 r_rx_data_over_s <= {(DEJITTER_LEVEL+13){1'b0}};
451 end
452 else
453 begin
454 r_rx_data_en_s <= {r_rx_data_en_s[DEJITTER_LEVEL-2+13:0],w_rx_data_en};
455 r_rx_data_over_s <= {r_rx_data_over_s[DEJITTER_LEVEL-2+13:0],w_rx_data_over};
456 end
457 end
458
459 generate
460 if(SDI_WIDTH==1)
461 begin:One_SDI
462 assign w_rx_data_tempa = r_rx_data_tempa;
463 assign w_rx_data_tempb = r_rx_data_tempb;
464 end
465 if(SDI_WIDTH==2)
466 begin:Dual_SDI
467 assign w_rx_data_tempa[3:0] = {r_rx_data_tempa[9],r_rx_data_tempa[1],r_rx_data_tempa[8],r_rx_data_tempa[0]};
468 assign w_rx_data_tempa[7:4] = {r_rx_data_tempa[11],r_rx_data_tempa[3],r_rx_data_tempa[10],r_rx_data_tempa[2]};
469 assign w_rx_data_tempa[11:8] = {r_rx_data_tempa[13],r_rx_data_tempa[5],r_rx_data_tempa[12],r_rx_data_tempa[4]};
470 assign w_rx_data_tempa[15:12] = {r_rx_data_tempa[15],r_rx_data_tempa[7],r_rx_data_tempa[14],r_rx_data_tempa[6]};
471 assign w_rx_data_tempb[3:0] = {r_rx_data_tempb[9],r_rx_data_tempb[1],r_rx_data_tempb[8],r_rx_data_tempb[0]};
472 assign w_rx_data_tempb[7:4] = {r_rx_data_tempb[11],r_rx_data_tempb[3],r_rx_data_tempb[10],r_rx_data_tempb[2]};
473 assign w_rx_data_tempb[11:8] = {r_rx_data_tempb[13],r_rx_data_tempb[5],r_rx_data_tempb[12],r_rx_data_tempb[4]};
474 assign w_rx_data_tempb[15:12] = {r_rx_data_tempb[15],r_rx_data_tempb[7],r_rx_data_tempb[14],r_rx_data_tempb[6]};
475 end
476 else
477 begin
478 assign w_rx_data_tempa[3:0] = {r_rx_data_tempa[12],r_rx_data_tempa[8],r_rx_data_tempa[4],r_rx_data_tempa[0]};
479 assign w_rx_data_tempa[7:4] = {r_rx_data_tempa[13],r_rx_data_tempa[9],r_rx_data_tempa[5],r_rx_data_tempa[1]};
480 assign w_rx_data_tempa[11:8] = {r_rx_data_tempa[14],r_rx_data_tempa[10],r_rx_data_tempa[6],r_rx_data_tempa[2]};
481 assign w_rx_data_tempa[15:12] = {r_rx_data_tempa[15],r_rx_data_tempa[11],r_rx_data_tempa[7],r_rx_data_tempa[3]};
482 assign w_rx_data_tempb[3:0] = {r_rx_data_tempb[12],r_rx_data_tempb[8],r_rx_data_tempb[4],r_rx_data_tempb[0]};
483 assign w_rx_data_tempb[7:4] = {r_rx_data_tempb[13],r_rx_data_tempb[9],r_rx_data_tempb[5],r_rx_data_tempb[1]};
484 assign w_rx_data_tempb[11:8] = {r_rx_data_tempb[14],r_rx_data_tempb[10],r_rx_data_tempb[6],r_rx_data_tempb[2]};
485 assign w_rx_data_tempb[15:12] = {r_rx_data_tempb[15],r_rx_data_tempb[11],r_rx_data_tempb[7],r_rx_data_tempb[3]};
486 end
487 endgenerate
488
489 assign o_spi_rx_data = {w_rx_data_tempa,w_rx_data_tempb};
490 assign o_spi_rx_single_valid = r_tx_data_temp[19] ? 1'b0 : r_rx_data_over_s[DEJITTER_LEVEL-1+13];
491 assign o_spi_rx_valid = r_rx_data_over_s[DEJITTER_LEVEL-1+13];
492 /******************************************************************************\
493 等待时间
494 \******************************************************************************/
495 always @ (posedge i_sys_clk)
496 begin
497 if(~w_spi_reset | (~r_tx_data_temp[19]))
498 begin
499 r_spi_sample_cnt <= 32'd1;
500 end
501 else
502 begin
503 r_spi_sample_cnt <= r_spi_sample_cnt + 32'd1;
504 end
505 end
506
507 always @ (posedge i_sys_clk)
508 begin
509 if(~w_spi_reset | (~r_tx_data_temp[19]))
510 begin
511 r_sample_end <= 1'b0;
512 end
513 else if(w_spi_wait_over)
514 begin
515 r_sample_end <= 1'b1;
516 end
517 end
518 assign w_spi_wait_over = (i_spi_sample_time == r_spi_sample_cnt);
519
520 /******************************************************************************\
521 CONVST
522 \******************************************************************************/
523
524 always@(posedge i_sys_clk)
525 begin
526 if(~w_spi_reset | r_spi_state[SPI_IDLE])
527 begin
528 r_cnv_cnt <= 32'd1;
529 end
530 else if(r_cnv_cnt==i_fre_sample)
531 begin
532 r_cnv_cnt <= 32'd1;
533 end
534 else
535 begin
536 r_cnv_cnt <=r_cnv_cnt + 32'd1;
537 end
538 end
539
540 reg r_spi_cnv;
541 always@(posedge i_sys_clk)
542 begin
543 if(~w_spi_reset | r_spi_state[SPI_IDLE])
544 begin
545 r_spi_cnv <= 1'b0;
546 end
547 else if(r_tx_data_temp[16])
548 begin
549 if(r_cnv_cnt <= (i_fre_sample>>1))
550 begin
551 r_spi_cnv <= 1'b1;
552 end
553 else
554 begin
555 r_spi_cnv <= 1'b0;
556 end
557 end
558 else
559 begin
560 r_spi_cnv <= 1'b0;
561 end
562 end
563
564 assign o_spi_cnv = r_spi_cnv;
565 /******************************************************************************\
566 CS
567 \******************************************************************************/
568 assign o_spi_cs = ~r_spi_state[SPI_DEAL] ;
569 /******************************************************************************\
570 CLK
571 \******************************************************************************/
572 assign w_spi_clk_temp_10 = o_spi_cs ? 1'b1 : ( r_spi_sclk_temp);
573 assign w_spi_clk_temp_00 = o_spi_cs ? 1'b0 : ( r_spi_sclk_temp);
574 assign w_spi_clk_temp_11 = o_spi_cs ? 1'b1 : ~( r_spi_sclk_temp);
575 assign w_spi_clk_temp_01 = o_spi_cs ? 1'b0 : ~( r_spi_sclk_temp);
576
577 always @ (*)
578 begin
579 case(i_spi_type)
580 2'b00 : o_spi_sclk = w_spi_clk_temp_00;
581 2'b01 : o_spi_sclk = w_spi_clk_temp_01;
582 2'b10 : o_spi_sclk = w_spi_clk_temp_10;
583 2'b11 : o_spi_sclk = w_spi_clk_temp_11;
584 endcase
585 end
586 /******************************************************************************\
587 SPI BUS status
588 \******************************************************************************/
589
590 always @ (posedge i_sys_clk)
591 begin
592 if(~w_spi_reset)
593 begin
594 r_spi_bus_busy <= 1'b0;
595 end
596 else if(r_tx_data_temp[19])
597 begin
598 if(r_spi_state[SPI_IDLE] && r_sample_end)
599 r_spi_bus_busy <= 1'b0;
600 else
601 r_spi_bus_busy <= 1'b1;
602 end
603 else
604 begin
605 if(r_spi_state[SPI_IDLE]&&(~i_spi_tx_valid))
606 r_spi_bus_busy <= 1'b0;
607 else
608 r_spi_bus_busy <= 1'b1;
609 end
610 end
611
612 assign o_spi_bus_busy = r_spi_bus_busy;
613 endmodule
芯片ADS9224R的FPGA驱动实现的更多相关文章
- FPGA驱动VGA显示静态图片
一 .前言 本文设计思想采用明德扬至简设计法.VGA是最常见的视频显示接口,时序也较为简单.本文从利用显示屏通过VGA方式显示测试图案及静态图片着手带大家接触图像显示应用,算是为后续VGA显示摄像头采 ...
- FPGA驱动LCD显示红绿蓝彩条
实验目的:先简单熟悉LCD灯的驱动和时序图的代码实现.设计功能是让LCD显示红绿蓝三种颜色,即三个彩带.本次实验比较容易实现,主要是对LCD驱动时序图的理解和时序参数的配置. 实验条件:1.LCD原理 ...
- FPGA驱动步进电机
步进电机 步进电机是将电脉冲信号转变为角位移或线位移的开环控制电机,是现代数字程序控制系统中的主要执行元件,应用极为广泛.在非超载的情况下,电机的转速.停止的位置只取决于脉冲信号的频率和脉冲数,而不受 ...
- 基于FPGA驱动VGA显示图片的小问题
学习VGA显示图片的过程中,遇到了一个小问题,我在显示屏上开了一个60x60的框,放了一张图片进去显示,但是最终的结果如下图所示. 出现了一个竖黑边,看了看代码,分析了一下逻辑没问题,然而看这个显示那 ...
- 嵌入式开发之zynq——赛灵思的一款两a9加一fpga芯片的开发板
没办法,回家入职新公司,做通信的,用到这款zynq加ad9163射频架构的开发版,要我做驱动,这可是初次接触zynq,带fpga的集成芯片,心里还是有点惊喜和忧愁,忧愁怎么最快啃下这个硬骨头,好吧上网 ...
- 10-8位7段数码管驱动实验——小梅哥FPGA设计思想与验证方法视频教程配套文档
芯航线--普利斯队长精心奉献 实验目的: 1.实现FPGA驱动数码管动态显示: 2.使用In system sources and probes editor工具,输入需要显示在数码管上的的数据, ...
- Linux编译安装RTL8192CU芯片驱动,使用TP_LINK wn823n无线网卡
前几天给自己的台式电脑安装了Window 7+CentOS 6.4 Linux双系统,发现在Windows 7下面可以正常使用TP_LINK wn823n无线网卡来连接无线网络,但是在Linux下面, ...
- 基于FPGA的4x4矩阵键盘驱动调试
好久不见,因为博主最近两个月有点事情,加上接着考试,考完试也有点事情要处理,最近才稍微闲了一些,这才赶紧记录分享一篇博文.FPGA驱动4x4矩阵键盘.这个其实原理是十分简单,但是由于博主做的时候遇到了 ...
- 【资讯】天啦鲁,这十余款创客设计居然由FPGA搞定 [转]
按理说‘高大上’的FPGA,多出现在航天航空(如火星探测器).通信(如基站.数据中心).测试测量等高端应用场景.但麦迪却也发现,近期,在很多创客的作品内部都有FPGA的影子.这或许也从侧面看出,打从总 ...
- 【FPGA】相关介绍
什么是 FPGA ? FPGA是Field Programmable Gate Array的缩写,即现场可编程门阵列,它是在PAL.GAL.EPLD等可编程器件的基础上进一步发展的产物.它是作为专用集 ...
随机推荐
- JZOJ 2483. 【GDKOI 2021提高组DAY1】回文(palindrome)
题目 求区间最长回文串长度 \(1 \le n\le 5 \times 10^5\) 题解 比较妙的做法,主要是在询问部分 预处理出以某位为中心回文半径长 \(p_i\),马拉车和二分+哈希均可 然后 ...
- leaflet动态加载/手动绘制(圆、多边形)demo
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3 ...
- Unity3D 不挂载脚本自动初始化
https://blog.csdn.net/piai9568/article/details/98886028
- npm -D与-S
--save == -S -S, --save 安装包信息将加入到dependencies(生产阶段的依赖,也就是项目运行时的依赖,就是程序上线后仍然需要依赖) --save-dev == -D -D ...
- HttpProxyCacheServer (音视频缓存框架)
implementation 'com.danikula:videocache:2.7.0' //包 MyApplication 中: //音视频缓存框架private HttpProxyCacheS ...
- mybatis全局配置:下划线转驼峰
处理字段名和属性名不一致的情况: mybatis-config.xml配置 <settings> <setting name="mapUnderscoreToCamelCa ...
- 在orangepi 3 lts上使用SmartCardReader(读卡器)
前期工作 orangepi 3 lts使用全志的H6芯片,通过查询该芯片的datasheet和user manual,可以发现H6有两个scr接口,分别为scr0和scr1,理论上是支持读卡器接口的, ...
- Deer_GF之图片
Hi,今天介绍一下Deer_Gf里的图片组件. 框架介绍请移步[Deer_GF之框架介绍] 接下来为大家介绍一下框架里用到的图片组件及加载流程. 目录 大图(Texture)存 ...
- 只会Jquery,后端程序员如何学会前端(webpack,react,babel,es5,es6)
写在前 希望通过短暂的学习,可以达到一下目标: 1.能看懂现在前端的工程化手段 2.知道当前前端群体中大致的解决问题的思路 3.当前的问题在哪里,技术发展趋势是什么 4.建立起自己的认知模型 文章内容 ...
- 动态class 及 动态style
动态改变某一范围内的字体颜色 低于90 大于90小于95 大于95 两种方法都可以 <div class="dhd-num4" :style="{'col ...