DHT11之Verilog 驱动代码

测试平台: Vivado 2018.3+Xilinx XC7A35TFGG484-2
关于DHT11时序,优缺点网上很多,就不说了.
话不多说了,直接上代码:
代码有不懂的地方欢迎与我交流.微信1247652780

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang e-mail:1247652780@qq.com
// File : dht11.v
// Create : 2020-12-12 21:04:12
// Revise : 2020-12-13 10:45:10
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
module dht11(
input	wire			clk,//100MHz
input	wire			rst,
input	wire			start,
inout	wire			data_io,
output	reg				vld_falg,
output	reg		[7:0]	himi,
output	reg		[7:0]	temp
);
parameter	START_MAX 	=2000000-1;
parameter	RESP_MAX  	=8200-1;
parameter	LOW_MIN	  	=2200-1;
parameter	LOW_MAX	  	=2800-1;
parameter	HIGH_MIN	=6700-1;
parameter	HIGH_MAX	=7500-1;
parameter	END_MAX		=5300-1;
parameter	IDLE	=5'b00_001;
parameter	START	=5'b00_010;
parameter	RESP	=5'b00_100;
parameter	RECE	=5'b01_000;
parameter	END 	=5'b10_000;
reg	[4:0]	state;	
reg	[1:0]	data_dly;
reg			pos_flag;
reg			neg_flag;
reg	[21:0]	level_cnt;
reg	[5:0]	bit_cnt;
reg	[42:0]	data_temp;
reg			oe;
reg			data_o;
reg			check_ok;
always @(posedge clk) begin
if (rst) begin
oe<=1'b0;
end
else if(state==START)begin
oe<=1'b1;
end
else begin
oe<=1'b0;
end
end
assign data_io = (oe==1'b1)?data_o:1'bz;
always @(posedge clk) begin
if (rst) begin
data_o<=1'b1;
end
else if (state==START && level_cnt==START_MAX) begin
data_o<=1'b1;
end
else if (state==START) begin
data_o<=1'b0;
end
end
always @(posedge clk) begin
data_dly<={ data_dly[0],data_io};
end
always @(*) begin
if(data_dly==2'b10)begin
neg_flag =1'b1;
end
else begin
neg_flag =1'b0;
end
end
always @(*) begin
if(data_dly==2'b01)begin
pos_flag =1'b1;
end
else begin
pos_flag =1'b0;
end
end
//state
always @(posedge clk) begin
if (rst) begin
state<=IDLE;
end
else  begin
case(state)
IDLE:begin
if(start==1'b1)begin
state<=START;
end
end
START:begin
if(level_cnt == START_MAX)begin
state<=RESP;
end
end
RESP:begin
if(pos_flag==1'b1 && level_cnt > RESP_MAX)begin
state<=RECE;
end
end
RECE:begin
if(bit_cnt=='d41)begin
state<=END;
end
end
END:begin
if(pos_flag==1'b1 && level_cnt > END_MAX)begin
state<=IDLE;
end
end
default:state<=IDLE;
endcase
end
end
//low_cnt
always @(posedge clk) begin
if (rst) begin
level_cnt<='d0;
end
else begin
case(state)
START:begin
if(level_cnt==START_MAX)begin
level_cnt<='d0;
end
else if(data_o==1'b0)begin
level_cnt<=level_cnt+1'b1;
end
end
RESP:begin
if(pos_flag==1'b1)begin
level_cnt<='d0;
end
else if(data_dly[1]==1'b0)begin
level_cnt<=level_cnt+1'b1;
end
end
RECE:begin
if(neg_flag==1'b1)begin
level_cnt<='d0;
end
else if(data_dly[1]==1'b1)begin
level_cnt<=level_cnt+1'b1;
end
end
END:begin
if(pos_flag==1'b1)begin
level_cnt<='d0;
end
else if(data_dly[1]==1'b0)begin
level_cnt<=level_cnt+1'b1;
end
end
default:level_cnt<='d0;
endcase
end
end
//bit_cnt
always @(posedge clk) begin
if (rst) begin
bit_cnt<='d0;
end
else if(state!=RECE)begin
bit_cnt<='d0;
end
else if (state==RECE && neg_flag==1'b1 && level_cnt > LOW_MIN) begin
bit_cnt<= bit_cnt+1'b1;
end
end
//data_temp
always @(posedge clk) begin
if (rst) begin
data_temp<='d0;
end
else if(state==RECE && neg_flag==1'b1 && level_cnt > LOW_MIN && level_cnt < LOW_MAX ) begin
data_temp<={ data_temp[38:0],1'b0};
end
else if(state==RECE && neg_flag==1'b1 && level_cnt > HIGH_MIN && level_cnt < HIGH_MAX )begin
data_temp<={ data_temp[38:0],1'b1};
end
end
//check_ok
always @(posedge clk) begin
if (rst) begin
check_ok<=1'b0;
end
else if (state==END) begin
check_ok<=({ data_temp[39:32]+data_temp[15:8]+data_temp[23:16]+data_temp[31:24]}==data_temp[7:0])?1'b1:1'b0;
end
else begin
check_ok<=1'b0;
end
end
//himi
always @(posedge clk) begin
if (rst) begin
himi<='d0;
end
else if (state==END && pos_flag==1'b1) begin
himi<= (data_temp[42:36]<<3) +(data_temp[40:36]<<1)+data_temp[35:32];
end
end
//temp
always @(posedge clk) begin
if (rst) begin
temp<='d0;
end
else if (state==END && pos_flag==1'b1 && data_temp[15]==1'b0) begin
temp<= (data_temp[26:20]<<3)+(data_temp[24:20]<<1)+data_temp[19:16];
end
else if (state==END && pos_flag==1'b1 && data_temp[15]==1'b1) begin
temp[6:0]	<= ~((data_temp[26:20]<<3)+(data_temp[24:20]<<1)+data_temp[19:16])+1'b1;
temp[7]		<= 1'b1;
end
end
//vld_falg
always @(posedge clk) begin
if (rst) begin
vld_falg<=1'b0;
end
else if (state==END && pos_flag==1'b1) begin
vld_falg<=1'b1;
end
else begin
vld_falg<=1'b0;
end
end
endmodule 

下面为顶层:

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang e-mail:1247652780@qq.com
// File : top_dht11.v
// Create : 2020-12-12 21:03:56
// Revise : 2020-12-12 22:54:08
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
module top_dht11(
input	wire		clk,//50MHz
input	wire		rst_n,//active low
inout	wire		data_io//data input/output
);
parameter	TIME_MAX = 200000000-1;//2s ==need more than 2s
reg			start;//signal of start =2s
wire		vld_falg;//valid data flag
wire[7:0]	himi;//data of humidity
wire[7:0]	temp;//data of temperature
reg	[31:0]	time_cnt;//timer for 2s
wire sclk;
wire	rst;
assign rst = ~rst_n;
gen_clk100 inst_gen_clk100(
// Clock out ports
.clk_100m(sclk),     // output clk_100m
// Clock in ports
.clk_in1(clk)
);      // input clk_in1
always @(posedge sclk) begin
if (rst) begin
time_cnt<='d0;
end
else if (time_cnt==TIME_MAX) begin
time_cnt<='d0;
end
else begin
time_cnt<=time_cnt+1'b1;
end
end
always @(posedge sclk) begin
if (rst) begin
start<=1'b0;
end
else if (time_cnt==TIME_MAX) begin
start<=1'b1;
end
else begin
start<=1'b0;
end
end
dht11  inst_dht11 (
.clk      (sclk),
.rst      (rst),//active high
.start    (start),
.data_io  (data_io),
.vld_falg (vld_falg),
.himi     (himi),
.temp     (temp)
);
wire [127:0] probe0;
assign  probe0 ={ 
start,
time_cnt,
vld_falg,
himi,
temp
} ;
ila_0 ila_0_inst (
.clk(sclk), // input wire sclk
.probe0(probe0) // input wire [31:0] probe0
);
endmodule

最后为testbench:

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2020 All rights reserved
// -----------------------------------------------------------------------------
// Author : zhufu.liang e-mail:1247652780@qq.com
// File : tb_dht11.v
// Create : 2020-12-12 21:04:19
// Revise : 2020-12-12 21:04:21
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale 1ns/1ns
module tb_dht11 (); /* this is automatically generated */
reg 		clk;
reg			start;
reg       	data_io_r;
wand		data_io;
wire       	vld_falg;
wire [7:0] 	himi;
wire [7:0] 	temp;
// clock
initial begin
clk = 0;
forever #(5) clk = ~clk;
end
// synchronous reset
reg       	rst;
initial begin
start=0;
data_io_r=1;
rst <= 1;
repeat(100)@(posedge clk)
rst <= 0;
#100;
gen_data(32'h33005500);
@(negedge vld_falg);
#1000;
gen_data(32'h77004480);
@(negedge vld_falg);
#1000;
gen_data(32'h88006680);
@(negedge vld_falg);
#10000;
$stop;
end
assign data_io = data_io_r;
dht11 inst_dht11(
.clk      (clk),
.rst      (rst),
.start	  (start),
.data_io  (data_io),
.vld_falg (vld_falg),
.himi     (himi),
.temp     (temp)
);
task gen_data;
input [31:0] data;
integer i;
reg	[7:0]	check_sum;
reg	[39:0]	temp;
reg	[21:0]	tiem_cnt;
begin
check_sum={ data[7:0]+data[15:8]+data[23:16]+data[31:24]};
temp={ data,check_sum};
start=0;
tiem_cnt=0;
#10;
start=1;
#10;
start=0;
@(negedge data_io)
@(posedge data_io)
data_io_r=1;
#13_000;
data_io_r=0;
#83_000;
data_io_r=1;
#87_000;
for(i=0;i<40;i=i+1)begin
data_io_r=0;
#54_000;
if(temp[39])begin
data_io_r=1;
#71_000;
end
else begin
data_io_r=1;
#24_000;
end
temp=temp<<1;
end
data_io_r=0;
#54_000;
data_io_r=1;
end
endtask
endmodule

板级验证:

本文地址:https://blog.csdn.net/quanqiuying33/article/details/111089643

(0)
上一篇 2022年3月22日
下一篇 2022年3月22日

相关推荐