Author: Jose Pinilla

Today, the use of UART serial communication in embedded systems and electronics projects is very common. UART communication is found in Bluetooth devices (SPP), WiFi, Ethernet, USB conversion, audio and video devices, and communication with a wide variety of OEM cards.

 

UART

 

Verilog code UART Full Duplex(UART_FullDuplex.v):

change parameter "baud_rate" to change speed rate

//=======================UART_FullDuplex=====================
//Engineer: Jose Pablo Pinilla
//Website:	semilleroadt.upbbga.edu.co


module UART_FullDuplex (
	input 	clk,
	//Transmitter
	input 	Tx_Start,
	input 	[7:0]Tx_Data,
	output 	Tx,
	output	TxD_Busy,
	//Receiver
	input 	Rx,
	output	[7:0]Rx_Data,
	output	RxD_Ready
	);

//========================Tx/Rx Control=====================

reg		Frame_Rx=0;						//Frame is being received
reg		Frame_Tx=0;						//Frame is being transmitted

assign	TxD_Busy = Frame_Tx;
assign 	RxD_Ready= ~Frame_Rx;

//=====================Baud Rate Generation==================
parameter clk_in_freq = 50000000;
parameter baud_rate = 4800;
localparam counter_limit = clk_in_freq/(2*baud_rate);

//Baud Rate
reg [15:0]div_clk_counter=0;
reg clk_count_reset=0;
reg baud_clk=0;

always @ (posedge clk or posedge clk_count_reset)
	if (clk_count_reset)
		div_clk_counter <= 0;
	else
		begin
			if (Frame_Tx|Frame_Rx)
				div_clk_counter <= div_clk_counter+1;
		end		

always @ (negedge clk)
	clk_count_reset <= (div_clk_counter==counter_limit-1);
	
always @ (posedge clk_count_reset)
	baud_clk <= ~baud_clk;
		
//======================Tx========================

//Tx Data Frame Counter

reg [3:0]Tx_counter=0;
	
always @ (negedge baud_clk or negedge Frame_Tx)
	if (~Frame_Tx)
		Tx_counter <= 0;
	else
		Tx_counter <= Tx_counter+4'd1;

wire Tx_Counter_Reset = (Tx_counter==10);

//Tx Detection

always@(posedge Tx_Start or posedge Tx_Counter_Reset)
	if (Tx_Counter_Reset)
		Frame_Tx <= 0;
	else
		Frame_Tx <= 1;

//Tx Shift Register

reg [9:0]OutBuffer = 10'b11111111_0_1;

always @ (posedge baud_clk or negedge Frame_Tx)
	if (~Frame_Tx)
		OutBuffer <= {Tx_Data,2'b01};
	else
		OutBuffer <= {1'b1,OutBuffer[9:1]};
				
//======================Rx=========================

//Rx Data Frame Counter

reg [3:0]Rx_counter=0;
	
always @ (negedge baud_clk or negedge Frame_Rx)
	if (~Frame_Rx)
		Rx_counter <= 0;
	else
		Rx_counter <= Rx_counter+4'd1;

wire Rx_Counter_Reset = (Rx_counter==10);
	
//Rx Detection
always@(negedge  Rx or posedge Rx_Counter_Reset)
	if (Rx_Counter_Reset)
		Frame_Rx <= 0;
	else
		Frame_Rx <= 1;
	
//Rx Shift Register

reg [9:0]InBuffer=0;

always @ (posedge baud_clk)
	if (Frame_Rx)
		InBuffer <= {Rx,InBuffer[9:1]};

//================Output Assignment==============
		
assign Tx = OutBuffer[0];

assign Rx_Data = InBuffer[8:1];

endmodule