Research-Stack/4-Infrastructure/hardware/uart_rx.v

84 lines
2.6 KiB
Verilog

// UART Receiver for Tang Nano 9K
// 115200 baud, 8N1 configuration
// Clock: 27 MHz
// Baud divider: 27MHz / 115200 ≈ 234
`timescale 1ns / 1ps
module uart_rx (
input clk,
input rst_n,
input rx_pin,
output [7:0] rx_data,
output rx_done
);
localparam BAUD_DIV = 16'd234;
localparam IDLE = 2'd0;
localparam START = 2'd1;
localparam DATA = 2'd2;
localparam STOP = 2'd3;
reg [15:0] baud_counter;
reg [2:0] bit_counter;
reg [1:0] state;
reg [7:0] rx_shift;
reg rx_done_r;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
baud_counter <= 16'd0;
bit_counter <= 3'd0;
rx_shift <= 8'd0;
rx_done_r <= 1'b0;
end else begin
rx_done_r <= 1'b0;
case (state)
IDLE: begin
if (rx_pin == 1'b0) begin // Start bit detected
state <= START;
baud_counter <= 16'd0;
end
end
START: begin
if (baud_counter == BAUD_DIV / 2) begin // Sample in the middle
if (rx_pin == 1'b0) begin
state <= DATA;
baud_counter <= 16'd0;
bit_counter <= 3'd0;
end else begin
state <= IDLE;
end
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
DATA: begin
if (baud_counter == BAUD_DIV) begin
rx_shift <= {rx_pin, rx_shift[7:1]};
if (bit_counter == 3'd7) begin
state <= STOP;
end else begin
bit_counter <= bit_counter + 1'b1;
end
baud_counter <= 16'd0;
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
STOP: begin
if (baud_counter == BAUD_DIV) begin
state <= IDLE;
rx_done_r <= 1'b1;
end else begin
baud_counter <= baud_counter + 1'b1;
end
end
endcase
end
end
assign rx_data = rx_shift;
assign rx_done = rx_done_r;
endmodule