| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- module uart_tx #(parameter DATA_WIDTH = 8, FIFO_DEPTH = 1) (
- input clk,
- input rstn,
- input baud16,
- input tx_write,
- input [DATA_WIDTH-1:0] tx_data,
- input lcr_sps,
- input lcr_stp2,
- input lcr_eps,
- input lcr_pen,
- input tx_clear,
- output tx_full,
- output tx_empty,
- output tx_busy,
- output reg tx_complete,
- input tx_dma_en,
- input tx_dma_clr,
- output reg tx_dma_req,
- output reg uart_txd
- );
- parameter UART_IDLE = 3'h0;
- parameter UART_START = 3'h1;
- parameter UART_DATA = 3'h2;
- parameter UART_PARITY = 3'h3;
- parameter UART_STOP = 3'h4;
- reg [2:0] tx_state;
- reg [DATA_WIDTH-1:0] tx_shift_reg;
- reg tx_parity;
- reg [3:0] tx_baud_cnt;
- reg tx_bit;
- reg [$clog2(DATA_WIDTH)-1:0] tx_data_cnt;
- reg tx_stop_cnt;
- wire fifo_rden = !tx_empty && (!tx_busy || tx_state == UART_STOP && tx_stop_cnt == 0 && tx_bit);
- wire [DATA_WIDTH-1:0] fifo_out;
- wire tx_stop = tx_empty && !tx_busy;
- sync_fifo #(.WIDTH(DATA_WIDTH), .DEPTH(FIFO_DEPTH), .SHOWAEAD(1)) tx_fifo(
- .clk (clk ),
- .rstn (rstn ),
- .wren (tx_write ),
- .rden (fifo_rden),
- .din (tx_data ),
- .dout (fifo_out ),
- .full (tx_full ),
- .empty(tx_empty )
- );
- assign tx_busy = tx_state != UART_IDLE;
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_state <= UART_IDLE;
- end else begin
- case (tx_state)
- UART_IDLE: if (fifo_rden) tx_state <= UART_START;
- UART_START: if (tx_bit) tx_state <= UART_DATA;
- UART_DATA: if (tx_bit && tx_data_cnt == 0) tx_state <= lcr_pen ? UART_PARITY : UART_STOP;
- UART_PARITY: if (tx_bit) tx_state <= UART_STOP;
- UART_STOP: if (tx_bit && tx_stop_cnt == 0) tx_state <= tx_empty ? UART_IDLE : UART_START;
- endcase
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_shift_reg <= 0;
- end else if (fifo_rden) begin
- tx_shift_reg <= fifo_out;
- end else if (tx_bit && tx_state == UART_DATA) begin
- tx_shift_reg <= { tx_shift_reg[0], tx_shift_reg[DATA_WIDTH-1:1] };
- end
- end
- always @(posedge clk) begin
- if (tx_state == UART_START) begin
- tx_parity <= !lcr_eps;
- end else if (tx_state == UART_DATA && tx_bit && !lcr_sps) begin
- tx_parity <= tx_parity ^ tx_shift_reg[0];
- end
- end
- always @(posedge clk) begin
- if (tx_state == UART_START) begin
- tx_data_cnt <= DATA_WIDTH - 1;
- end else if (tx_state == UART_DATA && tx_bit) begin
- tx_data_cnt <= tx_data_cnt - 1;
- end
- end
- always @(posedge clk) begin
- if (tx_state == UART_START) begin
- tx_stop_cnt <= lcr_stp2;
- end else if (tx_state == UART_STOP && tx_bit) begin
- tx_stop_cnt <= tx_stop_cnt - 1;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_baud_cnt <= 0;
- end else if (tx_stop) begin
- tx_baud_cnt <= 0;
- end else if (baud16) begin
- tx_baud_cnt <= tx_baud_cnt + 1;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_bit <= 1'b0;
- end else if (baud16 && tx_baud_cnt == 15) begin
- tx_bit <= 1'b1;
- end else begin
- tx_bit <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_complete <= 1'b0;
- end else if (tx_state == UART_STOP && tx_bit && tx_stop_cnt == 0 && tx_empty) begin
- tx_complete <= 1'b1;
- end else if (tx_clear || !tx_empty) begin
- tx_complete <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- tx_dma_req <= 1'b0;
- end else if (!tx_dma_en || tx_dma_clr) begin
- tx_dma_req <= 1'b0;
- end else if (!tx_full) begin
- tx_dma_req <= 1'b1;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- uart_txd <= 1'b1;
- end else begin
- case (tx_state)
- UART_IDLE: uart_txd <= 1'b1;
- UART_START: uart_txd <= 1'b0;
- UART_DATA: uart_txd <= tx_shift_reg[0];
- UART_PARITY: uart_txd <= tx_parity;
- UART_STOP: uart_txd <= 1'b1;
- endcase
- end
- end
- endmodule
|