diff --git a/Semaine 1/UARTV2/memo.png b/Semaine 1/UARTV2/memo.png new file mode 100644 index 0000000..87b7ec1 Binary files /dev/null and b/Semaine 1/UARTV2/memo.png differ diff --git a/Semaine 1/UARTV2/tb_top_uart_rx_tx.v b/Semaine 1/UARTV2/tb_top_uart_rx_tx.v new file mode 100644 index 0000000..6c9dc52 --- /dev/null +++ b/Semaine 1/UARTV2/tb_top_uart_rx_tx.v @@ -0,0 +1,69 @@ +`timescale 1ns / 1ps + +module tb_top_uart_rx_tx; + + parameter CLK_FREQ = 27_000_000; + parameter BAUD_RATE = 115200; + + // Signaux + reg clk = 0; + reg start = 0; + reg [7:0] data_in = 0; + wire [7:0] data_out; + wire valid; + wire tx; + wire rx; // On connecte tx directement à rx pour le test + + // Instance du module à tester + top_uart_rx_tx #( + .CLK_FREQ(CLK_FREQ), + .BAUD_RATE(BAUD_RATE) + ) uut ( + .clk(clk), + .start(start), + .data_in(data_in), + .rx(rx), + .data_out(data_out), + .valid(valid), + .tx(tx) + ); + + // Boucle le tx sur rx + assign rx = tx; + + // Clock à 50 MHz (20 ns période) + always #10 clk = ~clk; + + // Simulation principale + initial begin + $display("Début de la simulation"); + $dumpfile("uart_loopback.vcd"); // Pour GTKWave + $dumpvars(0, tb_top_uart_rx_tx); + + // Attendre un peu + #(20 * 10); + + // Envoi d'une valeur + data_in = 8'hA5; // Exemple de data + start = 1; + #20; + start = 0; + + // Attendre la réception (valeur valid = 1) + wait(valid == 1); + + // Affichage des résultats + $display("Data envoyee : 0x%h", data_in); + $display("Data recue : 0x%h", data_out); + + if (data_out == data_in) + $display("Test reussi !"); + else + $display("Test echoue..."); + + // Fin de simulation + #(20 * 10); + $finish; + end + +endmodule \ No newline at end of file diff --git a/Semaine 1/UARTV2/tb_uart_rx.v b/Semaine 1/UARTV2/tb_uart_rx.v new file mode 100644 index 0000000..874dfd7 --- /dev/null +++ b/Semaine 1/UARTV2/tb_uart_rx.v @@ -0,0 +1,64 @@ +`timescale 1ns / 1ps + +module tb_uart_rx; + + reg clk = 0; + reg rx = 1; + wire [7:0] data; + wire valid; + wire ready; + + localparam CLK_FREQ = 27_000_000; + localparam BAUD_RATE = 115_200; + localparam BIT_PERIOD = CLK_FREQ / BAUD_RATE; + localparam CLK_PERIOD_NS = 1000000000 / CLK_FREQ; + + uart_rx #( + .CLK_FREQ(CLK_FREQ), + .BAUD_RATE(BAUD_RATE) + ) rx_instance ( + .clk(clk), + .rx(rx), + .data(data), + .valid(valid), + .ready(ready) + ); + + always #(CLK_PERIOD_NS/2) clk = ~clk; + + task send_bit(input reg b); + begin + rx <= b; + #(BIT_PERIOD * CLK_PERIOD_NS); + end + endtask + + integer i; + + task send_byte(input [7:0] byte); + begin + send_bit(0); + for (i = 0; i < 8; i = i + 1) + send_bit(byte[i]); + send_bit(1); + + #(BIT_PERIOD * CLK_PERIOD_NS); + end + endtask + + initial begin + $display("Start UART RX test"); + #100; + + send_byte(8'b01010101); + + #(10 * BIT_PERIOD * CLK_PERIOD_NS); + + if (valid && data == 8'b01010101) + $display("Test ok : data = %b", data); + else + $display("Test pas ok : data = %b, valid = %b", data, valid); + + $finish; + end +endmodule diff --git a/Semaine 1/UARTV2/tb_uart_tx.v b/Semaine 1/UARTV2/tb_uart_tx.v new file mode 100644 index 0000000..4c1fe2d --- /dev/null +++ b/Semaine 1/UARTV2/tb_uart_tx.v @@ -0,0 +1,49 @@ +`timescale 1ns/1ps + +module tb_uart_tx; + + reg clk = 0; + reg start = 0; + reg [7:0] data = 8'h00; + wire tx; + wire busy; + + always #18.5 clk = ~clk; + + uart_tx #( + .CLK_FREQ(27_000_000), + .BAUD_RATE(115_200) + )tx_instance ( + .clk(clk), + .start(start), + .data(data), + .tx(tx), + .busy(busy) + ); + + initial begin + $dumpfile("uart_tx.vcd"); + $dumpvars(0, tb_uart_tx); + + #100; + + data <= 8'hA5; // 10100101 0xA5 + start <= 1; + #37 start <= 0; + + // Attendre + wait (busy == 0); + + #1000; + + data <= 8'h3C; // 00111100 0x3C + start <= 1; + #37 start <= 0; + + wait (busy == 0); + + #1000; + $stop; + end + +endmodule \ No newline at end of file diff --git a/Semaine 1/UARTV2/top_led_uart.v b/Semaine 1/UARTV2/top_led_uart.v new file mode 100644 index 0000000..d198e56 --- /dev/null +++ b/Semaine 1/UARTV2/top_led_uart.v @@ -0,0 +1,61 @@ +module top_led_uart( + input wire clk, + input wire rx, + output wire tx, + output reg [5:0] leds +); + wire [7:0] data_out; + wire valid; + reg start_tx = 0; + reg [7:0] data_in = 0; + + top_uart_rx_tx uart ( + .clk(clk), + .start(start_tx), + .data_in(data_in), + .rx(rx), + .data_out(data_out), + .valid(valid), + .tx(tx) + ); + + reg [1:0] state = 0; + localparam IDLE = 2'd0; + localparam TOGGLE = 2'd1; + localparam SEND_BACK = 2'd2; + + always @(posedge clk) begin + case (state) + INIT: begin + leds <= 6'b000000; + start_tx <= 0; + if (valid) begin + + leds <= data_out[5:0]; + state <= SEND_BACK; + + end + end + IDLE: begin + start_tx <= 0; + if (valid) begin + + leds <= data_out[5:0]; + state <= SEND_BACK; + + end + end + + SEND_BACK: begin + data_in <= data_out; + start_tx <= 1; + state <= TOGGLE; + end + + TOGGLE: begin + start_tx <= 0; + state <= IDLE; + end + endcase + end +endmodule diff --git a/Semaine 1/UARTV2/top_uart_rx_tx.v b/Semaine 1/UARTV2/top_uart_rx_tx.v new file mode 100644 index 0000000..02cd774 --- /dev/null +++ b/Semaine 1/UARTV2/top_uart_rx_tx.v @@ -0,0 +1,119 @@ +module uart_top( + input clk, + input rst, + input uart_rx, + output uart_tx +); + +parameter CLK_FRE = 27_000_000; // Mhz +parameter UART_FRE = 115200; // Baud + +localparam IDLE = 0; +localparam SEND = 1; // send +localparam WAIT = 2; // wait 1 second and send uart received data + +reg[7:0] tx_data; +reg[7:0] tx_str; +reg tx_data_valid; +wire tx_data_ready; +reg[7:0] tx_cnt; + +wire[7:0] rx_data; +wire rx_data_valid; +wire rx_data_ready; + +reg[31:0] wait_cnt; +reg[3:0] state; + +wire rst_p = rst; + +assign rx_data_ready = 1'b1; //always can receive data, + +always@(posedge clk or negedge rst_p) +begin + if(rst_p == 1'b1) + begin + wait_cnt <= 32'd0; + tx_data <= 8'd0; + state <= IDLE; + tx_cnt <= 8'd0; + tx_data_valid <= 1'b0; + end + else + case(state) + IDLE:begin + state <= SEND; + end + + SEND:begin + wait_cnt <= 32'd0; + tx_data <= tx_str; + + if(tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < DATA_NUM - 1)//Send 12 bytes data + begin + tx_cnt <= tx_cnt + 8'd1; //Send data counter + end + else if(tx_data_valid && tx_data_ready)//last byte sent is complete + begin + tx_cnt <= 8'd0; + tx_data_valid <= 1'b0; + state <= WAIT; + end + else if(~tx_data_valid) + begin + tx_data_valid <= 1'b1; + end + end + + WAIT:begin + wait_cnt <= wait_cnt + 32'd1; + + if(rx_data_valid == 1'b1) + begin + tx_data_valid <= 1'b1; + tx_data <= rx_data; // send uart received data + end + else if(tx_data_valid && tx_data_ready) + begin + tx_data_valid <= 1'b0; + end + else if(wait_cnt >= CLK_FRE * 1000_000) // wait for 1 second + state <= SEND; + end + + default: + state <= IDLE; + endcase +end + +always@(*) + tx_str <= send_data[(DATA_NUM - 1 - tx_cnt) * 8 +: 8]; + +uart_rx# +( + .CLK_FRE(CLK_FRE), + .BAUD_RATE(UART_FRE) +) uart_rx_inst +( + .clk (clk), + .rst_p (rst_p), + .rx_data (rx_data), + .rx_data_valid (rx_data_valid), + .rx_data_ready (rx_data_ready), + .rx_pin (uart_rx) +); + +uart_tx# +( + .CLK_FRE(CLK_FRE), + .BAUD_RATE(UART_FRE) +) uart_tx_inst +( + .clk (clk), + .rst_p (rst_p), + .tx_data (tx_data), + .tx_data_valid (tx_data_valid), + .tx_data_ready (tx_data_ready), + .tx_pin (uart_tx) +); +endmodule \ No newline at end of file diff --git a/Semaine 1/UARTV2/uart_rx.v b/Semaine 1/UARTV2/uart_rx.v new file mode 100644 index 0000000..278ee7c --- /dev/null +++ b/Semaine 1/UARTV2/uart_rx.v @@ -0,0 +1,145 @@ +module uart_rx #( + parameter CLK_FREQ = 27_000_000, + parameter BAUD_RATE = 115200 +)( + input clk, //clock input + input rst_p, //asynchronous reset input, high active + input rx_data_ready, //data receiver module ready + input rx_pin, //serial data input + + output reg[7:0] rx_data, //received serial data + output reg rx_data_valid //received serial data is valid +); + +localparam CYCLE = CLK_FREQ * / BAUD_RATE; + +//state machine code +localparam S_IDLE = 1; +localparam S_START = 2; //start bit +localparam S_REC_BYTE = 3; //data bits +localparam S_STOP = 4; //stop bit +localparam S_DATA = 5; + +reg[2:0] state; +reg[2:0] next_state; + +reg rx_d0; //delay 1 clock for rx_pin +reg rx_d1; //delay 1 clock for rx_d0 +wire rx_negedge; //negedge of rx_pin +reg[7:0] rx_bits; //temporary storage of received data +reg[15:0] cycle_cnt; //baud counter +reg[2:0] bit_cnt; //bit counter + +assign rx_negedge = rx_d1 && ~rx_d0; // Front déscendant + +always@(posedge clk or negedge rst_p) // Filtrage du signial +begin + if(rst_p == 1'b1)begin + rx_d0 <= 1'b0; + rx_d1 <= 1'b0; + + end else begin + rx_d0 <= rx_pin; + rx_d1 <= rx_d0; + end +end + + +always@(posedge clk or negedge rst_p)begin // Compteur d'etat + if(rst_p == 1'b1) + state <= S_IDLE; + else + state <= next_state; +end + +always@(*)begin + case(state) + S_IDLE: + if(rx_negedge) // Detection du start bit + next_state = S_START; + else + next_state = S_IDLE; + + S_START: + if(cycle_cnt == CYCLE - 1) //one data cycle + next_state = S_REC_BYTE; + else + next_state = S_START; + + S_REC_BYTE: + if(cycle_cnt == CYCLE - 1 && bit_cnt == 3'd7) //receive 8bit data + next_state = S_STOP; + else + next_state = S_REC_BYTE; + + S_STOP: + if(cycle_cnt == CYCLE/2 - 1) //half bit cycle,to avoid missing the next byte receiver + next_state = S_DATA; + else + next_state = S_STOP; + + S_DATA: + if(rx_data_ready) //data receive complete + next_state = S_IDLE; + else + next_state = S_DATA; + + default: + next_state = S_IDLE; + endcase +end + +always@(posedge clk or negedge rst_p) +begin + if(rst_p == 1'b1) + rx_data_valid <= 1'b0; + else if(state == S_STOP && next_state != state) + rx_data_valid <= 1'b1; + else if(state == S_DATA && rx_data_ready) + rx_data_valid <= 1'b0; +end + +always@(posedge clk or negedge rst_p) +begin + if(rst_p == 1'b1) + rx_data <= 8'd0; + else if(state == S_STOP && next_state != state) + rx_data <= rx_bits;//latch received data +end + +always@(posedge clk or negedge rst_p) +begin + if(rst_p == 1'b1) + begin + bit_cnt <= 3'd0; + end + else if(state == S_REC_BYTE) + 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 negedge rst_p) +begin + if(rst_p == 1'b1) + cycle_cnt <= 16'd0; + else if((state == S_REC_BYTE && cycle_cnt == CYCLE - 1) || next_state != state) + cycle_cnt <= 16'd0; + else + cycle_cnt <= cycle_cnt + 16'd1; +end +//receive serial data bit data +always@(posedge clk or negedge rst_p) +begin + if(rst_p == 1'b1) + rx_bits <= 8'd0; + else if(state == S_REC_BYTE && cycle_cnt == CYCLE/2 - 1) + rx_bits[bit_cnt] <= rx_pin; + else + rx_bits <= rx_bits; +end +endmodule \ No newline at end of file diff --git a/Semaine 1/UARTV2/uart_tx.v b/Semaine 1/UARTV2/uart_tx.v new file mode 100644 index 0000000..748631e --- /dev/null +++ b/Semaine 1/UARTV2/uart_tx.v @@ -0,0 +1,133 @@ +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_data_valid, + + output wire tx, + output reg tx_data_ready +); + + 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 [3:0] bit_index = 0; + reg [15:0] clk_count = 0; + reg [7:0] tx_data = 0; + reg tx_reg; + + 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_data_valid == 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_data_ready block + if(rst_p == 1'b1) + begin + tx_data_ready <= 1'b0; + end + + else if(state == IDLE) + if(tx_data_valid == 1'b1) + tx_data_ready <= 1'b0; + else + tx_data_ready <= 1'b1; + + else if(state == STOP && cycle_cnt == CYCLE - 1) + tx_data_ready <= 1'b1; + 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_data_valid == 1'b1) + tx_data_latch <= tx_data; + + 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