module ultrasonic_fpga #( parameter integer CLK_FREQ = 27_000_000 // Fréquence d'horloge en Hz )( input wire clk, input wire start, inout wire sig, // Broche bidirectionnelle vers le capteur output reg [15:0] distance, // Distance mesurée en cm output reg [2:0] state = IDLE ); reg [15:0] trig_counter; reg [31:0] echo_counter; reg [31:0] echo_div_counter; reg [15:0] distance_counter; reg sig_out; reg sig_dir; // 1: output, 0: input assign sig = sig_dir ? sig_out : 1'bz; // bz pour dire que le fpga laisse le fils libre et n'oblige pas de valeur reg sig_int, sig_ok; always_ff(@posedge clk) {sig_ok, sig_int} = {sig_int, sig}; localparam IDLE = 3'd0, TRIG_HIGH = 3'd1, TRIG_LOW = 3'd2, WAIT_ECHO = 3'd3, MEASURE_ECHO = 3'd4, DONE = 3'd5, WAIT_NEXT = 3'd6; localparam integer TRIG_PULSE_CYCLES = CLK_FREQ / 100_000; // 10us pulse localparam integer DIST_DIVISOR = (58 * CLK_FREQ) / 1_000_000; // pour conversion us -> cm localparam integer MAX_CM = 350; localparam integer TIMEOUT_CYCLES = (MAX_CM * 58 * CLK_FREQ) / 1_000_000; localparam WAIT_NEXT_CYCLES = (CLK_FREQ / 1000) * 100; // 60 ms reg [31:0] wait_counter; always @(posedge clk) begin // FSM case (state) IDLE: begin sig_out <= 0; sig_dir <= 1; distance <= 0; if (start) begin state <= TRIG_HIGH; trig_counter <= 0; end end TRIG_HIGH: begin sig_out <= 1; sig_dir <= 1; if (trig_counter < TRIG_PULSE_CYCLES) begin trig_counter <= trig_counter + 1; end else begin trig_counter <= 0; state <= TRIG_LOW; end end TRIG_LOW: begin sig_out <= 0; sig_dir <= 0; // Mettre en entrée state <= WAIT_ECHO; end WAIT_ECHO: begin if (sig_ok) begin echo_counter <= 0; state <= MEASURE_ECHO; end else if (echo_counter >= TIMEOUT_CYCLES) begin distance <= 0; state <= DONE; end else begin echo_counter <= echo_counter + 1; end end MEASURE_ECHO: begin if (sig_ok) begin if (echo_counter < TIMEOUT_CYCLES) begin echo_counter <= echo_counter + 1; end else begin distance <= 0; state <= DONE; end end else begin //Comptage par cycle de dist diviseur echo_counter <= echo_counter + 1; if (echo_div_counter >= DIST_DIVISOR - 1) begin echo_div_counter <= 0; distance_counter <= distance_counter + 1; end else begin echo_div_counter <= echo_div_counter + 1; end distance <= distance_counter; state <= DONE; end end DONE: begin if (start) begin wait_counter <= 0; state <= WAIT_NEXT; end else begin state <= IDLE; end end WAIT_NEXT: begin wait_counter <= wait_counter + 1; if (wait_counter >= WAIT_NEXT_CYCLES) begin state <= TRIG_HIGH; end end endcase end endmodule