1
0
forked from tanchou/Verilog
Files

132 lines
3.6 KiB
Coq
Raw Permalink Normal View History

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;
2025-05-02 11:03:14 +02:00
reg [15:0] cycle_cnt; //baud counter
reg tx_reg;
2025-05-02 11:03:14 +02:00
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)
2025-05-02 11:03:14 +02:00
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)
2025-05-02 11:03:14 +02:00
tx_data_ready <= 1'b1;
else if(state == STOP && cycle_cnt == CYCLE - 1)
2025-05-02 11:03:14 +02:00
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
2025-05-02 11:03:14 +02:00
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
2025-05-02 11:03:14 +02:00
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