| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- module uart_rx #(parameter DATA_WIDTH = 8, FIFO_DEPTH = 4) (
- input clk,
- input rstn,
- input baud16,
- input uart_rxd,
- input lcr_sps,
- input lcr_stp2,
- input lcr_eps,
- input lcr_pen,
- input rx_read,
- input rx_clear,
- output rx_full,
- output rx_empty,
- output [DATA_WIDTH-1:0] rx_data,
- output reg rx_idle,
- input rx_dma_en,
- input rx_dma_clr,
- output reg rx_dma_req,
- output reg framing_error,
- output reg parity_error,
- output reg break_error,
- output reg overrun_error
- );
- 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;
- parameter BAUD_CNT = 16;
- parameter SAMPLE_CNT = 3;
- reg [2:0] rx_state;
- reg [SAMPLE_CNT+1:0] rx_in; // 2 extra bits for synchronization
- reg [1:0] rx_val;
- reg [3:0] rx_baud_cnt;
- reg rx_bit;
- reg rx_parity;
- reg [$clog2(DATA_WIDTH):0] rx_data_cnt;
- reg [DATA_WIDTH-1:0] rx_shift_reg;
- reg rx_idle_en;
- wire rx_lo = rx_val <= 1;
- wire rx_hi = !rx_lo;
- wire rx_sample = baud16 && rx_baud_cnt == BAUD_CNT / 2 + 1; // Where to sample rx input
- wire fifo_wren = rx_state == UART_STOP && rx_sample;
- sync_fifo #(.WIDTH(DATA_WIDTH), .DEPTH(FIFO_DEPTH), .SHOWAEAD(1)) rx_fifo(
- .clk (clk ),
- .rstn (rstn ),
- .wren (fifo_wren ),
- .rden (rx_read ),
- .din (rx_shift_reg),
- .dout (rx_data ),
- .full (rx_full ),
- .empty(rx_empty )
- );
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_in <= {SAMPLE_CNT+1{1'b1}};
- end else if (baud16) begin
- rx_in <= { rx_in[SAMPLE_CNT:0], uart_rxd };
- end
- end
- integer i;
- always @(*) begin
- rx_val = 0;
- for (i = 2; i < SAMPLE_CNT + 2; i = i + 1)
- rx_val = rx_val + rx_in[i];
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_bit <= 1'b0;
- end else if (baud16 && rx_baud_cnt == 15) begin
- rx_bit <= 1'b1;
- end else begin
- rx_bit <= 1'b0;
- end
- end
- always @(posedge clk) begin
- if (rx_state == UART_START) begin
- rx_data_cnt <= DATA_WIDTH - 1;
- end else if (rx_bit) begin
- if (rx_state == UART_DATA && rx_data_cnt == 0) begin
- rx_data_cnt <= DATA_WIDTH + 1 + lcr_pen + lcr_stp2;
- end else begin
- rx_data_cnt <= rx_data_cnt - 1;
- end
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_shift_reg <= 0;
- end else if (rx_state == UART_DATA && rx_sample) begin
- rx_shift_reg <= { rx_hi, rx_shift_reg[DATA_WIDTH-1:1] };
- end
- end
- always @(posedge clk) begin
- if (rx_state == UART_START) begin
- rx_parity <= !lcr_eps;
- end else if (rx_state == UART_DATA && rx_bit && !lcr_sps) begin
- rx_parity <= rx_parity ^ rx_shift_reg[7];
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_baud_cnt <= 0;
- end else if (rx_state == UART_IDLE && rx_lo) begin
- rx_baud_cnt <= SAMPLE_CNT - 1;
- end else if (baud16) begin
- rx_baud_cnt <= rx_baud_cnt + 1;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_idle_en <= 1'b0;
- end else if (!rx_empty) begin
- rx_idle_en <= 1'b1;
- end else if (rx_clear) begin
- rx_idle_en <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_idle <= 1'b0;
- end else if (rx_state == UART_IDLE && rx_data_cnt == 0 && rx_bit && rx_idle_en) begin
- rx_idle <= 1'b1;
- end else if (rx_clear) begin
- rx_idle <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- framing_error <= 1'b0;
- end else if (rx_state == UART_STOP && rx_sample && rx_lo) begin
- framing_error <= 1'b1;
- end else if (rx_clear) begin
- framing_error <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- parity_error <= 1'b0;
- end else if (rx_state == UART_PARITY && rx_sample && rx_parity != rx_hi) begin
- parity_error <= 1'b1;
- end else if (rx_clear) begin
- parity_error <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- break_error <= 1'b0;
- end else if (rx_state == UART_STOP && rx_sample && rx_lo && rx_shift_reg == 0) begin
- break_error <= 1'b1;
- end else if (rx_clear) begin
- break_error <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- overrun_error <= 1'b0;
- end else if (fifo_wren && rx_full) begin
- overrun_error <= 1'b1;
- end else if (rx_clear) begin
- overrun_error <= 1'b0;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_dma_req <= 1'b0;
- end else if (!rx_dma_en || rx_dma_clr) begin
- rx_dma_req <= 1'b0;
- end else if (!rx_empty) begin
- rx_dma_req <= 1'b1;
- end
- end
- always @(posedge clk or negedge rstn) begin
- if (!rstn) begin
- rx_state <= UART_IDLE;
- end else begin
- case (rx_state)
- UART_IDLE: if (rx_lo) rx_state <= UART_START;
- UART_START: if (rx_bit && rx_baud_cnt == 0) rx_state <= UART_DATA;
- UART_DATA: if (rx_bit && rx_data_cnt == 0) rx_state <= lcr_pen ? UART_PARITY : UART_STOP;
- UART_PARITY: if (rx_bit) rx_state <= UART_STOP;
- UART_STOP: if (rx_sample && rx_hi) rx_state <= UART_IDLE;
- endcase
- end
- end
- endmodule
|