forked from tanchou/Verilog
142 lines
5.1 KiB
Coq
142 lines
5.1 KiB
Coq
|
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
|