[Xiaoyue Electronics] ALTERA FPGA development board system learning tutorial-LESSON7 serial communication

Serial communication routine explanation

To view the video tutorial accompanying this blog, click this link

Development board physical picture

Insert image description here

Insert image description here

Figure 1. FPGA design flow
Based on many years of work experience, the FPGA design process has been summarized in a total of the above 12 steps, some of which can be omitted depending on the difficulty of the project. For example, for very simple projects, we can omit the steps in the dotted box, but our introductory course, no matter how simple it is, will be explained according to these 12 steps.

1. Interpretation of requirements

1.1 Requirements

Control 8 LED lights through the serial port with a baud rate of 9600. For example, if 8'h55 is sent through the serial port, 4 LED lights will be on and 4 LED lights will be off on the development board. At the same time, the serial port assistant will receive 8'h 55

1.2 Knowledge background

Serial port is the abbreviation of "serial interface", that is, an interface that uses serial communication. Serial communication divides data bytes into bits and transmits them one by one on a data line. It is characterized by simple communication lines but slow transmission speed. Therefore, serial ports are widely used in embedded, industrial control and other fields where data transmission speed is not required.
Serial communication is divided into two methods: synchronous serial communication and asynchronous serial communication. Synchronous serial communication requires both communicating parties to transmit data synchronously under the control of the same clock; asynchronous serial communication means that both communicating parties use their own clocks to control the sending and receiving process of data.
UART is a universal asynchronous receiver-transmitter that uses asynchronous serial communication. When sending data, it converts parallel data into serial data for transmission, and when receiving data, it converts the received serial data into serial data. Data is converted into parallel data.
UART serial port communication requires two signal lines, one for serial port transmission and the other for serial port reception. A frame of data during UART transmission or reception consists of 4 parts, start bit, data bit, parity bit and stop bit. The specific timing is shown in Figure 1. Among them, the start bit marks the beginning of a frame of data, the stop bit marks the end of a frame of data, and the data bit is the valid data in a frame of data. The parity bits are divided into odd parity and even parity, which are used to check whether there are errors in the data during transmission. In odd parity, the sender should make the sum of the number of 1s in the data bits and the number of 1s in the check bits an odd number; when the receiver receives the data, it should check the number of 1s. If it is not an odd number
, It means that there is an error in the data transmission process. Similarly, even parity checks whether the number of 1's is even.
The data format and transmission rate during UART communication can be set. For correct communication, both the sending and receiving parties should agree on and follow the same settings. The data bits can be selected as 5, 6, 7 or 8 bits, among which 8 data bits are the most commonly used. In practical applications, 8 data bits are generally selected; the parity bit can be odd parity, even parity or none. Check bit; stop bit can be selected from 1 bit (default), 1.5 or 2 bits. The rate of serial communication is represented by the baud rate, which represents the number of binary data transmitted per second, and the unit is bps (bits/second). Commonly used baud rates are 9600, 19200, 38400, 57600, and 115200.
After setting the data format and transmission rate, the UART is responsible for completing the serial-to-parallel conversion of the data, while the signal transmission is implemented by an external drive circuit. The transmission process of electrical signals has different level standards and interface specifications. The interface standards for asynchronous serial communication include RS232, RS422, RS485, etc., which define different electrical characteristics of the interface. For example, RS-232 is a single-ended input and output. RS-422/485 is differential input and output, etc.
The RS232 interface standard appeared earlier and can realize full-duplex working mode, that is, data sending and receiving can be carried out at the same time. When the transmission distance is short (no more than 15m), RS232 is the most commonly used interface standard for serial communication. This chapter mainly introduces UART serial communication for the RS-232 standard.
The most common interface type of the RS-232 standard serial port is DB9, as shown in Figure 2. Industrial computers used in the field of industrial control are generally equipped with multiple serial ports, and many old-fashioned desktop computers are also equipped with serial ports. However, laptops and newer desktop computers do not have serial ports. They generally use USB-to-serial cables (Figure 3) to achieve serial communication with external devices.
Insert image description here

Figure 1. Asynchronous serial port timing diagram

Insert image description here

Figure 2. DB9 connector

Insert image description here

Figure 3. USB serial cable

The DB9 interface definition and the function description of each pin are shown in Figure 16.1.4. We generally only use pins 2 (RXD), 3 (TXD), and 5 (GND). The other pins are generally used in normal serial port mode. Do not use.
Insert image description here

Figure 4. DB9 interface definition
Baud rate 9600bps: 9600 bits transmitted per second. The time to transmit 1 bit is: 1/9600 (second) = 104167ns, which is 5208 clock cycles. It needs to be collected more than once. This is just to introduce the knowledge related to the serial port. Our XLOGIC development board has a USB to TTL chip (CH340) onboard. Serial communication with the computer can be carried out using a USB cable.

1.3 Hardware design

Insert image description here

Active crystal oscillator, connected to E1 pin

Insert image description here

Serial communication circuit
Taking KEY1 as an example, when the button is not pressed, the network KEY1 is pulled up to 3.3V, which is a high level; when the button is pressed, the network KEY1 is directly connected to the ground, which is a low level.

1.4 Interface description

Signal name direction FPGA pin number illustrate
CLK_50M enter E1 System clock, 50Mhz
KEY1 enter M1 Independent button, press low level, used as reset signal
CH340_RX enter B11 Serial signal input
CH340_TX output A11 Serial signal output

    Summary: Through the above description, the requirement can be interpreted as: the serial port assistant sends a number at a baud rate of 9600, and sends it to the FPGA through the serial port sending port. The FPGA parses the number according to the serial port timing, and then assigns this number to 8 LED will do. At the same time, the FPGA sends this number through the serial port receiving port, so that the sent data can be displayed on the serial port assistant.

2. Draw theoretical waveform diagram

Insert image description here

Logic block diagram

Insert image description here

Serial port receiving theoretical waveform diagram

Insert image description here

Serial port transmission theoretical waveform diagram

3. Create a new QuartusII project

In order to make the project look tidy and facilitate project transplantation. We create 4 new folders, namely Project, Source, Sim, and Doc.
Project — project folder, which contains the QuartusII project
Source — source code folder, which contains the project source code (.v file or .vhd file)
Sim — simulation folder, which contains simulation-related files
Doc — stores related information , such as data manuals, requirements documents, etc.

4. Write code

4.1 Serial port receiving module code

///
//QQ:3181961725
//TEL/WX:13540738439
//作者:Mr Wang
//模块介绍:实现异步串口接收功能
///
module async_uart_rev(
	input				rst_n	,//复位信号,低电平有效
	input				clk		,//时钟信号,50MHZ
	input				rxd		,//串行接收数据
	output	reg	[7:0]	rev_data,//并行数据
	output	reg			rev_dvld //并行数据有效标志
	);
	parameter	baud_num=5207;//1/9600*1000000000/20
	parameter	IDLE		=4'd0;
	parameter	START_ST    =4'd1;
	parameter	STOP_ST     =4'd2;
	reg	[12:0]	baud_cnt;
	reg			baud_cnt_en;
	wire		sample_en;
	reg	[3:0]	sample_num;
	reg			rxd_ff1;
	reg			rxd_ff2;
	reg	[3:0]	curr_st;
	//打两拍操作
	always@(posedge clk)rxd_ff2<=rxd_ff1;
	always@(posedge clk)rxd_ff1<=rxd;
	assign	sample_en=(baud_cnt==baud_num[12:1])?1'b1:1'b0;
	//状态机跳转程序
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st<=IDLE;
		else case(curr_st)
			IDLE:begin
				if(rxd_ff2==0)
					curr_st<=START_ST;
				else;
			end
			START_ST:begin
				if(sample_num==8&&sample_en)
					curr_st<=STOP_ST;
				else;
			end
			STOP_ST:begin
				if(rxd_ff2==1&&sample_en)
					curr_st<=IDLE;
				else;
			end
			default:;
		endcase
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			baud_cnt<=0;
		else if(curr_st==START_ST||curr_st==STOP_ST)begin
			if(baud_cnt==baud_num)
				baud_cnt<=0;
			else 
				baud_cnt<=baud_cnt+1;
		end else
			baud_cnt<=0;
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			sample_num<=0;
		else if(sample_en&&sample_num==9)
			sample_num<=0;
		else if(sample_en)
			sample_num<=sample_num+1;
		else;
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			rev_data<=0;
		else if(sample_en)
			case(sample_num)
			1:rev_data[0]<=rxd_ff2;
			2:rev_data[1]<=rxd_ff2;
			3:rev_data[2]<=rxd_ff2;
			4:rev_data[3]<=rxd_ff2;
			5:rev_data[4]<=rxd_ff2;
			6:rev_data[5]<=rxd_ff2;
			7:rev_data[6]<=rxd_ff2;
			8:rev_data[7]<=rxd_ff2;
			default:;
		endcase
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			rev_dvld<=0;
		else if(sample_num==9&&sample_en)
			rev_dvld<=1;
		else
			rev_dvld<=0;
	end
endmodule

4.2 Serial port sending module code

///
//QQ:3181961725
//TEL/WX:13540738439
//作者:Mr Wang
//模块介绍:实现异步串口发送功能
///
module async_uart_tran(
	input			rst_n		,//复位信号,低电平有效
	input			clk			,//时钟,50MHZ
	input	[7:0]	tran_data	,//输入的并行数据
	input			tran_dvld	,//输入的并行数据有效标志
	output	reg		txd          //串行输出数据
	);
	parameter	baud_num=5207;//1/9600*1000000000/20
	parameter	IDLE		=4'd0;
	parameter	DATA_ST    =4'd1;
	parameter	START_ST    =4'd2;
	parameter	STOP_ST     =4'd3;
	reg	[12:0]	baud_cnt;
	reg			baud_cnt_en;
	wire		sample_en;
	reg	[3:0]	sample_num;
	reg	[3:0]	curr_st;

	assign	sample_en=(baud_cnt==baud_num)?1'b1:1'b0;
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			curr_st<=IDLE;
		else case(curr_st)
			IDLE:begin
				if(tran_dvld==1)
					curr_st<=START_ST;
				else;
			end
			START_ST:begin
				if(sample_en==1)
					curr_st<=DATA_ST;
			end
			DATA_ST:begin
				if(sample_en&&sample_num==8)
					curr_st<=STOP_ST;
				else;
			end
			STOP_ST:begin
				if(sample_en==1)
					curr_st<=IDLE;
				else;
			end
			default:;
		endcase
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			baud_cnt<=0;
		else if(curr_st==START_ST||curr_st==DATA_ST||curr_st==STOP_ST)begin
			if(baud_cnt==baud_num)
				baud_cnt<=0;
			else 
				baud_cnt<=baud_cnt+1;
		end else
			baud_cnt<=0;
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)	
			sample_num<=0;
		else if(curr_st==IDLE)
			sample_num<=0;
		else if(sample_en)
			sample_num<=sample_num+1;
		else;
	end
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			txd<=1;
		else if(sample_en)
			case(sample_num)
			0:txd<=1'b0;
			1:txd<=tran_data[0];
			2:txd<=tran_data[1];
			3:txd<=tran_data[2];
			4:txd<=tran_data[3];
			5:txd<=tran_data[4];
			6:txd<=tran_data[5];
			7:txd<=tran_data[6];
			8:txd<=tran_data[7];
			9:txd<=1'b1;
			default:txd<=1;
		endcase
	end
endmodule

4.3 Top-level module code

///
//QQ:3181961725
//TEL/WX:13540738439
//作者:Mr Wang
//模块介绍:顶层模块,例化接收和发送模块
///
module async_uart_top(
	input	clk			,//时钟,50MHZ
	input	rst_n		,//复位信号,低电平有效
	input	rxd			,//串行接收数据
	output	txd			,//串行发送数据
	output	[7:0] led
	);
	wire	[7:0]	rev_data;
	wire			rev_dvld;
	assign	led=rev_data;
	async_uart_rev Uasync_uart_rev(
	.rst_n		(rst_n),
	.clk		(clk),
	.rxd		(rxd),
	.rev_data	(rev_data),
	.rev_dvld   (rev_dvld)
	);
	async_uart_tran async_uart_tran(
	.rst_n		(rst_n),
	.clk		(clk),
	.tran_data	(rev_data),
	.tran_dvld	(rev_dvld),
	.txd        (txd)
	);
endmodule

5. Write simulation test stimulus file

Insert image description here

Simulation block diagram

Simulation test stimulus file (TB file)

`timescale 1ns/1ns
module async_uart_top_tb;
	reg					clk		;
	reg					rst_n	;
	wire				rxd		;
	wire				tran_dvld;
	reg	[17:0]	cnt=0;
initial
begin
	clk = 0;
	rst_n=0;
	#1000
	rst_n=1;
end
always #10 clk=~clk;
always@(posedge clk)cnt<=cnt+1;
assign	tran_dvld=(cnt==100)?1'b1:1'b0;
async_uart_tran Uasync_uart_tran(
	.rst_n		(rst_n),
	.clk		(clk),
	.tran_data	(8'h55),
	.tran_dvld	(tran_dvld),
	.txd        (rxd)
	);
async_uart_top async_uart_top(
	.clk	(clk),
	.rst_n	(rst_n),
	.rxd	(rxd),
	.txd	(),
	.led    ()
	);
endmodule

6.Modelsim simulation

There are generally two methods for Modelsim simulation:

  1. Graphical interface simulation means that all operations are completed on the Modelsim software interface. The advantage of this method is that it is easy to learn and suitable for simple projects. The disadvantage is that the operation steps are cumbersome.

  2. Batch simulation , this method requires writing corresponding script files before simulation. The advantage of this method is that the simulation can be completed with one click, saving time and effort. The disadvantage is that script files need to be written in the early stage. The first two lectures use graphical interface simulation; in order to be closer to engineering reality, starting from the third lecture, we use batch processing simulation. For specific operation steps, please refer to our video tutorial.
    The simulated waveform is shown below:
    Insert image description here

7. Compare waveforms

Compare the theoretical waveform diagram drawn in the second step with the waveform diagram simulated by Modelsim in the sixth step. The results are consistent, indicating that our logic design is correct. If the comparison results are found to be inconsistent, you need to find the reason for the inconsistency, and ultimately ensure that the comparison results are consistent.
By comparison, the theoretical waveform is consistent with the simulated waveform, indicating that the function meets the design requirements.

8. Compilation and synthesis

Insert image description here

9. Bind pins

When the project is compiled successfully, pin assignment can be made (you need to refer to the schematic diagram of the development board). The development boards and modules in our store are marked with signal names on the PCB, and you can directly refer to the physical connection relationships when binding pins.
Insert image description here
The pin mapping relationship is as follows:
Insert image description here

10. Compile and synthesize again

Insert image description here

11 Download SOF file

After successful compilation and synthesis again, the generated SOF file can be downloaded to the development board.
Insert image description here
Insert image description here
After the download is successful, the experimental phenomena on the development board can be observed. If the experimental phenomena are consistent with the design requirements, it means that there is no problem with our design, that is, You can proceed to the next step of solidifying the JIC file.

12 Generate and solidify JIC files

FPGA has a characteristic that the configuration information will be lost after power failure, so we need to store the configuration information in the configuration chip (FLASH). After the development board is powered on, the FPGA will read the configuration information in the configuration chip, so the development The board can still work normally after powering off and on again. To solidify the program to the configuration chip, you need to generate a JIC file first. The steps to convert SOF files into JIC files are as follows:

12.1 file–>Convert Programming File…

Insert image description here

12.2 Select the JIC file and configure the chip model and FPGA modelInsert image description here

Label 1 : Select the format of the generated file, we choose the JIC file
Label 2 : Select the model of the configuration chip, we choose EPCS16
Label 3 : Modify the name and storage path of the generated JIC file
Label 4 : Click the left mouse button on the Flash Loader
Label 5 : Select As for the FPGA model, our development board uses the EP4CE6F17C8 FPGA, so we should also choose this model, as shown in the figure below:
Insert image description here

12.3 Select SOF file

Insert image description here
Label 1 : Click the left mouse button on SOF Data
Label 2 : Add SOF file, select the SOF file generated by our project, as shown below:
Insert image description here

12.3 Generate JIC file

Insert image description here
At this point, the JIC file is generated and the curing operation can be performed.

12.4 Curing JIC files

Insert image description here
After curing, the program will not be lost when the power is turned off!

Experimental phenomena

It matches the design requirements and the design is completed!

Guess you like

Origin blog.csdn.net/Moon_3181961725/article/details/126759932