diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/.gitignore b/Semaine_6/UART_ULTRASON_COMMANDS/.gitignore
new file mode 100644
index 0000000..029ea4f
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/.gitignore
@@ -0,0 +1,5 @@
+runs
+.vscode
+workspace.code-workspace
+*.pyc
+.idea
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/fifo.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/fifo.v
new file mode 100644
index 0000000..82915e2
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/fifo.v
@@ -0,0 +1,48 @@
+ module fifo #(
+ parameter SIZE = 16,
+ parameter WIDTH = 8
+)(
+ input wire clk,
+ input wire wr_en,
+ input wire[WIDTH-1:0] wr_data,
+ input wire rd_en,
+ output reg[WIDTH-1:0] rd_data,
+
+ output wire full,
+ output wire empty
+);
+
+ localparam LOGSIZE = $clog2(SIZE);
+
+ reg [WIDTH-1:0] fifo[0:SIZE-1];
+ reg [LOGSIZE-1:0] wr_ptr;
+ reg [LOGSIZE-1:0] rd_ptr;
+ reg [LOGSIZE:0] count;
+
+ assign full = (count == SIZE);
+ assign empty = (count == 0);
+
+ initial begin
+ wr_ptr = 0;
+ rd_ptr = 0;
+ count = 0;
+ end
+
+ always @(posedge clk) begin // IN
+ rd_data <= fifo[rd_ptr];
+ if (wr_en && !full && rd_en && !empty) begin
+ fifo[wr_ptr] <= wr_data;
+ wr_ptr <= (wr_ptr == SIZE - 1) ? 0 : (wr_ptr + 1) ;
+ rd_ptr <= (rd_ptr == SIZE - 1) ? 0 : (rd_ptr + 1) ;
+ end else if (wr_en && !full) begin
+ fifo[wr_ptr] <= wr_data;
+ wr_ptr <= (wr_ptr == SIZE - 1) ? 0 : (wr_ptr + 1) ;
+ count <= count + 1;
+ end else if (rd_en && !empty) begin // OUT
+ rd_ptr <= (rd_ptr == SIZE - 1) ? 0 : (rd_ptr + 1) ;
+ count <= count - 1;
+ end
+
+ end
+
+endmodule
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/rxuartlite.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/rxuartlite.v
new file mode 100644
index 0000000..a527848
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/rxuartlite.v
@@ -0,0 +1,796 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Filename: rxuartlite.v
+// {{{
+// Project: wbuart32, a full featured UART with simulator
+//
+// Purpose: Receive and decode inputs from a single UART line.
+//
+//
+// To interface with this module, connect it to your system clock,
+// and a UART input. Set the parameter to the number of clocks per
+// baud. When data becomes available, the o_wr line will be asserted
+// for one clock cycle.
+//
+// This interface only handles 8N1 serial port communications. It does
+// not handle the break, parity, or frame error conditions.
+//
+//
+// Creator: Dan Gisselquist, Ph.D.
+// Gisselquist Technology, LLC
+//
+////////////////////////////////////////////////////////////////////////////////
+// }}}
+// Copyright (C) 2015-2024, Gisselquist Technology, LLC
+// {{{
+// This program is free software (firmware): you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or (at
+// your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. (It's in the $(ROOT)/doc directory. Run make with no
+// target there if the PDF file isn't present.) If not, see
+// for a copy.
+// }}}
+// License: GPL, v3, as defined and found on www.gnu.org,
+// {{{
+// http://www.gnu.org/licenses/gpl.html
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+`default_nettype none
+// }}}
+module rxuartlite #(
+ // {{{
+ parameter TIMER_BITS = 10,
+`ifdef FORMAL
+ parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 16, // Necessary for formal proof
+`else
+ parameter [(TIMER_BITS-1):0] CLOCKS_PER_BAUD = 234, // 115200 Baud at 100MHz
+`endif
+ localparam TB = TIMER_BITS,
+ //
+ localparam [3:0] RXUL_BIT_ZERO = 4'h0,
+ // Verilator lint_off UNUSED
+ // These are used by the formal solver
+ localparam [3:0] RXUL_BIT_ONE = 4'h1,
+ localparam [3:0] RXUL_BIT_TWO = 4'h2,
+ localparam [3:0] RXUL_BIT_THREE = 4'h3,
+ localparam [3:0] RXUL_BIT_FOUR = 4'h4,
+ localparam [3:0] RXUL_BIT_FIVE = 4'h5,
+ localparam [3:0] RXUL_BIT_SIX = 4'h6,
+ localparam [3:0] RXUL_BIT_SEVEN = 4'h7,
+ // Verilator lint_on UNUSED
+ localparam [3:0] RXUL_STOP = 4'h8,
+ localparam [3:0] RXUL_WAIT = 4'h9,
+ localparam [3:0] RXUL_IDLE = 4'hf
+ // }}}
+ ) (
+ // {{{
+ input wire i_clk, i_reset,
+ input wire i_uart_rx,
+ output reg o_wr,
+ output reg [7:0] o_data
+ // }}}
+ );
+
+ // Signal/register declarations
+ // {{{
+ wire [(TB-1):0] half_baud;
+ reg [3:0] state;
+
+ assign half_baud = { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] };
+ reg [(TB-1):0] baud_counter;
+ reg zero_baud_counter;
+
+ reg q_uart, qq_uart, ck_uart;
+ reg [(TB-1):0] chg_counter;
+ reg half_baud_time;
+ reg [7:0] data_reg;
+ // }}}
+
+ // ck_uart
+ // {{{
+ // Since this is an asynchronous receiver, we need to register our
+ // input a couple of clocks over to avoid any problems with
+ // metastability. We do that here, and then ignore all but the
+ // ck_uart wire.
+ initial q_uart = 1'b1;
+ initial qq_uart = 1'b1;
+ initial ck_uart = 1'b1;
+ always @(posedge i_clk)
+ if (i_reset)
+ { ck_uart, qq_uart, q_uart } <= 3'b111;
+ else
+ { ck_uart, qq_uart, q_uart } <= { qq_uart, q_uart, i_uart_rx };
+ // }}}
+
+ // chg_counter
+ // {{{
+ // Keep track of the number of clocks since the last change.
+ //
+ // This is used to determine if we are in either a break or an idle
+ // condition, as discussed further below.
+ initial chg_counter = {(TB){1'b1}};
+ always @(posedge i_clk)
+ if (i_reset)
+ chg_counter <= {(TB){1'b1}};
+ else if (qq_uart != ck_uart)
+ chg_counter <= 0;
+ else if (chg_counter != { (TB){1'b1} })
+ chg_counter <= chg_counter + 1;
+ // }}}
+
+ // half_baud_time
+ // {{{
+ // Are we in the middle of a baud iterval? Specifically, are we
+ // in the middle of a start bit? Set this to high if so. We'll use
+ // this within our state machine to transition out of the IDLE
+ // state.
+ initial half_baud_time = 0;
+ always @(posedge i_clk)
+ if (i_reset)
+ half_baud_time <= 0;
+ else
+ half_baud_time <= (!ck_uart)&&(chg_counter >= half_baud-1'b1-1'b1);
+ // }}}
+
+ // state
+ // {{{
+ initial state = RXUL_IDLE;
+ always @(posedge i_clk)
+ if (i_reset)
+ begin
+ state <= RXUL_IDLE;
+ end else if (state == RXUL_IDLE)
+ begin // Idle state, independent of baud counter
+ // {{{
+ // By default, just stay in the IDLE state
+ state <= RXUL_IDLE;
+ if ((!ck_uart)&&(half_baud_time))
+ // UNLESS: We are in the center of a valid
+ // start bit
+ state <= RXUL_BIT_ZERO;
+ // }}}
+ end else if ((state >= RXUL_WAIT)&&(ck_uart))
+ state <= RXUL_IDLE;
+ else if (zero_baud_counter)
+ begin
+ // {{{
+ if (state <= RXUL_STOP)
+ // Data arrives least significant bit first.
+ // By the time this is clocked in, it's what
+ // you'll have.
+ state <= state + 1;
+ // }}}
+ end
+ // }}}
+
+ // data_reg
+ // {{{
+ // Data bit capture logic.
+ //
+ // This is drastically simplified from the state machine above, based
+ // upon: 1) it doesn't matter what it is until the end of a captured
+ // byte, and 2) the data register will flush itself of any invalid
+ // data in all other cases. Hence, let's keep it real simple.
+ always @(posedge i_clk)
+ if ((zero_baud_counter)&&(state != RXUL_STOP))
+ data_reg <= { qq_uart, data_reg[7:1] };
+ // }}}
+
+ // o_wr, o_data
+ // {{{
+ // Our data bit logic doesn't need nearly the complexity of all that
+ // work above. Indeed, we only need to know if we are at the end of
+ // a stop bit, in which case we copy the data_reg into our output
+ // data register, o_data, and tell others (for one clock) that data is
+ // available.
+ //
+ initial o_wr = 1'b0;
+ initial o_data = 8'h00;
+ always @(posedge i_clk)
+ if (i_reset)
+ begin
+ o_wr <= 1'b0;
+ o_data <= 8'h00;
+ end else if ((zero_baud_counter)&&(state == RXUL_STOP)&&(ck_uart))
+ begin
+ o_wr <= 1'b1;
+ o_data <= data_reg;
+ end else
+ o_wr <= 1'b0;
+ // }}}
+
+ // baud_counter -- The baud counter
+ // {{{
+ // This is used as a "clock divider" if you will, but the clock needs
+ // to be reset before any byte can be decoded. In all other respects,
+ // we set ourselves up for CLOCKS_PER_BAUD counts between baud
+ // intervals.
+ initial baud_counter = 0;
+ always @(posedge i_clk)
+ if (i_reset)
+ baud_counter <= 0;
+ else if (((state==RXUL_IDLE))&&(!ck_uart)&&(half_baud_time))
+ baud_counter <= CLOCKS_PER_BAUD-1'b1;
+ else if (state == RXUL_WAIT)
+ baud_counter <= 0;
+ else if ((zero_baud_counter)&&(state < RXUL_STOP))
+ baud_counter <= CLOCKS_PER_BAUD-1'b1;
+ else if (!zero_baud_counter)
+ baud_counter <= baud_counter-1'b1;
+ // }}}
+
+ // zero_baud_counter
+ // {{{
+ // Rather than testing whether or not (baud_counter == 0) within our
+ // (already too complicated) state transition tables, we use
+ // zero_baud_counter to pre-charge that test on the clock
+ // before--cleaning up some otherwise difficult timing dependencies.
+ initial zero_baud_counter = 1'b1;
+ always @(posedge i_clk)
+ if (i_reset)
+ zero_baud_counter <= 1'b1;
+ else if ((state == RXUL_IDLE)&&(!ck_uart)&&(half_baud_time))
+ zero_baud_counter <= 1'b0;
+ else if (state == RXUL_WAIT)
+ zero_baud_counter <= 1'b1;
+ else if ((zero_baud_counter)&&(state < RXUL_STOP))
+ zero_baud_counter <= 1'b0;
+ else if (baud_counter == 1)
+ zero_baud_counter <= 1'b1;
+ // }}}
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// Formal properties
+// {{{
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+ // Declarations
+ // {{{
+`ifdef FORMAL
+`define FORMAL_VERILATOR
+`else
+`ifdef VERILATOR
+`define FORMAL_VERILATOR
+`endif
+`endif
+
+`ifdef FORMAL
+ localparam F_CKRES = 10;
+
+ (* anyseq *) wire f_tx_start;
+ (* anyconst *) wire [(F_CKRES-1):0] f_tx_step;
+ (* gclk *) wire gbl_clk;
+ reg f_tx_zclk;
+ reg [(TB-1):0] f_tx_timer;
+ wire [7:0] f_rx_newdata;
+ reg [TB-1:0] f_tx_baud;
+ wire f_tx_zbaud;
+
+ wire [(TB-1):0] f_max_baud_difference;
+ reg [(TB-1):0] f_baud_difference;
+ reg [(TB+3):0] f_tx_count, f_rx_count;
+ (* anyseq *) wire [7:0] f_tx_data;
+
+ wire f_txclk;
+ reg [1:0] f_rx_clock;
+ reg [(F_CKRES-1):0] f_tx_clock;
+ reg f_past_valid, f_past_valid_tx;
+
+ reg [9:0] f_tx_reg;
+ reg f_tx_busy;
+
+ // }}}
+
+ initial f_past_valid = 1'b0;
+ always @(posedge i_clk)
+ f_past_valid <= 1'b1;
+
+ initial f_rx_clock = 3'h0;
+ always @(posedge gbl_clk)
+ f_rx_clock <= f_rx_clock + 1'b1;
+
+ always @(*)
+ assume(i_clk == f_rx_clock[1]);
+
+ always @(posedge gbl_clk)
+ if (!$rose(i_clk))
+ assume(!$fell(i_reset));
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Assume a transmitted signal
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+
+ // First, calculate the transmit clock
+ localparam [(F_CKRES-1):0] F_MIDSTEP = { 2'b01, {(F_CKRES-2){1'b0}} };
+ //
+ // Need to allow us to slip by half a baud clock over 10 baud intervals
+ //
+ // (F_STEP / (2^F_CKRES)) * (CLOCKS_PER_BAUD)*10 < CLOCKS_PER_BAUD/2
+ // F_STEP * 2 * 10 < 2^F_CKRES
+ localparam [(F_CKRES-1):0] F_HALFSTEP= F_MIDSTEP/32;
+ localparam [(F_CKRES-1):0] F_MINSTEP = F_MIDSTEP - F_HALFSTEP + 1;
+ localparam [(F_CKRES-1):0] F_MAXSTEP = F_MIDSTEP + F_HALFSTEP - 1;
+
+ initial assert(F_MINSTEP <= F_MIDSTEP);
+ initial assert(F_MIDSTEP <= F_MAXSTEP);
+
+ // assume((f_tx_step >= F_MINSTEP)&&(f_tx_step <= F_MAXSTEP));
+ //
+ //
+ always @(*) assume((f_tx_step == F_MINSTEP)
+ ||(f_tx_step == F_MIDSTEP)
+ ||(f_tx_step == F_MAXSTEP));
+
+ always @(posedge gbl_clk)
+ f_tx_clock <= f_tx_clock + f_tx_step;
+
+ assign f_txclk = f_tx_clock[F_CKRES-1];
+ //
+ initial f_past_valid_tx = 1'b0;
+ always @(posedge f_txclk)
+ f_past_valid_tx <= 1'b1;
+
+ initial assume(i_uart_rx);
+
+ always @(*)
+ if (i_reset)
+ assume(i_uart_rx);
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // The simulated timing generator
+
+ always @(*)
+ if (i_reset)
+ assume(!f_tx_busy);
+
+ always @(*)
+ if (f_tx_busy || i_reset)
+ assume(!f_tx_start);
+
+ always @(*)
+ if (i_reset)
+ assume(f_tx_baud == CLOCKS_PER_BAUD-1);
+
+ initial f_tx_baud = 0;
+ always @(posedge f_txclk)
+ if (f_tx_zbaud && (f_tx_busy || f_tx_start))
+ f_tx_baud <= CLOCKS_PER_BAUD-1;
+ else if (!f_tx_zbaud)
+ f_tx_baud <= f_tx_baud - 1;
+
+ always @(*)
+ assert(f_tx_baud < CLOCKS_PER_BAUD);
+
+ always @(*)
+ if (!f_tx_busy)
+ assert(f_tx_baud == 0);
+
+ assign f_tx_zbaud = (f_tx_baud == 0);
+
+ // But only if we aren't busy
+ initial assume(f_tx_data == 0);
+ always @(posedge f_txclk)
+ if ((!f_tx_zbaud)||(f_tx_busy)||(!f_tx_start))
+ assume(f_tx_data == $past(f_tx_data));
+
+ // Force the data to change on a clock only
+ always @(posedge gbl_clk)
+ if ((f_past_valid)&&(!$rose(f_txclk)))
+ assume($stable(f_tx_data));
+ else if (f_tx_busy)
+ assume($stable(f_tx_data));
+
+ //
+ always @(posedge gbl_clk)
+ if ((!f_past_valid)||(!$rose(f_txclk)))
+ begin
+ assume($stable(f_tx_start));
+ assume($stable(f_tx_data));
+ end
+
+ //
+ //
+ //
+
+ // Here's the transmitter itself (roughly)
+ initial f_tx_busy = 1'b0;
+ initial f_tx_reg = 0;
+ always @(posedge f_txclk)
+ if (!f_tx_zbaud)
+ begin
+ assert(f_tx_busy);
+ end else begin
+ f_tx_reg <= { 1'b0, f_tx_reg[9:1] };
+ if (f_tx_start)
+ f_tx_reg <= { 1'b1, f_tx_data, 1'b0 };
+ end
+
+ // Create a busy flag that we'll use
+ always @(*)
+ if (!f_tx_zbaud)
+ f_tx_busy <= 1'b1;
+ else if (|f_tx_reg)
+ f_tx_busy <= 1'b1;
+ else
+ f_tx_busy <= 1'b0;
+
+ //
+ // Tie the TX register to the TX data
+ always @(posedge f_txclk)
+ if (f_tx_reg[9])
+ begin
+ assert(f_tx_reg[8:0] == { f_tx_data, 1'b0 });
+ end else if (f_tx_reg[8])
+ begin
+ assert(f_tx_reg[7:0] == f_tx_data[7:0] );
+ end else if (f_tx_reg[7])
+ begin
+ assert(f_tx_reg[6:0] == f_tx_data[7:1] );
+ end else if (f_tx_reg[6])
+ begin
+ assert(f_tx_reg[5:0] == f_tx_data[7:2] );
+ end else if (f_tx_reg[5])
+ begin
+ assert(f_tx_reg[4:0] == f_tx_data[7:3] );
+ end else if (f_tx_reg[4])
+ begin
+ assert(f_tx_reg[3:0] == f_tx_data[7:4] );
+ end else if (f_tx_reg[3])
+ begin
+ assert(f_tx_reg[2:0] == f_tx_data[7:5] );
+ end else if (f_tx_reg[2])
+ begin
+ assert(f_tx_reg[1:0] == f_tx_data[7:6] );
+ end else if (f_tx_reg[1])
+ begin
+ assert(f_tx_reg[0] == f_tx_data[7]);
+ end
+
+ // Our counter since we start
+ initial f_tx_count = 0;
+ always @(posedge f_txclk)
+ if (!f_tx_busy)
+ f_tx_count <= 0;
+ else
+ f_tx_count <= f_tx_count + 1'b1;
+
+ always @(*)
+ if (f_tx_reg == 10'h0)
+ assume(i_uart_rx);
+ else
+ assume(i_uart_rx == f_tx_reg[0]);
+
+ //
+ // Make sure the absolute transmit clock timer matches our state
+ //
+ always @(posedge f_txclk)
+ if (!f_tx_busy)
+ begin
+ if ((!f_past_valid_tx)||(!$past(f_tx_busy)))
+ assert(f_tx_count == 0);
+ end else if (f_tx_reg[9])
+ begin
+ assert(f_tx_count ==
+ CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[8])
+ begin
+ assert(f_tx_count ==
+ 2 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[7])
+ begin
+ assert(f_tx_count ==
+ 3 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[6])
+ begin
+ assert(f_tx_count ==
+ 4 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[5])
+ begin
+ assert(f_tx_count ==
+ 5 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[4])
+ begin
+ assert(f_tx_count ==
+ 6 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[3])
+ begin
+ assert(f_tx_count ==
+ 7 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[2])
+ begin
+ assert(f_tx_count ==
+ 8 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[1])
+ begin
+ assert(f_tx_count ==
+ 9 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else if (f_tx_reg[0])
+ begin
+ assert(f_tx_count ==
+ 10 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end else begin
+ assert(f_tx_count ==
+ 11 * CLOCKS_PER_BAUD -1 -f_tx_baud);
+ end
+
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Receiver
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //
+ // Count RX clocks since the start of the first stop bit, measured in
+ // rx clocks
+ initial f_rx_count = 0;
+ always @(posedge i_clk)
+ if (i_reset)
+ f_rx_count <= 0;
+ else if (state == RXUL_IDLE)
+ f_rx_count <= (!ck_uart) ? (chg_counter+2) : 0;
+ else
+ f_rx_count <= f_rx_count + 1'b1;
+
+ always @(posedge i_clk)
+ case(state)
+ 0: assert(f_rx_count == half_baud + (CLOCKS_PER_BAUD-baud_counter));
+ 1: assert(f_rx_count == half_baud + 2 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 2: assert(f_rx_count == half_baud + 3 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 3: assert(f_rx_count == half_baud + 4 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 4: assert(f_rx_count == half_baud + 5 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 5: assert(f_rx_count == half_baud + 6 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 6: assert(f_rx_count == half_baud + 7 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 7: assert(f_rx_count == half_baud + 8 * CLOCKS_PER_BAUD
+ - baud_counter);
+ 8: assert((f_rx_count == half_baud + 9 * CLOCKS_PER_BAUD
+ - baud_counter)
+ ||(f_rx_count == half_baud + 10 * CLOCKS_PER_BAUD
+ - baud_counter));
+ 9: begin end
+ 4'hf: begin end
+ default:
+ assert(1'b0);
+ endcase
+
+ always @(*)
+ assert( ((!zero_baud_counter)
+ &&(state == RXUL_IDLE)
+ &&(baud_counter == 0))
+ ||((zero_baud_counter)&&(baud_counter == 0))
+ ||((!zero_baud_counter)&&(baud_counter != 0)));
+
+ always @(posedge i_clk)
+ if (!f_past_valid)
+ assert((state == RXUL_IDLE)&&(baud_counter == 0)
+ &&(zero_baud_counter));
+
+ always @(*)
+ begin
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h2);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h4);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h5);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h6);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'h9);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'ha);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hb);
+ assert({ ck_uart,qq_uart,q_uart,i_uart_rx } != 4'hd);
+ end
+
+ always @(posedge i_clk)
+ if ((f_past_valid)&&($past(state) >= RXUL_WAIT)&&($past(ck_uart)))
+ assert(state == RXUL_IDLE);
+
+ always @(posedge i_clk)
+ if ((f_past_valid)&&($past(state) >= RXUL_WAIT)
+ &&(($past(state) != RXUL_IDLE)||(state == RXUL_IDLE)))
+ assert(zero_baud_counter);
+
+ // Calculate an absolute value of the difference between the two baud
+ // clocks
+ always @(posedge i_clk)
+ if (f_past_valid && !$past(i_reset)
+ && $past(state)==RXUL_IDLE &&(state == RXUL_IDLE))
+ begin
+ assert(($past(ck_uart))
+ ||(chg_counter <=
+ { 1'b0, CLOCKS_PER_BAUD[(TB-1):1] }));
+ end
+
+ always @(posedge f_txclk)
+ if (!f_past_valid_tx)
+ assert((state == RXUL_IDLE)&&(baud_counter == 0)
+ &&(zero_baud_counter)&&(!f_tx_busy));
+
+ wire [(TB+3):0] f_tx_count_two_clocks_ago;
+ assign f_tx_count_two_clocks_ago = f_tx_count - 2;
+ always @(*)
+ if (f_tx_count >= f_rx_count + 2)
+ f_baud_difference = f_tx_count_two_clocks_ago - f_rx_count;
+ else
+ f_baud_difference = f_rx_count - f_tx_count_two_clocks_ago;
+
+ localparam F_SYNC_DLY = 8;
+
+ reg [(TB+4+F_CKRES-1):0] f_sub_baud_difference;
+ reg [F_CKRES-1:0] ck_tx_clock;
+ reg [((F_SYNC_DLY-1)*F_CKRES)-1:0] q_tx_clock;
+ reg [TB+3:0] ck_tx_count;
+ reg [(F_SYNC_DLY-1)*(TB+4)-1:0] q_tx_count;
+ initial q_tx_count = 0;
+ initial ck_tx_count = 0;
+ initial q_tx_clock = 0;
+ initial ck_tx_clock = 0;
+ always @(posedge gbl_clk)
+ if (!f_past_valid || i_reset)
+ { ck_tx_clock, q_tx_clock } <= 0;
+ else
+ { ck_tx_clock, q_tx_clock } <= { q_tx_clock, f_tx_clock };
+ always @(posedge gbl_clk)
+ if (!f_past_valid || i_reset)
+ { ck_tx_count, q_tx_count } <= 0;
+ else
+ { ck_tx_count, q_tx_count } <= { q_tx_count, f_tx_count };
+
+
+ reg [TB+4+F_CKRES-1:0] f_ck_tx_time, f_rx_time;
+ always @(*)
+ f_ck_tx_time = { ck_tx_count, !ck_tx_clock[F_CKRES-1],
+ ck_tx_clock[F_CKRES-2:0] };
+ always @(*)
+ f_rx_time = { f_rx_count, !f_rx_clock[1], f_rx_clock[0],
+ {(F_CKRES-2){1'b0}} };
+
+ reg [TB+4+F_CKRES-1:0] f_signed_difference;
+ always @(*)
+ f_signed_difference = f_ck_tx_time - f_rx_time;
+
+ always @(*)
+ if (f_signed_difference[TB+4+F_CKRES-1])
+ f_sub_baud_difference = -f_signed_difference;
+ else
+ f_sub_baud_difference = f_signed_difference;
+
+ always @(posedge gbl_clk)
+ if (state == RXUL_WAIT)
+ assert((!f_tx_busy)||(f_tx_reg[9:1] == 0));
+
+ always @(posedge gbl_clk)
+ if (f_past_valid && !$past(i_reset))
+ begin
+ if (state == RXUL_IDLE)
+ begin
+ assert((!f_tx_busy)||(f_tx_reg[9])||(f_tx_reg[9:1]==0));
+ if (ck_uart)
+ assert((f_tx_reg[9:1]==0)||(f_tx_count < (3 + CLOCKS_PER_BAUD/2)));
+ end else if (state == 0)
+ begin
+ assert(f_sub_baud_difference
+ <= 2 * ((CLOCKS_PER_BAUD< 6))
+ // assert(i_uart_rx == ck_uart);
+
+ // Make sure the data register matches
+ always @(posedge i_clk)
+ case(state)
+ 4'h0: assert(!data_reg[7]);
+ 4'h1: assert((data_reg[7] == $past(f_tx_data[0]))&&(!data_reg[6]));
+ 4'h2: assert(data_reg[7:6] == $past(f_tx_data[1:0]));
+ 4'h3: assert(data_reg[7:5] == $past(f_tx_data[2:0]));
+ 4'h4: assert(data_reg[7:4] == $past(f_tx_data[3:0]));
+ 4'h5: assert(data_reg[7:3] == $past(f_tx_data[4:0]));
+ 4'h6: assert(data_reg[7:2] == $past(f_tx_data[5:0]));
+ 4'h7: assert(data_reg[7:1] == $past(f_tx_data[6:0]));
+ 4'h8: assert(data_reg[7:0] == $past(f_tx_data[7:0]));
+ endcase
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Cover properties
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+ always @(posedge i_clk)
+ cover(o_wr); // Step 626, takes about 20mins
+
+ always @(posedge i_clk)
+ if (!i_reset && f_past_valid && !$past(i_reset))
+ begin
+ cover(!ck_uart);
+ cover((f_past_valid)&&($rose(ck_uart))); // 82
+ cover((zero_baud_counter)&&(state == RXUL_BIT_ZERO)); // 110
+ cover((zero_baud_counter)&&(state == RXUL_BIT_ONE)); // 174
+ cover((zero_baud_counter)&&(state == RXUL_BIT_TWO)); // 238
+ cover((zero_baud_counter)&&(state == RXUL_BIT_THREE));// 302
+ cover((zero_baud_counter)&&(state == RXUL_BIT_FOUR)); // 366
+ cover((zero_baud_counter)&&(state == RXUL_BIT_FIVE)); // 430
+ cover((zero_baud_counter)&&(state == RXUL_BIT_SIX)); // 494
+ cover((zero_baud_counter)&&(state == RXUL_BIT_SEVEN));// 558
+ cover((zero_baud_counter)&&(state == RXUL_STOP)); // 622
+ cover((zero_baud_counter)&&(state == RXUL_WAIT)); // 626
+ end
+`endif
+ // }}}
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Properties to test via Verilator *and* formal
+ // {{{
+ ////////////////////////////////////////////////////////////////////////
+ //
+`ifdef FORMAL_VERILATOR
+ // FORMAL properties which can be tested via Verilator as well as
+ // Yosys FORMAL
+ always @(*)
+ assert((state == 4'hf)||(state <= RXUL_WAIT));
+ always @(*)
+ assert(zero_baud_counter == (baud_counter == 0)? 1'b1:1'b0);
+ always @(*)
+ assert(baud_counter <= CLOCKS_PER_BAUD-1'b1);
+ // }}}
+`endif
+// }}}
+endmodule
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/txuartlite.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/txuartlite.v
new file mode 100644
index 0000000..c43edfe
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/txuartlite.v
@@ -0,0 +1,472 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Filename: txuartlite.v
+// {{{
+// Project: wbuart32, a full featured UART with simulator
+//
+// Purpose: Transmit outputs over a single UART line. This particular UART
+// implementation has been extremely simplified: it does not handle
+// generating break conditions, nor does it handle anything other than the
+// 8N1 (8 data bits, no parity, 1 stop bit) UART sub-protocol.
+//
+// To interface with this module, connect it to your system clock, and
+// pass it the byte of data you wish to transmit. Strobe the i_wr line
+// high for one cycle, and your data will be off. Wait until the 'o_busy'
+// line is low before strobing the i_wr line again--this implementation
+// has NO BUFFER, so strobing i_wr while the core is busy will just
+// get ignored. The output will be placed on the o_txuart output line.
+//
+// (I often set both data and strobe on the same clock, and then just leave
+// them set until the busy line is low. Then I move on to the next piece
+// of data.)
+//
+// Creator: Dan Gisselquist, Ph.D.
+// Gisselquist Technology, LLC
+//
+////////////////////////////////////////////////////////////////////////////////
+// }}}
+// Copyright (C) 2015-2024, Gisselquist Technology, LLC
+// {{{
+// This program is free software (firmware): you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or (at
+// your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. (It's in the $(ROOT)/doc directory. Run make with no
+// target there if the PDF file isn't present.) If not, see
+// for a copy.
+// }}}
+// License: GPL, v3, as defined and found on www.gnu.org,
+// {{{
+// http://www.gnu.org/licenses/gpl.html
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+`default_nettype none
+// }}}
+module txuartlite #(
+ // {{{
+ // TIMING_BITS -- the number of bits required to represent
+ // the number of clocks per baud. 24 should be sufficient for
+ // most baud rates, but you can trim it down to save logic if
+ // you would like. TB is just an abbreviation for TIMING_BITS.
+ parameter [4:0] TIMING_BITS = 5'd8,
+ localparam TB = TIMING_BITS,
+ // CLOCKS_PER_BAUD -- the number of system clocks per baud
+ // interval.
+ parameter [(TB-1):0] CLOCKS_PER_BAUD = 234 // 24'd868
+ // }}}
+ ) (
+ // {{{
+ input wire i_clk, i_reset,
+ input wire i_wr,
+ input wire [7:0] i_data,
+ // And the UART input line itself
+ output reg o_uart_tx,
+ // A line to tell others when we are ready to accept data. If
+ // (i_wr)&&(!o_busy) is ever true, then the core has accepted
+ // a byte for transmission.
+ output wire o_busy
+ // }}}
+ );
+
+ // Register/net declarations
+ // {{{
+ localparam [3:0] TXUL_BIT_ZERO = 4'h0,
+ // TXUL_BIT_ONE = 4'h1,
+ // TXUL_BIT_TWO = 4'h2,
+ // TXUL_BIT_THREE = 4'h3,
+ // TXUL_BIT_FOUR = 4'h4,
+ // TXUL_BIT_FIVE = 4'h5,
+ // TXUL_BIT_SIX = 4'h6,
+ // TXUL_BIT_SEVEN = 4'h7,
+ TXUL_STOP = 4'h8,
+ TXUL_IDLE = 4'hf;
+
+ reg [(TB-1):0] baud_counter;
+ reg [3:0] state;
+ reg [7:0] lcl_data;
+ reg r_busy, zero_baud_counter;
+ // }}}
+
+ // Big state machine controlling: r_busy, state
+ // {{{
+ //
+ initial r_busy = 1'b1;
+ initial state = TXUL_IDLE;
+ always @(posedge i_clk)
+ if (i_reset)
+ begin
+ r_busy <= 1'b1;
+ state <= TXUL_IDLE;
+ end else if (!zero_baud_counter)
+ // r_busy needs to be set coming into here
+ r_busy <= 1'b1;
+ else if (state > TXUL_STOP) // STATE_IDLE
+ begin
+ state <= TXUL_IDLE;
+ r_busy <= 1'b0;
+ if ((i_wr)&&(!r_busy))
+ begin // Immediately start us off with a start bit
+ r_busy <= 1'b1;
+ state <= TXUL_BIT_ZERO;
+ end
+ end else begin
+ // One clock tick in each of these states ...
+ r_busy <= 1'b1;
+ if (state <=TXUL_STOP) // start bit, 8-d bits, stop-b
+ state <= state + 1'b1;
+ else
+ state <= TXUL_IDLE;
+ end
+ // }}}
+
+ // o_busy
+ // {{{
+ //
+ // This is a wire, designed to be true is we are ever busy above.
+ // originally, this was going to be true if we were ever not in the
+ // idle state. The logic has since become more complex, hence we have
+ // a register dedicated to this and just copy out that registers value.
+ assign o_busy = (r_busy);
+ // }}}
+
+ // lcl_data
+ // {{{
+ //
+ // This is our working copy of the i_data register which we use
+ // when transmitting. It is only of interest during transmit, and is
+ // allowed to be whatever at any other time. Hence, if r_busy isn't
+ // true, we can always set it. On the one clock where r_busy isn't
+ // true and i_wr is, we set it and r_busy is true thereafter.
+ // Then, on any zero_baud_counter (i.e. change between baud intervals)
+ // we simple logically shift the register right to grab the next bit.
+ initial lcl_data = 8'hff;
+ always @(posedge i_clk)
+ if (i_reset)
+ lcl_data <= 8'hff;
+ else if (i_wr && !r_busy)
+ lcl_data <= i_data;
+ else if (zero_baud_counter)
+ lcl_data <= { 1'b1, lcl_data[7:1] };
+ // }}}
+
+ // o_uart_tx
+ // {{{
+ //
+ // This is the final result/output desired of this core. It's all
+ // centered about o_uart_tx. This is what finally needs to follow
+ // the UART protocol.
+ //
+ initial o_uart_tx = 1'b1;
+ always @(posedge i_clk)
+ if (i_reset)
+ o_uart_tx <= 1'b1;
+ else if (i_wr && !r_busy)
+ o_uart_tx <= 1'b0; // Set the start bit on writes
+ else if (zero_baud_counter) // Set the data bit.
+ o_uart_tx <= lcl_data[0];
+ // }}}
+
+ // Baud counter
+ // {{{
+ // All of the above logic is driven by the baud counter. Bits must last
+ // CLOCKS_PER_BAUD in length, and this baud counter is what we use to
+ // make certain of that.
+ //
+ // The basic logic is this: at the beginning of a bit interval, start
+ // the baud counter and set it to count CLOCKS_PER_BAUD. When it gets
+ // to zero, restart it.
+ //
+ // However, comparing a 28'bit number to zero can be rather complex--
+ // especially if we wish to do anything else on that same clock. For
+ // that reason, we create "zero_baud_counter". zero_baud_counter is
+ // nothing more than a flag that is true anytime baud_counter is zero.
+ // It's true when the logic (above) needs to step to the next bit.
+ // Simple enough?
+ //
+ // I wish we could stop there, but there are some other (ugly)
+ // conditions to deal with that offer exceptions to this basic logic.
+ //
+ // 1. When the user has commanded a BREAK across the line, we need to
+ // wait several baud intervals following the break before we start
+ // transmitting, to give any receiver a chance to recognize that we are
+ // out of the break condition, and to know that the next bit will be
+ // a stop bit.
+ //
+ // 2. A reset is similar to a break condition--on both we wait several
+ // baud intervals before allowing a start bit.
+ //
+ // 3. In the idle state, we stop our counter--so that upon a request
+ // to transmit when idle we can start transmitting immediately, rather
+ // than waiting for the end of the next (fictitious and arbitrary) baud
+ // interval.
+ //
+ // When (i_wr)&&(!r_busy)&&(state == TXUL_IDLE) then we're not only in
+ // the idle state, but we also just accepted a command to start writing
+ // the next word. At this point, the baud counter needs to be reset
+ // to the number of CLOCKS_PER_BAUD, and zero_baud_counter set to zero.
+ //
+ // The logic is a bit twisted here, in that it will only check for the
+ // above condition when zero_baud_counter is false--so as to make
+ // certain the STOP bit is complete.
+ initial zero_baud_counter = 1'b1;
+ initial baud_counter = 0;
+ always @(posedge i_clk)
+ if (i_reset)
+ begin
+ zero_baud_counter <= 1'b1;
+ baud_counter <= 0;
+ end else begin
+ zero_baud_counter <= (baud_counter == 1);
+
+ if (state == TXUL_IDLE)
+ begin
+ baud_counter <= 0;
+ zero_baud_counter <= 1'b1;
+ if ((i_wr)&&(!r_busy))
+ begin
+ baud_counter <= CLOCKS_PER_BAUD - 1'b1;
+ zero_baud_counter <= 1'b0;
+ end
+ end else if (!zero_baud_counter)
+ baud_counter <= baud_counter - 1'b1;
+ else if (state > TXUL_STOP)
+ begin
+ baud_counter <= 0;
+ zero_baud_counter <= 1'b1;
+ end else if (state == TXUL_STOP)
+ // Need to complete this state one clock early, so
+ // we can release busy one clock before the stop bit
+ // is complete, so we can start on the next byte
+ // exactly 10*CLOCKS_PER_BAUD clocks after we started
+ // the last one
+ baud_counter <= CLOCKS_PER_BAUD - 2;
+ else // All other states
+ baud_counter <= CLOCKS_PER_BAUD - 1'b1;
+ end
+ // }}}
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// FORMAL METHODS
+// {{{
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+`ifdef FORMAL
+ // Declarations
+`ifdef TXUARTLITE
+`define ASSUME assume
+`else
+`define ASSUME assert
+`endif
+ reg f_past_valid, f_last_clk;
+ reg [(TB-1):0] f_baud_count;
+ reg [9:0] f_txbits;
+ reg [3:0] f_bitcount;
+ reg [7:0] f_request_tx_data;
+ wire [3:0] subcount;
+
+ // Setup
+ // {{{
+ initial f_past_valid = 1'b0;
+ always @(posedge i_clk)
+ f_past_valid <= 1'b1;
+
+ initial `ASSUME(!i_wr);
+ always @(posedge i_clk)
+ if ((f_past_valid)&&($past(i_wr))&&($past(o_busy)))
+ begin
+ `ASSUME(i_wr == $past(i_wr));
+ `ASSUME(i_data == $past(i_data));
+ end
+ // }}}
+
+ // Check the baud counter
+ // {{{
+ always @(posedge i_clk)
+ assert(zero_baud_counter == (baud_counter == 0));
+
+ always @(posedge i_clk)
+ if (f_past_valid && !$past(i_reset) && $past(baud_counter != 0)
+ && $past(state != TXUL_IDLE))
+ assert(baud_counter == $past(baud_counter - 1'b1));
+
+ always @(posedge i_clk)
+ if (f_past_valid && !$past(i_reset) && !$past(zero_baud_counter)
+ && $past(state != TXUL_IDLE))
+ assert($stable(o_uart_tx));
+
+ initial f_baud_count = 1'b0;
+ always @(posedge i_clk)
+ if (zero_baud_counter)
+ f_baud_count <= 0;
+ else
+ f_baud_count <= f_baud_count + 1'b1;
+
+ always @(posedge i_clk)
+ assert(f_baud_count < CLOCKS_PER_BAUD);
+
+ always @(posedge i_clk)
+ if (baud_counter != 0)
+ assert(o_busy);
+ // }}}
+
+ // {{{
+ initial f_txbits = 0;
+ always @(posedge i_clk)
+ if (zero_baud_counter)
+ f_txbits <= { o_uart_tx, f_txbits[9:1] };
+
+ always @(posedge i_clk)
+ if (f_past_valid && !$past(i_reset)&& !$past(zero_baud_counter)
+ && !$past(state==TXUL_IDLE))
+ assert(state == $past(state));
+
+ initial f_bitcount = 0;
+ always @(posedge i_clk)
+ if ((!f_past_valid)||(!$past(f_past_valid)))
+ f_bitcount <= 0;
+ else if ((state == TXUL_IDLE)&&(zero_baud_counter))
+ f_bitcount <= 0;
+ else if (zero_baud_counter)
+ f_bitcount <= f_bitcount + 1'b1;
+
+ always @(posedge i_clk)
+ assert(f_bitcount <= 4'ha);
+
+ always @(*)
+ if (!o_busy)
+ assert(zero_baud_counter);
+
+ always @(posedge i_clk)
+ if ((i_wr)&&(!o_busy))
+ f_request_tx_data <= i_data;
+
+ assign subcount = 10-f_bitcount;
+ always @(posedge i_clk)
+ if (f_bitcount > 0)
+ assert(!f_txbits[subcount]);
+
+ always @(posedge i_clk)
+ if (f_bitcount == 4'ha)
+ begin
+ assert(f_txbits[8:1] == f_request_tx_data);
+ assert( f_txbits[9]);
+ end
+
+ always @(posedge i_clk)
+ assert((state <= TXUL_STOP + 1'b1)||(state == TXUL_IDLE));
+
+ always @(posedge i_clk)
+ if ((f_past_valid)&&($past(f_past_valid))&&($past(o_busy)))
+ cover(!o_busy);
+ // }}}
+
+`endif // FORMAL
+`ifdef VERIFIC_SVA
+ reg [7:0] fsv_data;
+
+ //
+ // Grab a copy of the data any time we are sent a new byte to transmit
+ // We'll use this in a moment to compare the item transmitted against
+ // what is supposed to be transmitted
+ //
+ always @(posedge i_clk)
+ if ((i_wr)&&(!o_busy))
+ fsv_data <= i_data;
+
+ //
+ // One baud interval
+ // {{{
+ //
+ // 1. The UART output is constant at DAT
+ // 2. The internal state remains constant at ST
+ // 3. CKS = the number of clocks per bit.
+ //
+ // Everything stays constant during the CKS clocks with the exception
+ // of (zero_baud_counter), which is *only* raised on the last clock
+ // interval
+ sequence BAUD_INTERVAL(CKS, DAT, SR, ST);
+ ((o_uart_tx == DAT)&&(state == ST)
+ &&(lcl_data == SR)
+ &&(!zero_baud_counter))[*(CKS-1)]
+ ##1 (o_uart_tx == DAT)&&(state == ST)
+ &&(lcl_data == SR)
+ &&(zero_baud_counter);
+ endsequence
+ // }}}
+
+ //
+ // One byte transmitted
+ // {{{
+ //
+ // DATA = the byte that is sent
+ // CKS = the number of clocks per bit
+ //
+ sequence SEND(CKS, DATA);
+ BAUD_INTERVAL(CKS, 1'b0, DATA, 4'h0)
+ ##1 BAUD_INTERVAL(CKS, DATA[0], {{(1){1'b1}},DATA[7:1]}, 4'h1)
+ ##1 BAUD_INTERVAL(CKS, DATA[1], {{(2){1'b1}},DATA[7:2]}, 4'h2)
+ ##1 BAUD_INTERVAL(CKS, DATA[2], {{(3){1'b1}},DATA[7:3]}, 4'h3)
+ ##1 BAUD_INTERVAL(CKS, DATA[3], {{(4){1'b1}},DATA[7:4]}, 4'h4)
+ ##1 BAUD_INTERVAL(CKS, DATA[4], {{(5){1'b1}},DATA[7:5]}, 4'h5)
+ ##1 BAUD_INTERVAL(CKS, DATA[5], {{(6){1'b1}},DATA[7:6]}, 4'h6)
+ ##1 BAUD_INTERVAL(CKS, DATA[6], {{(7){1'b1}},DATA[7:7]}, 4'h7)
+ ##1 BAUD_INTERVAL(CKS, DATA[7], 8'hff, 4'h8)
+ ##1 BAUD_INTERVAL(CKS-1, 1'b1, 8'hff, 4'h9);
+ endsequence
+ // }}}
+
+ //
+ // Transmit one byte
+ // {{{
+ // Once the byte is transmitted, make certain we return to
+ // idle
+ //
+ assert property (
+ @(posedge i_clk)
+ (i_wr)&&(!o_busy)
+ |=> ((o_busy) throughout SEND(CLOCKS_PER_BAUD,fsv_data))
+ ##1 (!o_busy)&&(o_uart_tx)&&(zero_baud_counter));
+ // }}}
+
+ // {{{
+ assume property (
+ @(posedge i_clk)
+ (i_wr)&&(o_busy) |=>
+ (i_wr)&&($stable(i_data)));
+
+ //
+ // Make certain that o_busy is true any time zero_baud_counter is
+ // non-zero
+ //
+ always @(*)
+ assert((o_busy)||(zero_baud_counter) );
+
+ // If and only if zero_baud_counter is true, baud_counter must be zero
+ // Insist on that relationship here.
+ always @(*)
+ assert(zero_baud_counter == (baud_counter == 0));
+
+ // To make certain baud_counter stays below CLOCKS_PER_BAUD
+ always @(*)
+ assert(baud_counter < CLOCKS_PER_BAUD);
+
+ //
+ // Insist that we are only ever in a valid state
+ always @(*)
+ assert((state <= TXUL_STOP+1'b1)||(state == TXUL_IDLE));
+ // }}}
+
+`endif // Verific SVA
+// }}}
+endmodule
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_rx_fifo.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_rx_fifo.v
new file mode 100644
index 0000000..d521fde
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_rx_fifo.v
@@ -0,0 +1,56 @@
+module uart_rx_fifo #(
+ parameter CLK_FREQ = 27_000_000,
+ parameter BAUD_RATE = 115200,
+ parameter FIFO_SIZE = 8
+)(
+ input clk,
+ input rd_en,
+ output wire [7:0] rd_data,
+ input rx_pin,
+ output data_available
+);
+
+ // UART RX wires
+ wire [7:0] rx_data;
+ wire rx_received;
+
+ // FIFO control
+ reg wr_en;
+ wire fifo_empty;
+ wire fifo_full;
+
+ // UART Receiver instance
+ rxuartlite uart_rx_inst (
+ .i_clk(clk),
+ .i_reset(1'b0),
+ .i_uart_rx(rx_pin),
+ .o_wr(rx_received),
+ .o_data(rx_data)
+ );
+
+ // FIFO instance
+ fifo #(
+ .WIDTH(8),
+ .SIZE(FIFO_SIZE)
+ ) fifo_inst (
+ .clk(clk),
+ .wr_en(wr_en),
+ .wr_data(rx_data),
+ .rd_en(rd_en),
+ .rd_data(rd_data),
+ .empty(fifo_empty),
+ .full(fifo_full)
+ );
+
+ assign data_available = ~fifo_empty;
+
+ // Écriture dans la FIFO uniquement si donnée reçue ET FIFO pas pleine
+ always @(posedge clk) begin
+ if (rx_received && !fifo_full) begin
+ wr_en <= 1'b1;
+ end else begin
+ wr_en <= 1'b0;
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx.v
new file mode 100644
index 0000000..9f48d93
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx.v
@@ -0,0 +1,131 @@
+module uart_tx #(
+ parameter CLK_FREQ = 27_000_000,
+ parameter BAUD_RATE = 115200
+)(
+ input wire clk,
+ input wire rst_p,
+ input wire[7:0] data,
+ input wire tx_enable,
+
+ output reg tx_ready,
+ output wire tx
+);
+
+ localparam CYCLE = CLK_FREQ / BAUD_RATE;
+
+ localparam IDLE = 2'd0;
+ localparam START = 2'd1;
+ localparam DATA = 2'd2;
+ localparam STOP = 2'd3;
+
+ reg [1:0] state = IDLE;
+ reg [1:0] next_state;
+ reg [15:0] cycle_cnt; //baud counter
+ reg tx_reg;
+ reg [2:0] bit_cnt;
+ reg [7:0] tx_data_latch = 0;
+
+
+ assign tx = tx_reg;
+
+ always@(posedge clk or posedge rst_p)begin // Avance d'etat
+ if(rst_p == 1'b1)
+ state <= IDLE;
+ else
+ state <= next_state;
+ end
+
+ always@(*) begin
+ case(state)
+ IDLE:
+ if(tx_enable == 1'b1)
+ next_state = START;
+ else
+ next_state = IDLE;
+
+ START:
+ if(cycle_cnt == CYCLE - 1)
+ next_state = DATA;
+ else
+ next_state = START;
+
+ DATA:
+ if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7)
+ next_state = STOP;
+ else
+ next_state = DATA;
+
+ STOP:
+ if(cycle_cnt == CYCLE - 1)
+ next_state = IDLE;
+ else
+ next_state = STOP;
+ default:
+ next_state = IDLE;
+ endcase
+ end
+
+ always@(posedge clk or posedge rst_p)begin // tx_ready block
+ if(rst_p == 1'b1)
+ tx_ready <= 1'b0; // Reset
+ else if(state == IDLE && tx_enable == 1'b1)
+ tx_ready <= 1'b0; // Pas prêt tant que les données sont valides
+ else if(state == IDLE)
+ tx_ready <= 1'b1;
+ else if(state == STOP && cycle_cnt == CYCLE - 1)
+ tx_ready <= 1'b1; // Prêt une fois le bit STOP envoyé
+ else
+ tx_ready <= tx_ready; // Reste inchangé dans d'autres cas
+ end
+
+
+
+ always@(posedge clk or posedge rst_p) begin // tx_data_latch block
+ if(rst_p == 1'b1) begin
+ tx_data_latch <= 8'd0;
+ end else if(state == IDLE && tx_enable == 1'b1) begin
+ tx_data_latch <= data; // Charger les données de data dans tx_data_latch
+ end
+ end
+
+
+ always@(posedge clk or posedge rst_p)begin // DATA bit_cnt block
+ if(rst_p == 1'b1)begin
+ bit_cnt <= 3'd0;
+
+ end else if(state == DATA)
+ if(cycle_cnt == CYCLE - 1)
+ bit_cnt <= bit_cnt + 3'd1;
+ else
+ bit_cnt <= bit_cnt;
+ else
+ bit_cnt <= 3'd0;
+ end
+
+
+ always@(posedge clk or posedge rst_p)begin // Cycle counter
+ if(rst_p == 1'b1)
+ cycle_cnt <= 16'd0;
+
+ else if((state == DATA && cycle_cnt == CYCLE - 1) || next_state != state)
+ cycle_cnt <= 16'd0;
+ else
+ cycle_cnt <= cycle_cnt + 16'd1;
+ end
+
+ always@(posedge clk or posedge rst_p)begin // tx state managment
+ if(rst_p == 1'b1)
+ tx_reg <= 1'b1;
+ else
+ case(state)
+ IDLE,STOP:
+ tx_reg <= 1'b1;
+ START:
+ tx_reg <= 1'b0;
+ DATA:
+ tx_reg <= tx_data_latch[bit_cnt]; // SENDING BYTE HERE
+ default:
+ tx_reg <= 1'b1;
+ endcase
+ end
+endmodule
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx_fifo.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx_fifo.v
new file mode 100644
index 0000000..5d5387b
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/uart_tx_fifo.v
@@ -0,0 +1,89 @@
+module uart_tx_fifo #(
+ parameter CLK_FREQ = 27_000_000,
+ parameter BAUD_RATE = 115200,
+ parameter FIFO_SIZE = 8
+)(
+ input clk,
+ input wr_en,
+ input [7:0] wr_data,
+ output tx_pin,
+ output fifo_full
+);
+
+ // FIFO wires
+ wire [7:0] fifo_rd_data;
+ wire fifo_empty;
+ reg fifo_rd_en;
+
+ // UART wires
+ wire tx_busy;
+ reg uart_tx_enable;
+ reg [7:0] uart_tx_data;
+
+ // FSM
+ typedef enum logic [1:0] {
+ IDLE,
+ WAIT_READY,
+ READ_FIFO,
+ SEND
+ } state_t;
+
+ state_t state = IDLE;
+
+ // FIFO instantiation
+ fifo #(
+ .WIDTH(8),
+ .SIZE(FIFO_SIZE)
+ ) fifo_inst (
+ .clk(clk),
+ .wr_en(wr_en),
+ .wr_data(wr_data),
+ .rd_en(fifo_rd_en),
+ .rd_data(fifo_rd_data),
+ .empty(fifo_empty),
+ .full(fifo_full)
+ );
+
+ // UART TX instantiation
+ txuartlite uart_tx_inst (
+ .i_clk(clk),
+ .i_reset(1'b0),
+ .i_wr(uart_tx_enable),
+ .i_data(uart_tx_data),
+ .o_uart_tx(tx_pin),
+ .o_busy(tx_busy)
+ );
+
+ always_ff @(posedge clk) begin
+ fifo_rd_en <= 0;
+ uart_tx_enable <= 0;
+
+ case (state)
+ IDLE: begin
+ if (!fifo_empty)
+ state <= WAIT_READY;
+ end
+
+ WAIT_READY: begin
+ if (!tx_busy) begin
+ fifo_rd_en <= 1;
+ uart_tx_data <= fifo_rd_data;
+ state <= READ_FIFO;
+ end
+ end
+
+ READ_FIFO: begin
+ // fifo_rd_data sera valide ici
+ fifo_rd_en <= 0;
+ uart_tx_enable <= 1;
+ state <= SEND;
+ end
+
+ SEND: begin
+ state <= IDLE;
+ uart_tx_enable <= 0;
+ end
+ endcase
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_fpga.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_fpga.v
new file mode 100644
index 0000000..c11d19e
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_fpga.v
@@ -0,0 +1,152 @@
+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 busy,
+ output reg done
+);
+ reg [15:0] trig_counter = 0;
+ reg [31:0] echo_counter = 0;
+ reg [31:0] echo_div_counter = 0;
+ reg [15:0] distance_counter = 0;
+
+ 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;
+
+
+ localparam IDLE = 3'd0,
+ TRIG_HIGH = 3'd1,
+ TRIG_LOW = 3'd2,
+ WAIT_ECHO = 3'd3,
+ MEASURE_ECHO = 3'd4,
+ COMPUTE = 3'd5,
+ DONE = 3'd6,
+ WAIT_NEXT = 3'd7;
+ reg [2:0] state = IDLE;
+
+
+ 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) / 1000000;
+
+ localparam WAIT_NEXT_CYCLES = (CLK_FREQ / 1000) * 100; // 60 ms
+
+ reg [31:0] wait_counter;
+
+ always @(posedge clk) begin
+ sig_int <= sig;
+ sig_ok <= sig_int;
+ end
+
+ always @(posedge clk) begin
+ busy <= (state != IDLE);
+ end
+
+ always @(posedge clk) begin // FSM
+
+ case (state)
+ IDLE: begin
+ done <= 0;
+ sig_out <= 0;
+ sig_dir <= 0;
+ distance <= 0;
+ if (start) begin
+ state <= TRIG_HIGH;
+ trig_counter <= 0;
+ done <= 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
+
+ if (sig_ok) begin
+ state <= TRIG_LOW;
+ end else
+ 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
+ state <= DONE;
+ end
+
+ end else begin
+ state <= COMPUTE;
+ end
+ end
+
+ COMPUTE: begin
+ if (echo_counter >= DIST_DIVISOR) begin
+ echo_counter <= echo_counter - DIST_DIVISOR;
+ distance_counter <= distance_counter + 1;
+ state <= COMPUTE;
+ end else begin
+ distance <= distance_counter;
+ state <= DONE;
+ end
+ end
+
+ DONE: begin
+ if (start) begin
+ wait_counter <= 0;
+ state <= WAIT_NEXT;
+ end else begin
+ state <= IDLE;
+ end
+ done <= 1;
+ end
+
+ WAIT_NEXT: begin
+ wait_counter <= wait_counter + 1;
+ if (wait_counter >= WAIT_NEXT_CYCLES) begin
+ state <= TRIG_HIGH;
+ trig_counter <= 0;
+ distance_counter <= 0;
+ echo_counter <= 0;
+ end
+ end
+
+ default: begin
+ state <= IDLE; // Reset to IDLE state in case of an error
+ end
+ endcase
+
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_sensor.v b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_sensor.v
new file mode 100644
index 0000000..ea560c0
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/IP/verilog/ultrasonic_sensor.v
@@ -0,0 +1,95 @@
+module ultrasonic_sensor( // Simulation of an ultrasonic sensor
+ input wire clk,
+ inout wire signal // Signal from the ultrasonic sensor
+);
+ parameter integer CLK_FREQ = 27_000_000;
+
+ reg [2:0] state = 3'd0; // State of the FSM
+ reg [2:0] next_state;
+ reg sig_dir; // 1: output, 0: input
+ reg [15:0] trig_counter = 0; // Counter for the trigger pulse
+ reg [31:0] echo_counter = 0; // Echo signal
+ reg valid_trig = 0; // Valid trigger signal
+
+ reg echo_sended = 0; // Flag to indicate if echo has been sent
+
+ reg signal_out = 0;
+ assign signal = sig_dir ? signal_out : 1'bz; // Assign the signal to the output if sig_dir is high, otherwise set it to high impedance
+
+ localparam S_WAIT_TRIG = 3'd0,
+ S_MEASURE_TRIG = 3'd1,
+ S_SEND_ECHO = 3'd2;
+
+ localparam integer TRIG_PULSE_CYCLES = CLK_FREQ / 100_000; // 10us pulse
+
+ always @(*) begin
+ case (state)
+ S_WAIT_TRIG: begin
+ sig_dir = 0;
+ if (signal == 1) begin
+ next_state = S_MEASURE_TRIG;
+ end else begin
+ next_state = S_WAIT_TRIG;
+ end
+ end
+
+ S_MEASURE_TRIG: begin
+ sig_dir = 0;
+ if (valid_trig)begin
+ next_state = S_SEND_ECHO;
+ end
+ end
+
+ S_SEND_ECHO: begin
+ sig_dir = 1; // Mettre en sortie
+
+ if (echo_sended) begin
+ echo_sended = 0; // Reset flag
+ next_state = S_WAIT_TRIG;
+ end else begin
+ next_state = S_SEND_ECHO;
+ end
+ end
+
+ default: begin
+ sig_dir = 0;
+ next_state = S_WAIT_TRIG;
+ end
+ endcase
+ end
+
+ always @(posedge clk) begin
+ state <= next_state;
+ end
+
+ always @(posedge clk) begin
+ if (state == S_MEASURE_TRIG) begin
+ if (signal == 1) begin
+ trig_counter <= trig_counter + 1;
+ end else begin
+ if (trig_counter >= TRIG_PULSE_CYCLES-20) begin
+ valid_trig <= 1;
+ end else begin
+ valid_trig <= 0;
+ end
+ end
+ end
+ end
+
+ reg [15:0] echo_delay_counter;
+
+ always @(posedge clk) begin
+ if (state == S_SEND_ECHO) begin
+ if (echo_delay_counter == 5800) begin //
+ signal_out <= 0;
+ echo_sended <= 1;
+ end else begin
+ signal_out <= 1;
+ echo_delay_counter <= echo_delay_counter + 1;
+ end
+ end else begin
+ echo_delay_counter <= 0;
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/README.md b/Semaine_6/UART_ULTRASON_COMMANDS/README.md
new file mode 100644
index 0000000..34702e3
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/README.md
@@ -0,0 +1,9 @@
+# ULTRASON VIA UART
+
+## Description
+This project is designed to control an ultrasonic sensor using UART communication. The ultrasonic sensor is used to measure distance, and the data is transmitted via UART to a connected device.
+
+## Commands
+0x01: Start one mesurement of the distance.
+0x02: Start continuous mesurement of the distance.
+0x03: Stop continuous mesurement of the distance.
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/constraints/top_uart_ultrason_command.cst b/Semaine_6/UART_ULTRASON_COMMANDS/constraints/top_uart_ultrason_command.cst
new file mode 100644
index 0000000..110a02b
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/constraints/top_uart_ultrason_command.cst
@@ -0,0 +1,24 @@
+IO_LOC "tx" 69;
+IO_PORT "tx" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
+
+IO_LOC "rx" 70;
+IO_PORT "rx" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
+
+IO_LOC "clk" 4;
+IO_PORT "clk" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
+
+IO_LOC "ultrason_sig" 73;
+IO_PORT "ultrason_sig" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
+
+IO_LOC "leds[0]" 15;
+IO_PORT "leds[0]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
+IO_LOC "leds[1]" 16;
+IO_PORT "leds[1]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
+IO_LOC "leds[2]" 17;
+IO_PORT "leds[2]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
+IO_LOC "leds[3]" 18;
+IO_PORT "leds[3]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
+IO_LOC "leds[4]" 19;
+IO_PORT "leds[4]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
+IO_LOC "leds[5]" 20;
+IO_PORT "leds[5]" PULL_MODE=UP DRIVE=8 BANK_VCCIO=1.8;
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/project.bat b/Semaine_6/UART_ULTRASON_COMMANDS/project.bat
new file mode 100644
index 0000000..c087898
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/project.bat
@@ -0,0 +1,6 @@
+@call c:\oss-cad-suite\environment.bat
+@echo off
+if "%1"=="sim" call scripts\windows\simulate.bat
+if "%1"=="wave" call scripts\windows\gtkwave.bat
+if "%1"=="clean" call scripts\windows\clean.bat
+if "%1"=="build" call scripts\windows\build.bat
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/project.sh b/Semaine_6/UART_ULTRASON_COMMANDS/project.sh
new file mode 100644
index 0000000..7c0497b
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/project.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# Charger l'environnement OSS CAD Suite
+source /home/louis/oss-cad-suite/environment
+
+case "$1" in
+ sim)
+ bash scripts/linux/simulate.sh
+ ;;
+ wave)
+ bash scripts/linux/gtkwave.sh
+ ;;
+ clean)
+ bash scripts/linux/clean.sh
+ ;;
+ build)
+ bash scripts/linux/build.sh
+ ;;
+ *)
+ echo "Usage: $0 {sim|wave|clean|build}"
+ ;;
+esac
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/build.sh b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/build.sh
new file mode 100644
index 0000000..3c59fe2
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/build.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Aller à la racine du projet
+cd "$(dirname "$0")/../.." || exit 1
+
+# Config de base
+DEVICE="GW2AR-LV18QN88C8/I7"
+BOARD="tangnano20k"
+TOP="top_uart_ultrason_command"
+CST_FILE="$TOP.cst"
+JSON_FILE="runs/$TOP.json"
+PNR_JSON="runs/pnr_$TOP.json"
+BITSTREAM="runs/$TOP.fs"
+
+# Créer le dossier runs si nécessaire
+mkdir -p runs
+
+echo "=== Étape 1 : Synthèse avec Yosys ==="
+yosys -p "read_verilog -sv src/verilog/$TOP.v IP/verilog/ultrasonic_fpga.v IP/verilog/uart_tx_fifo.v IP/verilog/uart_rx_fifo.v IP/verilog/rxuartlite.v IP/verilog/fifo.v IP/verilog/uart_tx.v; synth_gowin -top $TOP -json $JSON_FILE"
+if [ $? -ne 0 ]; then
+ echo "=== Erreur lors de la synthèse ==="
+ exit 1
+fi
+
+echo "=== Étape 2 : Placement & Routage avec nextpnr-himbaechel ==="
+nextpnr-himbaechel --json "$JSON_FILE" --write "$PNR_JSON" --device "$DEVICE" --vopt cst=constraints/"$CST_FILE" --vopt family=GW2A-18C
+if [ $? -ne 0 ]; then
+ echo "=== Erreur lors du placement/routage ==="
+ exit 1
+fi
+
+echo "=== Étape 3 : Packing avec gowin_pack ==="
+gowin_pack -d "$DEVICE" -o "$BITSTREAM" "$PNR_JSON"
+if [ $? -ne 0 ]; then
+ echo "=== Erreur lors du packing ==="
+ exit 1
+fi
+
+echo "=== Étape 4 : Flash avec openFPGALoader ==="
+openFPGALoader -b "$BOARD" "$BITSTREAM"
+if [ $? -ne 0 ]; then
+ echo "=== Erreur lors du flash ==="
+ exit 1
+fi
+
+echo "=== Compilation et flash réussis ==="
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/clean.sh b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/clean.sh
new file mode 100644
index 0000000..a505cb7
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/clean.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo "=== Nettoyage des fichiers générés ==="
+rm -rf runs/*
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/gtkwave.sh b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/gtkwave.sh
new file mode 100644
index 0000000..3c97f71
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/gtkwave.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+echo "=== Lancement de GTKWave ==="
+gtkwave runs/ultrason_commands.vcd
+echo "=== GTKWave terminé ==="
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/simulate.sh b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/simulate.sh
new file mode 100644
index 0000000..72e0421
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/linux/simulate.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+echo "=== Simulation avec Icarus Verilog ==="
+
+OUT="runs/sim.vvp"
+TOP="tb_ultrason_commands"
+DIRS=("src/verilog" "tests/verilog" "IP/verilog")
+
+FILES=()
+for dir in "${DIRS[@]}"; do
+ for file in "$dir"/*.v; do
+ FILES+=("$file")
+ done
+done
+
+iverilog -g2012 -o "$OUT" -s "$TOP" "${FILES[@]}"
+vvp "$OUT"
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/build.bat b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/build.bat
new file mode 100644
index 0000000..8182a70
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/build.bat
@@ -0,0 +1,45 @@
+@echo off
+setlocal
+
+rem === Aller à la racine du projet ===
+cd /d %~dp0\..\..
+
+rem === Config de base ===
+set DEVICE=GW2AR-LV18QN88C8/I7
+set BOARD=tangnano20k
+set TOP=top_uart_ultrason_command
+set CST_FILE=%TOP%.cst
+set JSON_FILE=runs/%TOP%.json
+set PNR_JSON=runs/pnr_%TOP%.json
+set BITSTREAM=runs/%TOP%.fs
+
+rem === Créer le dossier runs si nécessaire ===
+if not exist runs (
+ mkdir runs
+)
+
+echo === Étape 1 : Synthèse avec Yosys ===
+yosys -p "read_verilog -sv src/verilog/%TOP%.v IP/verilog/ultrasonic_fpga.v IP/verilog/uart_tx_fifo.v IP/verilog/uart_rx_fifo.v IP/verilog/rxuartlite.v IP/verilog/txuartlite.v IP/verilog/fifo.v; synth_gowin -top %TOP% -json %JSON_FILE%"
+if errorlevel 1 goto error
+
+echo === Étape 2 : Placement & Routage avec nextpnr-himbaechel ===
+nextpnr-himbaechel --json %JSON_FILE% --write %PNR_JSON% --device %DEVICE% --vopt cst=constraints/%CST_FILE% --vopt family=GW2A-18C
+if errorlevel 1 goto error
+
+echo === Étape 3 : Packing avec gowin_pack ===
+gowin_pack -d %DEVICE% -o %BITSTREAM% %PNR_JSON%
+if errorlevel 1 goto error
+
+echo === Étape 4 : Flash avec openFPGALoader ===
+openFPGALoader -b %BOARD% %BITSTREAM%
+if errorlevel 1 goto error
+
+echo === Compilation et flash réussis ===
+goto end
+
+:error
+echo === Une erreur est survenue ===
+
+:end
+endlocal
+pause
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/clean.bat b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/clean.bat
new file mode 100644
index 0000000..6192ae1
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/clean.bat
@@ -0,0 +1,4 @@
+@echo off
+echo === Nettoyage du dossier runs ===
+rd /s /q runs
+mkdir runs
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/gtkwave.bat b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/gtkwave.bat
new file mode 100644
index 0000000..a9771b8
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/gtkwave.bat
@@ -0,0 +1,3 @@
+@echo off
+echo === Lancement de GTKWave ===
+gtkwave runs/ultrason_commands.vcd
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/simulate.bat b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/simulate.bat
new file mode 100644
index 0000000..f238785
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/scripts/windows/simulate.bat
@@ -0,0 +1,29 @@
+@echo off
+echo === Simulation avec Icarus Verilog ===
+setlocal enabledelayedexpansion
+
+:: Dossier de sortie
+set OUT=runs/sim.vvp
+
+:: Top-level testbench module
+set TOP=tb_ultrason_commands
+
+:: Répertoires contenant des fichiers .v
+set DIRS=src/verilog tests/verilog IP/verilog
+
+:: Variable pour stocker les fichiers
+set FILES=
+
+:: Boucle sur chaque dossier
+for %%D in (%DIRS%) do (
+ for %%F in (%%D\*.v) do (
+ set FILES=!FILES! %%F
+ )
+)
+
+:: Compilation avec Icarus Verilog
+iverilog -g2012 -o %OUT% -s %TOP% %FILES%
+
+endlocal
+
+vvp runs/sim.vvp
\ No newline at end of file
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/src/verilog/top_uart_ultrason_command.v b/Semaine_6/UART_ULTRASON_COMMANDS/src/verilog/top_uart_ultrason_command.v
new file mode 100644
index 0000000..eb56ab0
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/src/verilog/top_uart_ultrason_command.v
@@ -0,0 +1,177 @@
+module top_uart_ultrason_command (
+ input wire clk, // 27 MHz
+ output wire tx,
+ input wire rx,
+ inout wire ultrason_sig, // Capteur ultrason
+ output reg [5:0] leds
+);
+
+ // === UART RX WIRE ===
+ wire [7:0] rd_data;
+ reg rd_en = 0;
+ wire data_available;
+
+ // RX FIFO Instance
+ uart_rx_fifo uart_rx_inst (
+ .clk(clk),
+ .rx_pin(rx),
+ .rd_data(rd_data),
+ .rd_en(rd_en),
+ .data_available(data_available)
+ );
+
+ // === UART TX WIRE ===
+ reg [7:0] wr_data;
+ reg wr_en;
+ wire tx_fifo_full;
+
+ // === UART TX FIFO ===
+ uart_tx_fifo uart_tx_inst (
+ .clk(clk),
+ .wr_en(wr_en),
+ .wr_data(wr_data),
+ .fifo_full(tx_fifo_full),
+ .tx_pin(tx)
+ );
+
+ // === Ultrasonic ===
+ reg start = 0;
+ wire ultrasonic_busy;
+ wire [15:0] distance;
+ wire ultrason_done;
+
+ ultrasonic_fpga #(
+ .CLK_FREQ(27_000_000)
+ ) ultrasonic_inst (
+ .clk(clk),
+ .start(start),
+ .sig(ultrason_sig),
+ .distance(distance),
+ .busy(ultrasonic_busy),
+ .done(ultrason_done)
+ );
+
+ // === FSM ===
+ localparam IDLE = 0, ONESTART = 1, ONESTOP = 2, CONTINUOUSSTART = 3, CONTINUOUSSTOP = 4, WAIT = 5, NEXT_FIFO = 6;
+
+ reg [1:0] command = 0;
+
+ reg [31:0] delay_counter = 0;
+
+ localparam US_STATE_WIDTH = $clog2(NEXT_FIFO)+1;
+ reg [US_STATE_WIDTH-1:0] mesure_state = IDLE;
+
+ always @(posedge clk) begin
+ if (data_available) begin
+ command <= rd_data[1:0];
+ leds <= rd_data[7:2];
+ end
+ end
+
+ always @(posedge clk) begin // Mesure state machine
+ case (mesure_state)
+ IDLE: begin
+ if (command == 2'd1 && data_available) begin
+ mesure_state <= ONESTART;
+ rd_en <= 1;
+ end else if (command == 2'd2 && data_available) begin
+ mesure_state <= CONTINUOUSSTART;
+ rd_en <= 1;
+ end else begin
+ mesure_state <= IDLE;
+ rd_en <= 0;
+ end
+ end
+
+ ONESTART: begin
+ start <= 1;
+ mesure_state <= ONESTOP;
+ rd_en <= 0;
+ end
+
+ ONESTOP: begin
+ start <= 0;
+ mesure_state <= IDLE;
+ end
+
+ CONTINUOUSSTART: begin
+ if (command == 3) begin
+ mesure_state <= NEXT_FIFO;
+ rd_en <= 1;
+ end else begin
+ mesure_state <= CONTINUOUSSTOP;
+ start <= 1;
+ rd_en <= 0;
+ end
+ end
+
+ CONTINUOUSSTOP: begin
+ start <= 0;
+ mesure_state <= WAIT;
+ end
+
+ WAIT: begin // Compteur 0.5s
+ if (delay_counter > 1) begin
+ delay_counter <= delay_counter - 1;
+ end else begin
+ mesure_state <= CONTINUOUSSTART;
+ delay_counter <= 13500000;
+ end
+ end
+
+ NEXT_FIFO: begin
+ rd_en <= 1;
+ mesure_state <= IDLE;
+ end
+
+ endcase
+ end
+
+ localparam BUSY = 1, SEND_LOW = 2, SEND_HIGH = 3, DONE = 4;
+ reg [1:0] saver_state = IDLE;
+ always @(posedge clk) begin // FSM Pour enregistrer la distance
+ case (saver_state)
+ IDLE: begin
+ wr_en <= 0;
+ if (ultrasonic_busy) begin
+ saver_state <= BUSY;
+ end else begin
+ saver_state <= IDLE;
+ end
+ end
+
+ BUSY: begin
+ if (ultrason_done) begin
+ saver_state <= SEND_LOW;
+ wr_en <= 1;
+ wr_data <= distance[7:0];
+ end else if(ultrasonic_busy) begin
+ saver_state <= BUSY;
+ end else begin
+ saver_state <= IDLE;
+ end
+ end
+
+ SEND_LOW: begin
+ wr_en <= 1;
+ wr_data <= distance[15:8];
+ saver_state <= SEND_HIGH;
+
+ end
+
+ SEND_HIGH: begin
+ wr_en <= 0;
+ saver_state <= DONE;
+ end
+
+ DONE: begin
+ wr_data <= 0;
+ wr_en <= 0;
+ saver_state <= IDLE;
+ end
+
+ endcase
+
+ end
+
+endmodule
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/tests/Python/ultrason_command.py b/Semaine_6/UART_ULTRASON_COMMANDS/tests/Python/ultrason_command.py
new file mode 100644
index 0000000..2bdab1e
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/tests/Python/ultrason_command.py
@@ -0,0 +1,68 @@
+import serial
+import time
+import struct
+
+# === Paramètres de communication ===
+SERIAL_PORT = "COM6" # Modifie selon ton système, ex. "/dev/ttyUSB0" sur Linux
+BAUDRATE = 115200 # Change si différent
+TIMEOUT = 2 # secondes
+
+# === Commandes (doivent correspondre aux valeurs Verilog) ===
+CMD_STOP = 3
+CMD_ONE = 1
+CMD_CONTINUOUS = 2
+
+def send_command(ser, command):
+ """Envoie une commande au FPGA"""
+ ser.write(bytes([command]))
+
+def read_distance(ser):
+ """Lit 2 octets et les convertit en distance (int16)"""
+ data = ser.read(2)
+ if len(data) != 2:
+ return None
+ # Interprétation little-endian (LSB, MSB)
+ lsb, msb = data[0], data[1]
+ distance = msb << 8 | lsb
+ return distance
+
+def main():
+ with serial.Serial(SERIAL_PORT, BAUDRATE, timeout=TIMEOUT) as ser:
+ print("Connexion ouverte sur", SERIAL_PORT)
+
+ mode = input("Mode (one / continuous / stop) ? ").strip().lower()
+
+ if mode == "one":
+ send_command(ser, CMD_ONE)
+ print("Mesure unique demandée. Attente résultat...")
+ time.sleep(0.05)
+ distance = read_distance(ser)
+ if distance is not None:
+ print(f"Distance mesurée : {distance} cm")
+ else:
+ print("Erreur : distance non reçue.")
+
+ elif mode == "continuous":
+ send_command(ser, CMD_CONTINUOUS)
+ print("Mesures continues (CTRL+C pour stopper) :")
+ try:
+ while True:
+ distance = read_distance(ser)
+ if distance is not None:
+ print(f"Distance : {distance} cm")
+ else:
+ print("... (aucune donnée reçue)")
+ time.sleep(0.1)
+ except KeyboardInterrupt:
+ send_command(ser, CMD_STOP)
+ print("\nMesure continue arrêtée.")
+
+ elif mode == "stop":
+ send_command(ser, CMD_STOP)
+ print("Commande STOP envoyée.")
+
+ else:
+ print("Commande invalide.")
+
+if __name__ == "__main__":
+ main()
diff --git a/Semaine_6/UART_ULTRASON_COMMANDS/tests/verilog/tb_ultrason_commands.v b/Semaine_6/UART_ULTRASON_COMMANDS/tests/verilog/tb_ultrason_commands.v
new file mode 100644
index 0000000..dedeead
--- /dev/null
+++ b/Semaine_6/UART_ULTRASON_COMMANDS/tests/verilog/tb_ultrason_commands.v
@@ -0,0 +1,187 @@
+`timescale 1ns/1ps
+
+module tb_ultrason_commands;
+
+ // === Signaux ===
+ reg clk = 0;
+ always #18.5 clk = ~clk; // Horloge 27 MHz (période ~37ns)
+
+ wire tx, rx;
+ wire [5:0] leds;
+ wire ultrason_sig;
+
+ reg tx_enable = 0;
+ wire tx_ready;
+ reg [7:0] data_in = 8'h00;
+ wire [7:0] data_out;
+ wire data_available;
+ reg rd_en = 0;
+
+ // === Paramètres ===
+ localparam CLK_FREQ = 27_000_000;
+ localparam BAUD_RATE = 115_200;
+ localparam CLK_PERIOD = 37; // ns
+
+ // === Module testé ===
+ top_uart_ultrason_command dut (
+ .clk(clk),
+ .rx(rx),
+ .tx(tx),
+ .ultrason_sig(ultrason_sig),
+ .leds(leds)
+ );
+
+ // === Simulation capteur ultrason ===
+ // Supposons que fake_sensor fournit un signal 'distance' pour vérification
+ wire [15:0] sensor_distance;
+ ultrasonic_sensor fake_sensor (
+ .clk(clk),
+ .signal(ultrason_sig),
+ );
+
+ // === RX FIFO pour observer la sortie UART ===
+ uart_rx_fifo #(
+ .CLK_FREQ(CLK_FREQ),
+ .BAUD_RATE(BAUD_RATE)
+ ) uart_rx_fifo_inst (
+ .clk(clk),
+ .rx_pin(tx),
+ .rd_en(rd_en),
+ .rd_data(data_out),
+ .data_available(data_available)
+ );
+
+ // === TX pour injecter des commandes UART ===
+ uart_tx #(
+ .CLK_FREQ(CLK_FREQ),
+ .BAUD_RATE(BAUD_RATE)
+ ) uart_tx_inst (
+ .clk(clk),
+ .tx_enable(tx_enable),
+ .tx_ready(tx_ready),
+ .data(data_in),
+ .tx(rx),
+ .rst_p(1'b0)
+ );
+
+ // === Tâches pour simplifier les tests ===
+ task send_command(input [7:0] cmd);
+ begin
+ wait(tx_ready);
+ $display("[%0t ns] Envoi commande: %0d", $time, cmd);
+ data_in = cmd;
+ tx_enable = 1;
+ #(CLK_PERIOD * 2);
+ tx_enable = 0;
+ end
+ endtask
+
+ task read_distance(output [15:0] distance);
+ reg [7:0] lsb, msb;
+ begin
+ // Attendre premier octet (LSB)
+ wait(data_available);
+ #(CLK_PERIOD);
+ rd_en = 1;
+ #(CLK_PERIOD);
+ lsb = data_out;
+ rd_en = 0;
+ $display("[%0t ns] Reçu octet LSB: %0d", $time, lsb);
+
+ // Attendre second octet (MSB)
+ wait(data_available);
+ #(CLK_PERIOD);
+ rd_en = 1;
+ #(CLK_PERIOD);
+ msb = data_out;
+ rd_en = 0;
+ $display("[%0t ns] Reçu octet MSB: %0d", $time, msb);
+
+ distance = {msb, lsb};
+ end
+ endtask
+
+ task check_leds(input [7:0] cmd);
+ begin
+ #(CLK_PERIOD * 10); // Attendre mise à jour des LEDs
+ if (leds !== cmd[7:2]) begin
+ $display("[%0t ns] ERREUR: LEDs=%b, attendu=%b", $time, leds, cmd[7:2]);
+ end else begin
+ $display("[%0t ns] LEDs correctes: %b", $time, leds);
+ end
+ end
+ endtask
+
+ // === Séquence de test ===
+ initial begin
+ $dumpfile("runs/ultrason_commands.vcd");
+ $dumpvars(0, tb_ultrason_commands);
+
+ $display("==== Début Test UART Ultrason ====");
+
+ // Initialisation
+ #(CLK_PERIOD * 10);
+
+ // Test 1: Commande ONE (8'd1)
+ $display("=== Test 1: Commande ONE ===");
+ send_command(8'd1); // Commande: ONE
+ check_leds(8'd1);
+ begin
+ reg [15:0] received_distance;
+ read_distance(received_distance);
+ if (received_distance == sensor_distance) begin
+ $display("[%0t ns] Distance correcte: %0d", $time, received_distance);
+ end else begin
+ $display("[%0t ns] ERREUR: Distance reçue=%0d, attendu=%0d", $time, received_distance, sensor_distance);
+ end
+ end
+
+ // Test 2: Commande CONTINUOUS (8'd2)
+ $display("=== Test 2: Commande CONTINUOUS ===");
+ send_command(8'd2); // Commande: CONTINUOUS
+ check_leds(8'd2);
+ repeat (3) begin // Lire 3 mesures consécutives
+ reg [15:0] received_distance;
+ read_distance(received_distance);
+ if (received_distance == sensor_distance) begin
+ $display("[%0t ns] Distance continue correcte: %0d", $time, received_distance);
+ end else begin
+ $display("[%0t ns] ERREUR: Distance reçue=%0d, attendu=%0d", $time, received_distance, sensor_distance);
+ end
+ #(CLK_PERIOD * 13500000); // Attendre ~0.5s (délai dans WAIT)
+ end
+
+ // Test 3: Commande STOP (8'd3)
+ $display("=== Test 3: Commande STOP ===");
+ send_command(8'd3); // Commande: STOP
+ check_leds(8'd3);
+ #(CLK_PERIOD * 13500000); // Attendre pour vérifier l'arrêt
+
+ if (data_available) begin
+ $display("[%0t ns] Vérification STOP: aucune donnée ne doit être reçue", $time);
+ #(CLK_PERIOD * 1000);
+ if (data_available) begin
+ $display("[%0t ns] ERREUR: Données reçues après STOP", $time);
+ end else begin
+ $display("[%0t ns] STOP correct: aucune donnée reçue", $time);
+ end
+ end
+
+ // Test 4: Commande invalide (8'd4)
+ $display("=== Test 4: Commande invalide ===");
+ send_command(8'd4); // Commande invalide
+ #(CLK_PERIOD * 1000);
+ if (data_available) begin
+ $display("[%0t ns] ERREUR: Données reçues pour commande invalide", $time);
+ end else begin
+ $display("[%0t ns] Commande invalide ignorée correctement", $time);
+ end
+
+ // Fin de la simulation
+ $display("==== Fin Test UART Ultrason ====");
+ #(CLK_PERIOD * 1000);
+ $stop;
+ end
+
+
+endmodule
\ No newline at end of file