赞
踩
本文不细究AD7606芯片工作供电及参考电压相关引脚,只讨论与控制相关的引脚。
引脚号 | 名称 | 作用 |
---|---|---|
5,4,3 | OS[2:0] | 过采样倍率控制位,具体见下表 |
6 | PAR_n/SER/BYTE SEL | 拉低为并行接口模式,拉高为串行接口模式,拉高且#33引脚拉高为并行字节接口模式 |
9,10 | CONVST A,B | AD7606开始采样控制位,两个直接短接使用 |
11 | RESET | AD7606复位引脚,拉高50ns以上有效 |
12 | RD_n/SCLK | 并行接口模式下拉低读取数据,串行接口模式下为时钟接口 |
13 | CS_n | 片选信号 |
15 | FRSTDATA | 正在读取第一个采样值标志位,高有效 |
OS[2:0] | 过采样倍率 | 最大转换频率(KHz) |
---|---|---|
000 | NO OS | 200 |
001 | 2 | 100 |
010 | 4 | 50 |
011 | 8 | 25 |
100 | 16 | 12.5 |
101 | 32 | 6.25 |
110 | 64 | 3.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引脚。
`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路的采集卡,自上而下的开发思路没有应用导致现在写的代码还需重新修改,还是有待锻炼。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。