module dht11_interface #( parameter CLK_FREQ = 27_000_000 )( input wire i_clk, inout wire io_dht11_sig, input wire i_start, output reg o_dht11_data_ready, output reg o_busy, output reg [7:0] o_temp_data, output reg [7:0] o_hum_data, output reg o_dht11_error ); // === DHT11 INTERFACE === // === PARAMÈTRES === 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_26US = CLK_FREQ * 26 / 1_000_000; localparam T_20US = CLK_FREQ * 20 / 1_000_000; // === 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; // === FSM === 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_BITS_LOW = 4'd5, READ_BITS_HIGH = 4'd6, DONE = 4'd7, ERROR = 4'd8; // === 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 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 // Code a testé ici pour etre sur de capter le dernier bit 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