ad7606的八通道modelsim仿真

ad7606的八通道modelsim仿真

解决的疑问主要有一下几点:
(1)之前一直困惑于如何确定AD的采样频率,后来在朋友的提示下,在程序中加入了定时器,每50us读取一次数据,实现采样频率变为20K。
(2)对ad_reset信号,之前一直以为计数器记满之后,会自动复位,似的该信号会马上变为高电平,仿真后才发现并未如此,满量程的计数器将会一直保持在ff的状态,使得ad-reset信号保持为低,也就进入了循环采样的状态。cnt计数器只是对ad复位进行操作,这正决定采样频率的是cnt50us计数器。
(3)使用$random函数模拟采样信号,使得仿真结果更真实可观。

ad的采样程序如下:

`timescale 1ns / 1ns
//
// Module Name: ad7606
//
module ad7606(
input clk, //50mhz
input rst_n,

input [15:0]        ad_data,            //ad7606 采样数据
input               ad_busy,            //ad7606 忙标志位

input first_data, //ad7606 第一个数据标志位

output [2:0]        ad_os,              //ad7606 过采样倍率选择
output reg          ad_cs,              //ad7606 AD cs
output reg          ad_rd,              //ad7606 AD data read
output reg          ad_reset,           //ad7606 AD reset
output reg          ad_convstab,         //ad7606 AD convert start

output reg [15:0] ad_ch1,              //AD第1通道的数据
output reg [15:0] ad_ch2,              //AD第2通道的数据
output reg [15:0] ad_ch3,              //AD第3通道的数据
output reg [15:0] ad_ch4,              //AD第4通道的数据
output reg [15:0] ad_ch5,              //AD第5通道的数据
output reg [15:0] ad_ch6,              //AD第6通道的数据
output reg [15:0] ad_ch7,              //AD第7通道的数据
output reg [15:0] ad_ch8,              //AD第8通道的数据  

output reg [3:0] state
//output reg [3:0] cnt

);

reg [7:0] cnt = 0 ;
reg [15:0] cnt50us = 0;
reg [5:0] i;
//reg [3:0] state;

parameter IDLE=4’d0;
parameter AD_CONV=4’d1;
parameter Wait_1=4’d2;
parameter Wait_busy=4’d3;
parameter READ_CH1=4’d4;
parameter READ_CH2=4’d5;
parameter READ_CH3=4’d6;
parameter READ_CH4=4’d7;
parameter READ_CH5=4’d8;
parameter READ_CH6=4’d9;
parameter READ_CH7=4’d10;
parameter READ_CH8=4’d11;
parameter READ_DONE=4’d12;
//parameter display=4’d13;

assign ad_os=3’b000; //无过采样

//ad复位
always@(posedge clk)
begin
if(cnt<8’hff) begin
cnt<=cnt+1;
ad_reset<=1’b1;
end
else
ad_reset<=1’b0; //计数器达到ff后停止,ad_reset恒为零
end

//使用定时器来设置采样频率
always @(posedge clk or negedge rst_n) //每50us读取一次数据,ad的采样率为20K
begin
if(rst_n == 0)
cnt50us <= 0;
else begin
if(cnt50us < 16’d2499)
begin
cnt50us <= cnt50us + 1;
end
else
cnt50us <= 0;
end
end

always @(posedge clk)
begin
if (ad_reset1’b1) begin //初始化ad
state<=IDLE;
ad_ch1<=0;
ad_ch2<=0;
ad_ch3<=0;
ad_ch4<=0;
ad_ch5<=0;
ad_ch6<=0;
ad_ch7<=0;
ad_ch8<=0;
ad_cs<=1’b1;
ad_rd<=1’b1;
ad_convstab<=1’b1; //8通道同步采样
i<=0;
end
else begin
case(state) //need time:(20+2+5+1+3*8+1)*20ns=1060ns, fmax=1/1060ns=1MHZ
IDLE: begin
ad_cs<=1’b1;
ad_rd<=1’b1;
ad_convstab<=1’b1;
if(i
20) begin //延时20个时钟后开始转换
i<=0;
state<=AD_CONV;
end
else
i<=i+1’b1;
end
AD_CONV: begin
if(i2) begin //等待2个lock,convstab的下降沿最少为25ns,故至少需要两个时钟
i<=0;
state<=Wait_1;
ad_convstab<=1’b1;
end
else begin
i<=i+1’b1;
ad_convstab<=1’b0; //启动AD转换
end
end
Wait_1: begin
if(i
5) begin //等待5个clock, 等待busy信号为高(tconv)
i<=0;
state<=Wait_busy;
end
else
i<=i+1’b1;
end
Wait_busy: begin
if(ad_busy1’b0) begin //等待busy为低电平 即转换之后读取模式
i<=0;
state<=READ_CH1;
end
end
READ_CH1: begin
ad_cs<=1’b0; //cs信号有效 直到读取8通道结束
if(i
3) begin // 低电平持续3个时钟,完成通道1的读入
ad_rd<=1’b1;
i<=0;
ad_ch1<=ad_data; //读CH1
state<=READ_CH2;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH2: begin
if(i3) begin
ad_rd<=1’b1;
i<=0;
ad_ch2<=ad_data; //读CH2
state<=READ_CH3;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH3: begin
if(i
3) begin
ad_rd<=1’b1;
i<=0;
ad_ch3<=ad_data; //读CH3
state<=READ_CH4;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH4: begin
if(i3) begin
ad_rd<=1’b1;
i<=0;
ad_ch4<=ad_data; //读CH4
state<=READ_CH5;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH5: begin
if(i
3) begin
ad_rd<=1’b1;
i<=0;
ad_ch5<=ad_data; //读CH5
state<=READ_CH6;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH6: begin
if(i3) begin
ad_rd<=1’b1;
i<=0;
ad_ch6<=ad_data; //读CH6
state<=READ_CH7;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH7: begin
if(i
3) begin
ad_rd<=1’b1;
i<=0;
ad_ch7<=ad_data; //读CH7
state<=READ_CH8;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_CH8: begin
if(i==3) begin
ad_rd<=1’b1;
i<=0;
ad_ch8<=ad_data; //读CH8
state<=READ_DONE;
end
else begin
ad_rd<=1’b0;
i<=i+1’b1;
end
end
READ_DONE:begin //完成读,回到idle状态
ad_rd<=1’b1;
ad_cs<=1’b1;
if(cnt50us == 16’d2499) //不加此条件,则ad完成一次读取需1280ns,采样频率781.25K,但需注意ad每通道的追高采样只能为200K
state<=IDLE;
else
state<=READ_DONE;
end
default: state<=IDLE;
endcase
end

end

endmodule

仿真测试程序如下:

`timescale 1 ns/ 1 ns
module ad7606_vlg_tst();
// constants
// general purpose registers

// test vector input registers
reg ad_busy;
reg [15:0] ad_data;
reg clk;
reg first_data;
reg rst_n;
// wires
wire [15:0] ad_ch1;
wire [15:0] ad_ch2;
wire [15:0] ad_ch3;
wire [15:0] ad_ch4;
wire [15:0] ad_ch5;
wire [15:0] ad_ch6;
wire [15:0] ad_ch7;
wire [15:0] ad_ch8;
wire ad_convstab;
wire ad_cs;
wire [2:0] ad_os;
wire ad_rd;
wire ad_reset;
wire [3:0] state;

// assign statements (if any)
ad7606 i1 (
// port map - connection between master ports and signals/registers
.ad_busy(ad_busy),
.ad_ch1(ad_ch1),
.ad_ch2(ad_ch2),
.ad_ch3(ad_ch3),
.ad_ch4(ad_ch4),
.ad_ch5(ad_ch5),
.ad_ch6(ad_ch6),
.ad_ch7(ad_ch7),
.ad_ch8(ad_ch8),
.ad_convstab(ad_convstab),
.ad_cs(ad_cs),
.ad_data(ad_data),
.ad_os(ad_os),
.ad_rd(ad_rd),
.ad_reset(ad_reset),
.clk(clk),
.first_data(first_data),
.rst_n(rst_n),
.state(state)
//.cnt(cnt)
);
initial
begin
ad_busy = 0;
first_data = 0;
clk = 0;
forever //50MHz
#10
clk = ~clk;
$display(“Running testbench”);
end
initial
begin
rst_n = 1;
#10;
rst_n = 0;
#20;
rst_n = 1;
end

always@(posedge clk)
begin

  ad_data <= $random;      //使用随机数模拟采样信号        

end  

endmodule


版权声明:本文为CSDN博主「yy2122」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yy2122/article/details/70050150


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值