本帖最后由 小雨也倾盆 于 2015-4-7 16:45 编辑
module ad_ctr(
clk,rst_n,adc_in1,adc_in2,
scl,sda,sys_rddata,
);
input clk; // 50MHz
input rst_n; //复位信号,低有效
output scl;
inout sda;
output[7:0] sys_rddata; //总线读取数据
input adc_in1;
input adc_in2;
//--------------------------------------------
//---------------------------------------------
//分频部分
reg[2:0] cnt; // cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间
reg[8:0] cnt_delay; //500循环计数,产生iic所需要的时钟
reg scl_r; //时钟脉冲寄存器
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt_delay <= 9'd0;
else if(cnt_delay == 9'd499) cnt_delay <= 9'd0; //计数到10us为scl的周期,即100KHz
else cnt_delay <= cnt_delay+1'b1; //时钟计数
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) cnt <= 3'd5;
else begin
case (cnt_delay)
9'd124: cnt <= 3'd1; //cnt=1:scl高电平中间,用于数据采样
9'd249: cnt <= 3'd2; //cnt=2:scl下降沿
9'd374: cnt <= 3'd3; //cnt=3:scl低电平中间,用于数据变化
9'd499: cnt <= 3'd0; //cnt=0:scl上升沿
default: cnt <= 3'd5;
endcase
end
end
`define SCL_POS (cnt==3'd0) //cnt=0:scl上升沿
`define SCL_HIG (cnt==3'd1) //cnt=1:scl高电平中间,用于数据采样
`define SCL_NEG (cnt==3'd2) //cnt=2:scl下降沿
`define SCL_LOW (cnt==3'd3) //cnt=3:scl低电平中间,用于数据变化
always @ (posedge clk or negedge rst_n)
if(!rst_n) scl_r <= 1'b0;
else if(cnt==3'd0) scl_r <= 1'b1; //scl信号上升沿
else if(cnt==3'd2) scl_r <= 1'b0; //scl信号下降沿
assign scl = scl_r; //产生iic所需要的时钟
//---------------------------------------------
//需要写入24C02的地址和数据
`define ADDRESS1 8'b1001_0000 //被寻址器件地址(写操作)
`define CONTROLBYTE 8'b0100_0101 //控制字
`define ADDRESS2 8'b1001_0001 //被寻址器件地址(读操作)
reg[7:0] adc_din;
reg[4:0] cstate;
reg[4:0] nstate;
reg[2:0] bitnum; //采样数据位寄存器7-0
//数据锁存
always @(posedge clk or negedge rst_n)
if(!rst_n) adc_din <= 8'h00;
else if (nstate == DATA1) sys_rddata[bitnum] <= adc_in1; //数据锁存
always @(posedge clk or negedge rst_n)
if(!rst_n) adc_din <= 8'h00;
else if(nstate == DATA2) sys_rddata[bitnum] <= adc_in2; //数据锁存
reg[7:0] db_r;
reg[7:0] adc_data; //模数转换数据寄存器
reg[7:0] CONTROLBYTE;
//reg[7:0] DATA11;
//reg[7:0] DATA22;
//---------------------------------------------
//读、写时序
parameter IDLE = 4'd0;
parameter START1 = 4'd1;
parameter ADD1 = 4'd2;
parameter ACK1 = 4'd3;
parameter CONTROL= 4'd4;
parameter ACK2 = 4'd5;
parameter STOP1 = 4'd6;
parameter START2 = 4'd7;
parameter ADD2 = 4'd8;
parameter ACK3 = 4'd9;
parameter DATA1 = 4'd10;
parameter ACK4 = 4'd11;
parameter DATA2 = 4'd12;
parameter ACK5 = 4'd13;
parameter STOP2 = 4'd14;
reg sda_r; //输出数据寄存器
reg sda_link; //输出数据sda信号inout方向控制位
//reg[3:0] num; //
always @(posedge clk or negedge rst_n)
if(!rst_n) cstate <= IDLE;
else cstate <= nstate;
//IIC状态转换控制
always @(cstate or `SCL_HIG or `SCL_LOW or bcnt) begin
case(cstate)
IDLE: if(!rst_n) nstate <= IDLE;
else nstate <= START1;
START1: if(`SCL_HIG) nstate <= ADD1;
else nstate <= START;
ADD1: if(`SCL_LOW && bcnt == 3'd0) nstate <= ACK1;
else nstate <= ADDR;
ACK1: if(`SCL_LOW) nstate <= CONTROL;
else nstate <= ACK1;
CONTROL: if(`SCL_LOW && bcnt == 3'd0) nstate <= ACK2;
else nstate <= CONTROL;
ACK2: if(`SCL_LOW) nstate <= STOP1;
else nstate <= ACK2;
STOP1: if(`SCL_HIG) nstate <= START2;
else nstate <= STOP1;
START2: if(`SCL_LOW) nstate <= ADD2;
else nstate <= START2;
ADD2: if(`SCL_LOW) nstate <= ACK3;
else nstate <= ADD2;
ACK3: if(`SCL_LOW) nstate <= ADTA1;
else nstate <= ACK3;
DATA1: if (`SCL_LOW && bcnt == 3'd0) nstate <= ACK4;
else nstate <= DATA1;
ACK4: if(`SCL_LOW) nstate <=DATA2;
else natate <= ACK4;
DATA2: if(`SCL_LOW && bcnt == 3'd0) nstate <= ACK5;
else nstate <= DATA2;
ACK5: if(`SCL_LOW) nstate <= STOP2;
else nstate <= ACK5;
STOP2: if(`SCL_HIG) nstate <= IDLE;
else nstate <= STOP2;
default: nstate <= IDLE;
endcase
end
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
sdar = 1'b1;
sdlink = 1'b1;
end
else begin
case (cstate)
IDLE: begin
sda_link <= 1'b1; //数据线sda为output
sda_r <= 1'b1;
end
START1:
if(`SCL_HIG) begin //scl为高电平期间
sda_link <= 1'b1; //数据线sda为output
sda_r <= 1'b0; //拉低数据线sda,产生起始位信号
end
ADD1: //自我感觉这里不对,应该是
if(`SCL_LOW) begin
sda_r <= ADD1[bcut];
sda_link <= 1'b1; //数据线sda为output
end
ACK1: begin
if(`SCL_LOW) begin
sda_r <= 1'b0;
sda_link <= 1'b0; //数据线sda为input
end
CONTROL:
if(`SCL_LOW) begin
sdar <= CONTROLBYTE[bcnt]; //依次发送地址bit7-0
sdlink <= 1'b1; //sda输出
end
ACK2:
if(`SCL_LOW) begin
sda_r <= 1'b0;
sda_link <= 1'b0; //数据线sda为input
end
STOP1:
if(`SCL_HIG) begin
sda_link <= 1'b1;
sda_r <= 1'b1;
end
START2:
if(`SCL_HIG) begin //scl为高电平期间
sda_link <= 1'b1; //数据线sda为output
sda_r <= 1'b0; //拉低数据线sda,产生起始位信号
end
ADD2:
if(`SCL_LOW) begin
sda_r <= ADD2[bcut];
sda_link <= 1'b1; //数据线sda为output
end
ACK3:
if(`SCL_LOW) begin
sda_r <= 1'b0;
sda_link <= 1'b0; //数据线sda为input
end
DATA1: if(scl_low) begin
sdar <= sys_rddata[bcnt]; //
sdlink <= 1'b0; //sda输入
end
ACK4: if(scl_low) begin
sdar <= 1'b0;
sdlink <= 1'b0; //sda输入input
end
DATA2: if(scl_low) begin
sdar <= sys_rddata[bcnt]; //送LSB/invalid字节
sdlink <= 1'b0; //sda输入
end
ACK5: if(scl_low) begin
sdar <= 1'b0;
sdlink <= 1'b0; //sda输入
end
STOP2: if(`SCL_HIG) begin
sdar <= 1'b1;
sdlink <= 1'b1; //sda输出
end
default: ;
endcase
end
always @(posedge clk or negedge rst_n)
if(!rst_n) bcnt <= 3'd0;
else begin
case(cstate)
ADD1,ADD2,CONTROL,DATA1,DATA2: begin
if(scl_low) bcnt <= bcnt-1'b1; //bit7-0
else ;
end
default: bcnt <= 3'd7;
endcase
end
assign sda = sdlink ? sdar : 1'bz ; //SDA输入输出控制逻辑 1为输出 0为输入
endmodule
file:///C:UsersAdministratorAppDataRoamingTencentUsers571815206QQWinTempRichOle16B_OCA3(`THAMBQY)H`_81.png
-
一周热门 更多>