UART stands for Universal Asynchronous Receive Transmit. It is one of the most popular Asynchronous Serial Communication protocols. It is not only simple to implement but also economical to use. It uses only two wires to communicate between two devices. UART can also be implemented in a multi-drop configuration but then proper termination is necessary (see RS-485 Wikipedia Link). UART is capable of approximately 2-MBit/s in single-ended configuration but upto 10-Mbit/s in Differential Configuration. Higher speeds usually come at the penalty of using shorter transmission lines (also Impedance Matching is recommended). In this project ,we shall implement a UART Transmitter in an FPGA. The FPGA which was used for testing was a Xilinx Spartan-6 XC6SLX9 FPGA. The FPGA was clocked by a 50Mhz Crystal. In the project the Verilog module implemented has an 8-bit Input and the UART-Tx Output along with a Tx_Enable Input .
The UART transmitter works in this way-- A Shift Register is used to convert the Parallel input data into Serial data. The Register is clocked by a Baud-Rate Counter which provides clock to the Shift Register at the required baud rate. In UART the Tx-pin is Idle-High. To start the transmission of a byte, the Tx-pin goes low for one bit period, and then individual bits are transmitted with LSB first and the MSB last. At the end of the byte, the line goes high for one bit period. The Tx-pin stays at high logic if there is no subsequent byte to transmit. In the given Verilog Code, instead of a Shift Register, a 10 to 1 Multiplexer is used. The inputs of the Multiplexer is connected to the data input with the exception of the first and the last bit. The first bit is kept logic low(for the start bit) and the last bit is kept logic high for the stop bit. The control lines of the multiplexer are connected to a counter which is incremented at the baud-rate. The baud rate is controlled by the Clock_Divider Register and it is possible to change the baud rate by simply changing the rate of counting by the Clock_Divider register. For example, for 115200 baud ,the Clock_Divider Register resets at (50Mhz)/(115200) = 434 i.e. there are 434 clocks per bit at 50 Mhz clock input to the FPGA. The Transmitter module transmits as long as the Tx_Enable pin is Logic high.
Now we come to the actual Verilog Code
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
//
// Create Date: 12:03:50 04/25/2019
// Design Name:
// Module Name: UART_Transmitter
// Project Name:
// Target Devices:
// Tool versions:
// Description: UART Transmitter in Verilog, transmission rate at 115200 bits per second
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module UART_Transmitter(Input,clock,Tx,Tx_Enable);
input [7:0] Input;
input clock, Tx_Enable;
output Tx;
reg [9:0] Clock_Divider;
always @(posedge clock)
begin
if(Tx_Enable == 1'b1)
Clock_Divider <= Clock_Divider+1;
if (Clock_Divider == 434) // Since 50Mhz/115200 = 434 i.e 434 clocks per bit @ 50Mhz clock
Clock_Divider <= 0;
else
Clock_Divider <= 0;
end
reg clk; // An additional register for the clock at the baud rate
always @(Clock_Divider)
begin
if(Clock_Divider == 434)
clk = 1'b1;
else
clk = 1'b0;
end
reg[4:0] Counter_1; // The Counter to control the Multiplexer
always @(posedge clk)
begin
Counter_1 <= Counter_1+1;
if (Counter_1 == 9) // Since there are a total of 10 bits including the start and the stop bit
Counter_1 <= 0;
end
reg Output; // The Multiplexer
always @(Counter_1 or Input)
begin
if (Counter_1 == 4'b0000)
Output <= 0;// Start Bit
else if (Counter_1 == 4'b0001)
Output <= Input[0]; //Connect to LSB
else if (Counter_1 == 4'b0010)
Output <= Input[1];
else if (Counter_1 == 4'b0011)
Output <= Input[2];
else if (Counter_1 == 4'b0100)
Output <= Input[3];
else if (Counter_1 == 4'b0101)
Output <= Input[4];
else if (Counter_1 == 4'b0110)
Output <= Input[5];
else if (Counter_1 == 4'b0111)
Output <= Input[6];
else if (Counter_1 == 4'b1000)
Output <= Input[7]; //Connect to MSB
else if (Counter_1 == 4'b1001)
Output <= 1; // Stop Bit
else
Output <= 1; // The idle state
end
assign D_Out = Tx;
endmodule
The UART transmitter works in this way-- A Shift Register is used to convert the Parallel input data into Serial data. The Register is clocked by a Baud-Rate Counter which provides clock to the Shift Register at the required baud rate. In UART the Tx-pin is Idle-High. To start the transmission of a byte, the Tx-pin goes low for one bit period, and then individual bits are transmitted with LSB first and the MSB last. At the end of the byte, the line goes high for one bit period. The Tx-pin stays at high logic if there is no subsequent byte to transmit. In the given Verilog Code, instead of a Shift Register, a 10 to 1 Multiplexer is used. The inputs of the Multiplexer is connected to the data input with the exception of the first and the last bit. The first bit is kept logic low(for the start bit) and the last bit is kept logic high for the stop bit. The control lines of the multiplexer are connected to a counter which is incremented at the baud-rate. The baud rate is controlled by the Clock_Divider Register and it is possible to change the baud rate by simply changing the rate of counting by the Clock_Divider register. For example, for 115200 baud ,the Clock_Divider Register resets at (50Mhz)/(115200) = 434 i.e. there are 434 clocks per bit at 50 Mhz clock input to the FPGA. The Transmitter module transmits as long as the Tx_Enable pin is Logic high.
Now we come to the actual Verilog Code
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
//
// Create Date: 12:03:50 04/25/2019
// Design Name:
// Module Name: UART_Transmitter
// Project Name:
// Target Devices:
// Tool versions:
// Description: UART Transmitter in Verilog, transmission rate at 115200 bits per second
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module UART_Transmitter(Input,clock,Tx,Tx_Enable);
input [7:0] Input;
input clock, Tx_Enable;
output Tx;
reg [9:0] Clock_Divider;
always @(posedge clock)
begin
if(Tx_Enable == 1'b1)
Clock_Divider <= Clock_Divider+1;
if (Clock_Divider == 434) // Since 50Mhz/115200 = 434 i.e 434 clocks per bit @ 50Mhz clock
Clock_Divider <= 0;
else
Clock_Divider <= 0;
end
reg clk; // An additional register for the clock at the baud rate
always @(Clock_Divider)
begin
if(Clock_Divider == 434)
clk = 1'b1;
else
clk = 1'b0;
end
reg[4:0] Counter_1; // The Counter to control the Multiplexer
always @(posedge clk)
begin
Counter_1 <= Counter_1+1;
if (Counter_1 == 9) // Since there are a total of 10 bits including the start and the stop bit
Counter_1 <= 0;
end
reg Output; // The Multiplexer
always @(Counter_1 or Input)
begin
if (Counter_1 == 4'b0000)
Output <= 0;// Start Bit
else if (Counter_1 == 4'b0001)
Output <= Input[0]; //Connect to LSB
else if (Counter_1 == 4'b0010)
Output <= Input[1];
else if (Counter_1 == 4'b0011)
Output <= Input[2];
else if (Counter_1 == 4'b0100)
Output <= Input[3];
else if (Counter_1 == 4'b0101)
Output <= Input[4];
else if (Counter_1 == 4'b0110)
Output <= Input[5];
else if (Counter_1 == 4'b0111)
Output <= Input[6];
else if (Counter_1 == 4'b1000)
Output <= Input[7]; //Connect to MSB
else if (Counter_1 == 4'b1001)
Output <= 1; // Stop Bit
else
Output <= 1; // The idle state
end
assign D_Out = Tx;
endmodule
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
By changing the Clock_Divider reset value, various baud rates can be achieved. The output of the transmitter can be verified by using a terminal software in PC such as PuTTY or Tera Term. The transmitted data has to be converted to USB protocol by using a suitable IC such as FT232RL. An easy solution would be to connect the Tx pin to the Rx pin in an Arduino and then use the Serial Monitor of the Arduino software to view the data.
Comments
Post a Comment