Verilog实现AD574驱动(有限状态机)
程序员文章站
2024-03-19 18:04:52
...
Verilog实现AD574驱动
AD574简介
AD574是12位A/D转换器,引脚图如下图1所示:
pin3-CS(in): 片选 低有效
pin5-RC(in): 状态控制 0-转换,1-读数
pin6-CE(in): 使能
pin16~27-DB(out): AD574转换的12位数据输出
pin28-STS(out): 状态指示:1-转换,0-转换结束
关于pin2(12/8)和pin4(A0)的用法请看下面的真值表
官方也有给出典型的参考电路
我们在了解一款数字芯片时,除了真值表最关心的就是时序图了
在编写程序之前,必须把时序图看明白,官方给出的时序图有两个,图3是转换过程时序图,图4是取数过程时序图
对AD574A 有了充分的了解后,我们来开始编写Verilog程序。
源程序
module ADC574A(clk,DB,clr,STS,CS,CE,RC,q);
input clk;
input clr; //复位
input STS; //状态:1-转换,0-转换结束
input [11:0] DB; //AD574转换好的12位数据
output CS; //片选 低有效
output reg CE; //ADC使能
output reg RC; //0-转换,1-读数
output [11:0] q; //12位数据输出
parameter S0='d0,S1='d1,S2='d2,S3='d3,S4='d4;
reg [2:0] current_state,next_state;
reg lock; //转换后数据输出锁存信号
reg [11:0] rel; //12位数据寄存器
assign CS=0; //片选
assign q=rel;
always @(posedge clk or posedge clr)
begin
if(clr) current_state<=S0;
else current_state<=next_state;
end
always @(posedge lock) //lock上升沿锁存数据
begin
rel<=DB;
end
always @(current_state,STS)
begin
case(current_state)
S0:begin //AD574初始化
CE<=1'b0;
RC<=1'b1;
lock<=1'b0;
next_state<=S1;
end
S1:begin //启动采样
CE<=1'b1;
RC<=1'b0;
lock<=1'b0;
next_state<=S2;
end
S2:begin
CE<=1'b1;
RC<=1'b0;
lock<=1'b0;
if(~STS) next_state<=S3; //STS变为0,转换结束
else next_state<=S2; //转换未结束,等待
end
S3:begin //AD574输出转换好的数据
CE<=1'b1;
lock<=1'b0;
RC<=1'b1;
next_state<=S4;
end
S4:begin
CE<=1'b1;
RC<=1'b1;
lock<=1'b1; //FPGA读取AD输出的数据
next_state<=S0;
end
default: next_state<=S0;
endcase;
end
刚开始综合时因为状态编码不当,即写成:
parameter S0=5’b0000,S1=5’b00010,S2=5’b00100,
S3=5’b01000,S4=5’b10000;
一直不能萃取到状态机。
其实官方提供的帮助文档中也给出了状态机的萃取条件,编写状态机时应严格按照要求。下面是文档中的5条要求:
1.表现状态机的信号或变量必须为枚举类型。
2.状态转移必须由clk触发,并且是用if语句检测的上升沿进行转移。
3.状态转移到下一个状态由CASE语句判断
4.所有信号,变量赋值都要放在状态机进程里进行。
5.状态机的状态必须多于两个状态。
RTL图
状态转移图
testbench编写
initial
begin
clk=0;
DB=12'bzzzzzzzzzzzz;
clr=1;
STS=0;
#80 clr=0;STS=1;
#160 DB=12'b101111000010;
#160 STS=0;
#240 DB=12'bzzzzzzzzzzzz;
#80 STS=1;
#160 DB=12'b111111111111;
#160 STS=0;
#240 DB=12'bzzzzzzzzzzzz;
#80 STS=1;
#160 DB=12'b000000000000;
#160 STS=0;
#320 $stop;
$display("Running testbench");
end
always
begin
#40 clk=~clk;
end