1
0
forked from tanchou/Verilog
Files
Verilog_Louis/Semaine_6/DHT11/src/verilog/dht11_model.v

142 lines
5.1 KiB
Coq
Raw Normal View History

module dht11_model (
inout wire data, // Ligne de données bidirectionnelle
input wire clk, // Horloge système (50 MHz)
input wire rst_n // Reset actif bas
);
// Paramètres pour les timings (basés sur une horloge de 50 MHz, période 20 ns)
localparam CLK_FREQ = 50_000_000; // 50 MHz
localparam START_LOW_TIME = 18_000 / 20; // 18 ms pour le signal de démarrage
localparam START_HIGH_TIME = 40_000 / 20; // 20-40 µs pour le relâchement
localparam RESPONSE_LOW = 80_000 / 20; // 80 µs pour la réponse basse
localparam RESPONSE_HIGH = 80_000 / 20; // 80 µs pour la réponse haute
localparam BIT0_LOW = 50_000 / 20; // 50 µs pour bit '0'
localparam BIT1_LOW = 70_000 / 20; // 70 µs pour bit '1'
localparam DATA_BITS = 40; // 40 bits de données
// États de la machine à états
localparam IDLE = 3'd0,
START = 3'd1,
RESPONSE = 3'd2,
SEND_DATA = 3'd3,
ENDED = 3'd4;
reg [2:0] state, next_state;
reg [15:0] counter; // Compteur pour les timings
reg [5:0] bit_index; // Index du bit à envoyer
reg data_out; // Valeur de sortie sur la ligne data
reg data_oe; // Contrôle de l'output enable (1 = sortie, 0 = haute impédance)
wire data_in; // Valeur lue sur la ligne data
// Données simulées (exemple : humidité = 45.0%, température = 23.0°C)
reg [7:0] humidity_int = 8'h2D; // 45 en décimal
reg [7:0] humidity_dec = 8'h00; // 0
reg [7:0] temp_int = 8'h17; // 23 en décimal
reg [7:0] temp_dec = 8'h00; // 0
reg [7:0] checksum; // Checksum = sum des 4 octets
reg [39:0] data_shift; // Registre pour les 40 bits de données
// Gestion de la ligne bidirectionnelle
assign data = data_oe ? data_out : 1'bz;
assign data_in = data;
// Calcul du checksum
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
checksum <= 8'h00;
end else begin
checksum <= humidity_int + humidity_dec + temp_int + temp_dec;
end
end
// Concaténation des données à envoyer
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_shift <= 40'b0;
end else begin
data_shift <= {humidity_int, humidity_dec, temp_int, temp_dec, checksum};
end
end
// Machine à états
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
counter <= 16'b0;
bit_index <= 6'b0;
data_out <= 1'b1;
data_oe <= 1'b0;
end else begin
state <= next_state;
case (state)
IDLE: begin
counter <= 16'b0;
bit_index <= 6'b0;
data_out <= 1'b1;
data_oe <= 1'b0;
end
START: begin
counter <= counter + 1;
data_out <= 1'b0;
data_oe <= 1'b1;
end
RESPONSE: begin
counter <= counter + 1;
if (counter < RESPONSE_LOW) begin
data_out <= 1'b0;
data_oe <= 1'b1;
end else begin
data_out <= 1'b1;
data_oe <= 1'b1;
end
end
SEND_DATA: begin
counter <= counter + 1;
if (counter == 0) begin
data_out <= 1'b0; // Début du bit (toujours bas)
data_oe <= 1'b1;
end else if (counter == (data_shift[39-bit_index] ? BIT1_LOW : BIT0_LOW)) begin
data_out <= 1'b1; // Fin du bit
data_oe <= 1'b1;
end else if (counter >= (data_shift[39-bit_index] ? BIT1_LOW + 50 : BIT0_LOW + 50)) begin
counter <= 16'b0;
bit_index <= bit_index + 1;
end
end
ENDED: begin
data_out <= 1'b1;
data_oe <= 1'b0;
counter <= 16'b0;
end
endcase
end
end
// Logique de transition des états
always @(*) begin
next_state = state;
case (state)
IDLE: begin
if (data_in == 1'b0) // Détection du signal de démarrage
next_state = START;
end
START: begin
if (counter >= START_LOW_TIME && data_in == 1'b1)
next_state = RESPONSE;
end
RESPONSE: begin
if (counter >= RESPONSE_LOW + RESPONSE_HIGH)
next_state = SEND_DATA;
end
SEND_DATA: begin
if (bit_index >= DATA_BITS)
next_state = ENDED;
end
ENDED: begin
next_state = IDLE;
end
endcase
end
endmodule