高云FPGA控制AD7606满速采集

AD7606简介

关键引脚介绍

本文不细究AD7606芯片工作供电及参考电压相关引脚,只讨论与控制相关的引脚。
AD7606引脚图

引脚号名称作用
5,4,3OS[2:0]过采样倍率控制位,具体见下表
6PAR_n/SER/BYTE SEL拉低为并行接口模式,拉高为串行接口模式,拉高且#33引脚拉高为并行字节接口模式
9,10CONVST A,BAD7606开始采样控制位,两个直接短接使用
11RESETAD7606复位引脚,拉高50ns以上有效
12RD_n/SCLK并行接口模式下拉低读取数据,串行接口模式下为时钟接口
13CS_n片选信号
15FRSTDATA正在读取第一个采样值标志位,高有效
OS[2:0]过采样倍率最大转换频率(KHz)
000NO OS200
0012100
010450
011825
1001612.5
101326.25
110643.125
111无效~

控制时序介绍

这里只阐述并行接口模式下,转换完成后读取的时序。如下图,当CONVST引脚短接情况下,当RESET拉高后25ns可拉低CONVSTA,B,经过25ns拉低RESET,再经过25ns拉高CONVSTA,完成第一次采集开始命令,以后只需执行50ns以上CONVST低电平持续时间,就可以开始采样。在OS为3‘b000时,AD7606的BUSY引脚至多维持4200ns,也就是说在大于t1时间后检测BUSY是否为低电平即可完成检测AD7606是否完成转换。
在这里插入图片描述
本文介绍的是CS_n与RD_n分别控制的读取时序,在判断BUSY有下降沿后,拉低CS、RD,当供电电压大于4.75V时,等待19ns可以读取第一通道数据,然后拉高RD,等待15ns以上,拉低RD,延迟19ns读取第二通道数据,以此类推。本文程序未用到FRSTDATA引脚。
在这里插入图片描述

单段状态机实现控制单个AD7606

控制程序

`timescale 1ns / 1ps
module AD7606(
    input clk,              //module operating frequency 500MHz
    input rst_n,            //reset, active low
    input en_read;          //enable to read data, active high
    
    input [15:0] data_in,   //sampling data input
    input busy,             //ad7606 busy flag
    
    output reg cs,          //ad7606 chip select
    output reg rd,          //ad7606 read control signal
    output reg reset,       //ad7606 reset
    output reg convstab,    //ad7606 AD convert start
    output [2:0] os,        //ad7606 oversampling rate selection

    output reg [15:0] ch1,  //ad7606 channel1 data
    output reg [15:0] ch2,  //ad7606 channel2 data
    output reg [15:0] ch3,  //ad7606 channel3 data
    output reg [15:0] ch4,  //ad7606 channel4 data
    output reg [15:0] ch5,  //ad7606 channel5 data
    output reg [15:0] ch6,  //ad7606 channel6 data
    output reg [15:0] ch7,  //ad7606 channel7 data
    output reg [15:0] ch8,  //ad7606 channel8 data
    
    output reg receive_over //the module cycle over
);

localparam CONVST_DOWN      = 5'd0;
localparam WAIT_BUSY_UP     = 5'd1;
localparam WAIT_BUSY_DOWN   = 5'd2;
localparam WAIT1            = 5'd3;            //delay from cs until DB[15:0] three-state disabled
localparam READ_CH1         = 5'd4;
localparam RD_HIGH_CH1      = 5'd5;
localparam READ_CH2         = 5'd6;
localparam RD_HIGH_CH2      = 5'd7;
localparam READ_CH3         = 5'd8;
localparam RD_HIGH_CH3      = 5'd9;
localparam READ_CH4         = 5'd10;
localparam RD_HIGH_CH4      = 5'd11;
localparam READ_CH5         = 5'd12;
localparam RD_HIGH_CH5      = 5'd13;
localparam READ_CH6         = 5'd14;
localparam RD_HIGH_CH6      = 5'd15;
localparam READ_CH7         = 5'd16;
localparam RD_HIGH_CH7      = 5'd17;
localparam READ_CH8         = 5'd18;
localparam END_CIRCUL       = 5'd20;

//set ad7606 oversampling rate selection
assign os = 3'b000;

//ad7606 reset port
reg [7:0] cnt_rst;
always @ (posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_rst <= 8'd0;
    end else if(cnt_rst < 8'd25) begin
        reset <= 1'b1;
        cnt_rst <= cnt_rst + 8'd1;
    end else
        reset <= 1'b0;
end

//ad7606 sampling port
reg [7:0] cnt_sample;
reg [4:0] state;
always @ (posedge clk) begin
    if(!rst_n) begin
        state <= CONVST_DOWN;
        cnt_sample <= 8'd25;
        ch1 <= 16'd0;
        ch2 <= 16'd0;
        ch3 <= 16'd0;
        ch4 <= 16'd0;
        ch5 <= 16'd0;
        ch6 <= 16'd0;
        ch7 <= 16'd0;
        ch8 <= 16'd0;
        cs <= 1'b1;
        rd <= 1'b1;
        convstab <= 1'b1;
        receive_over <= 1'b0;
    end else if(!reset) begin
        case(state)
            CONVST_DOWN: begin
                convstab <= 1'b0;
                ch1 <= 16'd0;
                ch2 <= 16'd0;
                ch3 <= 16'd0;
                ch4 <= 16'd0;
                ch5 <= 16'd0;
                ch6 <= 16'd0;
                ch7 <= 16'd0;
                ch8 <= 16'd0;
                receive_over <= 1'b0;
                if(cnt_sample == 8'd0) begin
                    cnt_sample <= 8'd200;
                    state <= WAIT_BUSY_UP;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            WAIT_BUSY_UP: begin
                convstab <= 1'b1;
                if(cnt_sample == 8'd0)
                    state <= WAIT_BUSY_DOWN;
                else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            WAIT_BUSY_DOWN: begin
                if(!busy) begin
                    state <= WAIT1;
                    cnt_sample <= 8'd10;
                end
            end
            WAIT1: begin
                if (en_read) begin
                    cs <= 1'b0;
                    if(cnt_sample == 8'd0) begin
                        state <= READ_CH1;
                        cnt_sample <= 8'd20;
                    end else
                        cnt_sample <= cnt_sample - 8'd1;
                end
            end
            READ_CH1: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH1;
                        cnt_sample <= 8'd12;
                    end
                        8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch1 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase    
            end
            RD_HIGH_CH1: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH2;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH2: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH2;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch2 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH2: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH3;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH3: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH3;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch3 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH3: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH4;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH4: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH4;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch4 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH4: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH5;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH5: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH5;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch5 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH5: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH6;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH6: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH6;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch6 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH6: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH7;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH7: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= RD_HIGH_CH7;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch7 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            RD_HIGH_CH7: begin
                rd <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= READ_CH8;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            READ_CH8: begin
                rd <= 1'b0;
                case(cnt_sample)
                    8'd0: begin
                        state <= END_CIRCUL;
                        cnt_sample <= 8'd12;
                    end
                    8'd15: begin
                        cnt_sample <= cnt_sample - 8'd1;
                        ch8 <= data_in;
                    end
                    default:
                        cnt_sample <= cnt_sample - 8'd1;
                endcase
            end
            END_CIRCUL: begin
                rd <= 1'b1;
                cs <= 1'b1;
                receive_over <= 1'b1;
                if(cnt_sample == 8'd0) begin
                    state <= CONVST_DOWN;
                    cnt_sample <= 8'd20;
                end else
                    cnt_sample <= cnt_sample - 8'd1;
            end
            default: state <= CONVST_DOWN;
        endcase
    end
end

endmodule

仿真程序

`timescale 1ns / 1ps
module AD7606_sim();
    reg clk;
    reg rst_n;
    reg [15:0] data_in;
    reg busy;

    wire [2:0] os;
    wire cs;
    wire rd;
    wire reset;
    wire convstab;
    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 receive_over;

    AD7606 AD7606(
        .clk(clk),
        .rst_n(rst_n),
        .data_in(data_in),
        .busy(busy),
        .os(os),
        .cs(cs),
        .rd(rd),
        .reset(reset),
        .convstab(convstab),
        .ch1(ch1),
        .ch2(ch2),
        .ch3(ch3),
        .ch4(ch4),
        .ch5(ch5),
        .ch6(ch6),
        .ch7(ch7),
        .ch8(ch8),
        .receive_over(receive_over)
    );

    reg [15:0] cnt;

    initial begin
        data_in = 16'd255;
        clk = 1'b1;
        busy = 1'b0;
    end

    always #1 clk = ~clk;

    always @(posedge convstab) begin
        busy <= 1'b1;
        #4200 busy <= 1'b0;
    end

    initial begin
        rst_n = 1'b0;
        #200;
        rst_n = 1'b1;
        #200;
        #100000000;
    end

endmodule

仿真结果

在这里插入图片描述

存在的问题及接下来的工作

由于是第一次自己写Verilog程序,思路上还有很多欠缺,比如状态机写成了揉在一起的,而不是推荐的三段式;程序相对复杂,不够精简。接下来我是想做一个64路的采集卡,自上而下的开发思路没有应用导致现在写的代码还需重新修改,还是有待锻炼。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值