FPGA学习笔记:数据采集传输系统设计(三):AD采集驱动ADC128S052

这篇具有很好参考价值的文章主要介绍了FPGA学习笔记:数据采集传输系统设计(三):AD采集驱动ADC128S052。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、ADC128S052时序图

1.时序图

ADC128S052为12 位、8通道的模数转换器 (ADC),转换速度高达 10 MSPS,采用SPI串行通信。
(1)工作时序图
fpgaad采集,FPGA学习笔记,fpga开发,学习,笔记
应注意DIN中配置好的通道地址ADD在下一次采样时才生效
从时序图中可得出,ADC芯片在上升沿时采样,读取DIN数据;DOUT在下降沿时改变数据。

(2)串行时序图
fpgaad采集,FPGA学习笔记,fpga开发,学习,笔记
片选信号在SCLK第16个上升沿时被拉高。

2.设计要点

根据时序图和数据手册,得出以下设计要点:
(1)DIN在SCLK第3、4、5个下降沿改变,发送通道值ADD,先发高位,后发低位
(2)FPGA在SCLK上升沿时读取DOUT数据,DOUT前4位为0,在SCLK第5个上升沿开始读取DB11
(3)SCLK时钟为3.2-8Mhz,系统时钟为50Mhz,取8分频6.25Mhz
(4)片选信号在SCLK第16个上升沿时被拉高

二、ADC128S052代码设计

1.模块端口说明

端口名称 方向 说明
Clk input 系统时钟
Rst_n input 系统复位
Channel[2:1] input 通道选择
Start input 采集开始标志位
Conv_done output 采集完成标志位
DATA[11:0] output 采集到的并行数字信号
ADC_CS_N output ADC片选
ADC_DIN output 串行数据输出至ADC芯片
ADC_SCLK output ADC工作时钟
ADC_OUT input 采集到的串行数字信号

fpgaad采集,FPGA学习笔记,fpga开发,学习,笔记
ADC芯片将转换后的数字信号通过ADC_OUT串行传送给模块,模块将其变成并行信号data传输给FPGA,保存到FIFO存储器中。

2.代码设计

模块采用线性序列机编写SPI时序,代码逻辑与DAC类似,可分为以下5个部分:通道地址缓存、分频计数器、生成序列计数器、SPI线性序列机、标志位赋值及DATA输出。
(1)通道地址缓存
接收到Start开始转换信号时,开始AD转换,为避免在发送过程中由于干扰导致输入的数据变化,在Start为高电平时,将通道地址Channel缓存到r_Channel中。

	reg [2:0] r_Channel;	//通道地址寄存
	always@(posedge Clk or negedge Rst_n)//数据缓存
	if(!Rst_n)
		r_Channel <= 3'd0;
	else if(Start)
		r_Channel <= Channel;
	else
		r_Channel <= r_Channel;

(2)分频计数器
前面提到SCLK频率范围为3.2-8Mhz,取系统时钟的八分频6.25Mhz为SCLK的时钟。由于数据在SCLK边沿变化和读取,需计算SCLK二倍频以区分上升沿和下降沿。

	parameter DIV_PARAM = 8;//分频系数 50/8 = 6.25Mhz
	reg [7:0] DIV_cnt;		//分频计数器
	reg SCLK2X;					//SCLK二倍频

	always@(posedge Clk or negedge Rst_n)//分频计数器
	if(!Rst_n)
		DIV_cnt <= 8'd0;
	else if(ADC_State) begin
		if(DIV_cnt == DIV_PARAM/2 - 1)
			DIV_cnt <= 8'd0;
		else
			DIV_cnt <= DIV_cnt + 1'b1;
	end
	else
		DIV_cnt <= 8'd0;

	always@(posedge Clk or negedge Rst_n)//SCLK二倍频
	if(!Rst_n)
		SCLK2X <= 1'b0;
	else if(ADC_State && (DIV_cnt == DIV_PARAM/2 - 1))
		SCLK2X <= 1'b1;
	else
		SCLK2X <= 1'b0;

(3)生成序列计数器
线性序列机在写代码时,应根据时序图列出信号在不同时刻的状态,这里根据时序图将SPI划分为34个状态,故生成序列计数器SCLK_GEN_CNT计数到33,对SCLK的边沿进行计数。

	always@(posedge Clk or negedge Rst_n)//生成序列计数器,对SCLK脉冲进行计数
	if(!Rst_n)
		SCLK_GEN_CNT <= 6'd0;
	else if(ADC_State)
		if(SCLK2X) begin
			if(SCLK_GEN_CNT == 33)
				SCLK_GEN_CNT <= 6'd0;
			else
				SCLK_GEN_CNT <= SCLK_GEN_CNT + 1'b1;
		end
		else
			SCLK_GEN_CNT <= SCLK_GEN_CNT;
	else
		SCLK_GEN_CNT <= 6'd0;

(4)SPI线性序列机
根据时序图和前面总结的设计要点,DIN在SCLK第3、4、5个下降沿改变,发送通道值,先发高位,后发低位;在SCLK第5个上升沿开始读取DB11;片选信号在SCLK第16个上升沿时被拉高。

	always@(posedge Clk or negedge Rst_n)//线性序列机发送数据
	if(!Rst_n) begin
		ADC_SCLK <= 1'b1;
		ADC_CS_N <= 1'b1;
		ADC_DIN <= 1'b1;
	end
	else if(SCLK2X)
		case(SCLK_GEN_CNT)
			0: begin ADC_CS_N <= 1'b0; ADC_SCLK <= 1'b1; end
			1: ADC_SCLK <= 1'b0;
			2: ADC_SCLK <= 1'b1;
			3: ADC_SCLK <= 1'b0;
			4: ADC_SCLK <= 1'b1;
			5: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[2]; end
			6: ADC_SCLK <= 1'b1;
			7: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[1]; end
			8: ADC_SCLK <= 1'b1;
			9: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[0]; end
			11,13,15,17,19,21,23,25,27,29,31: ADC_SCLK <= 1'b0;
			10:begin ADC_SCLK <= 1'b1; r_data[11] <= ADC_OUT; end
			12:begin ADC_SCLK <= 1'b1; r_data[10] <= ADC_OUT; end
			14:begin ADC_SCLK <= 1'b1; r_data[9] <= ADC_OUT; end
			16:begin ADC_SCLK <= 1'b1; r_data[8] <= ADC_OUT; end
			18:begin ADC_SCLK <= 1'b1; r_data[7] <= ADC_OUT; end
			20:begin ADC_SCLK <= 1'b1; r_data[6] <= ADC_OUT; end
			22:begin ADC_SCLK <= 1'b1; r_data[5] <= ADC_OUT; end
			24:begin ADC_SCLK <= 1'b1; r_data[4] <= ADC_OUT; end
			26:begin ADC_SCLK <= 1'b1; r_data[3] <= ADC_OUT; end
			28:begin ADC_SCLK <= 1'b1; r_data[2] <= ADC_OUT; end
			30:begin ADC_SCLK <= 1'b1; r_data[1] <= ADC_OUT; end
			32:begin ADC_SCLK <= 1'b1; r_data[0] <= ADC_OUT; end
			33:ADC_CS_N <= 1'b1;
			default:ADC_CS_N <= 1'b1;
		endcase

(5)标志位赋值及DATA输出
从ADC中读取的串行数据按位寄存在r_data中,在AD转换结束时,Conv_done置1,将寄存的r_data传给DATA一并输出。

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		ADC_State <= 1'b0;
	else if(Start)
		ADC_State <= 1'b1;
	else if((SCLK_GEN_CNT == 33) && SCLK2X && ADC_State)
		ADC_State <= 1'b0;
		
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n) begin
		Conv_done <= 1'b0;
		DATA <= 12'd0;
	end
	else if((SCLK_GEN_CNT == 33) && SCLK2X && ADC_State)
		begin
			Conv_done <= 1'b1;
			DATA <= r_data;
		end
	else begin
		Conv_done <= 1'b0;
		DATA <= DATA;
	end

AD采集源代码

module adc128s052(
	input Clk,					//系统时钟
	input Rst_n,				//系统复位
	
	input [2:0] Channel,		//通道选择
	input Start,   			//开始标志位
	output reg Conv_done,	//完成标志位
	output reg [11:0] DATA,	//并行数字信号
	
	output reg ADC_CS_N,		//片选
	output reg ADC_DIN, 		//串行数据送给ADC芯片
	output reg ADC_SCLK,		//工作时钟
	input ADC_OUT				//串行数字信号
);

	reg ADC_State;			//AD采集状态标志
	reg [2:0] r_Channel;	//通道地址寄存
	reg [11:0] r_data;	//采集数据缓存,一次性输出
	
	parameter DIV_PARAM = 8;//分频系数 50/8 = 6.25Mhz
	reg [7:0] DIV_cnt;		//分频计数器
	reg SCLK2X;					//SCLK二倍频
	reg [5:0] SCLK_GEN_CNT;	//SCLK序列生成计数器
	
	always@(posedge Clk or negedge Rst_n)//数据缓存
	if(!Rst_n)
		r_Channel <= 3'd0;
	else if(Start)
		r_Channel <= Channel;
	else
		r_Channel <= r_Channel;
	
	always@(posedge Clk or negedge Rst_n)//分频计数器
	if(!Rst_n)
		DIV_cnt <= 8'd0;
	else if(ADC_State) begin
		if(DIV_cnt == DIV_PARAM/2 - 1)
			DIV_cnt <= 8'd0;
		else
			DIV_cnt <= DIV_cnt + 1'b1;
	end
	else
		DIV_cnt <= 8'd0;

	always@(posedge Clk or negedge Rst_n)//SCLK二倍频
	if(!Rst_n)
		SCLK2X <= 1'b0;
	else if(ADC_State && (DIV_cnt == DIV_PARAM/2 - 1))
		SCLK2X <= 1'b1;
	else
		SCLK2X <= 1'b0;
		
	always@(posedge Clk or negedge Rst_n)//生成序列计数器,对SCLK脉冲进行计数
	if(!Rst_n)
		SCLK_GEN_CNT <= 6'd0;
	else if(ADC_State)
		if(SCLK2X) begin
			if(SCLK_GEN_CNT == 33)
				SCLK_GEN_CNT <= 6'd0;
			else
				SCLK_GEN_CNT <= SCLK_GEN_CNT + 1'b1;
		end
		else
			SCLK_GEN_CNT <= SCLK_GEN_CNT;
	else
		SCLK_GEN_CNT <= 6'd0;

	always@(posedge Clk or negedge Rst_n)//线性序列机发送数据
	if(!Rst_n) begin
		ADC_SCLK <= 1'b1;
		ADC_CS_N <= 1'b1;
		ADC_DIN <= 1'b1;
	end
	else if(SCLK2X)
		case(SCLK_GEN_CNT)
			0: begin ADC_CS_N <= 1'b0; ADC_SCLK <= 1'b1; end
			1: ADC_SCLK <= 1'b0;
			2: ADC_SCLK <= 1'b1;
			3: ADC_SCLK <= 1'b0;
			4: ADC_SCLK <= 1'b1;
			5: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[2]; end
			6: ADC_SCLK <= 1'b1;
			7: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[1]; end
			8: ADC_SCLK <= 1'b1;
			9: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[0]; end
			11,13,15,17,19,21,23,25,27,29,31: ADC_SCLK <= 1'b0;
			10:begin ADC_SCLK <= 1'b1; r_data[11] <= ADC_OUT; end
			12:begin ADC_SCLK <= 1'b1; r_data[10] <= ADC_OUT; end
			14:begin ADC_SCLK <= 1'b1; r_data[9] <= ADC_OUT; end
			16:begin ADC_SCLK <= 1'b1; r_data[8] <= ADC_OUT; end
			18:begin ADC_SCLK <= 1'b1; r_data[7] <= ADC_OUT; end
			20:begin ADC_SCLK <= 1'b1; r_data[6] <= ADC_OUT; end
			22:begin ADC_SCLK <= 1'b1; r_data[5] <= ADC_OUT; end
			24:begin ADC_SCLK <= 1'b1; r_data[4] <= ADC_OUT; end
			26:begin ADC_SCLK <= 1'b1; r_data[3] <= ADC_OUT; end
			28:begin ADC_SCLK <= 1'b1; r_data[2] <= ADC_OUT; end
			30:begin ADC_SCLK <= 1'b1; r_data[1] <= ADC_OUT; end
			32:begin ADC_SCLK <= 1'b1; r_data[0] <= ADC_OUT; end
			33:ADC_CS_N <= 1'b1;
			default:ADC_CS_N <= 1'b1;
		endcase

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		ADC_State <= 1'b0;
	else if(Start)
		ADC_State <= 1'b1;
	else if((SCLK_GEN_CNT == 33) && SCLK2X && ADC_State)
		ADC_State <= 1'b0;
		
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n) begin
		Conv_done <= 1'b0;
		DATA <= 12'd0;
	end
	else if((SCLK_GEN_CNT == 33) && SCLK2X && ADC_State)
		begin
			Conv_done <= 1'b1;
			DATA <= r_data;
		end
	else begin
		Conv_done <= 1'b0;
		DATA <= DATA;
	end	
endmodule

三、仿真

1.ADC芯片采集信号模拟

模拟ADC芯片采集过程,在SCLK下降沿时改变ADC_OUT的值,将这个过程封装成task任务。

	task GENE_ADC_OUT;
		input [15:0] v_data;
		integer i;
		begin
			wait(!ADC_CS_N);//等待CS_N被拉低
			for(i=0;i<16;i=i+1) begin
				@(negedge ADC_SCLK)
					ADC_OUT = v_data[15-i];
			end
		end
	endtask

2.仿真文件

仿真时,调用ADC芯片采集信号模拟任务,模拟采集到的数字信号为12’h678和12’h9ab,等待AD采集完成,代码如下:

`timescale 1ns/1ns
module adc128s052_tb();

	reg Clk,Rst_n,Start,ADC_OUT;
	reg [2:0]Channel;
	
	wire ADC_CS_N,ADC_DIN,ADC_SCLK;
	wire Conv_done;
	wire [11:0] DATA;
	
	adc128s052 adc128s052(
		.Clk(Clk),
		.Rst_n(Rst_n),
		
		.DATA(DATA),
		.Channel(Channel),
		.Start(Start),   
		.Conv_done(Conv_done),
		
		.ADC_CS_N(ADC_CS_N),
		.ADC_DIN(ADC_DIN),
		.ADC_SCLK(ADC_SCLK),
		.ADC_OUT(ADC_OUT)
	);
	
	initial Clk = 1'b1;
	always #10 Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		Start = 1'b0;
		Channel = 3'd0;
		#201;
		
		Rst_n = 1'b1;
		#20;
		
		Channel = 3'd6;
		Start = 1'b1;
		#20;
		Start = 1'b0;
		GENE_ADC_OUT(16'h0678);
		wait(Conv_done);
		#2000;
		
		Channel = 3'd3;
		Start = 1'b1;
		#20;
		Start = 1'b0;
		GENE_ADC_OUT(16'h09ab);
		wait(Conv_done);
		#2000;
		$stop;
	end
	
	task GENE_ADC_OUT;
		input [15:0] v_data;
		integer i;
		begin
			wait(!ADC_CS_N);//等待CS_N被拉低
			for(i=0;i<16;i=i+1) begin
				@(negedge ADC_SCLK)
					ADC_OUT = v_data[15-i];
			end
		end
	endtask
endmodule

3.仿真结果

fpgaad采集,FPGA学习笔记,fpga开发,学习,笔记文章来源地址https://www.toymoban.com/news/detail-723811.html

到了这里,关于FPGA学习笔记:数据采集传输系统设计(三):AD采集驱动ADC128S052的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【N32L40X】学习笔记11-ADC规则通道采集+dma数据传输

    支持 1 个 ADC,支持单端输入和差分输入,最多可测量 16 个外部和 3 个内部源。 支持 12 位、10 位、8 位、6 位分辨率。 ADC 时钟源分为 工作时钟源、采样时钟源和计时时钟源 仅可配置 AHB_CLK 作为 工作时钟源 。 可配置 PLL 作为 采样时钟源 ,最高可到 64MHz,支持分频 1,2,4,6,8,

    2024年02月15日
    浏览(40)
  • FPGA采集AD7606数据UDP网络传输 提供工程源码和技术支持 附带上位机接收软件

    目前网上的fpga实现udp基本生态如下: 1:verilog编写的udp收发器,但不带ping功能,这样的代码功能正常也能用,但不带ping功能基本就是废物,在实际项目中不会用这样的代码,试想,多机互联,出现了问题,你的网卡都不带ping功能,连基本的问题排查机制都不具备,这样的代

    2023年04月24日
    浏览(56)
  • 基于FPGA+JESD204B 时钟双通道 6.4GSPS 高速数据采集设计(三)连续多段触发存储及传输逻辑设计

    本章将完成数据速率为 80MHz 、位宽为 12bits 的 80 路并行采样数据的连续多 段触发存储。首先,给出数据触发存储的整体框架及功能模块划分。然后,简介 MIG 用户接口、设置及读写时序。最后,进行数据跨时钟域模块设计,内存控制 模块设计以实现连续多段触发存储。触发

    2024年02月05日
    浏览(47)
  • 008-关于FPGA/ZYNQ直接处理图像传感器数据输出的若干笔记(裸板采集思路)

    最近也是未来需要考虑做的一件事情是,如何通过FPGA/ZYNQ去做显微镜图像观测下的图像采集传输与后续的处理。目前显微镜观测领域通常是以PC端连接工业相机接口,这个接口可以是USB3.0,可以是网口,也可以是其它传输方式。常常通过工业相机输出的为视频流数据,厂商会

    2024年01月23日
    浏览(43)
  • 水库安全监测方案(实时数据采集、高速数据传输)

    ​ 一、引言 水库的安全监测对于防止水灾和保障人民生命财产安全至关重要。为了提高水库安全监测的效率和准确性,本文将介绍一种使用星创易联DTU200和SG800 5g工业路由器部署的水库安全监测方案。 二、方案概述 本方案主要通过使用星创易联DTU200和SG800 5g工业路由器实现

    2024年02月08日
    浏览(41)
  • 【数据采集与预处理】数据传输工具Sqoop

    目录 一、Sqoop简介 二、Sqoop原理 三、Sqoop安装配置 (一)下载Sqoop安装包并解压 (二)修改配置文件 (三)拷贝JDBC驱动 (四)验证Sqoop (五)测试Sqoop是否能够成功连接数据库 四、导入数据 (一)RDBMS到HDFS (二)RDBMS到HBase (三)RDBMS到Hive 五、导出数据 HDFS/Hive到RDBMS 六、

    2024年01月21日
    浏览(48)
  • 节点数据采集和标签信息的远程洪泛传输

    要求:         完成节点数据采集和标签信息的远程洪泛传输,在与 Sink 节点相连接的 PC 上能看到结果(标签信息、感知的数据)。其中,节点感知数据采集包括光照值、温湿度值,采集节点每 20s 采集一次温湿度、每10s 采集一次光照。标签数据读写控制周期自行决定。

    2024年02月11日
    浏览(38)
  • 基于FPGA的数据采集系统 ADDA采集 采集卡

    基于FPGA的数据采集系统 ADDA采集 采集卡 采用FPGA与ADC设计一个可以在200K Hz采样率情况下以16bits精度同时对8通道的模拟信号进行采集的采集系统。 基于FPGA的数据采集系统ADD采集卡是一种高效的数据采集设备。采用FPGA与ADC设计的这种设备可以在200 KHz采样率情况下以16位精度同

    2024年02月03日
    浏览(47)
  • 高速大面阵相机数据采集传输带宽分析与随笔

    目前,高速相机的传输瓶颈,受限于传输的带宽。 这里的高速相机指的是大面阵(2048*2048@1000fps)的应用场景。 目前符合条件的CMOS比较少,长光辰芯的4510和4521是符合的。 高速相机从CMOS读取数据,到FPGA进行处理,通过高速收发器GT系列,进行大数据量的传输,最后通过传输

    2024年02月07日
    浏览(38)
  • 基于USB总线技术的数据采集系统接口FPGA实现——高效、稳定的数据采集神器!

    基于USB总线技术的数据采集系统接口FPGA实现——高效、稳定的数据采集神器! USB总线技术已经成为了当今数据传输领域的主流技术,它具有现场可编程性强、对外部器件兼容性好以及传输速度高等优点。因此,基于USB总线技术的数据采集系统已经广泛应用于各种实际场景。

    2024年02月09日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包