尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

AD7612 ADC 采集驱动 FPGA 设计 Verilog Vivado

AD7612 ADC 采集驱动 FPGA 设计 Verilog Vivado 名称AD7612 ADC 采集驱动 FPGA 设计 Verilog Vivado软件Vivado语言Verilog功能介绍本设计实现 AD7612 模数转换器的 FPGA 采集驱动逻辑主模块为 AD7612_driver使用 Verilog 编写可在 Vivado 工程中直接查看、综合和仿真。设计面向 ADC 转换控制与串行数据接收场景提供转换启动信号、串行时钟、16 位并行采样数据输出以及 data_valid 数据有效标志。 模块以 25MHz 时钟作为输入时钟外部 adc_trig_i 信号作为一次 ADC 转换的触发来源。触发信号经过同步寄存后进行下降沿检测触发后由状态机依次完成启动转换、等待 BUSY、读取串行数据、锁存并行数据和结束等待等流程。 数据读取部分按照 MSB first 的方式接收 ad_adout 串行数据在读取状态下通过 data_cnt 对 16 位数据逐位计数并将结果整理到 adc_data[15:0]。当一次采样数据整理完成后data_valid 输出一个有效标志方便后级模块进行数据缓存、滤波、显示或通信发送。运行环境开发语言Verilog 开发软件Vivado 工程形式Vivado FPGA 工程包含 AD7612_driver 顶层驱动模块与 AD7612_driver_tb 测试文件。设计思路设计核心采用同步状态机控制 ADC 的一次转换周期。系统复位后处于空闲状态等待 adc_trig_i 的下降沿触发触发到来后输出 ADC 转换启动控制信号并结合 ad_busy 状态进入后续读取流程。这样的结构将触发、转换、等待和读数过程拆分为清晰的状态便于理解 AD7612 的工作时序也方便后续根据实际硬件时序要求调整状态停留时间。 触发输入采用两级寄存器同步处理降低异步触发信号直接进入时序逻辑带来的亚稳态风险。下降沿检测逻辑由同步后的两拍信号组合得到保证状态机只在有效触发边沿启动一次转换流程避免长电平触发造成重复启动。 串行读取阶段由 data_cnt 计数控制前 16 个读取周期使能串行时钟并采样 ad_adout。采样顺序从最高位到最低位写入 rd_data完成后进入数据输出状态将 rd_data 锁存到 adc_data同时拉高 data_valid。后级逻辑只需要关注 adc_data 与 data_valid 即可获取一次完整的 16 位 ADC 数据。 整体结构适合用于学习 ADC 芯片时序控制、串行数据采集、FPGA 状态机设计以及 Vivado testbench 仿真流程也可以作为 AD7612 采集接口的工程参考。模块结构主要模块包括 AD7612_driverADC 采集驱动顶层模块负责触发同步、转换控制、BUSY状态处理、串行时钟输出、16位串行数据接收、并行数据输出和数据有效标志生成。 AD7612_driver_tb仿真测试模块用于对驱动逻辑进行行为仿真验证。 glblVivado 仿真环境相关全局模块。开发板验证工程配有开发板实物验证参考图片可用于对照硬件连接和板级运行效果。开发板验证内容与 AD7612 驱动工程配套便于在实际 FPGA 硬件环境中核对 ADC 控制信号、采集流程和演示效果。演示视频配有演示视频可直观看到工程运行和验证过程适合下载前了解实际操作效果与板级演示状态。演示视频请关注公众号后获取对应资料查看。仿真图/仿真说明/设计文档图片配套设计文档包含工程文件、程序文件、程序编译、testbench 和仿真图等内容说明并提供时序图、配置图等参考图片。仿真工程中包含 AD7612_driver_tb 相关文件和 VCD 波形结果可用于查看驱动逻辑的触发、状态跳转、串行读取和数据有效输出过程。部分代码以下展示顶层模块AD7612_driver的部分代码完整代码可关注下方公众号卡片获取。module AD7612_driver ( input clk_i, // 25MHz时钟输入 input rst_n_i, // 异步复位(低电平有效) input adc_trig_i, // ADC转换触发信号 output ad_cnv_n, // ADC转换启动信号(低电平有效) input ad_busy, // ADC忙状态指示 output ad_sdclk, // ADC串行数据时钟 input ad_sync, // (未使用) input ad_adout, // ADC串行数据输出 output reg [15:0] adc_data, // 并行ADC数据输出 output reg data_valid // 数据有效标志 ); // 触发器同步电路(消除亚稳态) reg adc_trig_r0; reg adc_trig_r1; wire adc_trig_n; // 下降沿检测信号 always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) adc_trig_r0 0; else adc_trig_r0 adc_trig_i; always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) adc_trig_r1 0; else adc_trig_r1 adc_trig_r0; assign adc_trig_n ~adc_trig_r0 adc_trig_r1; // 下降沿检测 // 状态机状态定义 parameter S_IDLE 3d0; // 空闲状态 parameter S_CNV 3d1; // 启动转换状态 parameter S_BUSY 3d2; // 等待忙状态 parameter S_READ 3d3; // 读取数据状态 parameter S_DATA 3d4; // 数据有效状态 parameter S_END 3d5; // 转换结束状态 reg [2:0] cur_state; // 当前状态寄存器 reg [4:0] data_cnt; // 数据位计数器 wire sclk_en; // 串行时钟使能 reg [15:0] rd_data; // 数据移位寄存器 // 数据位计数器控制 always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) data_cnt 5d0; else if (cur_state S_READ) data_cnt data_cnt 5d1; else data_cnt 5d0; assign sclk_en (cur_state S_READ) (data_cnt 5d16); // 仅在前16个时钟周期使能 // 串行数据移位寄存(MSB first) always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) rd_data 16d0; else if (cur_state S_READ) begin case (data_cnt) 5d0: rd_data[15] ad_adout; 5d1: rd_data[14] ad_adout; 5d2: rd_data[13] ad_adout; 5d3: rd_data[12] ad_adout; 5d4: rd_data[11] ad_adout; 5d5: rd_data[10] ad_adout; 5d6: rd_data[9] ad_adout; 5d7: rd_data[8] ad_adout; 5d8: rd_data[7] ad_adout; 5d9: rd_data[6] ad_adout; 5d10: rd_data[5] ad_adout; 5d11: rd_data[4] ad_adout; 5d12: rd_data[3] ad_adout; 5d13: rd_data[2] ad_adout; 5d14: rd_data[1] ad_adout; 5d15: rd_data[0] ad_adout; default: ; endcase end // 并行数据输出和数据有效信号 always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) begin adc_data 16d0; data_valid 1b0; end else if (cur_state S_DATA) begin adc_data rd_data; data_valid 1b1; end else data_valid 1b0; // 主状态机控制 always (posedge clk_i or negedge rst_n_i) if (!rst_n_i) cur_state S_IDLE; else case (cur_state) S_IDLE: if (adc_trig_n) // 检测到触发下降沿 cur_state S_CNV; S_CNV: if (ad_busy) // 等待ADC进入忙状态 cur_state S_BUSY; S_BUSY: cur_state S_READ; // 立即进入读取状态 S_READ: if (data_cnt 5d16) // 读完16位数据 cur_state S_DATA; S_DATA: cur_state S_END; // 数据输出完成 S_END: if (!ad_busy) // 等待ADC结束忙状态 cur_state S_IDLE; default: cur_state S_IDLE; endcase // ... 以下代码略完整源码请下载压缩包查看代码获取点击下方公众号卡片
返回列表