1
0
forked from tanchou/Verilog
This commit is contained in:
Gamenight77
2025-05-02 15:51:18 +02:00
parent 0faab53c30
commit f5e73d7379
105 changed files with 707398 additions and 1 deletions

4
Semaine_4/UART/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
runs
.vscode
workspace.code-workspace
*.pyc

View File

@@ -0,0 +1,6 @@
@call c:\oss-cad-suite\environment.bat
@echo off
if "%1"=="sim" call scripts\simulate.bat
if "%1"=="wave" call scripts\gtkwave.bat
if "%1"=="clean" call scripts\clean.bat
if "%1"=="build" call scripts\build.bat

View File

@@ -0,0 +1,45 @@
@echo off
setlocal
rem === Config de base ===
set DEVICE=GW2AR-LV18QN88C8/I7
set BOARD=tangnano20k
set TOP=top_uart_loopback
set CST_FILE=%TOP%.cst
set SRC_FILE=../src/verilog/%TOP%.v
set JSON_FILE=%TOP%.json
set PNR_JSON=pnr_%TOP%.json
set BITSTREAM=%TOP%.fs
rem === Créer le dossier runs si nécessaire ===
if not exist ../runs (
mkdir ../runs
)
cd ../runs
echo === Étape 1 : Synthèse avec Yosys ===
yosys -p "read_verilog %SRC_FILE%; synth_gowin -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

View File

@@ -0,0 +1,4 @@
@echo off
echo === Nettoyage du dossier runs ===
rd /s /q runs
mkdir runs

View File

@@ -0,0 +1,3 @@
@echo off
echo === Lancement de GTKWave ===
gtkwave runs/uart_loopback.vcd

View File

@@ -0,0 +1,4 @@
@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
vvp runs/sim.vvp

View File

@@ -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 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

View File

@@ -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_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 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_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)
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
else if(state == IDLE)
tx_data_ready <= 1'b1;
else if(state == STOP && cycle_cnt == CYCLE - 1)
tx_data_ready <= 1'b1; // Prêt une fois le bit STOP envoyé
else
tx_data_ready <= tx_data_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_data_valid == 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

View File

@@ -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

View File

@@ -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