FPGA之ADS8344驱动程序
FPGA之ADS8344驱动程序*
前言
在学习完小梅老师的《线性序列机与TLV1544驱动设计》后,本人受到小梅老师“用线性序列机”设计AD/DA驱动程序的启发后开始渴望掌握这种方法,于是开始拿“ADS8344”练手。
ADS8344简介
ADS8344是采用20引脚QSDP封装或SSOP封装的芯片,是一个高速、低功耗、16位逐次逼近型ADC。(咱就做个简单的简介,更详细内容可以去参考ASD8344的数据手册)
模块代码分析
端口定义代码
module ADS8344(
Clk,
Rst_n,
Do_Conv, //开始转换使能信号
ADS_CHSEL, //模拟通道选择、模拟输入方式选择和功率管理选择信号
ADS_DONE, //转换完成信号
ADS_DATA,
DATA_Valid, //数据有效信号,转换完成的有效数据给ADS_DATA
ADS8344_CS,
ADS8344_DCLK,
ADS8344_DIN,
ADS8344_BUSY,
ADS8344_DOUT
);
端口类型定义
input Clk;
input Rst_n;
input Do_Conv;
input [7:0]ADS_CHSEL;
output reg [15:0]ADS_DATA;
output reg ADS_DONE;
output reg DATA_Valid;
output reg ADS8344_CS;
output reg ADS8344_DCLK;
output reg ADS8344_DIN;
input ADS8344_BUSY;
input ADS8344_DOUT;
定义两个寄存器,ADS_RDATA用于寄存ADS_DOUT转换输出的数据,LSM_CNT为9位的序列计数器
reg [15:0]ADS_RDATA; //ADS8344_DOUT输出的数据先寄存在ADS_RDATA,当DATA_Valid为1时数据给ADS_DATA
reg [8:0]LSM_CNT; //序列计数器
复位
aaa@qq.com(posedge Clk or negedge Rst_n )
if(!Rst_n)
LSM_CNT<=9'd0;
else if((LSM_CNT<301)&&Do_Conv)
LSM_CNT<=LSM_CNT+1'b1;
else if(LSM_CNT==301)
LSM_CNT<=9'd0;
aaa@qq.com(posedge Clk or negedge Rst_n )
if(!Rst_n)
begin
ADS8344_CS<=1'b1;
ADS8344_DCLK<=1'b0;
ADS8344_DIN<=1'b0;
ADS_DONE<=1'b0;
ADS_RDATA[15:0]<=16'd0;
DATA_Valid<=1'b0;
ADS_DATA<=16'd0;
end
当复位为1时(Rst_n==1’b1),开始执行程序,判断序列机LSM_CNT状态,根据其状态执行其相应状态下的语句。LSM_CNT计数值为0时,所有状态为复位时的状态,除复位为1外。
case(LSM_CNT)
0:
begin
ADS8344_CS<=1'b1;
ADS8344_DCLK<=1'b0;
ADS8344_DIN<=1'b0;
ADS_DONE<=1'b0;
ADS_RDATA[15:0]<=16'd0;
DATA_Valid<=1'b0;
ADS_DATA<=16'd0;
end
片选信号为0,芯片开始工作
1:
begin
ADS8344_CS<=1'b0;
end
DIN开始接受模拟通道选择、模拟输入方式选择和功率管理选择信号。
7:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[7];
end
13:
begin
ADS8344_DCLK<=1'b0;
end
19:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[6];
end
25:
begin
ADS8344_DCLK<=1'b0;
end
31:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[5];
end
37:
begin
ADS8344_DCLK<=1'b0;
end
43:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[4];
end
49:
begin
ADS8344_DCLK<=1'b0;
end
55:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[3];
end
61:
begin
ADS8344_DCLK<=1'b0;
end
67:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[2];
end
73:
begin
ADS8344_DCLK<=1'b0;
end
79:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[1];
end
85:
begin
ADS8344_DCLK<=1'b0;
end
91:
begin
ADS8344_DCLK<=1'b1;
ADS8344_DIN<=ADS_CHSEL[0];
end
97:
begin
ADS8344_DCLK<=1'b0;
end
数据采集完成,芯片开始转换,转换时间为一个时钟周期,此时BUSY被拉高。
97:
begin
ADS8344_DCLK<=1'b0;
end
103:
begin
ADS8344_DCLK<=1'b1;
end
109:
begin
ADS8344_DCLK<=1'b0;
end
当BUSY下降变成低电平时,ADS_DOUT开始输出转换完成的数据
127:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[14]<=ADS8344_DOUT;
end
133:
begin
ADS8344_DCLK<=1'b0;
end
139:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[13]<=ADS8344_DOUT;
end
145:
begin
ADS8344_DCLK<=1'b0;
end
151:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[12]<=ADS8344_DOUT;
end
157:
begin
ADS8344_DCLK<=1'b0;
end
163:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[11]<=ADS8344_DOUT;
end
169:
begin
ADS8344_DCLK<=1'b0;
end
175:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[10]<=ADS8344_DOUT;
end
181:
begin
ADS8344_DCLK<=1'b0;
end
187:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[9]<=ADS8344_DOUT;
end
193:
begin
ADS8344_DCLK<=1'b0;
end
199:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[8]<=ADS8344_DOUT;
end
205:
begin
ADS8344_DCLK<=1'b0;
end
211:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[7]<=ADS8344_DOUT;
end
217:
begin
ADS8344_DCLK<=1'b0;
end
223:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[6]<=ADS8344_DOUT;
end
229:
begin
ADS8344_DCLK<=1'b0;
end
235:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[5]<=ADS8344_DOUT;
end
241:
begin
ADS8344_DCLK<=1'b0;
end
247:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[4]<=ADS8344_DOUT;
end
253:
begin
ADS8344_DCLK<=1'b0;
end
259:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[3]<=ADS8344_DOUT;
end
265:
begin
ADS8344_DCLK<=1'b0;
end
271:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[2]<=ADS8344_DOUT;
end
277:
begin
ADS8344_DCLK<=1'b0;
end
283:
begin
ADS8344_DCLK<=1'b1;
ADS_RDATA[1]<=ADS8344_DOUT;
end
289:
begin
ADS8344_DCLK<=1'b0;
end
当最后一个转换数据输出时,输出数据有效信号DATA_Valid为1,ADS_RDATA寄存器的数据传输给数据输出端ADS_DATA。
295:
begin
ADS8344_DCLK<=1'b1;
if(! ADS8344_BUSY)
DATA_Valid<=1'b1; //转换数据有效,开始输出
else
DATA_Valid<=1'b0;
ADS_DATA<={ADS_RDATA[15:1],ADS8344_DOUT};
end
转换完成,片选拉高,转换完成信号拉高
301:
begin
ADS8344_DCLK<=1'b0;
ADS8344_CS<=1'b1;
ADS_DONE<=1'b1;
end
计数器的其他情况下数据输出有效信号无效(为0)。
default: DATA_Valid<=1'b0;
仿真代码
设置一个20ns的时钟
initial Clk=1'b1;
always #(`clk_period/2) Clk=~Clk;
部分端口初始化及产生仿真的激励信号
initial
begin
Do_Conv<=1'b0;
ADS_CHSEL<=8'b0;
ADS8344_DOUT<=1'b0;
Rst_n<=1'b0;
#(`clk_period*10+1); //加1为了与时钟信号上升沿错开好观察
Rst_n<=1'b1;
#(`clk_period*10)
Do_Conv<=1'b1;
ADS8344_BUSY<=1'b0;
ADS_CHSEL<=8'b10000100;
#(`clk_period)
@(posedge (ADS8344_0.LSM_CNT==9'd97))
ADS8344_BUSY<=1'b1;
@(posedge (ADS8344_0.LSM_CNT==9'd109))
ADS8344_BUSY<=1'b0;
#(`clk_period*1000);
$stop;
end
给ADS_DOUT设置一个简单的数据输出信号
initial
begin
forever begin
ADS8344_DOUT=~ADS8344_DOUT;
#100;
end
end
前仿真结果
复位为高电平
BUSY信号为低电平,ADS_DOUT开始输出转换数据
数据有效信号为1,ADS_DATA开始输出转换得到的数据;转换完成信号ASD_DONE变高电平,cs拉高。
仿真结果分析
按照前仿真结果来看,代码已经完成了ADS8344的驱动;本人未做板机验证,实际中是否能实现有待考究。
总结
小梅老师的设计方法让我受益匪浅,通过编写ADS8344的驱动让我对这种方法的掌握更加牢固,感谢小梅老师,感谢支持我的所有人。
上一篇: memcached安装与使用
下一篇: Memcached原理与部署