forked from tanchou/Verilog
134 lines
3.4 KiB
Coq
134 lines
3.4 KiB
Coq
![]() |
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
|