8通道adc,ad7606b与fpga采数模块的设计

本设计采用8通道adc7606b的硬件模式,并行输出模式。

ad7606b硬件电路图部分如下

 adc并行模式时序图如下,截自datasheet,

根据硬件电路与时序图写出verilog代码,modelsim仿真后用quartus编译综合。

module design_8ad(
	input	clk,
	input	rst_n,
	output  [2:0] os,
	output reg adc_cvt,
	output  adc_rst,
	output reg rd,
	output reg cs,
	input   busy,
	input   [15:0] ad_data,	








	output reg [2:0] state_c,
	output reg flag  ,
   output 	watch,
	output add
);

localparam IDLE    =3'D0,
		   CVT     =3'D1,
		   BUSY    =3'D2,
		   RD_ST   =3'D3,
		   GET_DATA=3'D4;

reg [15:0] ch1;
reg [15:0] ch2;
reg [15:0] ch3;
reg [15:0] ch4;
reg [15:0] ch5;
reg [15:0] ch6;
reg [15:0] ch7;
reg [15:0] ch8;

reg [2:0] state_n;
wire get_data_en;//dingyi

reg [7:0] cnt_mum;
reg [1:0] cnt_cvt;
reg [2:0] cnt_ch;

assign os=3'd0;
assign adc_rst=~rst_n;
assign get_data_en=(cnt_mum==8'd249);

integer i;

reg [3:0] cnt_watch;
always @ (posedge clk or negedge rst_n) begin
	if(~rst_n)
		cnt_watch<='d0;
	else
		cnt_watch<=cnt_watch+1'd1;
end
assign watch=cnt_watch[3];



always @ (posedge clk or negedge rst_n) begin
	if(~rst_n)
		cnt_mum<='d0;
	else begin
		if(cnt_mum==8'd249)
			cnt_mum<='d0;
		else
			cnt_mum<=cnt_mum+1'd1;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		state_c<=IDLE;
	end 
	else begin
		state_c<=state_n;
	end
	
end

always @ (*) begin
	state_n=state_c;
	case (state_c)
		IDLE   :begin
					if(get_data_en)
						state_n=CVT;
				end		
	    CVT    :begin
					if(adc_cvt)
						state_n=BUSY;
				end
	    BUSY   :begin
					if(~busy)
						state_n=RD_ST;
				end
	    RD_ST  :		state_n=GET_DATA;
	    GET_DATA:begin
					if(flag)
						state_n=IDLE;
				end
		default:		state_n=IDLE;
	endcase
end

always @ (posedge clk or negedge rst_n) 
begin
	if(~rst_n) 
	begin
		cs<=1'd1;
		adc_cvt<='d0;
		cnt_cvt<='d0;
		rd<='d1;
		flag<='d0;
		ch1<='d0;
		ch2<='d0;
		ch3<='d0;
		ch4<='d0;
		ch5<='d0;
		ch6<='d0;
		ch7<='d0;
		ch8<='d0;
	end		
	else 
	begin
		case(state_c)
		IDLE    :begin
			cs<=1'd1;
			cnt_cvt<='d0;
			adc_cvt<='d0;
			rd<=1'd1;
			cnt_ch<='d0;
			flag<='d0;
		end //hou mian bu chong
		CVT     :begin
			if(cnt_cvt<2)
				cnt_cvt<=cnt_cvt+1'd1;
			else begin
				adc_cvt<=1'd1;
				cnt_cvt<='d0;
		end
		end
		RD_ST   :
			cs<='d0;
		GET_DATA:begin
			if(rd)
				rd<='d0;
			else begin
				rd<='d1;
				cnt_ch<=cnt_ch+1'd1;
				case (cnt_ch)
				3'd0:ch1<=ad_data;
				3'd1:ch2<=ad_data;
				3'd2:ch3<=ad_data;
				3'd3:ch4<=ad_data;
				3'd4:ch5<=ad_data;
				3'd5:ch6<=ad_data;
				3'd6:ch7<=ad_data;
				3'd7:ch8<=ad_data;
				endcase
				end
			
			if(cnt_ch==3'd7)//zhuyi
				flag<=1'd1;
		end
		endcase
	end
		
end


assign add=^ch1+^ch2+^ch3+^ch4+^ch5+^ch6+^ch7+^ch8;



endmodule

 ps:因为使用quartus single tap 抓波形,所以附加了一部分逻辑,代码内部有部分逻辑可在实际应用时删除,大家可自行根据需要改动。

附上设计和tb代码(PS:下图设计模块代码与上图唯一区别是ch1~ch8放入output中,在fpga设计中不可综合因为输出引脚过多)

module design_8ad(
	input	clk,
	input	rst_n,
	output  [2:0] os,
	output reg adc_cvt,
	output  adc_rst,
	output reg rd,
	output reg cs,
	input   busy,
	input   [15:0] ad_data,	
	output reg [15:0] ch1,
    output reg [15:0] ch2,
    output reg [15:0] ch3,
    output reg [15:0] ch4,
    output reg [15:0] ch5,
    output reg [15:0] ch6,
    output reg [15:0] ch7,
    output reg [15:0] ch8,
	output reg [2:0] state_c,
	output reg flag  ,
   output 	watch,
	output add
);

localparam IDLE    =3'D0,
		   CVT     =3'D1,
		   BUSY    =3'D2,
		   RD_ST   =3'D3,
		   GET_DATA=3'D4;










reg [2:0] state_n;
wire get_data_en;//dingyi

reg [7:0] cnt_mum;
reg [1:0] cnt_cvt;
reg [2:0] cnt_ch;

assign os=3'd0;
assign adc_rst=~rst_n;
assign get_data_en=(cnt_mum==8'd249);

integer i;

reg [3:0] cnt_watch;
always @ (posedge clk or negedge rst_n) begin
	if(~rst_n)
		cnt_watch<='d0;
	else
		cnt_watch<=cnt_watch+1'd1;
end
assign watch=cnt_watch[3];



always @ (posedge clk or negedge rst_n) begin
	if(~rst_n)
		cnt_mum<='d0;
	else begin
		if(cnt_mum==8'd249)
			cnt_mum<='d0;
		else
			cnt_mum<=cnt_mum+1'd1;
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(~rst_n) begin
		state_c<=IDLE;
	end 
	else begin
		state_c<=state_n;
	end
	
end

always @ (*) begin
	state_n=state_c;
	case (state_c)
		IDLE   :begin
					if(get_data_en)
						state_n=CVT;
				end		
	    CVT    :begin
					if(adc_cvt)
						state_n=BUSY;
				end
	    BUSY   :begin
					if(~busy)
						state_n=RD_ST;
				end
	    RD_ST  :		state_n=GET_DATA;
	    GET_DATA:begin
					if(flag)
						state_n=IDLE;
				end
		default:		state_n=IDLE;
	endcase
end

always @ (posedge clk or negedge rst_n) 
begin
	if(~rst_n) 
	begin
		cs<=1'd1;
		adc_cvt<='d0;
		cnt_cvt<='d0;
		rd<='d1;
		flag<='d0;
		ch1<='d0;
		ch2<='d0;
		ch3<='d0;
		ch4<='d0;
		ch5<='d0;
		ch6<='d0;
		ch7<='d0;
		ch8<='d0;
	end		
	else 
	begin
		case(state_c)
		IDLE    :begin
			cs<=1'd1;
			cnt_cvt<='d0;
			adc_cvt<='d0;
			rd<=1'd1;
			cnt_ch<='d0;
			flag<='d0;
		end //hou mian bu chong
		CVT     :begin
			if(cnt_cvt<2)
				cnt_cvt<=cnt_cvt+1'd1;
			else begin
				adc_cvt<=1'd1;
				cnt_cvt<='d0;
		end
		end
		RD_ST   :
			cs<='d0;
		GET_DATA:begin
			if(rd)
				rd<='d0;
			else begin
				rd<='d1;
				cnt_ch<=cnt_ch+1'd1;
				case (cnt_ch)
				3'd0:ch1<=ad_data;
				3'd1:ch2<=ad_data;
				3'd2:ch3<=ad_data;
				3'd3:ch4<=ad_data;
				3'd4:ch5<=ad_data;
				3'd5:ch6<=ad_data;
				3'd6:ch7<=ad_data;
				3'd7:ch8<=ad_data;
				endcase
				end
			
			if(cnt_ch==3'd7)//zhuyi
				flag<=1'd1;
		end
		endcase
	end
		
end


assign add=^ch1+^ch2+^ch3+^ch4+^ch5+^ch6+^ch7+^ch8;



endmodule
module my_8ad_tb ();
reg	         clk    ;
reg	         rst_n  ;
wire         adc_cvt;
wire         rd     ;
wire         cs     ;
reg          busy   ;
reg   [15:0] ad_data;
wire  [15:0] ch1    ;
wire  [15:0] ch2    ;
wire  [15:0] ch3    ;
wire  [15:0] ch4    ;
wire  [15:0] ch5    ;
wire  [15:0] ch6    ;
wire  [15:0] ch7    ;
wire  [15:0] ch8    ;
wire         flag   ;  	   
wire   [2:0]  state_c;

design_8ad tb(
	.clk     (clk    ),
    .rst_n   (rst_n  ),
    .adc_cvt (adc_cvt),
    .rd      (rd     ),
    .cs      (cs     ),
    .busy    (busy   ),
    .ad_data (ad_data),
    .ch1     (ch1    ),
    .ch2     (ch2    ),
    .ch3     (ch3    ),
    .ch4     (ch4    ),
    .ch5     (ch5    ),
    .ch6     (ch6    ),
    .ch7     (ch7    ),
    .ch8     (ch8    ),
    .flag    (flag   ),
	.state_c (state_c)
);

initial begin
	clk=1'd1;
	rst_n='d0;
	ad_data='d0;
	busy='d0;
	#100;
	rst_n=1'd1;
	#250000;
	$stop;
end

always #10 clk=~clk;

always @ (posedge adc_cvt)
begin
	#1 busy <=1'd1;
	#800 busy <=1'd0;
end

always @ (negedge rd)
#5 ad_data<=ad_data+1'd1;

endmodule

仿真波形 

modelsim验证无误后我用的是max10系列fpga 用quartus综合,也用过spartan6使用ise,具体用哪个软件看自己选择的芯片:

用quartus,建立工程,命名顶层模块,选择芯片,建立工程完成。addfiles,把设计添加进去,编译一遍,分配引脚,再编译。导入fpga,用示波器测adc输出引脚就能看到有规律波形,则表明编译没有问题,adc已经可以工作。打开single tap 设置采样时钟和采样信号,完成后再编译导入fpga,可以捕捉到波形

可以设置多比特数组的进制,我设置的是有符号十进制源码,系统默认是十六进制。

综合后我用的quartus singletap 抓波形,用信号发生器给正弦波和方波,抓到数后导出数据,用excle折线图绘制,成功还原出原波形。

示波器波形

还原出波形

 

ps:信号发生器产生的波形频率应符合设计的采样频率范围

/*******************************************************************************/

这是本人第一次在csdn发文章,水平尚且有限,目前尚处于学习阶段,希望我的经验能够给后来的同学们起到一个指导的作用。大家有什么意见和建议欢迎评论指出。大家的鼓励会是我以后发文的动力,谢谢大家。

  • 12
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
AD7606 数据采集模块,16位ADC,8通道同时200KHz频率采集,每秒8*200K样本。SPI接口或8080 16位并口,可自行选择。 AD7606 数据采集模块特性: 使用AD7606 高精度16位ADC芯片 8路模拟输入。阻抗1M欧姆。【无需负电源,无需前端模拟运放电路,可直接接传感器输出】 输入范围正负5V,正负10V。可通过IO控制量程。 分辨率 16位。 最大采样频率 200Ksps。 支持8档过采样设置(可以有效降低抖动) 内置基准 单5V供电 SPI接口或16位总线接口。接口IO电平可以是5V或3.3V AD7606 数据采集模块实物截图: 2种接口方式: 并口模式跳线:R1 悬空(不贴),R2贴10K电阻 SPI接口模式跳线:R1 贴10K电阻,R2 悬空(不贴) 附件内容例程主要包括AD7606_SPI例程、ADS7606_SPI_51单片机例程等 见截图; 【软件定时采集的实现方案1】 --- 我们提供的SPI例子采用这种方案,见bsp_spi_ad7606.c文件 在定时器中断服务程序中实现: 定时器中断ISR: { 中断入口; 读取8个通道的采样结果保存到RAM; ----> 读取的是上次的采集结果,对于连续采集来说,是没有关系的 启动下次ADC采集;(翻转CVA和CVB) 中断返回; } 定时器的频率就是ADC采样频率。这种模式可以不连接BUSY口线。 【软件定时采集的实现方案2】 --- 我们提供的8080接口例子采用这种方案,见bsp_ad7606.c文件 配置CVA、CVB引脚为PWM输出模式,周期设置为需要的采样频率; ----> 之后MCU将产生周期非常稳定的AD转换信号 将BUSY口线设置为中断下降沿触发模式; 外部中断ISR: { 中断入口; 读取8个通道的采样结果保存到RAM; } 【软件定时采集的实现方案1和方案2的差异】 (1)方案1 可以少用 BUSY口线,但是其他中断服务程序或者主程序临时关闭全局中断时,可能导致ADC转换周期存在轻微抖动。 (2)方案2 可以确保采集时钟的稳定性,因为它是MCU硬件产生的。但是需要多接一根BUSY口线。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DKsmile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值