【代码更新】SPI时序——AD数模数转换

AD芯片手册:https://www.ti.com.cn/cn/lit/ds/symlink/ads8558.pdf?ts=1709473143911&ref_url=https%253A%252F%252Fwww.ti.com.cn%252Fproduct%252Fcn%252FADS8558

下图是芯片需要配置信号的时序图

寄存器配置时序:

项目硬件连接图:

整体代码如下:

  1 //SCK  MAX  --->  36MHz
2 //
3 //PAR/SER = BVDD1 板子已经处于串行接口模式
4 //
5 //
6 //U57-M8 -->SDOC-->M8
7 //U57-M7 -->SDOB-->M7
8 //U57-N5 -->SDOA-->N5
9 //
10 //不控制:
11 //SEL_A
12 //SEL_B
13 //SEL_C 都接高电平,选择SDOA/SDOB/SDOC
14 //
15 //BUSY/INT ---->DO
16 //
17 //RANGE/XCLK---->U42-RANGE--->P8--->max 20MHz tpye 18MHz
18 //CLKSEL --->high ---> C11=1
19 //
20 //
21 `timescale 1ns / 1ps
22 module ad_collect(
23 //
24 input wire clk ,//50MHz
25 //
26 output wire xclk,//---->max 20MHz--->p8---->tpye 18MHz
27 output reg reset, //RESET---->PIN28 --->高复位中止转换----->大于50ns-->内部控制寄存器复位至0x000003FF
28 output wire hw_sw, //HW/SW = REFEN/WR --->T4-->'b1--->software mode(HW/SW =1)
29 output reg cs_fs, //--->帧同步/FS 的下降沿控制帧传输
30 //
31 input wire busy_int,
32 //
33 output reg convst_a,//IO_L05P_2----->CONVST_A--->T4
34 output wire convst_b,//IO_L06P_2----->CONVST_B--->T5
35 output wire convst_c,//IO_L06N_2----->CONVST_C--->T6 -->最好三个脚连在一起,不连在一起两两之间间隔不超过4ns
36 //
37 output reg sclk,
38 output reg sdi,
39 //
40 input wire sdo_a,
41 input wire sdo_b,
42 input wire sdo_c,
43 //
44 output reg [15:0] data_a0,//A通道数据高位
45 output reg [15:0] data_a1,//A通道数据低位
46 output reg [15:0] data_b0,
47 output reg [15:0] data_b1,
48 output reg [15:0] data_c0,
49 output reg [15:0] data_c1,
50 //
51 output wire ad_a0,//3-8译码器配置带你看
52 output wire ad_a1,
53 output wire ad_a2,
54 //
55 output reg data_abc_vaild
56 );
57 //
58 reg [15:0] cnt_rst_n ='d0;
59 always@(posedge clk)
60 begin
61 if(cnt_rst_n > 'd5000)
62 cnt_rst_n <='d5001;
63 else
64 cnt_rst_n<=cnt_rst_n+1'b1;
65 end
66 //
67 reg rst_n;
68 always@(posedge clk)
69 begin
70 if(cnt_rst_n == 'd5001)
71 rst_n<='b1;
72 else
73 rst_n<='b0;
74 end
75 //
76 //------------------------clock-分频-----------------------------------------
77 reg [1:0] div_cnt1;
78 always@(posedge clk)
79 begin
80 if(!rst_n)
81 div_cnt1<=2'b00;
82 else
83 div_cnt1<=div_cnt1+1'b1;
84 end
85
86 reg div4_o_r; //----->12.5MHz ---80ns
87 always@(posedge clk) //四分频
88 begin //计数器放在外面 来实现计数 div_cnt1
89 if(!rst_n) //00 01 10 11 捕捉00和10 实现四分频
90 div4_o_r<=1'b0;
91 else if(div_cnt1==2'b00 || div_cnt1==2'b10)
92 div4_o_r<=~div4_o_r;
93 else
94 div4_o_r<=div4_o_r;
95 end
96
97 assign xclk = div4_o_r;//----->12.5MHz//--->CR C11(CLKSE) set high
98
99 //FPGA 配置引脚
100 //HW/SW = REFEN/WR ------->T4-->'b1 ---->software mode(HW/SW =1)
101 assign hw_sw = 1'b1;
102 assign convst_b = convst_a;
103 assign convst_c = convst_a;
104 assign ad_a0=1'b0;
105 assign ad_a1=1'b0;
106 assign ad_a2=1'b1;
107 //
108 reg [5:0] cnt0;
109 wire add_cnt0;
110 wire end_cnt0;
111 always@(posedge clk or negedge rst_n)begin
112 if(rst_n==1'b0)begin
113 cnt0<=0;
114 end
115 else if(add_cnt0)begin
116 if(end_cnt0)
117 cnt0<=0;
118 else
119 cnt0<=cnt0+1;
120 end
121 end
122
123 reg cs_fs_temp;
124 assign add_cnt0 = cs_fs_temp == 1'b0;
125 // assign end_cnt0 = add_cnt0 && cnt0 == 10-1;//5MHz
126 assign end_cnt0 = add_cnt0 && cnt0 == 4-1;//50/4 = 12.5MHz //四分频计数器实现
127
128 reg [5:0] cnt1;
129 wire add_cnt1;
130 wire end_cnt1;
131 always@(posedge clk or negedge rst_n)begin
132 if(rst_n==1'b0)begin
133 cnt1<=0;
134 end
135 else if(add_cnt1)begin
136 if(end_cnt1)
137 cnt1<=0;
138 else
139 cnt1<=cnt1+1;
140 end
141 end
142 assign add_cnt1 = end_cnt0;
143 assign end_cnt1 = add_cnt1 && cnt1 == 34-1;//配置32bit计数器实现 32bit配置 冗余1bit
144 //
145 wire idle2s1_start;
146 wire s12s2_start;
147 wire s22s3_start;
148 wire s32s4_start;
149 wire s42s5_start;
150 wire s52s3_start;
151 //
152 reg [2:0] state_c;
153 reg [2:0] state_n;
154 parameter IDLE = 3'h0;
155 parameter S1 = 3'h1;
156 parameter S2 = 3'h2;
157 parameter S3 = 3'h3;
158 parameter S4 = 3'h4;
159 parameter S5 = 3'h5;
160 //
161 always@(posedge clk or negedge rst_n)begin
162 if(rst_n==1'b0)begin
163 state_c <=IDLE;
164 end
165 else begin
166 state_c <=state_n;
167 end
168 end
169 //
170 always@(*)begin
171 case(state_c)
172 IDLE:begin
173 if(idle2s1_start)begin
174 state_n = S1;
175 end
176 else begin
177 state_n = state_c;
178 end
179 end
180 S1:begin
181 if(s12s2_start)begin
182 state_n = S2;
183 end
184 else begin
185 state_n = state_c;
186 end
187 end
188 S2:begin
189 if(s22s3_start)begin
190 state_n = S3;
191 end
192 else begin
193 state_n = state_c;
194 end
195 end
196 S3:begin
197 if (s32s4_start)begin
198 state_n = S4;
199 end
200 else begin
201 state_n = state_c;
202 end
203 end
204 S4:begin
205 if(s42s5_start)begin
206 state_n = S5;
207 end
208 else begin
209 state_n = state_c;
210 end
211 end
212 S5:begin
213 if (s52s3_start)begin
214 state_n = S3;
215 end
216 else begin
217 state_n = state_c;
218 end
219 end
220 default:begin
221 state_n = IDLE;
222 end
223 endcase
224 end
225 //
226 reg [1:0] cnt_reset;
227 //
228 assign idle2s1_start = state_c == IDLE&& cnt_reset == 'd3;//&& busy_int == 1; 复位后进入下一个状态
229 assign s12s2_start = state_c == S1 && reset== 'b0;//&& busy_int == 0;
230 assign s22s3_start = state_c == S2 && end_cnt1; //配置完32bit
231 assign s32s4_start = state_c == S3 && busy_int == 1;//BUSY/INT ---->DO 忙的时候busy_int拉高
232 assign s42s5_start = state_c == S4 && busy_int == 0;//BUSY/INT ---->DO 不忙的时候busy_int拉低,进入下一个状态
233 assign s52s3_start = state_c == S5 && end_cnt1; //配置完32bit
234 //
235 always @(posedge clk or negedge rst_n)begin
236 if(!rst_n)begin
237 convst_a<=0;
238 end
239 else if(state_c == S5 && add_cnt1 && cnt1 == 33-1)begin
240 convst_a<=0;
241 end
242 else if((state_c == S2 || state_c == S5) && add_cnt1 && cnt1 == 34-1)begin
243 convst_a<=1;
244 end
245 end
246 //IO_L05P_2----->CONVST_A--->T4
247 //IO_L06P_2----->CONVST_B--->T5
248 //IO_L06N_2----->CONVST_C-->T6 -->最好三个脚连在一起,不连在一起两两之间间隔不超过4ns
249 //For simultaneous sampling, connecting all associated CONVST_x pins together is recommended.
250 //
251 always @(posedge clk or negedge rst_n)begin
252 if(!rst_n)begin
253 cs_fs_temp<=1;
254 end
255 else if((state_c == S2 || state_c == S5) )begin
256 cs_fs_temp<=0;
257 end
258 else begin
259 cs_fs_temp<=1;//中间信号
260 end
261 end
262
263 always @(posedge clk or negedge rst_n)begin
264 if(!rst_n)begin
265 cs_fs<=1;
266 end
267 else if( (~cs_fs_temp) && add_cnt1 && cnt1 == 1-1 )begin
268 cs_fs<=0;
269 end
270 else if( (~cs_fs_temp) && add_cnt1 && cnt1 == 33-1) begin
271 cs_fs<=1;//CS#/FS# --->帧同步/FS 的下降沿控制帧传输
272 end
273 end
274
275 always@(posedge clk or negedge rst_n)begin
276 if(rst_n==1'b0)begin
277 sclk<=1;
278 end
279 // else if(add_cnt0 && cnt0 == 5-1 && cnt1 >= 1 && cnt1 < 33)begin
280 else if(add_cnt0 && cnt0 == 2-1 && cnt1 >= 1 && cnt1 < 33)begin
281 sclk<=0;
282 end
283 else if(end_cnt0)begin
284 sclk<=1; //IO_L05P_2--->SCLK--->T4--->Serial interface clock input (36 MHz, max)
285 end
286 end
287
288 // parameter data1=32'b111_000_100_000_0_000_000_0_10_1111_1111_11;
289 // parameter data1=32'b111_000_000_000_0_000_000_0_10_1111_1111_11;
290 parameter data1=32'hE2000BFF;//首次配,参考CR 寄存器配置
291 // parameter data2=8'hE0;
292 parameter data2=8'hE2;//二次配 参考CR 寄存器配置
293 //---------------------CR------------------------------------------
294 //
295 //C26 C27 C28
296 //RANGE_A RANGE_B RANGE_C
297 //0-->4 VREF 1-->2 VREF
298 //
299 //C16
300 //C23:0_EN // 1 = Entire control register update enabled (serial mode only)
301 //
302 //C23
303 //SEQ 1 1 = Sequential convert start mode enabled (bit 11 must be '1' in this case)
304 //
305 //C11
306 //CLKSEL 1 = External conversion clock (applied through pin 27) used
307 //
308 //
309 //C20 BUSY L/H
310 //0 = BUSY active high when INT is active low (default)
311 // C21 BUSY/INT
312 //0 = BUSY/INT pin in normal mode (BUSY) (default)
313 //
314 //C18
315 //VREF 0 = Internal reference voltage: 2.5 V (default) //1 = 3V
316
317 always@(posedge clk or negedge rst_n)begin
318 if(rst_n==1'b0)begin
319 sdi <=1;
320 end
321 else if(state_c == S2 && end_cnt0 && cnt1 < 32)begin
322 sdi <=data1[31-cnt1];
323 end
324 else if(state_c == S5 && end_cnt0 && cnt1 < 8)begin
325 sdi <=data2[7-cnt1];
326 end
327 end
328 //SPI接口
329 //IO_L08P_2 --->SDI---->P7
330 //
331 reg [31:0] data_a;
332 always@(posedge clk or negedge rst_n)begin
333 if(rst_n==1'b0)begin
334 data_a<=0;
335 end
336 // else if(state_c == S5 && add_cnt0 && cnt0 == 5-1 && cnt1 >= 1 && cnt1 <= 32)begin
337 else if(state_c == S5 && add_cnt0 && cnt0 == 2-1 && cnt1 >= 1 && cnt1 <= 32)begin
338 data_a['d32- cnt1]<=sdo_a; //A通道数据过来采集
339 end
340 end
341
342 reg [31:0] data_b;
343 always@(posedge clk or negedge rst_n)begin
344 if(rst_n==1'b0)begin
345 data_b<=0;
346 end
347 // else if(state_c == S5 && add_cnt0 && cnt0 == 5-1 && cnt1 >= 1 && cnt1 <= 32)begin
348 else if(state_c == S5 && add_cnt0 && cnt0 == 2-1 && cnt1 >= 1 && cnt1 <= 32)begin
349 data_b['d32- cnt1]<=sdo_b; //B通道数据过来采集
350 end
351 end
352
353 reg [31:0] data_c;
354 always@(posedge clk or negedge rst_n)begin
355 if(rst_n==1'b0)begin
356 data_c<=0;//C通道数据过来采集
357 end
358 // else if(state_c == S5 && add_cnt0 && cnt0 == 5-1 && cnt1 >= 1 && cnt1 <= 32)begin
359 else if(state_c == S5 && add_cnt0 && cnt0 == 2-1 && cnt1 >= 1 && cnt1 <= 32)begin
360 data_c['d32- cnt1]<=sdo_c;
361 end
362 end
363
364 always@(posedge clk or negedge rst_n)begin
365 if(rst_n==1'b0)begin
366 data_abc_vaild<=0;
367 end
368 else if(state_c == S5 && add_cnt1 && cnt1 == 33-1)begin
369 data_abc_vaild<=1; //通道数据采集完毕
370 end
371 else begin
372 data_abc_vaild<=0;
373 end
374 end
375
376 always@(posedge clk or negedge rst_n)begin
377 if(rst_n==1'b0)begin
378 data_a0<='d0;
379 data_a1<='d0;
380 data_b0<='d0;
381 data_b1<='d0;
382 data_c0<='d0;
383 data_c1<='d0;
384 end
385 else if(data_abc_vaild)begin// 通道数据采集完毕,给出去
386 data_a0<=data_a[31:16];
387 data_a1<=data_a[15:0 ];
388 data_b0<=data_b[31:16];
389 data_b1<=data_b[15:0 ];
390 data_c0<=data_c[31:16];
391 data_c1<=data_c[15:0 ];
392 end
393 end
394 //
395 always@(posedge clk)
396 begin
397 if(!rst_n)
398 cnt_reset<='d0;
399 else
400 begin
401 if(cnt_reset == 'd3)
402 cnt_reset<= 'd3;
403 else
404 cnt_reset<=cnt_reset+1'b1;
405 end
406 end
407 //
408 always@(posedge clk)
409 begin
410 if(!rst_n)
411 reset<='b0;
412 else
413 begin
414 if(cnt_reset == 'd3)
415 reset<= 'b0;
416 else
417 reset<= 'b1; //4 x 20 = 80ns ---复位大于50ns
418 end
419 end
420 //
421 endmodule

ad_collect

【代码更新】SPI时序——AD数模数转换的更多相关文章

  1. FPGA构造spi时序——AD7176为例(转)

    reference:https://blog.csdn.net/fzhykx/article/details/79490330 项目中用到了一种常见的低速接口(spi),于是整理了一下关于spi相关的 ...

  2. SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)

    SPI接口扫盲   douqingl@gmail.com   为何要写这篇文档?百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释 ...

  3. Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测

    Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931   近日,Artur Suilin 等人发布了 Kaggl ...

  4. SPI总线协议及SPI时序图详解

    SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接口.SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚 ...

  5. Unity手游之路<十三>手游代码更新策略探讨

    http://blog.csdn.net/janeky/article/details/25923151 这几个月公司项目非常忙,加上家里事情也多,所以blog更新一直搁置了.最近在项目开发上线过程中 ...

  6. python学习之——计算给出代码中注释、代码、空行的行数

    题目:计算给出代码中注释.代码.空行的行数 来源:网络 思路:注释行以 ‘#’开头,空行以 ‘\n’ 开头,以此作为判断 def count_linenum(fname): fobj = open(f ...

  7. WebGIS中以version方式实现代码更新后前端自动读取更新代码的方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 前言 GIS代码进行更新后,由于用户前端已有缓存,导致更新的功能不 ...

  8. SPI总线协议及SPI时序图详解【转】

    转自:https://www.cnblogs.com/adylee/p/5399742.html SPI,是英语Serial Peripheral Interface的缩写,顾名思义就是串行外围设备接 ...

  9. Unity手游之路手游代码更新策略探讨

    版权声明: https://blog.csdn.net/janeky/article/details/25923151 这几个月公司项目非常忙.加上家里事情也多,所以blog更新一直搁置了. 近期在项 ...

  10. git如何merge github forked repository里的代码更新?(转)

    参考内容:git如何merge github forked repository里的代码更新? [refer to ]http://www.haojii.com/2011/08/how-to-git- ...

随机推荐

  1. uni-app 计算属性 computed

    功能:=>大于1000用kg表示 小于1000,用g表示 计算属性 计算属性必须是有一个返回值的哦 在html写被计算的值 在computed中去直接调用哈 <view> <t ...

  2. Asp.Net MVC中点击按钮导出Excel

    一.Excel导出帮助类,要安装包NPOI 1 using NPOI.HSSF.UserModel; 2 using NPOI.SS.UserModel; 3 using System; 4 usin ...

  3. 文字溢出hover展示

    我这个后端返回的是html结构,不然不用加v-html,需要依赖element Ui 的文字提示 <el-tooltip placement="top"> <p ...

  4. 《Mybatis 手撸专栏》第2章:创建简单的映射器代理工厂

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 着急和快,是最大的障碍! 慢下来,慢下来,只有慢下来,你才能看到更全的信息,才能学到 ...

  5. 多进程实现socket通信(Python)

    服务器端: #__author__:Kelvin #date:2020/5/9 11:35 import socket from multiprocessing import Process def ...

  6. 零基础入门学习JAVA课堂笔记 ——DAY07

    面向对象(下) 1. Instanceof 我们可以通过Instanceof关键词可以判断当前对象是否为某某类得父类 Object instanceof Student //true 注意:只有是两个 ...

  7. VSCode实现GDB图形界面远程调试

    前言 在习惯了集成开发环境的图形界面调试时,首次使用GDB远程调试必定很不习惯,下面讲述如何利用VSCode实现GDB图形界面远程调试 代码在Linux服务器上,而平常都在Windows上使用,那么V ...

  8. 逆天的全排列函数next_permutation()

    next_permutation 是算法库(<algorithm>)里的一个用于求全排列的函数,其定义为 next_permutation(_BidIt _First, _BidIt _L ...

  9. .NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记

    2.4.5 EF Core -- 查询 关联数据加载 客户端与服务端运算 跟踪与不跟踪 复杂查询运算 原生 SQL 查询 全局查询筛选器 关联数据加载 学员和助教都在项目分组中,调整模型,删除 Ass ...

  10. GCD,乘法逆元

    最大公约数 公约数:几个整数共有的约数.($ \pm 1是任何整数的公约数$) 最大公约数:显而易见,所有公约数中最大的那个. 欧几里得算法 为了求最大公约数(常记为GCD),我们常用欧几里得算法.以 ...