欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  互联网

DHT11之Verilog 驱动代码

程序员文章站 2022-03-11 09:11:16
测试平台:Vivado 2018.3+Xilinx XC7A35TFGG484-2关于DHT11时序,优缺点网上很多,就不说了.话不多说了,直接上代码:代码有不懂的地方欢迎与我交流.微信1247652780// -----------------------------------------------------------------------------// Copyright (c) 2014-2020 All rights reserved// ----------------...

测试平台: 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

板级验证:
DHT11之Verilog 驱动代码

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

相关标签: FPGA verilog