From c9a5fba97e3de0df9595152ced180742186c4d4c Mon Sep 17 00:00:00 2001 From: Gamenight77 Date: Mon, 5 May 2025 09:26:41 +0200 Subject: [PATCH] TX tested with other's rx code (its work) --- Semaine_4/UART/IP/verilog/other_rx.v | 143 +++++++++++++++++++++ Semaine_4/UART/scripts/simulate.bat | 27 +++- Semaine_4/UART/src/verilog/uart_rx.v | 145 ---------------------- Semaine_4/UART/src/verilog/uart_tx.v | 24 ++-- Semaine_4/UART/tests/verilog/tb_uart_rx.v | 64 ---------- Semaine_4/UART/tests/verilog/tb_uart_tx.v | 54 +++++--- 6 files changed, 220 insertions(+), 237 deletions(-) create mode 100644 Semaine_4/UART/IP/verilog/other_rx.v delete mode 100644 Semaine_4/UART/src/verilog/uart_rx.v delete mode 100644 Semaine_4/UART/tests/verilog/tb_uart_rx.v diff --git a/Semaine_4/UART/IP/verilog/other_rx.v b/Semaine_4/UART/IP/verilog/other_rx.v new file mode 100644 index 0000000..e0a14a9 --- /dev/null +++ b/Semaine_4/UART/IP/verilog/other_rx.v @@ -0,0 +1,143 @@ +module uart_rx +#( + parameter CLK_FRE = 27, //clock frequency(Mhz) + parameter BAUD_RATE = 115200 //serial baud rate +) +( + input clk, //clock input + input rst_n, //asynchronous reset input, low active + output reg[7:0] rx_data, //received serial data + output reg rx_data_valid, //received serial data is valid + input rx_data_ready, //data receiver module ready + input rx_pin //serial data input +); +//calculates the clock cycle for baud rate +localparam CYCLE = CLK_FRE * 1000000 / 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; + +always@(posedge clk or negedge rst_n) +begin + if(rst_n == 1'b0) + 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_n) +begin + if(rst_n == 1'b0) + state <= S_IDLE; + else + state <= next_state; +end + +always@(*) +begin + case(state) + S_IDLE: + if(rx_negedge) + 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_n) +begin + if(rst_n == 1'b0) + 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_n) +begin + if(rst_n == 1'b0) + 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_n) +begin + if(rst_n == 1'b0) + 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_n) +begin + if(rst_n == 1'b0) + 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_n) +begin + if(rst_n == 1'b0) + 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_4/UART/scripts/simulate.bat b/Semaine_4/UART/scripts/simulate.bat index f917631..f23649a 100644 --- a/Semaine_4/UART/scripts/simulate.bat +++ b/Semaine_4/UART/scripts/simulate.bat @@ -1,4 +1,29 @@ @echo off echo === Simulation avec Icarus Verilog === -iverilog -g2012 -o runs/sim.vvp -s uart_tb src/verilog/*.v tests/verilog/*.v IP/verilog/*.v +setlocal enabledelayedexpansion + +:: Dossier de sortie +set OUT=runs/sim.vvp + +:: Top-level testbench module +set TOP=tb_uart_tx + +:: 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_4/UART/src/verilog/uart_rx.v b/Semaine_4/UART/src/verilog/uart_rx.v deleted file mode 100644 index 1500c66..0000000 --- a/Semaine_4/UART/src/verilog/uart_rx.v +++ /dev/null @@ -1,145 +0,0 @@ -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 posedge 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 posedge 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 posedge 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 posedge 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 posedge 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 posedge 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 posedge 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_4/UART/src/verilog/uart_tx.v b/Semaine_4/UART/src/verilog/uart_tx.v index daf3d0b..cbc9505 100644 --- a/Semaine_4/UART/src/verilog/uart_tx.v +++ b/Semaine_4/UART/src/verilog/uart_tx.v @@ -5,10 +5,10 @@ module uart_tx #( input wire clk, input wire rst_p, input wire[7:0] data, - input wire tx_data_valid, + input wire tx_enable, - output wire tx, - output reg tx_data_ready + output reg tx_ready, + output wire tx ); localparam CYCLE = CLK_FREQ / BAUD_RATE; @@ -38,7 +38,7 @@ module uart_tx #( always@(*) begin case(state) IDLE: - if(tx_data_valid == 1'b1) + if(tx_enable == 1'b1) next_state = START; else next_state = IDLE; @@ -65,17 +65,17 @@ module uart_tx #( endcase end - always@(posedge clk or posedge rst_p)begin // tx_data_ready block + always@(posedge clk or posedge rst_p)begin // tx_ready block if(rst_p == 1'b1) - tx_data_ready <= 1'b0; // Reset - else if(state == IDLE && tx_data_valid == 1'b1) - tx_data_ready <= 1'b0; // Pas prêt tant que les données sont valides + 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_data_ready <= 1'b1; + tx_ready <= 1'b1; else if(state == STOP && cycle_cnt == CYCLE - 1) - tx_data_ready <= 1'b1; // Prêt une fois le bit STOP envoyé + tx_ready <= 1'b1; // Prêt une fois le bit STOP envoyé else - tx_data_ready <= tx_data_ready; // Reste inchangé dans d'autres cas + tx_ready <= tx_ready; // Reste inchangé dans d'autres cas end @@ -83,7 +83,7 @@ module uart_tx #( 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) begin + 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 diff --git a/Semaine_4/UART/tests/verilog/tb_uart_rx.v b/Semaine_4/UART/tests/verilog/tb_uart_rx.v deleted file mode 100644 index 874dfd7..0000000 --- a/Semaine_4/UART/tests/verilog/tb_uart_rx.v +++ /dev/null @@ -1,64 +0,0 @@ -`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_4/UART/tests/verilog/tb_uart_tx.v b/Semaine_4/UART/tests/verilog/tb_uart_tx.v index 4c1fe2d..b9b333a 100644 --- a/Semaine_4/UART/tests/verilog/tb_uart_tx.v +++ b/Semaine_4/UART/tests/verilog/tb_uart_tx.v @@ -3,44 +3,68 @@ module tb_uart_tx; reg clk = 0; - reg start = 0; - reg [7:0] data = 8'h00; + reg tx_enable = 0; + reg [7:0] data_in = 8'h00; + reg [7:0] data_out; wire tx; - wire busy; + reg tx_ready; + + wire rx_recieved; always #18.5 clk = ~clk; + uart_rx rx_instance( + .clk(clk), + .rx_pin(tx), // tx is connected to rx for testing + .rst_n(1'b1), + .rx_data(data_out), + .rx_data_valid(rx_recieved), + .rx_data_ready(1'b1) + ); + uart_tx #( .CLK_FREQ(27_000_000), .BAUD_RATE(115_200) )tx_instance ( .clk(clk), - .start(start), - .data(data), + .tx_enable(tx_enable), + .tx_ready(tx_ready), + .data(data_in), .tx(tx), - .busy(busy) + .rst_p(1'b0) ); initial begin - $dumpfile("uart_tx.vcd"); + $dumpfile("runs/uart_tx.vcd"); $dumpvars(0, tb_uart_tx); #100; - data <= 8'hA5; // 10100101 0xA5 - start <= 1; - #37 start <= 0; + data_in <= 8'd234; // 234 + tx_enable <= 1; + wait(tx_ready == 1'b0); + tx_enable <= 0; // Attendre - wait (busy == 0); + wait (rx_recieved == 1'b1); // Attendre que le signal de reception soit actif + + $display("Data received: %d", data_out); // Afficher la valeur recu + $display("Data expected: %d", data_in); // Afficher la valeur envoyee #1000; - data <= 8'h3C; // 00111100 0x3C - start <= 1; - #37 start <= 0; + wait(tx_ready == 1'b1); // Attendre que le signal de reception soit actif - wait (busy == 0); + data_in <= 8'd202; // 202 + tx_enable <= 1; + wait(tx_ready == 1'b0); + tx_enable <= 0; + + // Attendre + wait (rx_recieved == 1'b1); // Attendre que le signal de reception soit actif + + $display("Data received: %d", data_out); // Afficher la valeur recu + $display("Data expected: %d", data_in); // Afficher la valeur envoyee #1000; $stop;