1
0
forked from tanchou/Verilog

Refactor DHT11 interface to support 16-bit temperature and humidity data, update checksum handling, and improve state machine logic

This commit is contained in:
Gamenight77
2025-05-27 13:34:59 +02:00
parent 286ba6b33c
commit 425cc8d00c
3 changed files with 71 additions and 95 deletions

View File

@@ -1,3 +1,4 @@
`default_nettype none
module dht11_interface #( module dht11_interface #(
parameter CLK_FREQ = 27_000_000 parameter CLK_FREQ = 27_000_000
)( )(
@@ -6,45 +7,46 @@ module dht11_interface #(
input wire i_start, input wire i_start,
output reg o_dht11_data_ready, output reg o_dht11_data_ready,
output reg o_busy, output reg o_busy,
output reg [7:0] o_temp_data, output reg [15:0] o_temp_data,
output reg [7:0] o_hum_data, output reg [15:0] o_hum_data,
output reg o_dht11_error output reg [7:0] o_checksum,
output reg [3:0] o_state
); );
// === DHT11 INTERFACE === // === DHT11 INTERFACE ===
// === PARAMÈTRES === // === PARAMÈTRES ===
localparam T_18MS = CLK_FREQ * 18 / 1_000; // cycles pour 18ms a partir localparam T_18MS = CLK_FREQ * 18 / 1_000; // cycles pour 18ms a partir
localparam T_80US = CLK_FREQ * 81 / 1_000_000; localparam T_80US = CLK_FREQ * 90 / 1_000_000;
localparam T_79US = CLK_FREQ * 79 / 1_000_000; localparam T_79US = CLK_FREQ * 70 / 1_000_000;
localparam T_71US = CLK_FREQ * 71 / 1_000_000; localparam T_71US = CLK_FREQ * 81 / 1_000_000;
localparam T_51US = CLK_FREQ * 51 / 1_000_000; localparam T_51US = CLK_FREQ * 58 / 1_000_000;
localparam T_50US = CLK_FREQ * 50 / 1_000_000; localparam T_50US = CLK_FREQ * 50 / 1_000_000;
localparam T_49US = CLK_FREQ * 49 / 1_000_000; localparam T_49US = CLK_FREQ * 49 / 1_000_000;
localparam T_41US = CLK_FREQ * 41 / 1_000_000; localparam T_40US = CLK_FREQ * 40 / 1_000_000;
localparam T_28US = CLK_FREQ * 28 / 1_000_000; localparam T_28US = CLK_FREQ * 32 / 1_000_000;
localparam T_26US = CLK_FREQ * 26 / 1_000_000; localparam T_26US = CLK_FREQ * 25 / 1_000_000;
localparam T_20US = CLK_FREQ * 20 / 1_000_000; localparam T_20US = CLK_FREQ * 18 / 1_000_000;
// === Signal bidirectionnel === // === Signal bidirectionnel ===
reg sig_dir; reg sig_dir;
reg sig_out; reg sig_out;
wire sig_in; reg sig_in;
assign io_dht11_sig = sig_dir ? sig_out : 1'bz; // Si sig_dir = 1, on force la valeur de sig_out sur la ligne, sinon on laisse la ligne libre (1'bz) assign io_dht11_sig = sig_dir ? sig_out : 1'bz; // Si sig_dir = 1, on force la valeur de sig_out sur la ligne, sinon on laisse la ligne libre (1'bz)
assign sig_in = io_dht11_sig;
// === REGISTRES === // === REGISTRES ===
reg [3:0] state; reg [3:0] state;
reg [31:0] timer; reg [31:0] timer;
reg [7:0] temp_data, hum_data;
reg [7:0] temp_dec, hum_dec, checksum;
reg [2:0] bit_count; reg [2:0] bit_count;
reg [5:0] bit_index; reg [5:0] bit_index;
reg [39:0] raw_data; reg [39:0] raw_data;
reg [15:0] checksum;
// === FSM === // === FSM ===
localparam IDLE = 4'd0, // Pull up la ligne localparam IDLE = 4'd0, // Pull up la ligne
START = 4'd1, // Pull low 18ms START = 4'd1, // Pull low 18ms
@@ -65,11 +67,11 @@ module dht11_interface #(
bit_index = 0; bit_index = 0;
raw_data = 0; raw_data = 0;
o_dht11_data_ready = 0; o_dht11_data_ready = 0;
o_dht11_error = 0;
end end
// === FSM principale === // === FSM principale ===
always @(posedge i_clk) begin always @(posedge i_clk) begin
sig_in <= io_dht11_sig;
case (state) case (state)
IDLE: begin IDLE: begin
@@ -88,7 +90,6 @@ module dht11_interface #(
o_busy <= 1; o_busy <= 1;
state <= START; state <= START;
o_dht11_data_ready <= 0; o_dht11_data_ready <= 0;
o_dht11_error <= 0;
end end
end end
@@ -102,112 +103,88 @@ module dht11_interface #(
end end
WAIT_RESPONSE: begin WAIT_RESPONSE: begin
o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 0) begin if (sig_in == 0 && timer > 1) begin
if (timer > T_20US && timer < T_41US) begin
state <= RESPONSE_LOW;
state <= RESPONSE_LOW; timer <= 0;
timer <= 0;
end else begin
state <= ERROR;
end
end else if (timer > T_41US) begin
state <= ERROR;
end end
end end
RESPONSE_LOW: begin RESPONSE_LOW: begin
o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 1) begin if (sig_in == 1) begin
if (timer > T_79US && timer < T_80US) begin
timer <= 0; timer <= 0;
state <= RESPONSE_HIGH; state <= RESPONSE_HIGH;
end else begin
state <= ERROR;
end
end else if (timer > T_80US) begin
state <= ERROR;
end end
end end
RESPONSE_HIGH: begin RESPONSE_HIGH: begin
timer <= timer + 1; timer <= timer + 1;
o_state <= state;
if (sig_in == 0) begin if (sig_in == 0) begin
if (timer > T_79US && timer < T_80US) begin
timer <= 0; timer <= 0;
state <= READ_BITS_LOW; state <= READ_BITS_LOW;
end else begin
state <= ERROR;
end
end else if (timer > T_80US) begin
state <= ERROR;
end end
end end
READ_BITS_LOW: begin READ_BITS_LOW: begin
o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 1) begin if (sig_in == 1) begin
if (timer > T_49US && timer < T_51US) begin timer <= 0;
timer <= 0; state <= READ_BITS_HIGH;
state <= READ_BITS_HIGH;
end else begin
state <= ERROR;
end
end else if (timer > T_51US) begin
state <= ERROR;
end end
end end
READ_BITS_HIGH: begin // entre 26 et 28us = 0 et ~70us = 1 READ_BITS_HIGH: begin // entre 26 et 28us = 0 et ~70us = 1
o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 0) begin
if (timer <= T_26US) begin
state <= ERROR;
end
raw_data <= {raw_data[38:0], (timer > T_28US)}; // 1 si high > ~28us if (sig_in == 0) begin
raw_data <= {raw_data[38:0], (timer > T_40US)};
timer <= 0; timer <= 0;
bit_index <= bit_index + 1; bit_index <= bit_index + 1;
if (bit_index == 39) begin // Code a testé ici pour etre sur de capter le dernier bit if (bit_index == 39) begin
state <= DONE; state <= DONE;
end else begin end else begin
state <= READ_BITS_LOW; state <= READ_BITS_LOW;
end end
end else if (timer > T_71US) begin
state <= ERROR;
end end
end end
DONE: begin DONE: begin
hum_data <= raw_data[39:32]; o_state <= state;
hum_dec <= raw_data[31:24];
temp_data <= raw_data[23:16]; o_hum_data <= raw_data[39:24];
temp_dec <= raw_data[15:8]; o_temp_data <= raw_data[23:8];
checksum <= raw_data[7:0]; o_checksum <= raw_data[7:0];
o_dht11_data_ready <= 1;
if (raw_data[7:0] == (raw_data[39:32] + raw_data[31:24] + raw_data[23:16] + raw_data[15:8])) begin
o_hum_data <= raw_data[39:32];
o_temp_data <= raw_data[23:16];
o_dht11_data_ready <= 1;
end else begin
o_dht11_error <= 1;
end
o_busy <= 0; o_busy <= 0;
state <= IDLE; state <= IDLE;
end end
ERROR: begin
o_dht11_error <= 1;
state <= IDLE;
end
endcase endcase
end end
always_comb begin
checksum = raw_data[39:32] + raw_data[31:24] + raw_data[23:16] + raw_data[15:8];
end
endmodule endmodule

View File

@@ -10,9 +10,9 @@ module tb_dht11;
reg dht11_start; reg dht11_start;
wire dht11_data_ready; wire dht11_data_ready;
wire dht11_busy; wire dht11_busy;
wire [7:0] dht11_temp_data; wire [15:0] dht11_temp_data;
wire [7:0] dht11_hum_data; wire [15:0] dht11_hum_data;
wire dht11_error; wire [7:0] o_checksum;
// === Simulation du module DHT11 === // === Simulation du module DHT11 ===
dht11_model dht11_model ( dht11_model dht11_model (
@@ -30,7 +30,7 @@ module tb_dht11;
.o_busy(dht11_busy), .o_busy(dht11_busy),
.o_temp_data(dht11_temp_data), .o_temp_data(dht11_temp_data),
.o_hum_data(dht11_hum_data), .o_hum_data(dht11_hum_data),
.o_dht11_error(dht11_error) .o_checksum(o_checksum)
); );
pullup(io_dht11_sig); pullup(io_dht11_sig);
@@ -55,8 +55,9 @@ module tb_dht11;
wait(dht11_data_ready); // Attend que les données soient prêtes wait(dht11_data_ready); // Attend que les données soient prêtes
$display("DHT11 data ready..."); $display("DHT11 data ready...");
$display("Température : %d.%d °C", dht11_temp_data); $display("Température : %d.%d °C", dht11_temp_data[15:8], dht11_temp_data[7:0]);
$display("Humidité : %d.%d %%", dht11_hum_data); $display("Humidité : %d.%d %%", dht11_hum_data[15:8], dht11_hum_data[7:0]);
$display("Checksum : %d", o_checksum);
$display("==== End DHT11 Test ===="); $display("==== End DHT11 Test ====");
$finish; $finish;

View File

@@ -1,3 +1,4 @@
`default_nettype none
module dht11_interface #( module dht11_interface #(
parameter CLK_FREQ = 27_000_000 parameter CLK_FREQ = 27_000_000
)( )(
@@ -66,7 +67,6 @@ module dht11_interface #(
bit_index = 0; bit_index = 0;
raw_data = 0; raw_data = 0;
o_dht11_data_ready = 0; o_dht11_data_ready = 0;
o_dht11_error = 0;
end end
// === FSM principale === // === FSM principale ===
@@ -90,7 +90,6 @@ module dht11_interface #(
o_busy <= 1; o_busy <= 1;
state <= START; state <= START;
o_dht11_data_ready <= 0; o_dht11_data_ready <= 0;
o_dht11_error <= 0;
end end
end end
@@ -108,10 +107,10 @@ module dht11_interface #(
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 0) begin if (sig_in == 0 && timer > 1) begin
state <= RESPONSE_LOW; state <= RESPONSE_LOW;
timer <= 0; timer <= 0;
end end
end end
@@ -122,8 +121,8 @@ module dht11_interface #(
if (sig_in == 1) begin if (sig_in == 1) begin
timer <= 0; timer <= 0;
state <= RESPONSE_HIGH; state <= RESPONSE_HIGH;
end end
end end
@@ -142,26 +141,25 @@ module dht11_interface #(
READ_BITS_LOW: begin READ_BITS_LOW: begin
o_state <= state; o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 1) begin if (sig_in == 1) begin
timer <= 0;
timer <= 0; state <= READ_BITS_HIGH;
state <= READ_BITS_HIGH;
end end
end end
READ_BITS_HIGH: begin // entre 26 et 28us = 0 et ~70us = 1 READ_BITS_HIGH: begin // entre 26 et 28us = 0 et ~70us = 1
o_state <= state; o_state <= state;
timer <= timer + 1; timer <= timer + 1;
if (sig_in == 0) begin if (sig_in == 0) begin
raw_data <= {raw_data[38:0], (timer > T_40US)}; raw_data <= {raw_data[38:0], (timer > T_40US)};
timer <= 0; timer <= 0;
bit_index <= bit_index + 1; bit_index <= bit_index + 1;
if (bit_index == 40) begin if (bit_index == 39) begin
state <= DONE; state <= DONE;
end else begin end else begin
state <= READ_BITS_LOW; state <= READ_BITS_LOW;