`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 2016/3/1
// Design Name:
// Module Name: sht20
// Project Name:
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module sht20(
inputclk,
inputrst_n,
outputreg[7:0] t_msb,
outputreg[7:0] t_lsb, //read 8-bits data from sht20
output readfinish,
inouti2c_sda, //I2C data
inout i2c_scl //I2C clk 125K
);
/////////////////////////////////////////////////////////////////////////////////////状态参数
parameter idle_state = 'd0;
parameter start_state = 'd1;
parameter address_write_state = 'd2;
parameter wait_ack1_state = 'd3;
parameter wait_ack2_state = 'd4;
parameter wait_ack3_state = 'd5;
parameter command_send_state = 'd6;
parameter address_read_state = 'd7;
parameter hold_state = 'd8;
parameter data_msb_state = 'd9;
parameter ack_state = 'd10;
parameter data_lsb_state = 'd11;
parameter nack_state = 'd12;
parameter stop_state = 'd13;
/////////////////////////////////////////////////////////////////////////////////////////////获取高低电平中点,上升沿,下降沿
reg [7:0] delay_time;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
delay_time <= 'd0;
else if(delay_time == 'd199)
delay_time <= 'd0;
else
delay_time <= delay_time +1'b1;
end
reg [2:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 3'd5;
else
case(delay_time)
8'd49: cnt <= 3'd1;//高电平中间
8'd99: cnt <= 3'd2;//下降沿
8'd149:cnt <= 3'd3;//低电平中间
8'd199:cnt <= 3'd0;//上升沿
default: cnt <= 3'd5;
endcase
end
`define SCL_HIG (cnt == 3'd1)
`define SCL_NEG (cnt == 3'd2)
`define SCL_LOW (cnt == 3'd3)
`define SCL_POS (cnt == 3'd0)
/////////////////////////////////////////////////////////////////////////////////////////////定时1s测一次温度
reg [25:0] timer_cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
timer_cnt <= 26'd0;
else if(timer_cnt == 26'd49999999)
timer_cnt <= 26'd0;
else
timer_cnt <= timer_cnt + 1'b1;
end
//////////////////////////////////////////////////////////////////////////////////////////////for test
reg readfinish_reg;
assign readfinish = readfinish_reg;
/////////////////////////////////////////////////////////////////////////////////////////////sda输出寄存器
reg i2c_sda_reg;
reg sda_link;
assign i2c_sda = sda_link ? i2c_sda_reg : 1'bz;
//////////////////////////////////////////////////////////////////////////////////////////////scl输出寄存器
reg i2c_scl_reg;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
i2c_scl_reg <= 1'b0;
else if(`SCL_POS)
i2c_scl_reg <= 1'b1;
else if(`SCL_NEG)
i2c_scl_reg <= 1'b0;
end
reg scl_link;
assign i2c_scl = scl_link ? i2c_scl_reg : 1'bz;
///////////////////////////////////////////////////////////////////////////////////////////data输出寄存器
reg [7:0] t_msb_reg;
reg [7:0] t_lsb_reg;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
t_msb <= 8'd0;
t_lsb <= 8'd0;
end
else
begin
t_msb <= t_msb_reg;
t_lsb <= t_lsb_reg;
end
end
///////////////////////////////////////////////////////////////////////////////////////////状态寄存器
reg [5:0] state;
/////////////////////////////////////////////////////////////////////////////////////////////bit位计数寄存器
reg [2:0] bit_counter;
/////////////////////////////////////////////////////////////////////////////////////////////待发送数据寄存器
reg [7:0] byte_to_send;
/////////////////////////////////////////////////////////////////////////////////////////////STATE状态机
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= idle_state;
sda_link <= 1'b1;
scl_link <= 1'b1;
i2c_sda_reg <= 1'b1;
bit_counter <= 'd0;
t_msb_reg <= 'd0;
t_lsb_reg <= 'd0;
byte_to_send <= 8'b00000000;
readfinish_reg <= 1'b0;/////////////////////////////////////////////////////////////////for test
end
else
case(state)
idle_state://stage = 1,
begin
sda_link <= 1'b1;
scl_link <= 1'b1;
i2c_sda_reg <= 1'b1; //sda置1 ,if no data transfer ,i2c data is 1
if(timer_cnt == 26'd49999999) //定时1S开始测量
begin
state <= start_state;
end
else
state <= idle_state;
end
start_state://stage = 2,
begin
if(`SCL_HIG)
begin
i2c_sda_reg <= 1'b0; //ic2 data pull down.mean begin to transfer data
sda_link <= 1'b1;
state = address_write_state;
byte_to_send <= 8'b10000000;
bit_counter <= 'd0;
end
else
state = start_state;
end
address_write_state://stage = 3,
begin
if(`SCL_LOW) //delay 4us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
sda_link <= 1'b0;
state <= wait_ack1_state;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= address_write_state;
end
end
else
state <= address_write_state;
end
wait_ack1_state://stage=4
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= command_send_state;
byte_to_send = 8'b11100011;
sda_link <= 1'b1;
end
else //if no receice ack signal , means communication is wrong , back to idle state
state <= idle_state;
end
else
state <= wait_ack1_state;
end
command_send_state://stage = 5,
begin
if(`SCL_LOW) //delay 4us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
state <= wait_ack2_state;
sda_link <= 1'b0;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= command_send_state;
end
end
else
state <= command_send_state;
end
wait_ack2_state://stage=6
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= address_read_state;
byte_to_send <= 8'b10000001;
sda_link <= 1'b1;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
state <= idle_state;
end
end
else
state <= wait_ack2_state;
end
address_read_state://stage = 7,
begin
if(`SCL_LOW) //delay 8us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
state <= wait_ack3_state;
sda_link <= 1'b0;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= address_read_state;
end
end
else
state <= address_read_state;
end
wait_ack3_state://stage=8
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= hold_state;
scl_link <= 1'b0;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
state <= idle_state;
end
end
else
state <= wait_ack3_state;
end
hold_state:// stage=9
begin
if(`SCL_HIG)
begin
if(i2c_scl) //receive measurement finish signal
begin
state <= data_msb_state;
scl_link <= 1'b1;
end
else
state <= hold_state;
end
else
state <= hold_state;
end
data_msb_state://stage = 10,
begin
if(`SCL_HIG)
begin
bit_counter <= bit_counter + 1'b1;
t_msb_reg <= {t_msb_reg[6:0],i2c_sda};
state <= data_msb_state;
end
else if((bit_counter == 8)&&(`SCL_NEG)) //read_8-bits data
begin
bit_counter <= 'd0;
state <= ack_state;
sda_link <= 1'b1;
end
else
state <= data_msb_state;
end
ack_state://stage = 11,
begin
if(`SCL_LOW)
i2c_sda_reg <= 1'b0;
else if(`SCL_NEG)
begin
state <= data_lsb_state;
sda_link <= 1'b0;
end
else
state <= ack_state;
end
data_lsb_state://stage = 12
begin
if(`SCL_HIG)
begin
bit_counter <= bit_counter + 1'b1;
t_lsb_reg <= {t_lsb_reg[6:0],i2c_sda};
state <= data_lsb_state;
end
else if((bit_counter == 8)&&(`SCL_NEG)) //read_8-bits data
begin
bit_counter <= 'd0;
state <= nack_state;
sda_link <= 1'b1;
end
else
state <= data_lsb_state;
end
nack_state://stage = 13
begin
if(`SCL_LOW)
i2c_sda_reg <= 1'b1;
else if(`SCL_NEG)
begin
state <= stop_state;
sda_link <= 1'b1;
i2c_sda_reg <= 1'b0;
end
else
state <= nack_state;
end
stop_state://stage = 14
begin
if(`SCL_HIG)
begin
i2c_sda_reg <= 1'b1;
state <= idle_state;
readfinish_reg <= 1'b1;///////////////////////////////////////////////////////////for test
end
else
state <= stop_state;
end
default:
state <= idle_state;
endcase
end
endmodule
//////////////////////////////////////////////////////////////////////////////////
// Create Date: 2016/3/1
// Design Name:
// Module Name: sht20
// Project Name:
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module sht20(
inputclk,
inputrst_n,
outputreg[7:0] t_msb,
outputreg[7:0] t_lsb, //read 8-bits data from sht20
output readfinish,
inouti2c_sda, //I2C data
inout i2c_scl //I2C clk 125K
);
/////////////////////////////////////////////////////////////////////////////////////状态参数
parameter idle_state = 'd0;
parameter start_state = 'd1;
parameter address_write_state = 'd2;
parameter wait_ack1_state = 'd3;
parameter wait_ack2_state = 'd4;
parameter wait_ack3_state = 'd5;
parameter command_send_state = 'd6;
parameter address_read_state = 'd7;
parameter hold_state = 'd8;
parameter data_msb_state = 'd9;
parameter ack_state = 'd10;
parameter data_lsb_state = 'd11;
parameter nack_state = 'd12;
parameter stop_state = 'd13;
/////////////////////////////////////////////////////////////////////////////////////////////获取高低电平中点,上升沿,下降沿
reg [7:0] delay_time;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
delay_time <= 'd0;
else if(delay_time == 'd199)
delay_time <= 'd0;
else
delay_time <= delay_time +1'b1;
end
reg [2:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 3'd5;
else
case(delay_time)
8'd49: cnt <= 3'd1;//高电平中间
8'd99: cnt <= 3'd2;//下降沿
8'd149:cnt <= 3'd3;//低电平中间
8'd199:cnt <= 3'd0;//上升沿
default: cnt <= 3'd5;
endcase
end
`define SCL_HIG (cnt == 3'd1)
`define SCL_NEG (cnt == 3'd2)
`define SCL_LOW (cnt == 3'd3)
`define SCL_POS (cnt == 3'd0)
/////////////////////////////////////////////////////////////////////////////////////////////定时1s测一次温度
reg [25:0] timer_cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
timer_cnt <= 26'd0;
else if(timer_cnt == 26'd49999999)
timer_cnt <= 26'd0;
else
timer_cnt <= timer_cnt + 1'b1;
end
//////////////////////////////////////////////////////////////////////////////////////////////for test
reg readfinish_reg;
assign readfinish = readfinish_reg;
/////////////////////////////////////////////////////////////////////////////////////////////sda输出寄存器
reg i2c_sda_reg;
reg sda_link;
assign i2c_sda = sda_link ? i2c_sda_reg : 1'bz;
//////////////////////////////////////////////////////////////////////////////////////////////scl输出寄存器
reg i2c_scl_reg;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
i2c_scl_reg <= 1'b0;
else if(`SCL_POS)
i2c_scl_reg <= 1'b1;
else if(`SCL_NEG)
i2c_scl_reg <= 1'b0;
end
reg scl_link;
assign i2c_scl = scl_link ? i2c_scl_reg : 1'bz;
///////////////////////////////////////////////////////////////////////////////////////////data输出寄存器
reg [7:0] t_msb_reg;
reg [7:0] t_lsb_reg;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
t_msb <= 8'd0;
t_lsb <= 8'd0;
end
else
begin
t_msb <= t_msb_reg;
t_lsb <= t_lsb_reg;
end
end
///////////////////////////////////////////////////////////////////////////////////////////状态寄存器
reg [5:0] state;
/////////////////////////////////////////////////////////////////////////////////////////////bit位计数寄存器
reg [2:0] bit_counter;
/////////////////////////////////////////////////////////////////////////////////////////////待发送数据寄存器
reg [7:0] byte_to_send;
/////////////////////////////////////////////////////////////////////////////////////////////STATE状态机
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= idle_state;
sda_link <= 1'b1;
scl_link <= 1'b1;
i2c_sda_reg <= 1'b1;
bit_counter <= 'd0;
t_msb_reg <= 'd0;
t_lsb_reg <= 'd0;
byte_to_send <= 8'b00000000;
readfinish_reg <= 1'b0;/////////////////////////////////////////////////////////////////for test
end
else
case(state)
idle_state://stage = 1,
begin
sda_link <= 1'b1;
scl_link <= 1'b1;
i2c_sda_reg <= 1'b1; //sda置1 ,if no data transfer ,i2c data is 1
if(timer_cnt == 26'd49999999) //定时1S开始测量
begin
state <= start_state;
end
else
state <= idle_state;
end
start_state://stage = 2,
begin
if(`SCL_HIG)
begin
i2c_sda_reg <= 1'b0; //ic2 data pull down.mean begin to transfer data
sda_link <= 1'b1;
state = address_write_state;
byte_to_send <= 8'b10000000;
bit_counter <= 'd0;
end
else
state = start_state;
end
address_write_state://stage = 3,
begin
if(`SCL_LOW) //delay 4us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
sda_link <= 1'b0;
state <= wait_ack1_state;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= address_write_state;
end
end
else
state <= address_write_state;
end
wait_ack1_state://stage=4
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= command_send_state;
byte_to_send = 8'b11100011;
sda_link <= 1'b1;
end
else //if no receice ack signal , means communication is wrong , back to idle state
state <= idle_state;
end
else
state <= wait_ack1_state;
end
command_send_state://stage = 5,
begin
if(`SCL_LOW) //delay 4us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
state <= wait_ack2_state;
sda_link <= 1'b0;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= command_send_state;
end
end
else
state <= command_send_state;
end
wait_ack2_state://stage=6
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= address_read_state;
byte_to_send <= 8'b10000001;
sda_link <= 1'b1;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
state <= idle_state;
end
end
else
state <= wait_ack2_state;
end
address_read_state://stage = 7,
begin
if(`SCL_LOW) //delay 8us , 1-bits data transfer finish
begin
if(bit_counter == 8) //send_8-bits data finish
begin
bit_counter <= 'd0;
state <= wait_ack3_state;
sda_link <= 1'b0;
i2c_sda_reg <= 1'b1;//8位数据传输结束
end
else
begin
bit_counter <= bit_counter + 1'b1;
i2c_sda_reg <= byte_to_send[7-bit_counter];
state <= address_read_state;
end
end
else
state <= address_read_state;
end
wait_ack3_state://stage=8
begin
if(`SCL_HIG)
begin
if(!i2c_sda) //receive ack signal
begin
state <= hold_state;
scl_link <= 1'b0;
end
else //if no receice ack signal , means communication is wrong , back to idle state
begin
state <= idle_state;
end
end
else
state <= wait_ack3_state;
end
hold_state:// stage=9
begin
if(`SCL_HIG)
begin
if(i2c_scl) //receive measurement finish signal
begin
state <= data_msb_state;
scl_link <= 1'b1;
end
else
state <= hold_state;
end
else
state <= hold_state;
end
data_msb_state://stage = 10,
begin
if(`SCL_HIG)
begin
bit_counter <= bit_counter + 1'b1;
t_msb_reg <= {t_msb_reg[6:0],i2c_sda};
state <= data_msb_state;
end
else if((bit_counter == 8)&&(`SCL_NEG)) //read_8-bits data
begin
bit_counter <= 'd0;
state <= ack_state;
sda_link <= 1'b1;
end
else
state <= data_msb_state;
end
ack_state://stage = 11,
begin
if(`SCL_LOW)
i2c_sda_reg <= 1'b0;
else if(`SCL_NEG)
begin
state <= data_lsb_state;
sda_link <= 1'b0;
end
else
state <= ack_state;
end
data_lsb_state://stage = 12
begin
if(`SCL_HIG)
begin
bit_counter <= bit_counter + 1'b1;
t_lsb_reg <= {t_lsb_reg[6:0],i2c_sda};
state <= data_lsb_state;
end
else if((bit_counter == 8)&&(`SCL_NEG)) //read_8-bits data
begin
bit_counter <= 'd0;
state <= nack_state;
sda_link <= 1'b1;
end
else
state <= data_lsb_state;
end
nack_state://stage = 13
begin
if(`SCL_LOW)
i2c_sda_reg <= 1'b1;
else if(`SCL_NEG)
begin
state <= stop_state;
sda_link <= 1'b1;
i2c_sda_reg <= 1'b0;
end
else
state <= nack_state;
end
stop_state://stage = 14
begin
if(`SCL_HIG)
begin
i2c_sda_reg <= 1'b1;
state <= idle_state;
readfinish_reg <= 1'b1;///////////////////////////////////////////////////////////for test
end
else
state <= stop_state;
end
default:
state <= idle_state;
endcase
end
endmodule