/*
Input clock frequency is expected to 10.000MHz.
*/
#include "UART_Rx.nsh"
module UART_Rx {
/* ************************************************************ */
/* Declare internal signals */
wire BitLength[4] ;
reg ShiftCount[4] = 0 ;
reg x16_BaudCounter[16] = 0;
reg x16_ShiftTiming = FALSE ;
reg x1_BaudCounter[4] = 0 ;
reg x1_ShiftTiming = FALSE ;
reg Rx_ShiftReg[12] = 0 ; // Parallel -> Serial conversion shift register.
reg internal_RxD_in[3] = 3'b000 ;
wire Rx_Data[8] ;
wire Rx_Parity ; // Parity check node.
reg Detect_StartBit = 0 ;
func_name Receive_Start ;
/* ************************************************************ */
// Procedure description
// Declare function and procedure
proc_name shift_Operation( x1_ShiftTiming, internal_RxD_in ) , //
data_check() , // Parity check & Framing error check
access_complete() ; //
{
/* ************************************************************ */
/* Baud rate generator */
// This function is activate at Rx_Enable_i will be HIGH.
if ( Rx_Enable_i ) {
if ( x16_BaudCounter == Freq_Divide_Param_i ) {
x16_BaudCounter := 16'h0 ; // Reset baud rate counter
x16_ShiftTiming := TRUE ; // and assert Shift Timing indicator.
} else {
x16_BaudCounter := x16_BaudCounter + 16'h1 ; // Count up
x16_ShiftTiming := FALSE ; // Reset Shift Timing indicator.
}
} else {
x16_BaudCounter := 16'h0 ; // Reset baud rate counter
x16_ShiftTiming := FALSE ; // Reset Shift Timing indicator.
}
/* ************************************************************ */
/* Shift timing generation */
// Synchronous INPUT signal and detect center point of START bit.
internal_RxD_in := { internal_RxD_in[1:0] , RxD_i } ; // Clock synchronize and double latch
if ( x16_ShiftTiming ) {
if ( ( internal_RxD_in[2:1] == 2'b00 ) & ~Detect_StartBit ) { // All L level ?
Receive_Start() ; // Detect start bit and operation start.
}
}
if ( Detect_StartBit ) {
if ( x16_ShiftTiming ) {
x1_BaudCounter := x1_BaudCounter + 4'b1 ;
}
} else {
x1_BaudCounter := 4'b0 ;
}
if ( x16_ShiftTiming & x1_BaudCounter == 4'd7 ) {
x1_ShiftTiming := TRUE ; // Assert Shift Timing indicator.
} else {
x1_ShiftTiming := FALSE ; // Reset Shift Timing indicator.
}
/* ************************************************************ */
/* Bit length check */
any {
~Rx_ParityEN_i : any { // without Parity enable
Rx_BitLength_i == 2'b00 : BitLength = 4'd6 ;
// 5bit data length ( Data[4:0] + End )
Rx_BitLength_i == 2'b01 : BitLength = 4'd7 ;
// 6bit data length ( Data[5:0] + End )
Rx_BitLength_i == 2'b10 : BitLength = 4'd8 ;
// 7bit data length ( Data[6:0] + End )
else : BitLength = 4'd9 ;
// 8bit data length ( Data[7:0] + End )
}
else : any { // with Parity enable
Rx_BitLength_i == 2'b00 : BitLength = 4'd7 ;
// 5bit data length ( Data[4:0] + Parity + End )
Rx_BitLength_i == 2'b01 : BitLength = 4'd8 ;
// 6bit data length ( Data[5:0] + Parity + End )
Rx_BitLength_i == 2'b10 : BitLength = 4'd9 ;
// 7bit data length ( Data[6:0] + Parity + End )
else : BitLength = 4'd10;
// 8bit data length ( Data[7:0] + Parity + End )
}
}
/* ************************************************************ */
/* Parity generation */
any {
Rx_OddParity_i : Rx_Parity = ~^(Rx_Data) ; // Calculate ODD parity
else : Rx_Parity = ^(Rx_Data) ; // Calculate EVEN parity
}
/* ************************************************************ */
/* Equation for operation status */
Rx_operation_o = Detect_StartBit ;
Rx_ShiftClock_o = x1_ShiftTiming ;
/* ************************************************************ */
/* Equation for Transmit data output */
any {
~Rx_ParityEN_i : any { // without Parity enable
Rx_BitLength_i == 2'b00 : Rx_Data = { 3#1'b1 , Rx_ShiftReg[10:6] } ;
// output internal shift register value.
Rx_BitLength_i == 2'b01 : Rx_Data = { 2#1'b1 , Rx_ShiftReg[10:5] } ;
// output internal shift register value.
Rx_BitLength_i == 2'b10 : Rx_Data = { 1'b1 , Rx_ShiftReg[10:4] } ;
// output internal shift register value.
else : Rx_Data = Rx_ShiftReg[10:3] ;
// output internal shift register value.
}
else : any { // with Parity enable
Rx_BitLength_i == 2'b00 : Rx_Data = { 3#1'b1 , Rx_ShiftReg[ 9:5] } ;
// output internal shift register value.
Rx_BitLength_i == 2'b01 : Rx_Data = { 2#1'b1 , Rx_ShiftReg[ 9:4] } ;
// output internal shift register value.
Rx_BitLength_i == 2'b10 : Rx_Data = { 1'b1 , Rx_ShiftReg[ 9:3] } ;
// output internal shift register value.
else : Rx_Data = Rx_ShiftReg[ 9:2] ;
// output internal shift register value.
}
}
} // end of equation
/* ************************************************************ */
// Procedure description
function Receive_Start shift_Operation() ;
/* ************************************************************ */
/* Receiver operation */
proc shift_Operation {
Detect_StartBit := TRUE ;
if ( x1_ShiftTiming ) {
// Data capture to shift register
Rx_ShiftReg := { internal_RxD_in[1] , Rx_ShiftReg[11:1] } ;
// Capture synchronized RxD.
// Check bit length counter value
ShiftCount := ShiftCount + 4'b1 ; // Shift counter + 1
if ( ShiftCount == BitLength ) {
data_check() ;
}
}
}
proc data_check { // Parity check
if ( Rx_ParityEN_i & ( Rx_ShiftReg[10] != Rx_Parity ) ) {
// Check parity bit in the Bit<10>
// Assert status flag.
RxD_ParityError_o() ; // Assert ERROR flag.
} else {
if ( Rx_ShiftReg[11] == FALSE ) { // Check stop bit as "1" in the Bit<11>
// Assert status flag.
RxD_FramingError_o() ; // Assert ERROR flag.
} else {
// Assert status flag.
Rx_Data_o = Rx_Data ; // No error and data output
RxD_Ready_o() ; // Assert RECEIVER-READY flag
}
}
access_complete() ;
}
proc access_complete {
// Finish operation
Detect_StartBit := FALSE ;
Rx_ShiftReg := 12'h0 ;
ShiftCount := 4'b0 ;
// Procedure finish.
finish ;
}
/* ************************************************************ */
} // end of module