`timescale 1ns / 1ps
module ADC7606Driver
#(
parameter
CNVT_WIDTH = 8'd40,
parameter
BUSY_WIDTH = 16'd1800
//
OS = 1, Oversampling by 2, MAX 10us
)
(
input
nRst
,
input
ClkIn
,
input
AD_DB
,
input
clk2
,
output
reg
AD_Rst
,
output
reg
AD_CS
,
output
reg
AD_Convst
,
output
reg
[2:0]
OS
,
output reg convertoverflag,,
input
AD_BUSY
,
//
not exist ?????
output
reg
[15 : 0]
Ch0SampleData
,
//用于current:y奇数
output
reg
[15 : 0]
Ch1SampleData
,
//用于current:f奇数
output
reg
[15 : 0]
Ch2SampleData
,
//用于current:f偶数
output
reg
[15 : 0]
Ch3SampleData
,
//用于current:y偶数
output
reg
[15 : 0]
Ch4SampleData
, //一下Ch_SampleData未用
output
reg
[15 : 0]
Ch5SampleData
,
output
reg
[15 : 0]
Ch6SampleData
,
output
reg
[15 : 0]
Ch7SampleData
,
output reg
[2 : 0]
current_adc_state
,
output reg
[3 : 0]
rst_cntr
,
output
reg
AD_SCLK
);
//定义状态机的状态
代码中使用case语句的状态机 同时也使用分模块相连接
localparam
WAIT_CONST
= 3'b000,
//等待脉冲
START_CONVST
= 3'b001,
//开始转换
WAIT_BUSY
= 3'b010,
//等待忙碌
READ_DATA
= 3'b011,
//读数据
CONVST_FINISH
= 3'b100,
//数据转换完成
ADC_RESET
= 3'b101;
//数据复位
localparam
RD_PULSE_WIDTH
= 4'd10;
//读脉冲宽度
parameter SCLK_count_value = 8'd128;
reg
[7 : 0]
cnvt_cntr
;
reg
[15 : 0]
busy_cntr
;
reg [3:0]
rd_cntr
;
reg
[8:0] sclk_cntr
;
reg
[127:0]
AD_DB_info;
reg[7:0]cntr;
reg [3:0]OS_cntr;
always @(posedge clk2 or negedge nRst)
begin
if(!nRst)
begin
OS <= 3'b111;
OS_cntr <= 0;
end
else
begin
OS <= 3'b001;
if(AD_BUSY ==0)
begin
if(OS_cntr < 4)
begin
OS_cntr <= OS_cntr + 1'b1;
OS <= 3'b001;
end
else
//
if(OS_cntr == 4)
begin
//
OS_cntr <= 0;
OS <= 3'b111;
end
end
else
begin
OS <= 3'b001;
OS_cntr <= 0;
end
end
end
wire posedge_AD_BUSY;
wire negedge_AD_BUSY;
reg AD_BUSY_buf1;
reg AD_BUSY_buf2;
/************************AD_BUSY上升沿的产生**************************/
always @(negedge clk2)
begin
AD_BUSY_buf1 <= AD_BUSY;
AD_BUSY_buf2 <= AD_BUSY_buf1;
end
assign negedge_AD_BUSY = AD_BUSY_buf2 && (!AD_BUSY_buf1);
//下降沿
assign posedge_AD_BUSY = (!AD_BUSY_buf2) && AD_BUSY_buf1;
//上升沿
always @ (posedge clk2
or negedge nRst)
//
rd_cntr
begin
if(!nRst)
rd_cntr <= 4'd0;
else
begin
if(current_adc_state == WAIT_CONST)
begin
if(rd_cntr < 4'd4)
rd_cntr <= rd_cntr + 4'd1;
else rd_cntr <= 4'd0;
end
else;
end
end
always @ (posedge clk2
or negedge nRst)
//
sclk_cntr
begin
if(!nRst)
sclk_cntr <= 4'd0;
else if(current_adc_state == READ_DATA)
//判断状态机状态是否在读数据
begin
if(sclk_cntr == (RD_PULSE_WIDTH - 1))
//从0累加到9
sclk_cntr <= 4'd0;
else
sclk_cntr <= sclk_cntr + 4'd1;
end
else sclk_cntr <= 9'd0;
end
/**************结合上面程序 产生AD_SCL脉冲******************/
always @ (posedge clk2
or negedge nRst)
//
AD_SCLK 当rd_cntr = 5时 AD_SCLK = 1 也就是说片选为高电平
begin
if(!nRst)
AD_SCLK <= 1'b1;
else
begin
if(current_adc_state == READ_DATA && AD_CS == 0)
//
在读状态
begin
if(sclk_cntr == 0)
AD_SCLK <= 1'b0;
else if(sclk_cntr == RD_PULSE_WIDTH / 2)
AD_SCLK <= 1'b1;
else;
end
else
AD_SCLK <= 1'b1;
end
end
always @ (posedge clk2
or negedge nRst)
begin
if(!nRst)
cntr <= 0;
else
if(current_adc_state == READ_DATA && AD_CS == 0 )
//
在读状态
begin
if(sclk_cntr == RD_PULSE_WIDTH / 2)
cntr <= cntr + 1;
else ;
end
else
cntr <= 0;
end
always @ (posedge clk2
or negedge nRst)//AD_CS
begin
if(!nRst)
AD_CS <= 1;
else
begin
if(current_adc_state == WAIT_BUSY || current_adc_state == READ_DATA)
begin
//
if(negedge_AD_BUSY == 1 && AD_Convst == 1'b1)//&& CS_cntr < 9'd400)
AD_CS <= 0;
//
else;
end
else
AD_CS <= 1;
end
end
always @ (posedge clk2
or negedge nRst)//
cnvt_cntr 仅是START_CONVST 外部累加到cnvt_cntr = 10 转换到下一状态的过程
begin
if(!nRst)
cnvt_cntr <= 8'd0;
else
begin
if(current_adc_state == START_CONVST)
cnvt_cntr <= cnvt_cntr + 4'd1;
else
cnvt_cntr <= 8'd0;
end
end
always @ (posedge clk2
or negedge nRst)//
busy_cntr 跟上述情况一样 是一个计数累加 转换到下一状态的过程
对应WAIT_BUSY
begin
if(!nRst)
busy_cntr <= 16'd0;
else
begin
if(current_adc_state == WAIT_BUSY)
busy_cntr <= busy_cntr + 16'd1;
else
busy_cntr <= 16'd0;
end
end
always @ (posedge clk2
or negedge nRst)//(posedge ClkIn
or negedge nRst)
//
rst_cntr 累加的过程 等待
begin
if(!nRst)
begin
rst_cntr <= 4'd0;
AD_Rst <= 1'b0;
end
else
if(current_adc_state == ADC_RESET)
begin
//
if(rst_cntr < 4'd8)
if(rst_cntr < 4'd15)
begin
AD_Rst <= 1'b1;
rst_cntr <= rst_cntr + 4'd1;
end
else
rst_cntr <= rst_cntr;
end
else
begin
rst_cntr <= 4'd0;
AD_Rst <= 1'b0;
end
end
always @ (posedge clk2
or negedge nRst)//
adc_state
begin
if(!nRst)
current_adc_state <= ADC_RESET;
else
begin
case(current_adc_state)
WAIT_CONST://0
begin
if(rd_cntr == 4'd3)
current_adc_state <= START_CONVST;
else
current_adc_state <= WAIT_CONST;
end
START_CONVST://1
begin
if(cnvt_cntr <= (CNVT_WIDTH - 8'd1))
current_adc_state <= START_CONVST;
else
current_adc_state <= WAIT_BUSY;
end
WAIT_BUSY://2
begin
if(busy_cntr < (BUSY_WIDTH - 16'd1))
current_adc_state <= WAIT_BUSY;
else
current_adc_state <= READ_DATA;
end
READ_DATA://3
begin
if(cntr == 128)
current_adc_state <= CONVST_FINISH;
else
current_adc_state <= READ_DATA;
end
CONVST_FINISH://4
begin
if(convertoverflag)
current_adc_state <= ADC_RESET;
else current_adc_state <= CONVST_FINISH;
end
ADC_RESET://5
begin
//
if(rst_cntr == 4'd7)
if(rst_cntr == 4'd14)
current_adc_state <= WAIT_CONST;
else
current_adc_state <= ADC_RESET;
end
default:
current_adc_state <= ADC_RESET;
endcase
end
end
always @ (posedge clk2
or negedge nRst)//
AD_Convst
begin
if(!nRst)
AD_Convst <= 1'b1;
else
begin
if(current_adc_state == START_CONVST)
AD_Convst <= 1'b0;
else
AD_Convst <= 1'b1;
end
end
always @ (posedge clk2
or negedge nRst)//
begin
if(!nRst)
begin
Ch0SampleData[15:0] <= 16'd0;
Ch1SampleData[15:0] <= 16'd0;
Ch2SampleData[15:0] <= 16'd0;
Ch3SampleData[15:0] <= 16'd0;
Ch4SampleData[15:0] <= 16'd0;
Ch5SampleData[15:0] <= 16'd0;
Ch6SampleData[15:0] <= 16'd0;
Ch7SampleData[15:0] <= 16'd0;
convertoverflag<=0;
AD_DB_info[127:0] <= 0;
end
else
begin
case (current_adc_state)
WAIT_BUSY:
begin
AD_DB_info[127:0] <= 0;
end
READ_DATA:
begin
convertoverflag<=0;
if((sclk_cntr == RD_PULSE_WIDTH / 2 - 1) && cntr < 128 && AD_CS == 0)
AD_DB_info[127:0] <= {AD_DB_info[126:0],AD_DB};
else
AD_DB_info[127:0]<=AD_DB_info[127:0];
end
CONVST_FINISH:
begin
Ch0SampleData[15:0] <= AD_DB_info[127:112];
Ch1SampleData[15:0] <= AD_DB_info[111:96];
Ch2SampleData[15:0] <= AD_DB_info[95:80];
Ch3SampleData[15:0] <= AD_DB_info[79:64];
Ch4SampleData[15:0] <= AD_DB_info[63:48];
Ch5SampleData[15:0] <= AD_DB_info[47:32];
Ch6SampleData[15:0] <= AD_DB_info[31:16];
Ch7SampleData[15:0] <= AD_DB_info[15:0];
convertoverflag<=1;
end
default:
AD_DB_info[127:0] <= 0;
endcase
end
end
endmodule