Design and verification of the serial port receiving module for FPGA learning

Design and verification of the serial port receiving module for FPGA learning

1. The purpose of the experiment:

Realize a serial port reception, send data through the host computer, check whether the serial port receiving module receives the data.

2. Introduction to the experiment:

Learn the principle of UART communication and its hardware circuit design, use FPGA to realize the design of the data receiving part of UART communication, and use ISSP tool to carry out board-level verification.

3. Experimental principle

In the serial port sending module of the previous article, the sequence diagram of the serial port sending one byte is mentioned, as shown in the figure below:

Insert picture description here
In fact, when the serial port receiving module receives such timing bytes, each bit is sampled. Under normal circumstances, we believe that the middle point of each bit of data is the most stable, so the level at the middle of the collection is the data of this bit. The specific serial port receiving sequence is shown in the following figure:
Insert picture description here
but in actual applications, it is unreliable to collect the middle bit of the data only once, and it is easy to be interfered and cause data errors. This experiment uses more single-bit data receiving methods. Sub-sampling comparison level occurrence probability method. (Src: "FPGA System Design and Verification Practical Guide_V1.2") As you can see
Insert picture description here
from the figure above, a single bit of data is divided into 16 sub-segments evenly. The data at this bit has just occurred and will change (the dark gray part of the figure above) is considered to be extremely During the unstable period, it is determined that the acquisition level is invalid.

In the intermediate period (the light gray part of the figure above), the data is considered to be in a stable state, that is, the intermediate sampling method, but it cannot be denied that the error level is generated due to interference during this period. Therefore, the level of this period is sampled multiple times. This time, the intermediate time Sampling 6 times, after sampling, find the probability of occurrence of high and low levels, and the level of multiple occurrences is regarded as the data level of the bit.

(1) System framework

For the realization of the entire serial port receiving module, understand the following input and output ports:

1. The clock Clk and reset signal Rst_n are indispensable;

2. Like serial port transmission, select different baud rate signals baud_set[2:0];

3. It is learned from the serial port that the data is transmitted bit by bit, and the Rx232_Rx signal received by the receiving module is only 1 bit at a time;

4. After the data is received, a high pulse Rx_Done signal of 1 clock cycle should be required;

5. The received data is composed of [7:0] data_byte signal output for viewing.

Insert picture description here

(2) Detailed design

Data input synchronization processing

In the key debounce article, it is mentioned that the key signal needs to be processed synchronously with asynchronous signals. Similarly, when the Rx232_Rx signal crosses the clock domain, it also needs to be processed synchronously with asynchronous signals, and how to do edge detection. The specific principles are described in the key debounce chapter. The detailed introduction will not be repeated here.

Insert picture description here

Sampling clock generation module

Consistent with the serial port transmitter module, the main component of the serial port receiver module is also the baud rate clock generation design.

The difference is that the reception here uses single-bit 16-point sampling, and the speed is increased to 16 times the original. Assuming that the original sending baud rate is 9600bps, the current receiving baud rate is 9600*16=153600bps;

According to the previous serial port sending baud rate table, calculate the receiving module design frequency division count value. The code shown in the following table
Insert picture description here
uses the corresponding relationship of the baud rate sent by the previous serial port, that is, using the LUT look-up table to design the selector and generate the baud rate For the frequency division counter of the rate clock, first a set of three tricks is down. The code is shown in the figure below. Except for the different count value of bps_cnt, the rest is consistent with the serial port transmission.

Insert picture description here

Sampling clock counting design

When the sampling clock bps_clk we need is available, the next step is to start counting the rising edge of the clock.
Insert picture description here
As shown in the figure above, start bit + 8 data bits + stop bit, each bit is sampled 16 times, it needs to be sampled 160 times before the count value is cleared.

There is also the detection of the start bit. We know that the start bit START_BIT is actually a continuous low level, but how to judge that the start bit is an interference signal rather than the real start bit?

Now when there is a falling edge on the data line, assuming it is the start bit at this time, then the cumulative result of the calculated value obtained from the 6 intermediate samples is greater than 2, then it can be seen that at least half of the 6 intermediate samples are high, which is not satisfied. The start signal continues to be low level, so it can be judged that the signal on the data line is an interference signal at this time. (Src: "FPGA System Design and Verification Practical Guide_V1.2")

Insert picture description here

Data receiving module

After the data we receive is synchronized, it will eventually need to be transferred to data_byte[7:0], but we sample each bit 16 times, taking the middle 6 times, so an intermediate transition value process is required.

Therefore, the first step is to first accumulate the value of 6 samples of each bit of the 10-bit data and assign it to each bit, and then add 4 (when 111000 appears, the design does not deal with it, and the number of times 1 or 0 is found to be 4 times. 110000, 111100) to get this bit of data.

(1) The first step: accumulation of 6 sampling values

Insert picture description here
Compared with the value in the timing chart above, when the count value of bps_cnt is 6, 7, 8, 9, 10, 11, it is the middle 6 samplings. We need to accumulate these 6 values ​​and assign them to the START_BIT bit. The rest of the data is the same.

So here we need to define a ram, register the middle 8-bit data, and define the start bit and stop bit separately, so the ram has an 8-bit address, and each bit is 3 bits wide.

Insert picture description here
Insert picture description here

(2) Step 2: Compare the relationship between 8 data bits and 4

How do the middle 8 data bits determine what data it is? Here (src: "FPGA System Design and Verification Practical Guide_V1.2") provides the high-order comparison, because 3 (011) and 4 (100) will have high-order conversion, so when the highest bit of the data bit register value is 1 or 0 It can be concluded whether the bit is 1 or 0.
Insert picture description here

4. Experimental simulation and debugging

1. Functional simulation

1. Use the output of the serial port sending data module in the previous article to realize the input of the data of the module under test, so you only need to connect the Rx232_Tx of the sending module to the Rx232_Rx on the receiving module.

//--------------------------------------------------------------------------------------------
//      Component name  : uart_rx_tb	
//      Author          : 硬件嘟嘟嘟
//      time            : 2020.04.23
//      Description     : 串口发送模块
//      src             : FPGA系统设计与验证实战指南_V1.2
//--------------------------------------------------------------------------------------------
`timescale 1ns/1ns
`define clk_period 20

module uart_rx_tb;

	reg Clk;
	reg Rst_n;
	
	wire [7:0]data_byte_r;
	wire Rx_Done;	
	
	reg [7:0]data_byte_t;
	reg send_en;
	reg [2:0]baud_set;
	
	wire Rx232_Tx;
	wire Tx_Done;
	wire uart_state;
	
	uart_rx uart_rx(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.baud_set(baud_set),
		.Rx232_Rx(Rx232_Tx),
		
		.data_byte(data_byte_r),
		.Rx_Done(Rx_Done)
	);
	
	uart_tx uart_tx(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.data_byte(data_byte_t),
		.send_en(send_en),
		.baud_set(baud_set),
		
		.Rx232_Tx(Rx232_Tx),
		.Tx_Done(Tx_Done),
		.uart_state(uart_state)
	);
	
	initial Clk = 1;
	always#(`clk_period/2)Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		data_byte_t = 8'd0;
		send_en = 1'd0;
		baud_set = 3'd4;
		#(`clk_period*20 + 1 );
		Rst_n = 1'b1;
		#(`clk_period*50);
		data_byte_t = 8'hbb;
		send_en = 1'd1;
		#`clk_period;
		send_en = 1'd0;
		
		@(posedge Tx_Done)
		
		#(`clk_period*5000);
		data_byte_t = 8'h66;
		send_en = 1'd1;
		#`clk_period;
		send_en = 1'd0;
		@(posedge Tx_Done)
		#(`clk_period*5000);
		$stop;	
	end


endmodule

Check whether the waveform output is consistent with the design in the functional simulation
Insert picture description here

2. Board level debugging

The information sent by the serial port can be read correctly in ISSP.

Insert picture description here

Guess you like

Origin blog.csdn.net/sinat_41653350/article/details/105713332