140 lines
3.7 KiB
Verilog
140 lines
3.7 KiB
Verilog
/////////////////////////////////////////////////////////////////////
|
|
// File original code downloaded from http://www.nandland.com
|
|
/////////////////////////////////////////////////////////////////////
|
|
// This file contains the UART Receiver. This receiver is able to
|
|
// receive 8 bits of serial data, one start bit, one stop bit,
|
|
// and no parity bit. When receive is complete RsRx will be
|
|
// driven high for one clock cycle.
|
|
//
|
|
// Set Parameter CLKS_PER_BIT as follows:
|
|
// CLKS_PER_BIT = (Frequency of i_Clock)/(Frequency of UART)
|
|
// Example: 100 MHz Clock, 115200 baud UART
|
|
// (100_000_000)/(115200) = 868
|
|
//
|
|
// File source are form nandland.com
|
|
//
|
|
module UART_RX
|
|
#(parameter CLKS_PER_BIT = 868)
|
|
(
|
|
input clk,
|
|
input RsRx,
|
|
output o_RX_DV,
|
|
output [7:0] o_RX_Byte
|
|
);
|
|
|
|
localparam IDLE = 3'b000;
|
|
localparam RX_START_BIT = 3'b001;
|
|
localparam RX_DATA_BITS = 3'b010;
|
|
localparam RX_STOP_BIT = 3'b011;
|
|
localparam CLEANUP = 3'b100;
|
|
|
|
reg [9:0] r_Clock_Count = 0;
|
|
reg [2:0] r_Bit_Index = 0; //8 bits total
|
|
reg [7:0] r_RX_Byte = 0;
|
|
reg r_RX_DV = 0;
|
|
reg [2:0] r_SM_Main = 0;
|
|
|
|
|
|
// Purpose: Control RX state machine
|
|
always @(posedge clk)
|
|
begin
|
|
|
|
case (r_SM_Main)
|
|
IDLE :
|
|
begin
|
|
r_RX_DV <= 1'b0;
|
|
r_Clock_Count <= 0;
|
|
r_Bit_Index <= 0;
|
|
|
|
if (RsRx == 1'b0) // Start bit detected
|
|
r_SM_Main <= RX_START_BIT;
|
|
else
|
|
r_SM_Main <= IDLE;
|
|
end
|
|
|
|
// Check middle of start bit to make sure it's still low
|
|
RX_START_BIT :
|
|
begin
|
|
if (r_Clock_Count == (CLKS_PER_BIT)/2)
|
|
begin
|
|
if (RsRx == 1'b0)
|
|
begin
|
|
r_Clock_Count <= 0; // reset counter, found the middle
|
|
r_SM_Main <= RX_DATA_BITS;
|
|
end
|
|
else
|
|
r_SM_Main <= IDLE;
|
|
end
|
|
else
|
|
begin
|
|
r_Clock_Count <= r_Clock_Count + 1;
|
|
r_SM_Main <= RX_START_BIT;
|
|
end
|
|
end // case: RX_START_BIT
|
|
|
|
|
|
// Wait CLKS_PER_BIT-1 clock cycles to sample serial data
|
|
RX_DATA_BITS :
|
|
begin
|
|
if (r_Clock_Count < CLKS_PER_BIT-1)
|
|
begin
|
|
r_Clock_Count <= r_Clock_Count + 1;
|
|
r_SM_Main <= RX_DATA_BITS;
|
|
end
|
|
else
|
|
begin
|
|
r_Clock_Count <= 0;
|
|
r_RX_Byte[r_Bit_Index] <= RsRx;
|
|
|
|
// Check if we have received all bits
|
|
if (r_Bit_Index < 7)
|
|
begin
|
|
r_Bit_Index <= r_Bit_Index + 1;
|
|
r_SM_Main <= RX_DATA_BITS;
|
|
end
|
|
else
|
|
begin
|
|
r_Bit_Index <= 0;
|
|
r_SM_Main <= RX_STOP_BIT;
|
|
end
|
|
end
|
|
end // case: RX_DATA_BITS
|
|
|
|
|
|
// Receive Stop bit. Stop bit = 1
|
|
RX_STOP_BIT :
|
|
begin
|
|
// Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
|
|
if (r_Clock_Count < CLKS_PER_BIT-1)
|
|
begin
|
|
r_Clock_Count <= r_Clock_Count + 1;
|
|
r_SM_Main <= RX_STOP_BIT;
|
|
end
|
|
else
|
|
begin
|
|
r_RX_DV <= 1'b1;
|
|
r_Clock_Count <= 0;
|
|
r_SM_Main <= CLEANUP;
|
|
end
|
|
end // case: RX_STOP_BIT
|
|
|
|
|
|
// Stay here 1 clock
|
|
CLEANUP :
|
|
begin
|
|
r_SM_Main <= IDLE;
|
|
r_RX_DV <= 1'b0;
|
|
end
|
|
|
|
|
|
default :
|
|
r_SM_Main <= IDLE;
|
|
|
|
endcase
|
|
end
|
|
|
|
assign o_RX_DV = r_RX_DV;
|
|
assign o_RX_Byte = r_RX_Byte;
|
|
|
|
endmodule // UART_RX
|