秦韵FPGA 转载或原创(十三) 高云FPGAGW2A-18C
低速adc数据采集部分
主要为AD7606芯片,fpga驱动adc采集数据,我们主要依据芯片的数据手册,编写adc驱动代码,根据我们的硬件设计部分,本次adc的驱动采用并行模式,convtAB连接、OS信号不启用,只实现数据采集部分。
先贴一下时序图,我们采用转换后读取数据模式,阅读时序图我们开始写代码,硬件上江CONVSTAB连接在一起,因此我们只需要操作一个信号就可以,busy信号时输入信号,我们可以开始组织代码框架,要实现ad7606的最高采样率,即200kHZ,如果我们采用50M主频,那么我们就需要每250000个时钟出一次数据,也就是是能一次转换,即拉低一次convstab信号。
主题框架采用状态机实现,比如: IDLE、如果想做到采样率可控,可以添加一个START状态、添加CONVST状态、转换完成读取信号为等待busy拉低然后开始读取数据(这段时间是有从机也就是ac芯片决定的),即有WAITBUSY状态、然后进入数据读取READ状态、到这里整个adc数据读取状态也就结束了,即有END状态、然后回到IDLE状态。
状态机代码段: 推荐3段式状态机。
下面展示一些 内联代码片
。
// ===========Oooo==========================================Oooo========
// = Copyright (C) 2002-2022 WMPself.
// = All rights reserved.
// =====================================================================
//
// __ __ __
// \ \ / \ / /
// \ \ / /\ \ / /
// \ \/ / \ \/ / [File name ] ad7606.v
// \ \/ \/ / [Description ] adc7606 Driver
// /\/ \/\ [Timestamp ] Saturday Apr 23 19:53:30 2022
// / / \ \ [version ] 1.0.0
// / / \ \
// /_/ \_\
//
//
// ===========Oooo==========================================Oooo========
// Code Revision History :
// --------------------------------------------------------------------
// Ver: | Author |Mod. Date |Changes Made:
// V1.0 | wmp |23/04/22 |Initial version
// ===========Oooo==========================================Oooo========
module ad7606(
input clk,
input rst_n,
...
...
);
parameter IDLE = 3'd0;
parameter START= 3'd1;
parameter CONVST= 3'd2;
parameter WAITBUSY= 3'd3;
parameter READ= 3'd4;
parameter END= 3'd5;
reg [2:0] state_cs;
reg [2:0] state_ns;
always@(posedge clk or negedge rst_n)
if(!rst_n)
state_cs <= IDLE ;
else
state_cs <= state_ns;
always@(*) begin
case(state_cs)
IDLE : begin
if(ad7606_start_valid)
state_ns = START ;
else
state_ns = IDLE ;
end
START : begin
if(speed_start)
state_ns = CONVST ;
else
state_ns = START ;
end
CONVST : begin
if(ad7606_convst_done)
state_ns = WAITBUSY ;
else
state_ns = CONVST ;
end
WAITBUSY : begin
if(ad7606_busy_edge) //检测busy为低电平,或者检测busy为有高变低的边沿
state_ns = READ ;
else
state_ns = WAITBUSY ;
end
READ : begin
if(ad7606_read_done)
state_ns = END ;
else
state_ns = READ ;
end
END : begin
state_ns = IDLE ;
end
default : state_ns = IDLE ;
endcase
end
到这里整个数据的读取框架结构就完成了,下面简单讲解取数据的过程。
观察时序图,cs拉低,发送rd信号,可以在江rd信号拉高的上升沿去取数据,定义一个16bit的数据存取寄存器,frstdata可以使用,也可以不使用,简单的代码如下:
// ===========Oooo==========================================Oooo========
// = Copyright (C) 2002-2022 WMPself.
// = All rights reserved.
// =====================================================================
//
// __ __ __
// \ \ / \ / /
// \ \ / /\ \ / /
// \ \/ / \ \/ / [File name ] ad7606.v
// \ \/ \/ / [Description ] adc7606 Driver
// /\/ \/\ [Timestamp ] Saturday Apr 23 19:53:30 2022
// / / \ \ [version ] 1.0.0
// / / \ \
// /_/ \_\
//
//
// ===========Oooo==========================================Oooo========
// Code Revision History :
// --------------------------------------------------------------------
// Ver: | Author |Mod. Date |Changes Made:
// V1.0 | wmp |23/04/22 |Initial version
// ===========Oooo==========================================Oooo========
module ....(
...
...
ad7606_cs,
ad7606_rd,
ad7606_din,
...
...
);
//...
reg adc7606_rd_redge;
reg adc7606_rd_fedge;
reg [15:0] ad7606_data_r[7:0];
always@(posedge clk or negedge rst_n)
if(!rst_n)
ad7606_cs <= 1'b1 ;
else if(state_cs == READ )
ad7606_cs <= 'b0;
else
ad7606_cs <= 'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
ad7606_rd <= 1'b1 ;
else if(ad7606_cs == 'b0 ) begin
if(adc7606_rd_redge)
ad7606_rd <= 'b1;
else if(adc7606_rd_fedge)
ad7606_rd <= 'b0;
end
else
ad7606_rd <= 'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n) begin
ad7606_data_r[0] <= 'd0 ;
ad7606_data_r[1] <= 'd0 ;
ad7606_data_r[2] <= 'd0 ;
ad7606_data_r[3] <= 'd0 ;
ad7606_data_r[4] <= 'd0 ;
ad7606_data_r[5] <= 'd0 ;
ad7606_data_r[6] <= 'd0 ;
ad7606_data_r[7] <= 'd0 ;
end
else if(ad7606_cs == 'b0) begin
if(adc7606_rd_redge && ad7606_cnt == 1 )
ad7606_data_r[0] <= ad7606_din;
else if(adc7606_rd_redge && ad7606_cnt == 2 )
ad7606_data_r[1] <= ad7606_din;
...
...
...
ad7606_data_r[7] <= ad7606_din;
end
..
//frstdata 可以使用,也可以不使用,主要可以用来对齐第一个通道的数据。
到这里基本上就完成了,数据也读出来了,就完成了ad7606的驱动,如果想要调整采样率,只需要控制speed_start这个信号就可以了,还有如果想要了解过采样这部分的功能,可以自己了解数据手册,这里只给出了框架和设计思路,具体的需要下班验证才可使用。