当前位置:   article > 正文

高云FPGA控制AD7606满速采集_ad7606信号采集模块fpga设计

ad7606信号采集模块fpga设计

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316

仿真程序

`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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

仿真结果

在这里插入图片描述

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/1007138
推荐阅读
相关标签
  

闽ICP备14008679号