forked from tanchou/Verilog
132 lines
3.6 KiB
Verilog
132 lines
3.6 KiB
Verilog
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
|