//addr=4 濕度高8位
//addr=3 濕度低8位
//addr=2 溫度高8位
//addr=1 溫度低8位
//addr=0 校驗和8位 (該地址讀取后啟動溫濕度轉換)
module DHT22 (sys_clk, IO_port, nReset, nCS, nOE, addr, busy, data);
input sys_clk; //系統時鐘 1Mhz
input nCS, nOE, nReset; //芯片選擇|讀取資料|芯片復位
input [2:0] addr; //資料高低8位選擇
inout IO_port; //DHT資料引腳
output [7:0] data; //8位資料雙向總線
output busy; //正在讀取中
wire CHIP_RST;
tri1 IO_port;
//date介面濾波變數
reg F_OUT; //濾波后的IO-clk
//芯片復位
reg RST;
//開始復位DHT22資料
reg R_FIN; //復位完成
reg IO_OUT; //復位埠
//準備讀取DHT22資料
reg read_enable; //準備讀取DHT22資料
//位讀取保持
reg Read_Begin;
//資料位計數
reg [5:0] read_clk_count; //IO讀取時鐘計數器(狀態時序)
reg in_rdy; //讀取完成
//位讀取時鐘生成
reg read_pulse; //位讀取脈沖
//開始讀取DHT22資料介面時序行程
reg [39:0] in_buff; //讀取資料緩沖
//選擇資料位
reg [7:0] select_bit;
initial //上電初始化內部暫存器
begin
in_rdy <= 0;
RST <= 0;
read_pulse <= 0;
Read_Begin <= 0;
R_FIN <= 0;
IO_OUT <= 0;
end
assign data = (!nOE && !nCS)? select_bit : 8'bz; //三態8位資料總線,外部讀取PS2資料
assign IO_port = (IO_OUT)? 1'b0 : 1'bz;
assign busy = read_enable ;
assign CHIP_RST = ~nReset | RST;
//選擇資料位
always
begin : select
case (addr) /* synthesis full_case */
3'd0:
begin
select_bit[7:0] = in_buff[7:0];
end
3'd1:
begin
select_bit[7:0] = in_buff[15:8];
end
3'd2:
begin
select_bit[7:0] = in_buff[23:16];
end
3'd3:
begin
select_bit[7:0] = in_buff[31:24];
end
3'd4:
begin
select_bit[7:0] = in_buff[39:32];
end
endcase
end
//IO介面濾波
always @(posedge sys_clk or negedge nReset)
begin: Filter
reg [1:0] IOdat_s; //采樣計數器
if (!nReset) begin
IOdat_s <= 2'b0;
F_OUT <= 1'b1;
end
else begin
if (F_OUT != IO_port) begin //檢測data時鐘跳變
if (IOdat_s == 2'd3) begin //3次采樣ps_clk
F_OUT <= IO_port;
IOdat_s <= 0;
end
else begin
IOdat_s = IOdat_s + 2'b1;
end
end
else begin
IOdat_s <= 0;
end
end
end
//芯片復位
always @(nOE)
begin : C_RST
if ((addr == 3'd0) && !nCS && !nOE) begin
RST <= 1;
end
else begin
RST <= 0;
end
end
//準備讀取DHT22資料
always @(negedge nReset or negedge nOE or posedge in_rdy)
begin : read_first
if (in_rdy || !nReset) begin
read_enable <= 1'b0;
end
else begin
if ((addr == 3'd0) && !nCS && !in_rdy) begin
read_enable <= 1'b1;
end
end
end
//開始復位DHT22資料時序行程
always @(posedge sys_clk or posedge CHIP_RST or negedge read_enable)
begin: ResetPort
reg [8:0] R_TIM; //復位時間
if (CHIP_RST || !read_enable) begin
R_TIM <= 0;
R_FIN <= 0;
IO_OUT <= 0;
end
else begin
if (!R_FIN) begin
R_TIM <= R_TIM + 9'd1;
if (R_TIM==9'd510) begin
R_FIN <= 1;
IO_OUT <= 0;
end
else begin
IO_OUT <= 1;
end
end
end
end
//位讀取保持
always @(posedge F_OUT or posedge read_pulse or posedge CHIP_RST)
begin : Read_keep
if (read_pulse || CHIP_RST) begin
Read_Begin <= 0;
end
else begin
if (read_clk_count>1 && read_clk_count<42) begin
Read_Begin <= 1;
end
else Read_Begin <= 0;
end
end
//位讀取時鐘生成
always @(posedge sys_clk)
begin : Read_clk
reg [5:0] sc;
read_pulse <= 0;
if (CHIP_RST) sc <= 0;
else if (Read_Begin && read_enable) begin
if (sc<6'd40) sc <= sc + 6'b1;
else read_pulse <= 1;
end
else begin
sc <= 0;
end
end
//資料位計數
always @(posedge F_OUT or negedge read_enable or posedge CHIP_RST)
begin: bit_count
if (!read_enable || CHIP_RST) begin
read_clk_count <= 0;
in_rdy <= 0;
end
else begin
read_clk_count <= read_clk_count + 6'd1;
if (read_clk_count > 6'd41) in_rdy <= 1;
end
end
//開始讀取DHT22資料介面時序行程
always @(posedge read_pulse or negedge nReset)
begin: ReadIOData
if (!nReset) in_buff = 0;
else begin
in_buff[39:1] <= in_buff[38:0];
in_buff[0] <= F_OUT;
end
end
endmodule
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/125502.html
標籤:其他硬件開發
