| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- `timescale 1ns/1ps
- // 8-N-1 UART receiver.
- // RX input is first synchronized into clk domain.
- module uart_rx #(
- parameter integer CLK_HZ = 25000000,
- parameter integer BAUD = 115200
- )(
- input wire clk,
- input wire reset_n,
- input wire rx,
- output reg [7:0] data,
- output reg valid,
- output reg framing_error
- );
- localparam integer CLKS_PER_BIT = CLK_HZ / BAUD;
- localparam integer HALF_BIT = CLKS_PER_BIT / 2;
- localparam [1:0] R_IDLE = 2'd0;
- localparam [1:0] R_START = 2'd1;
- localparam [1:0] R_DATA = 2'd2;
- localparam [1:0] R_STOP = 2'd3;
- reg rx_meta;
- reg rx_sync;
- reg [1:0] state;
- reg [15:0] clk_count;
- reg [2:0] bit_index;
- reg [7:0] data_shift;
- always @(posedge clk or negedge reset_n) begin
- if (!reset_n) begin
- rx_meta <= 1'b1;
- rx_sync <= 1'b1;
- end else begin
- rx_meta <= rx;
- rx_sync <= rx_meta;
- end
- end
- always @(posedge clk or negedge reset_n) begin
- if (!reset_n) begin
- state <= R_IDLE;
- clk_count <= 16'd0;
- bit_index <= 3'd0;
- data_shift <= 8'd0;
- data <= 8'd0;
- valid <= 1'b0;
- framing_error <= 1'b0;
- end else begin
- valid <= 1'b0;
- framing_error <= 1'b0;
- case (state)
- R_IDLE: begin
- clk_count <= 16'd0;
- bit_index <= 3'd0;
- if (!rx_sync)
- state <= R_START;
- end
- R_START: begin
- // Sample around the middle of the start bit to reject a short glitch.
- if (clk_count == HALF_BIT - 1) begin
- clk_count <= 16'd0;
- if (!rx_sync)
- state <= R_DATA;
- else
- state <= R_IDLE;
- end else begin
- clk_count <= clk_count + 1'b1;
- end
- end
- R_DATA: begin
- if (clk_count == CLKS_PER_BIT - 1) begin
- clk_count <= 16'd0;
- data_shift[bit_index] <= rx_sync;
- if (bit_index == 3'd7) begin
- bit_index <= 3'd0;
- state <= R_STOP;
- end else begin
- bit_index <= bit_index + 1'b1;
- end
- end else begin
- clk_count <= clk_count + 1'b1;
- end
- end
- R_STOP: begin
- if (clk_count == CLKS_PER_BIT - 1) begin
- clk_count <= 16'd0;
- if (rx_sync) begin
- data <= data_shift;
- valid <= 1'b1;
- end else begin
- framing_error <= 1'b1;
- end
- state <= R_IDLE;
- end else begin
- clk_count <= clk_count + 1'b1;
- end
- end
- default: state <= R_IDLE;
- endcase
- end
- end
- endmodule
|