From 2a153aa1eb9fa588092bbbe8c8c8c8ca6c267b50 Mon Sep 17 00:00:00 2001 From: Gamenight77 Date: Wed, 14 May 2025 10:27:46 +0200 Subject: [PATCH] Enhance DHT11 interface: add start signal and busy output, improve FSM for better data handling --- Semaine_5/DHT11/src/verilog/dht11_interface.v | 207 ++++++++++++++++-- 1 file changed, 191 insertions(+), 16 deletions(-) diff --git a/Semaine_5/DHT11/src/verilog/dht11_interface.v b/Semaine_5/DHT11/src/verilog/dht11_interface.v index 70dd045..ec1116c 100644 --- a/Semaine_5/DHT11/src/verilog/dht11_interface.v +++ b/Semaine_5/DHT11/src/verilog/dht11_interface.v @@ -1,35 +1,210 @@ module dht11_interface ( input wire i_clk, // 27 MHz inout wire io_dht11_sig, + input wire i_start, output wire o_dht11_data_ready, + output wire o_busy, output wire [7:0] o_temp_data, output wire [7:0] o_hum_data, output wire o_dht11_error ); // === DHT11 INTERFACE === - // Le module DHT11 est connecté à la broche io_dht11_sig. - // La communication se fait en mode bidirectionnel. - wire sig_dir; - wire sig_out; + // === PARAMÈTRES === + parameter CLK_FREQ = 27_000_000; + localparam T_18MS = CLK_FREQ * 18 / 1000; // cycles pour 18ms + localparam T_80US = CLK_FREQ * 81 / 1_000_000; + localparam T_79US = CLK_FREQ * 79 / 1_000_000; + localparam T_71US = CLK_FREQ * 71 / 1_000_000; + localparam T_51US = CLK_FREQ * 51 / 1_000_000; + localparam T_50US = CLK_FREQ * 50 / 1_000_000; + localparam T_49US = CLK_FREQ * 49 / 1_000_000; + localparam T_40US = CLK_FREQ * 40 / 1_000_000; + localparam T_28US = CLK_FREQ * 28 / 1_000_000; + localparam T_20US = CLK_FREQ * 20 / 1_000_000; - assign io_dht11_sig = sig_dir ? sig_out : 1'bz; + // === Signal bidirectionnel === + reg sig_dir; + reg sig_out; + wire 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 sig_in = io_dht11_sig; + + // === REGISTRES === + reg [3:0] state; + 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 [5:0] bit_index; + reg [39:0] raw_data; + + // === INITIALISATION === + initial begin + sig_dir = 0; + sig_out = 1; + timer = 0; + state = IDLE; + bit_index = 0; + raw_data = 0; + o_dht11_data_ready = 0; + o_dht11_error = 0; + end // === FSM === - localparam IDLE = 3'd0, // Pull up la ligne + localparam IDLE = 4'd0, // Pull up la ligne + START = 4'd1, // Pull low 18ms + WAIT_RESPONSE = 4'd2, // Release la ligne (entre 20 et 40us) + RESPONSE_LOW = 4'd3, // DHT11 pull low 80us + RESPONSE_HIGH = 4'd4, // DHT11 pull high 80us + READ_READ_BITS_LOW = 4'd5, + READ_READ_BITS_HIGH = 4'd6, + DONE = 4'd7, + ERROR = 4'd8; - START = 3'd1, // Pull low 18ms - WAIT_RESPONSE = 3'd2, // Release la ligne (entre 20 et 40us) - - READ_HUM_INT = 3'd3, - READ_HUM_DEC = 3'd4; - READ_TEMP_INT = 3'd5, - READ_TEMP_DEC = 3'd6, - READ_CHECKSUM = 3'd7, // Last 8 bits of {1st Byte + 2nd Byte + 3rd Byte+ 4th Byte} - - DONE = 3'd8; + // === FSM principale === + always @(posedge i_clk) begin + case (state) + + IDLE: begin + sig_dir <= 0; + sig_out <= 1; + timer <= 0; + bit_index <= 0; + raw_data <= 0; + + o_busy <= 0; + + if (i_start) begin + sig_dir <= 1; + sig_out <= 0; + timer <= 0; + o_busy <= 1; + state <= START; + o_dht11_data_ready <= 0; + o_dht11_error <= 0; + end + end + + START: begin + timer <= timer + 1; + if (timer >= T_18MS) begin + sig_dir <= 0; // libérer la ligne + timer <= 0; + state <= WAIT_RESPONSE; + end + end + + WAIT_RESPONSE: begin + timer <= timer + 1; + if (sig_in == 0) begin + if (timer > T_20US && timer < T_40US) begin + timer <= 0; + state <= RESPONSE_LOW; + end else begin + state <= ERROR; + end + end else if (timer > T_40US) begin + state <= ERROR; + end + end + + RESPONSE_LOW: begin + timer <= timer + 1; + + if (sig_in == 1) begin + if (timer > T_79US && timer < T_80US) begin + timer <= 0; + state <= RESPONSE_HIGH; + end else begin + state <= ERROR; + end + end else if (timer > T_80US) begin + state <= ERROR; + end + end + + RESPONSE_HIGH: begin + timer <= timer + 1; + + if (sig_in == 0) begin + if (timer > T_79US && timer < T_80US) begin + timer <= 0; + state <= READ_BITS_LOW; + end else begin + state <= ERROR; + end + end else if (timer > T_80US) begin + state <= ERROR; + end + end + + READ_BITS_LOW: begin + timer <= timer + 1; + if (sig_in == 1) begin + if (timer > T_49US && timer < T_51US) begin + timer <= 0; + state <= READ_BITS_HIGH; + end else begin + state <= ERROR; + end + end else if (timer > T_28US) begin + state <= ERROR; + end + end + + READ_BITS_HIGH: begin // entre 26 et 28us = 0 et ~70us = 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 + timer <= 0; + bit_index <= bit_index + 1; + + if (bit_index == 39) begin + state <= DONE; + end else begin + state <= READ_BITS_LOW; + end + + end else if (timer > T_71US) begin + state <= ERROR; + end + end + + DONE: begin + hum_data <= raw_data[39:32]; + hum_dec <= raw_data[31:24]; + temp_data <= raw_data[23:16]; + temp_dec <= raw_data[15:8]; + checksum <= raw_data[7:0]; + + if (checksum == (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; + state <= IDLE; + end + + ERROR: begin + o_dht11_error <= 1; + state <= IDLE; + end + + endcase + end endmodule