A UART Receiver follows a UART Transmitter. It receives the serialized data and converts it back to a parallel form. The working of the receiver is a bit more complicated than the transmitter. Since UART is an Asynchronous Protocol, no clock is transmitted along the data. Therefore, the receiver has to identify the start of the incoming data frame to properly convert it to parallel form. To do this the transmitter and the receiver have to agree to the baud rate and the number of bits per frame. The transmitter and the receiver also have to agree with the length of the stop period (1 bit, 1.5 bit or 2 bits). In the given project the UART Receiver is configured for the baud rate of 1 Mbit/s, 1 stop bit, no parity or flow control. The receiver looks for the Rx_pin to go low which indicates the start bit. As the Rx_pin goes low, a Flip_Flop is Set which enables a counter which starts counting as the Rx_pin goes low. When the Counter reaches 25 (The counter is clocked at 50 Mhz in the given code, therefore there are 50 clocks in 1 bit duration at 1 Mbit/s, therefore 25th clock is at the middle of the start bit), it is at the middle of the start bit. An output latch is set whose input is connected to the Rx_pin. Similarly when the counter reaches 25+50 i.e 75, we are at the middle of the first bit. So, another latch is set whose input is connected to the Rx_pin. This goes on until the stop bit. Note that this code does not have an output Shift Register. Therefore an improvement would be to put another Shift Register at the Output so that we know that the entire byte has reached. By changing the values of the clock counter, various baud rates can be achieved. Another output called D_Rdy(Data Ready) is also present which goes high for 50 clock pulses which indicates the completion of the reception of the complete byte.
Now we come to the Verilog Code of the Receiver.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
//
//
// Create Date: 12:05:43 06/01/2019
// Design Name:
// Module Name: UART_RX_Module
// Project Name:
// Target Devices:
// Tool versions:
// Description:
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module UART_RX(clk,d_in,D_Out,D_Rdy);
input clk,d_in; //The clock and the data input; clock is at 50 Mhz
output [7:0] D_Out; //8-bit data output
output D_Rdy; //Data Ready output; indicates that the complete byte has been received
//////////////////////////////////////////////////////////////////////////////////
reg [9:0] Clock_Counter=0; //The Clock Counter Register; the value starts from zero
always @(posedge clk) //The register increments at the rising edge of the clock
begin
if (Flip_Flop == 1'b1)
Clock_Counter <= Clock_Counter+1;
if(Clock_Counter==475)
Clock_Counter <= 0;
end
//////////////////////////////////////////////////////////////////////////////////
reg Flip_Flop; //The Flip Flop which gets set at the falling edge of the start bit
always @(posedge clk)
begin
if(d_in == 1'b0)
Flip_Flop <= 1'b1;
if(Clock_Counter==475)
Flip_Flop <= 1'b0; //Flip Flop resets at the center of the stop bit
end
//////////////////////////////////////////////////////////////////////////////////
reg SIPO_0; //The Start Bit
always @(Clock_Counter)
begin
if(Clock_Counter==25)
SIPO_0 <= d_in;
end
reg SIPO_1; //The LSB
always @(Clock_Counter)
begin
if(Clock_Counter==75)
SIPO_1 <= d_in;
end
assign D_Out[0] = SIPO_1;
reg SIPO_2;
always @(Clock_Counter)
begin
if(Clock_Counter==125)
SIPO_2 <= d_in;
end
assign D_Out[1] = SIPO_2;
reg SIPO_3;
always @(Clock_Counter)
begin
if(Clock_Counter==175)
SIPO_3 <= d_in;
end
assign D_Out[2] = SIPO_3;
reg SIPO_4;
always @(Clock_Counter)
begin
if(Clock_Counter==225)
SIPO_4 <= d_in;
end
assign D_Out[3] = SIPO_4;
reg SIPO_5;
always @(Clock_Counter)
begin
if(Clock_Counter==275)
SIPO_5 <= d_in;
end
assign D_Out[4] = SIPO_5;
reg SIPO_6;
always @(Clock_Counter)
begin
if(Clock_Counter==325)
SIPO_6 <= d_in;
end
assign D_Out[5] = SIPO_6;
reg SIPO_7;
always @(Clock_Counter)
begin
if(Clock_Counter==375)
SIPO_7 <= d_in;
end
assign D_Out[6] = SIPO_7;
reg SIPO_8; // The MSB
always @(Clock_Counter)
begin
if(Clock_Counter==425)
SIPO_8 <= d_in;
end
assign D_Out[7] = SIPO_8;
reg SIPO_9; //The Stop bit
always @(Clock_Counter)
begin
if(Clock_Counter==475)
SIPO_9 <= d_in;
end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reg DataReady; //Data Ready Register; turns high after the reception of the MSB
always @(Clock_Counter)
begin
if(Clock_Counter > 425)
DataReady <= 1'b1;
if(Clock_Counter < 425)
DataReady <= 1'b0;
end
assign D_Rdy = DataReady;
endmodule
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
To test this, you can write a Verilog Testbench or you can synthesize and upload it to an FPGA.
To send the data, you can use an Arduino. A Spartan 6 XC6SLX9-TQG144 FPGA was used to test this. The device utilization is as follows :
Now we come to the Verilog Code of the Receiver.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
//
//
// Create Date: 12:05:43 06/01/2019
// Design Name:
// Module Name: UART_RX_Module
// Project Name:
// Target Devices:
// Tool versions:
// Description:
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module UART_RX(clk,d_in,D_Out,D_Rdy);
input clk,d_in; //The clock and the data input; clock is at 50 Mhz
output [7:0] D_Out; //8-bit data output
output D_Rdy; //Data Ready output; indicates that the complete byte has been received
//////////////////////////////////////////////////////////////////////////////////
reg [9:0] Clock_Counter=0; //The Clock Counter Register; the value starts from zero
always @(posedge clk) //The register increments at the rising edge of the clock
begin
if (Flip_Flop == 1'b1)
Clock_Counter <= Clock_Counter+1;
if(Clock_Counter==475)
Clock_Counter <= 0;
end
//////////////////////////////////////////////////////////////////////////////////
reg Flip_Flop; //The Flip Flop which gets set at the falling edge of the start bit
always @(posedge clk)
begin
if(d_in == 1'b0)
Flip_Flop <= 1'b1;
if(Clock_Counter==475)
Flip_Flop <= 1'b0; //Flip Flop resets at the center of the stop bit
end
//////////////////////////////////////////////////////////////////////////////////
reg SIPO_0; //The Start Bit
always @(Clock_Counter)
begin
if(Clock_Counter==25)
SIPO_0 <= d_in;
end
reg SIPO_1; //The LSB
always @(Clock_Counter)
begin
if(Clock_Counter==75)
SIPO_1 <= d_in;
end
assign D_Out[0] = SIPO_1;
reg SIPO_2;
always @(Clock_Counter)
begin
if(Clock_Counter==125)
SIPO_2 <= d_in;
end
assign D_Out[1] = SIPO_2;
reg SIPO_3;
always @(Clock_Counter)
begin
if(Clock_Counter==175)
SIPO_3 <= d_in;
end
assign D_Out[2] = SIPO_3;
reg SIPO_4;
always @(Clock_Counter)
begin
if(Clock_Counter==225)
SIPO_4 <= d_in;
end
assign D_Out[3] = SIPO_4;
reg SIPO_5;
always @(Clock_Counter)
begin
if(Clock_Counter==275)
SIPO_5 <= d_in;
end
assign D_Out[4] = SIPO_5;
reg SIPO_6;
always @(Clock_Counter)
begin
if(Clock_Counter==325)
SIPO_6 <= d_in;
end
assign D_Out[5] = SIPO_6;
reg SIPO_7;
always @(Clock_Counter)
begin
if(Clock_Counter==375)
SIPO_7 <= d_in;
end
assign D_Out[6] = SIPO_7;
reg SIPO_8; // The MSB
always @(Clock_Counter)
begin
if(Clock_Counter==425)
SIPO_8 <= d_in;
end
assign D_Out[7] = SIPO_8;
reg SIPO_9; //The Stop bit
always @(Clock_Counter)
begin
if(Clock_Counter==475)
SIPO_9 <= d_in;
end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reg DataReady; //Data Ready Register; turns high after the reception of the MSB
always @(Clock_Counter)
begin
if(Clock_Counter > 425)
DataReady <= 1'b1;
if(Clock_Counter < 425)
DataReady <= 1'b0;
end
assign D_Rdy = DataReady;
endmodule
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
To test this, you can write a Verilog Testbench or you can synthesize and upload it to an FPGA.
To send the data, you can use an Arduino. A Spartan 6 XC6SLX9-TQG144 FPGA was used to test this. The device utilization is as follows :
- No. of Slice Registers used - 11 out of 11,440 i.e 1%
- Out of which no. of Registers used as Flip_Flops - 11
- No. of Slice Look Up Tables used - 37 out of 5,720 i.e 1%
- No. of LUTs used as Logic - 36
- No. of Occupied Slices - 13 out of 1430 i.e 1%
- No. of IOBs used - 11 out of 102 i.e 10%
Comments
Post a Comment