123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- //////////////////////////////////////////////////////////////////////
- // File 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 o_rx_dv 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: 25 MHz Clock, 115200 baud UART
- // (25000000)/(115200) = 217
- module UARTrx (
- input i_Clock,
- input reset,
- input i_Rx_Serial,
- output o_Rx_DV,
- output [7:0] o_Rx_Byte
- );
- parameter CLKS_PER_BIT = 50; //1MBaud
- parameter s_IDLE = 3'b000;
- parameter s_RX_START_BIT = 3'b001;
- parameter s_RX_DATA_BITS = 3'b010;
- parameter s_RX_STOP_BIT = 3'b011;
- parameter s_CLEANUP = 3'b100;
- reg r_Rx_Data_R;
- reg r_Rx_Data;
- reg [8:0] r_Clock_Count;
- reg [2:0] r_Bit_Index ; //8 bits total
- reg [7:0] r_Rx_Byte;
- reg r_Rx_DV;
- reg [2:0] r_SM_Main;
- initial
- begin
- r_Rx_Data_R = 1'b1;
- r_Rx_Data = 1'b1;
- r_Clock_Count = 0;
- r_Bit_Index = 0;
- r_Rx_Byte = 0;
- r_Rx_DV = 0;
- r_SM_Main = 0;
- end
- // Purpose: Double-register the incoming data.
- // This allows it to be used in the UART RX Clock Domain.
- // (It removes problems caused by metastability)
- always @(posedge i_Clock)
- begin
- if (reset)
- begin
- r_Rx_Data_R = 1'b1;
- r_Rx_Data = 1'b1;
- end
- else
- begin
- r_Rx_Data_R <= i_Rx_Serial;
- r_Rx_Data <= r_Rx_Data_R;
- end
- end
- // Purpose: Control RX state machine
- always @(posedge i_Clock)
- begin
- if (reset)
- begin
- r_Clock_Count = 0;
- r_Bit_Index = 0;
- r_Rx_Byte = 0;
- r_Rx_DV = 0;
- r_SM_Main = 0;
- end
- else
- begin
- case (r_SM_Main)
- s_IDLE :
- begin
- r_Rx_DV <= 1'b0;
- r_Clock_Count <= 0;
- r_Bit_Index <= 0;
- if (r_Rx_Data == 1'b0) // Start bit detected
- r_SM_Main <= s_RX_START_BIT;
- else
- r_SM_Main <= s_IDLE;
- end
- // Check middle of start bit to make sure it's still low
- s_RX_START_BIT :
- begin
- if (r_Clock_Count == (CLKS_PER_BIT-1)/2)
- begin
- if (r_Rx_Data == 1'b0)
- begin
- r_Clock_Count <= 0; // reset counter, found the middle
- r_SM_Main <= s_RX_DATA_BITS;
- end
- else
- r_SM_Main <= s_IDLE;
- end
- else
- begin
- r_Clock_Count <= r_Clock_Count + 1;
- r_SM_Main <= s_RX_START_BIT;
- end
- end // case: s_RX_START_BIT
- // Wait CLKS_PER_BIT-1 clock cycles to sample serial data
- s_RX_DATA_BITS :
- begin
- if (r_Clock_Count < CLKS_PER_BIT-1)
- begin
- r_Clock_Count <= r_Clock_Count + 1;
- r_SM_Main <= s_RX_DATA_BITS;
- end
- else
- begin
- r_Clock_Count <= 0;
- r_Rx_Byte[r_Bit_Index] <= r_Rx_Data;
- // Check if we have received all bits
- if (r_Bit_Index < 7)
- begin
- r_Bit_Index <= r_Bit_Index + 1;
- r_SM_Main <= s_RX_DATA_BITS;
- end
- else
- begin
- r_Bit_Index <= 0;
- r_SM_Main <= s_RX_STOP_BIT;
- end
- end
- end // case: s_RX_DATA_BITS
- // Receive Stop bit. Stop bit = 1
- s_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 <= s_RX_STOP_BIT;
- end
- else
- begin
- r_Rx_DV <= 1'b1;
- r_Clock_Count <= 0;
- r_SM_Main <= s_CLEANUP;
- end
- end // case: s_RX_STOP_BIT
- // Stay here 1 clock
- s_CLEANUP :
- begin
- r_SM_Main <= s_IDLE;
- end
- default :
- r_SM_Main <= s_IDLE;
- endcase
- end
- end
- assign o_Rx_DV = r_Rx_DV;
- assign o_Rx_Byte = r_Rx_Byte;
- endmodule // uart_rx
|