📄 ds1631control.v
字号:
module 1631Control(clk,rst,ReadT,SCL,SDA,SegEn,SegData,key_row_low);
input clk,rst;
output SCL;//I2C时钟线
inout SDA;//I2C数据线
input ReadT;//读温度命令
output key_row_low; //输出一个低电平给矩阵键盘的某一行
output[7:0] SegEn; //数码管使能
output[7:0] SegData;//数码管数据
reg SCL;
reg[7:0] SegEn;
reg[7:0] SegData;
reg[3:0] dataout_code; //每一个数码管的显示数值,0~F
//reg[7:0] seg_data_buf;
reg[15:0] cnt_scan;
reg sda_buf;//sda输入输出数据缓存
reg link; //sda输出标志
reg phase0,phase1,phase2,phase3;//一个scl时钟周期的四个相位阶段,将一个scl周期分为4段
//phase0对应scl的上升沿时刻,phase2对应scl的下降沿时刻,phase1对应从scl高电平的中间时刻,phase3对应从scl低电平的中间时刻,
reg[7:0] clk_div;//分频计数器
reg[1:0] main_state;
reg[2:0] i2c_state;//对i2c操作的状态
reg[3:0] inner_state;//i2c每一操作阶段内部状态
reg[19:0] cnt_delay;//按键延时计数器
reg start_delaycnt;//按键延时开始
reg[7:0] readMSData_reg;//读回高8位数据的寄存器
reg[7:0] readLSData_reg;//读回低8位数据的寄存器
/*用于显示十进制温度数据*/
reg[3:0] baiwei; //十进制数百位
reg[3:0] shiwei;
reg[3:0] gewei;
reg[3:0] xiao1;
reg[3:0] xiao2;
reg[3:0] xiao3;
reg[3:0] xiao4;
parameter div_parameter=100;// 分频系数,AT24C02最大支持400K时钟速率
/****************SDA内部状态*******************/
parameter start=4'b0000, //开始
first=4'b0001, //第1位
second=4'b0010,//第2位
third=4'b0011, //第3位
fourth=4'b0100, //第4位
fifth=4'b0101, //第5位
sixth=4'b0110, //第6位
seventh=4'b0111, //第7位
eighth=4'b1000, //第8位
ack=4'b1001, //确认位
stop=4'b1010; //结束位
/****************I2C总线工作状态****************/
parameter ini=3'b000, //初始化状态
sendaddr=3'b001, //发送地址状态
write_data=3'b010, //写数据状态
read_ms_data=3'b011, //读高8位数据状态
read_ls_data=3'b100, //读低8位数据状态
read_ini=6'b101; //发送读信息状态
assign key_row_low=0;
assign SDA=(link)? sda_buf:1'bz;
//assign seg_data_buf = readData_reg;
//按键延时处理
always@(posedge clk or negedge rst)
begin
if(!rst)
cnt_delay<=0;
else begin
if(start_delaycnt) begin
if(cnt_delay!=20'd800000)
cnt_delay<=cnt_delay+1;
else
cnt_delay<=0;
end
end
end
//scl时钟周期的四个相位生成
always@(posedge clk or negedge rst)
begin
if(!rst) begin
clk_div<=0;
phase0<=0;
phase1<=0;
phase2<=0;
phase3<=0;
end
else begin
if(clk_div!=div_parameter-1)
clk_div<=clk_div+1;
else
clk_div<=0;
if(phase0)
phase0<=0;
else if(clk_div==99)
phase0<=1;
if(phase1)
phase1<=0;
else if(clk_div==24)
phase1<=1;
if(phase2)
phase2<=0;
else if(clk_div==49)
phase2<=1;
if(phase3)
phase3<=0;
else if(clk_div==74)
phase3<=1;
end
end
//////////////读温度I2C控制时序SDA配置/////////////
always@(posedge clk or negedge rst)
begin
if(!rst) begin
start_delaycnt<=0;
main_state<=2'b00;
i2c_state<=ini;
inner_state<=start;
SCL<=1;
sda_buf<=1;
link<=0;
readMSData_reg<=0;
readLSData_reg<=0;
end
else begin
case(main_state)
/*************等待读写要求*************/
2'b00: begin
//writeData_reg<=data_in;
SCL<=1;
sda_buf<=1;
link<=0;
inner_state<=start;
i2c_state<=ini;
if(cnt_delay==0)
start_delaycnt<=1;
else if(cnt_delay==20'd800000) begin
start_delaycnt<=0;
main_state<=2'b01;
end
end
/*************读Temperature的SDA配置*************/
2'b01: begin
if(phase0)
SCL<=1;
else if(phase2)
SCL<=0;
case(i2c_state)
/*****初始化输出*****/
ini: begin
case(inner_state)
//配置启动,S=0
start: begin
if(phase1) begin
link<=1;
sda_buf<=0;
end
//配置8位写控制字节1001xxxW(xxx为芯片地址A2A1A0)
if(phase3&&link) begin
inner_state<=first;
sda_buf<=1; //第8位
link<=1;
end
end
first:
if(phase3) begin
sda_buf<=0; //第7位
link<=1;
inner_state<=second;
end
second:
if(phase3) begin
sda_buf<=0; //第6位
link<=1;
inner_state<=third;
end
third:
if(phase3) begin
sda_buf<=1; //第5位
link<=1;
inner_state<=fourth;
end
fourth:
if(phase3) begin
sda_buf<=0; //A2
link<=1;
inner_state<=fifth;
end
fifth:
if(phase3) begin
sda_buf<=0; //A1
link<=1;
inner_state<=sixth;
end
sixth:
if(phase3) begin
sda_buf<=0; //A0
link<=1;
inner_state<=seventh;
end
seventh:
if(phase3) begin
sda_buf<=0; //W=0,写
link<=1;
inner_state<=eighth;
end
//接收芯片应答,ACK
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
ack: begin
if(phase0)
sda_buf<=SDA; //接收应答
if(phase1) begin
if(sda_buf==1)
main_state<=2'b00;
end
if(phase3) begin
link<=1;
sda_buf<=1; //命令字节第8位
inner_state<=first;
i2c_state<=sendaddr;
end
end
endcase
end
/*****命令字节输出*****/
sendaddr: begin //
case(inner_state)
//配置命令字节,读温度为10101010
first:
if(phase3) begin
link<=1;
sda_buf<=0; //第7位
inner_state<=second;
end
second:
if(phase3) begin
link<=1;
sda_buf<=1; //第6位
inner_state<=third;
end
third:
if(phase3) begin
link<=1;
sda_buf<=0; //第5位
inner_state<=fourth;
end
fourth:
if(phase3) begin
link<=1;
sda_buf<=1; //第4位
inner_state<=fifth;
end
fifth:
if(phase3) begin
link<=1;
sda_buf<=0; //第3位
inner_state<=sixth;
end
sixth:
if(phase3) begin
link<=1;
sda_buf<=1; //第2位
inner_state<=seventh;
end
seventh:
if(phase3) begin
link<=1;
sda_buf<=0; //第1位
inner_state<=eighth;
end
//接收芯片应答,ACK
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
ack: begin
if(phase0)
sda_buf<=SDA; //接收应答
if(phase1) begin
if(sda_buf==1)
main_state<=2'b00;
end
if(phase3) begin
link<=1;
sda_buf<=1; //为下一个S启动信号准备高电平
inner_state<=start;
i2c_state<=read_ini;
end
end
endcase
end
/*****读数据请求输出*****/
read_ini: begin
case(inner_state)
//配置启动,S=0
start: begin
if(phase1) begin
link<=1;
sda_buf<=0;
end
//配置8位读控制字节1001xxxR*****/
if(phase3&&link) begin
inner_state<=first;
sda_buf<=1; //第8位
link<=1;
end
end
first:
if(phase3) begin
sda_buf<=0; //第7位
link<=1;
inner_state<=second;
end
second:
if(phase3) begin
sda_buf<=0; //第6位
link<=1;
inner_state<=third;
end
third:
if(phase3) begin
sda_buf<=1; //第5位
link<=1;
inner_state<=fourth;
end
fourth:
if(phase3) begin
sda_buf<=0; //A2
link<=1;
inner_state<=fifth;
end
fifth:
if(phase3) begin
sda_buf<=0; //A1
link<=1;
inner_state<=sixth;
end
sixth:
if(phase3) begin
sda_buf<=0; //A0
link<=1;
inner_state<=seventh;
end
seventh:
if(phase3) begin
sda_buf<=1; //R=1,读
link<=1;
inner_state<=eighth;
end
eighth:
if(phase3) begin
link<=0;
inner_state<=ack;
end
//接收芯片应答,ACK
ack: begin
if(phase0)
sda_buf<=SDA; //接收应答
if(phase1) begin
if(sda_buf==1)
main_state<=2'b00;
end
if(phase3) begin
link<=0;
inner_state<=first;
i2c_state<=read_ms_data;
end
end
endcase
end
/*****读高8位数据输入*****/
read_ms_data: begin
case(inner_state)
//从芯片读取高8位数据
first: begin
if(phase0)
sda_buf<=SDA;
if(phase1) begin
readMSData_reg[7:1]<=readMSData_reg[6:0];
readMSData_reg[0]<=SDA;
end
if(phase3)
inner_state<=second;
end
second: begin
if(phase0)
sda_buf<=SDA;
if(phase1) begin
readMSData_reg[7:1]<=readMSData_reg[6:0];
readMSData_reg[0]<=SDA;
end
if(phase3)
inner_state<=third;
end
third: begin
if(phase0)
sda_buf<=SDA;
if(phase1) begin
readMSData_reg[7:1]<=readMSData_reg[6:0];
readMSData_reg[0]<=SDA;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -