您的位置:首页 > 其它

FPGA的AD芯片驱动

2013-06-01 22:44 423 查看

FPGA的AD芯片驱动

(2012-08-19 15:37:02)


转载▼


标签:

fpga

ad芯片驱动

it

分类: FPGA学习笔记
//2012年8月18日

//AD芯片驱动//作者:泪与汗的缠绵
module adc_ctrl(
clk,rst_n,
adc_data,adc_cs_n,adc_clk,
sys_cs_n,sys_rd_n,sys_rddata
);
input clk; //50MHz
input rst_n; //低电平复位信号

input adc_data; //TLC549数据信号
output adc_cs_n; //TLC549片选信号,低电平有效
output adc_clk; //TLC549时钟信号

input sys_cs_n; //总线读片选,低电平有效
input sys_rd_n; //总线读使能信号,低电平有效
output[7:0] sys_rddata; //总线读取数据

//---------------------------------------------------
//定时计数逻辑
reg[5:0] cntus; //1us计数器

always @(posedge clk or negedge rst_n)
if(!rst_n) cntus <= 6'd0;
else if((cntus < 6'd49) && (cstate != IDLE)) cntus <= cntus+1'b1;
else cntus <= 6'd0;

wire dchag_flag = (cntus == 6'd0); //ADC时钟下降沿标志位,高有效一个时钟周期
wire dlock_flag = (cntus == 6'd24); //ADC时钟上升沿标志位,高有效一个时钟周期

//---------------------------------------------------
//ADC工作状态机
parameter IDLE = 3'd0,
TSUDL = 3'd1,
START = 3'd2,
DTRAN = 3'd3,
STOP = 3'd4,
TWHDL = 3'd5;

reg[2:0] bitnum; //采样数据位寄存器7-0
reg[4:0] d17uscnt; //Twh延时计数器
reg[7:0] adc_dinr; //模数转换数据寄存器
reg[7:0] adc_dinlock; //模数转换数据寄存器,实时锁存
reg[2:0] cstate,nstate; //状态寄存器

//状态迁移
always @(posedge clk or negedge rst_n)
if(!rst_n) cstate <= IDLE;
else cstate <= nstate;

//数据采集位寄存器控制
always @(posedge clk or negedge rst_n)
if(!rst_n) bitnum <= 3'd0;
else if(nstate == IDLE) bitnum <= 3'd7;
else if((nstate == DTRAN) && dlock_flag) bitnum <= bitnum-1'b1;

//Twh延时计数器控制
always @(posedge clk or negedge rst_n)
if(!rst_n) d17uscnt <= 5'd0;
else if((nstate == TWHDL) && dchag_flag) d17uscnt <= d17uscnt+1'b1;
else if(nstate == IDLE) d17uscnt <= 5'd0;

//状态控制
always @(cstate or dchag_flag or bitnum or d17uscnt)
case(cstate)
IDLE: nstate <= TSUDL;
TSUDL: if(dchag_flag) nstate <= START;
else nstate <= TSUDL;
START: if(dchag_flag) nstate <= DTRAN;
else nstate <= START;
DTRAN: if(dchag_flag && (bitnum == 3'd7)) nstate <= STOP;
else nstate <= DTRAN;
STOP: if(dchag_flag) nstate <= TWHDL;
else nstate <= STOP;
TWHDL: if(dchag_flag && (d17uscnt == 5'd18)) nstate <= IDLE;
else nstate <= TWHDL;
default: nstate <= IDLE;
endcase

//数据锁存
always @(posedge clk or negedge rst_n)
if(!rst_n) adc_dinlock <= 8'h00;
else if((nstate == DTRAN) && dlock_flag) adc_dinlock[bitnum] <= adc_data; //数据锁存

always @(posedge clk or negedge rst_n)
if(!rst_n) adc_dinr <= 8'h00;
else if((nstate == STOP) && sys_rdcs_n) adc_dinr <= adc_dinlock;

assign adc_cs_n = ~((cstate == DTRAN) | (cstate == START) | (cstate == TSUDL));

//---------------------------------------------------
//时钟速率控制,1MHz
reg adc_clkr; //TLC549时钟信号寄存器

always @(posedge clk or negedge rst_n)
if(!rst_n) adc_clkr <= 1'b0;
else if((nstate == DTRAN) && (cntus > 5'd12)) adc_clkr <= 1'b1;
else adc_clkr <= 1'b0;

assign adc_clk = adc_clkr;

//---------------------------------------------------
//Avalon-MM接口逻辑
wire sys_rdcs_n = sys_cs_n | sys_rd_n;

reg sys_dlink; //数据输出控制,高电平有效

always @(posedge clk or negedge rst_n)
if(!rst_n) sys_dlink <= 1'b1;
else sys_dlink <= sys_rdcs_n; //锁存读片选译码

assign sys_rddata = sys_dlink ? 8'hzz:adc_dinr;

endmodule
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: