UART串口通信(回环测试)

这篇具有很好参考价值的文章主要介绍了UART串口通信(回环测试)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 UART串口通信简介

        UART(Universal Asynchronous Receiver-Transmitter)是采用异步串行通信方式的通用异步收发传输器,在发送数据时将并行数据转换为串行数据,在接收数据时将串行数据转换为并行数据。发送和接收的一帧数据由起始位、数据位、奇偶校验位和停止位组成,其数据帧格式如下:

UART串口通信(回环测试)

        串口通信的速率用波特率表示,单位为bps(位/秒),常用的波特率由9600、19200、38400、57600、115200。

        针对异步串行通信接口的标准有RS232、RS422、RS485等,其电器特性如下表所示:

接口类型

RS232

RS422

RS485

工作方式

单端(全双工)

差分(全双工)

差分(半双工)

节点数

1发1收

1发10收

1发32收

逻辑特性

逻辑1:-5V~-15V

逻辑0:+5V~+15V

逻辑1:+2V~+6V

逻辑0:-2V~-6V

逻辑1:+2V~+6V

逻辑0:-2V~-6V

传输速率

20Kbps

10Mbps

10Mbps

传输距离

15m

1200m

3000m

二UART串口通信实验

1. 实验内容

        UART串口通信实验内容位:当上位机通过串口调试工具发送数据给FPGA,FPGA通过串口接收数据并将接收到的数据发送给上位机,完成串口数据环回。当上位机未发送数据时候,FPGA每隔1s产生Hello World!发送给上位机并通过串口调试工具显示。

UART串口通信(回环测试)

2.工程代码

2.1串口发送模块

串口发送模块将输入的8位并行数据进行串行输出。串口发送模块uart_tx代码如下:

1  `timescale	1ns/1ps
2  module uart_tx
3  #(
4  	parameter	CLK_FREQ	=	50_000_000,			//系统时钟频率
5  	parameter	UART_BPS	=	9600				//串口波特率
6  )
7  (
8  	input					clk,
9  	input					rst_n,
10 	
11 	input			[7:0]	tx_data,			//待发送数据
12 	input					tx_en,				//发送使能信号
13 	output					uart_tx_busy,		//发送忙碌标志信号
14 	output	reg				uart_txd			//UART数据发送端口
15 	
16 );
17 
18 localparam	BPS_CNT	=	CLK_FREQ/UART_BPS;//当前波特率需要系统时钟计数BPS_CNT次
19 
20 reg			tx_en_r1;
21 reg			tx_en_r2;
22 
23 reg  [15:0]	clk_cnt;			//系统时钟计数器
24 reg  [3:0]	tx_bit_cnt;		//发送数据位计数器
25 reg			tx_flag;			//发送过程标志位
26 reg			bit_flag;
27 
28 wire		tx_start;
29 
30 //uart_tx_busy:串口发送忙碌状态
31 assign	uart_tx_busy	=	tx_flag;
32 
33 //tx_start:串口数据开始发送信号,捕获tx_en上升沿
34 assign	tx_start	=	!tx_en_r2 && tx_en_r1;
35 always @(posedge clk	or negedge rst_n)
36 begin
37 	if(!rst_n)
38 	begin
39 		tx_en_r1	<=	1'b0;
40 		tx_en_r2	<=	1'b0;	
41 	end
42 	else
43 	begin
44 		tx_en_r1	<=	tx_en;
45 		tx_en_r2	<=	tx_en_r1;
46 	end
47 end
48 
49 //tx_flag:接收过程标志信号
50 always @(posedge clk or negedge rst_n)
51 begin
52 	if(!rst_n)
53 		tx_flag	<=	1'b0;
54 	else if(tx_start)
55 		tx_flag	<=	1'b1;
56 	else if(tx_bit_cnt == 4'd9 && bit_flag == 1'b1)
57 		tx_flag <=	1'b0;
58 	else
59 		tx_flag	<=	tx_flag;		
60 end
61 
62 //clk_cnt:系统时钟计数器
63 always @(posedge clk or negedge rst_n)
64 begin
65 	if(!rst_n)
66 		clk_cnt	<=	16'd0;
67 	else if(tx_flag == 1'b0 || clk_cnt == BPS_CNT - 1'b1)
68 		clk_cnt	<=	16'd0;
69 	else if(tx_flag)
70 		clk_cnt	<=	clk_cnt + 1'b1;
71 	else
72 		clk_cnt	<=	16'd0;
73 end
74 
75 //bit_flag:当clk_cnt计数器计数到1时让bit_flag拉高一个时钟的高电平
76 always @(posedge clk or negedge rst_n)
77 begin
78 	if(!rst_n)
79 		bit_flag	<=	1'b0;
80 	else if(clk_cnt == 16'd1)
81 		bit_flag 	<=	 1'b1;
82 	else 
83 		bit_flag	<=	1'b0;
84 end
85 
86 //tx_bit_cnt:发送数据位计数器
87 always @(posedge clk or negedge rst_n)
88 begin
89 	if(!rst_n)
90 		tx_bit_cnt	<=	4'd0;
91 	else if((tx_bit_cnt == 4'd9) && (bit_flag == 1'b1))
92 		tx_bit_cnt	<=	4'd0;
93 	else if(bit_flag && tx_flag)
94 		tx_bit_cnt	<=	tx_bit_cnt + 1'b1;
95 	else 
96 		tx_bit_cnt	<=	tx_bit_cnt;
97 end	
98 
99 //uart_txd:根据发送数据计数器来给uart发送端口赋值
100always @(posedge clk or negedge rst_n)
101begin
102	if(!rst_n)
103		uart_txd	<=	1'b1;
104	else	if(bit_flag == 1'b1)
105	begin
106		case(tx_bit_cnt)
107			4'd0:uart_txd	<=	1'b0;				//发送起始位
108			4'd1:uart_txd	<=	tx_data[0];		//发送数据低位
109			4'd2:uart_txd	<=	tx_data[1];
110			4'd3:uart_txd	<=	tx_data[2];
111			4'd4:uart_txd	<=	tx_data[3];
112			4'd5:uart_txd	<=	tx_data[4];
113			4'd6:uart_txd	<=	tx_data[5];
114			4'd7:uart_txd	<=	tx_data[6];
115			4'd8:uart_txd	<=	tx_data[7];
116			4'd9:uart_txd	<=	1'b1;				//发送数据高位
117			default:uart_txd <= 1'b1;
118		endcase
119	end
120	else
121		uart_txd	<=	uart_txd;
122end
123
124endmodule
125

仿真代码如下:

1 	`timescale  1ns/1ps
2 	module uart_tx_tb();
3 
4 	reg			clk;
5 	reg			rst_n;
6 	reg	[7:0]	tx_data;		
7 	reg			tx_en;
8 		
9 	wire		uart_tx_busy;
10	wire		uart_txd;
11
12	initial 
13	begin
14		clk	=	1'b1;
15		rst_n	=	1'b0;
16		#200
17		rst_n	=	1'b1;
18	end
19
20	always #10	clk = ~clk;
21
22	initial begin
23			tx_data <= 8'b0;
24			tx_en 	<= 1'b0;
25			#200
26			//发送数据0
27			tx_data	<= 8'd0;
28			tx_en 	<= 1'b1;
29			#20
30			tx_en 	<= 1'b0;
31	//每发送1bit数据需要5208个时钟周期,一帧数据为10bit
32	//所以需要数据延时(5208*20*10)后再产生下一个数据
33			#(5208*20*10);
34			//发送数据1
35			tx_data<= 8'd1;
36			tx_en 	<= 1'b1;
37			#20
38			tx_en <= 1'b0;
39			#(5208*20*10);
40			//发送数据2
41			tx_data <= 8'd2;
42			tx_en <= 1'b1;
43			#20
44			tx_en <= 1'b0;
45			#(5208*20*10);
46			//发送数据3
47			tx_data<= 8'd3;
48			tx_en 	<= 1'b1;
49			#20
50			tx_en <= 1'b0;
51			#(5208*20*10);
52			//发送数据4
53			tx_data<= 8'd4;
54			tx_en 	<= 1'b1;
55			#20
56			tx_en 	<= 1'b0;
57			#(5208*20*10);
58			//发送数据5
59			tx_data<= 8'd5;
60			tx_en 	<= 1'b1;
61			#20
62			tx_en 	<= 1'b0;
63			#(5208*20*10);
64			//发送数据6
65			tx_data<= 8'd6;
66			tx_en 	<= 1'b1;
67			#20
68			tx_en <= 1'b0;
69			#(5208*20*10);
70			//发送数据7
71			tx_data<= 8'd7;
72			tx_en 	<= 1'b1;
73			#20
74			tx_en 	<= 1'b0;
75	end
76
77	uart_tx	u_uart_tx(
78		.clk(clk),
79		.rst_n(rst_n),
80		
81		.tx_data(tx_data),				//待发送数据
82		.tx_en(tx_en),					//发送使能信号
83		.uart_tx_busy(uart_tx_busy),	//发送忙碌标志信号
84		.uart_txd(uart_txd)				//UART数据发送端口
85		
86	);
87
88	endmodule
89

 仿真结果如下:

UART串口通信(回环测试)UART串口通信(回环测试)        仿真结果显示串口发送模块成功将数据0~7以UART数据帧格式进行发送。

2.2串口接收模块

        串口接收模块将串行的8位数据转化为并行的8位数据进行输出。串口接收模块uart_rx代码如下:

1  	`timescale 1ns/1ps
2  	module uart_rx
3  	#(
4  		parameter	CLK_FREQ	=	50_000_000,			//系统时钟频率
5  		parameter	UART_BPS	=	9600				//串口波特率
6  	)
7  	(
8  		input				clk,
9  		input				rst_n,
10 		
11 		input				uart_rxd,
12 		output				uart_rx_busy,
13 		output reg			rx_done,
14 		output reg [7:0]	rx_data
15 	);
16 
17 	localparam	BPS_CNT	=	CLK_FREQ/UART_BPS;//当前波特率需要系统时钟计数BPS_CNT次
18 
19 	reg			uart_rxd_r1;
20 	reg			uart_rxd_r2;
21 	reg [15:0]	clk_cnt;
22 	reg [3:0]	rx_bit_cnt;
23 	reg [7:0]	rx_data_r;
24 	reg			rx_flag;
25 	reg			bit_flag;
26 	reg			rx_done_r;
27 
28 
29 	assign	uart_rx_busy	=	rx_flag;
30 	wire	rx_start;
31 	//rx_start:接收开始信号
32 	assign	rx_start	=	uart_rxd_r2 && !uart_rxd_r1;
33 	always @(posedge clk or negedge rst_n)
34 	begin
35 		if(!rst_n)
36 		begin
37 			uart_rxd_r1	<=	1'b1;
38 			uart_rxd_r2	<=	1'b1;
39 		end
40 		else
41 		begin
42 			uart_rxd_r1	<=	uart_rxd;
43 			uart_rxd_r2	<=	uart_rxd_r1;
44 		end
45 	end
46 
47 	//rx_flag:接收过程标志位
48 	always @(posedge clk or negedge rst_n)
49 	begin
50 		if(!rst_n)
51 			rx_flag	<=	1'b0;
52 		else if(rx_start)
53 			rx_flag	<=	1'b1;
54 		else if(rx_bit_cnt == 4'd8 && bit_flag == 1'b1)
55 			rx_flag	<=	1'b0;
56 		else
57 			rx_flag	<=	rx_flag;
58 	end
59 
60 	//clk_cnt:系统时钟计数器
61 	always @(posedge clk or negedge rst_n)
62 	begin
63 		if(!rst_n)
64 			clk_cnt	<=	16'd0;
65 		else if(clk_cnt == BPS_CNT - 1'b1)
66 			clk_cnt	<=	16'd0;
67 		else if(rx_flag)
68 			clk_cnt	<=	clk_cnt + 1'b1;
69 		else
70 			clk_cnt	<=	16'd0;
71 	end
72 
73 	//bit_flag:接收过程标志位
74 	always @(posedge clk or negedge rst_n)
75 	begin
76 		if(!rst_n)
77 			bit_flag	<=	1'b0;
78 		else if(clk_cnt == BPS_CNT/2 - 1'b1)
79 			bit_flag	<=	1'b1;
80 		else
81 			bit_flag	<=	1'b0;
82 	end
83 
84 	//rx_bit_cnt:接收完成标志位
85 	always @(posedge clk or negedge rst_n)
86 	begin
87 		if(!rst_n)
88 			rx_bit_cnt	<=	4'd0;
89 		else if((rx_bit_cnt == 4'd8) && (bit_flag == 1'b1))
90 			rx_bit_cnt	<=	4'd0;
91 		else if(bit_flag == 1'b1)
92 			rx_bit_cnt	<=	rx_bit_cnt + 1'b1;
93 		else
94 			rx_bit_cnt	<=	rx_bit_cnt;
95 	end
96 
97 	//rx_data_r:输入数据进行移位
98 	always @(posedge clk or negedge rst_n)
99 	begin
100		if(!rst_n)
101			rx_data_r	<=	8'd0;
102		else if((rx_bit_cnt >= 4'd1) &&(rx_bit_cnt <= 4'd8) && (bit_flag == 1'b1))
103			rx_data_r	<=	{uart_rxd_r2 , rx_data_r[7:1]};
104		else
105			rx_data_r	<=	rx_data_r;
106	end
107
108	//rx_done_r:接收完成标志位
109	always @(posedge clk or negedge rst_n)
110	begin
111		if(!rst_n)
112			rx_done_r	<=	1'b0;
113		else if((rx_bit_cnt == 4'd8) && (bit_flag == 1'b1))
114			rx_done_r	<=	1'b1;
115		else
116			rx_done_r	<=	1'b0;
117	end
118
119	//rx_data:输出完整的8位有效数据
120	always @(posedge clk or negedge rst_n)
121	begin
122		if(!rst_n)
123			rx_data	<=	8'd0;
124		else if(rx_done_r)
125			rx_data	<=	rx_data_r;
126		else
127			rx_data	<=	rx_data;
128	end
129
130	//rx_done:接收完成标志位
131	always @(posedge clk or negedge rst_n)
132	begin
133		if(!rst_n)
134			rx_done	<=	1'b0;
135		else
136			rx_done	<=	rx_done_r;
137	end
138
139	endmodule

仿真代码如下:

1 	`timescale  1ns/1ns
2 	module uart_rx_tb();
3 
4 	reg				clk;
5 	reg				rst_n;
6 	reg				uart_rxd;
7 	wire			rx_done;
8 	wire [7:0]		rx_data;
9 
10	initial 
11	begin
12		clk			=	1'b1;
13		rst_n		=	1'b0;
14	 	uart_rxd  	= 	1'b1;
15		#200
16		rst_n		=	1'b1;
17	end
18
19	always #10	clk = ~clk;
20
21	initial 
22	begin
23		#200
24		rx_bit_data(8'd1);
25		rx_bit_data(8'd2);
26		rx_bit_data(8'd3);
27		rx_bit_data(8'd4);
28		rx_bit_data(8'd5);
29		rx_bit_data(8'd6);
30		rx_bit_data(8'd7);
31		rx_bit_data(8'd8);
32		rx_bit_data(8'd9);
33	end
34
35	task rx_bit_data(
36		input	[7:0]	data
37	);
38		integer	 i;
39		for(i = 0; i < 10; i = i + 1'b1)
40		begin
41			case(i)
42				0:uart_rxd	<=	1'b0;
43				1:uart_rxd	<=	data[0];
44				2:uart_rxd	<=	data[1];
45				3:uart_rxd	<=	data[2];
46				4:uart_rxd	<=	data[3];
47				5:uart_rxd	<=	data[4];
48				6:uart_rxd	<=	data[5];
49				7:uart_rxd	<=	data[6];
50				8:uart_rxd	<=	data[7];
51				9:uart_rxd 	<= 1'b1;
52			endcase
53			#(5208*20);
54		end	
55	endtask
56
57	uart_rx	u_uart_rx(
58		.clk(clk),
59		.rst_n(rst_n),
60		
61		.uart_rxd(uart_rxd),
62		.rx_done(rx_done),
63		.rx_data(rx_data)
64	);
65
66	endmodule

仿真结果如下: 

UART串口通信(回环测试)UART串口通信(回环测试)        仿真结果显示,rx_data成功将uart_rxd输入的串行数据转换为8位并行数据输出,rx_done为接收一帧数据完成信号。

2.3控制模块

       控制模块uart_ctrl用于控制串口通信发送使能和发送数据信号,当检测到s上位机串口调试工具助手发送数据给FPGA时,FPGA接收模块接收数据后并将发送到上位机完成数据回环。当上位机未发送数据时候,FPGA每隔1s产生Hello World!发送给上位机并通过串口调试工具显示。控制模块uart_ctrl代码如下:

1  	`timescale 1ns/1ps
2  	module uart_ctrl 
3  	#(
4  		parameter	CLK_FREQ	=	50_000_000,			//系统时钟频率
5  		parameter	UART_BPS	=	9600				//串口波特率
6  	)
7  	(
8  		input					clk,
9  		input					rst_n,
10 		
11 		input					rx_done,
12 		input		[7:0]	    rx_data,
13 		
14 		input					uart_tx_busy,
15 		output 				    uart_en,
16 		output 		[7:0]	    uart_data
17 
18 	);
19 
20 	localparam	BPS_CNT	=	CLK_FREQ/UART_BPS;//当前波特率需要系统时钟计数BPS_CNT次
21 
22 	reg			rx_done_r1;
23 	reg			rx_done_r2;
24 	reg			tx_start;
25 	reg			tx_en;
26 	reg	[7:0]	tx_data;
27 
28 	reg	[25:0]	uart_wait;			//发送等待时间计数器
29 	reg	[19:0]	uart_cnt;			//发送时间计数器
30 	reg			rx_data_valid;		//接收数据有效信号
31 	reg [7:0] 	store [14:0];		//存储待发送的8位数据  
32 	reg [2:0] 	uart_state;   		//状态机
33 	reg	[7:0]	bit_cnt;				//发送数据计数器
34 	reg			data_sel;			//发送数据选择信号
35 	reg			tx_en_r;
36 	reg	[7:0]	tx_data_r;
37 
38 	wire		rx_done_flag;
39 
40 	//rx_done_flag:接收完成标志信号
41 	assign	rx_done_flag	=	!rx_done_r2 && rx_done_r1;
42 	always @(posedge clk or negedge rst_n)
43 	begin
44 		if(!rst_n)
45 		begin
46 			rx_done_r1	<=	1'b0;
47 			rx_done_r2	<=	1'b0;
48 		end
49 		else
50 		begin
51 			rx_done_r1	<=	rx_done;
52 			rx_done_r2	<=	rx_done_r1;
53 		end
54 	end
55 
56 	//tx_en:发送使能信号
57 	//tx_data:发送数据
58 	always @(posedge clk or negedge rst_n)
59 	begin
60 		if(!rst_n)
61 		begin
62 			tx_start	<=	1'b0;
63 			tx_en		<=	1'b0;
64 			tx_data		<=	8'd0;
65 		end
66 		else 
67 		begin
68 			if(rx_done_flag)
69 			begin
70 				tx_start	<=	1'b1;
71 				tx_en		<=	1'b0;
72 				tx_data		<=	rx_data;
73 			end
74 			else if(tx_start && !uart_tx_busy)
75 			begin
76 				tx_start	<=	1'b0;
77 				tx_en		<=	1'b1;
78 				tx_data		<=	tx_data;
79 			end
80 			else
81 			begin
82 				tx_start	<=	1'b0;
83 				tx_en		<=	1'b0;
84 				tx_data		<=	tx_data;		
85 			end
86 		end
87 	end
88 
89 	//uart_en:串口发送使能信号
90 	//uart_data:串口发送数据
91 	//发送数据选择:data_sel高,选择存储的字符串,data_sel:低,选择接收的数据
92 	assign	uart_en		=	data_sel ? tx_en_r 	    :  tx_en	;
93 	assign	uart_data	=	data_sel ? tx_data_r	:  tx_data	;
94 
95 	//存储待发送的数据
96 	always @(*)
97 	begin
98 		if(!rst_n)
99 		begin
100			store[0]	=	8'd72; 		//存储字符H
101			store[1]	=  	8'd101;		//存储字符e	
102			store[2]	=	8'd108;		//存储字符l
103			store[3]	=	8'd108;		//存储字符l
104			store[4]	=	8'd111;		//存储字符o
105			store[5]	=	8'd32;    	//存储字符空格
106			store[6]	=	8'd87;    	//存储字符W
107			store[7]	=	8'd111;    	//存储字符o
108			store[8]	=	8'd114;    	//存储字符r
109			store[9]	=	8'd108;    	//存储字符l
110			store[10]	=	8'd100;    	//存储字符d
111			store[11]	=	8'd33;    	//存储字符!
112			store[12]	=	8'd32;    	//存储字符空格
113			store[13]	=	8'd10;      //换行符	
114			store[14]	=	8'd13;      //回车符	
115		end
116		else
117		begin
118			store[0]	=	store[0];
119			store[1]	=  	store[1];
120			store[2]	=	store[2];
121			store[3]	=	store[3];
122			store[4]	=	store[4];
123			store[5]	=	store[5];
124			store[6]	=	store[6];
125			store[7]	=	store[7];
126			store[8]	=  	store[8];
127			store[9]	=	store[9];
128			store[10]	=	store[10];
129			store[11]	=	store[11];
130			store[12]	=	store[12];
131			store[13]	=	store[13];
132			store[14]	=	store[14];
133		end
134	end
135
136	 //串口发送控制,每个一段时间发送字符串的命令
137	always @(posedge clk or negedge rst_n)
138	begin
139		if(!rst_n)
140		begin
141			uart_wait		<=	26'd0;
142			rx_data_valid	<=	1'b0;
143		end
144		else if(rx_done)
145		begin
146			uart_wait		<=	26'd0;
147			rx_data_valid	<=	1'b0;
148		end
149		else
150		begin
151			if(uart_wait == 26'd49_999_999)
152			begin
153				uart_wait		<=	26'd0;
154				rx_data_valid	<=	1'b1;
155			end
156			else
157			begin
158				uart_wait		<=	uart_wait + 1'b1;
159				rx_data_valid	<=	1'b0;
160			end
161		end
162	end
163
164	// //串口发送字符串数据,依次发送存储的字符串
165	always @(posedge clk or negedge rst_n)
166	begin
167		if(!rst_n)
168		begin
169			uart_cnt	<=	20'd0;
170			uart_state	<=	3'b001;
171			data_sel	<=	1'b0;
172			bit_cnt		<=	8'd0;
173			tx_data_r	<=	8'd0;
174			tx_en_r		<=	1'b0;
175		end
176		else
177		begin
178			if(rx_done)
179			begin
180				uart_cnt	<=	20'd0;
181				uart_state	<=	3'b001;
182				data_sel	<=	1'b0;
183				bit_cnt		<=	8'd0;
184				tx_data_r	<=	8'd0;
185				tx_en_r		<=	1'b0;	
186			end
187			else
188			begin
189				case(uart_state)
190				
191				3'b001:begin
192					if(rx_data_valid)
193					begin
194						uart_state	<=	3'b010;
195						data_sel	<=	1'b1;
196					end
197					else
198					begin
199						uart_state	<=	3'b001;
200						data_sel	<=	1'b0;
201					end
202				end
203				
204				3'b010:begin
205					if(bit_cnt == 8'd14)
206					begin
207						if(uart_cnt	== 20'd0)
208						begin
209							tx_data_r	<=	store[14];
210							tx_en_r		<=	1'b1;
211							uart_cnt	<=	uart_cnt + 1'b1;	
212						end
213						else if(uart_cnt == BPS_CNT*10 - 1'b1)
214						begin
215							uart_state	<=	3'b100;
216							tx_en_r		<=	1'b0;
217							uart_cnt	<=	20'd0;
218							bit_cnt		<=	8'd0;
219						end
220						else
221						begin
222							uart_cnt	<=	uart_cnt + 1'b1;
223							tx_en_r		<=	1'b0;
224						end
225					end
226					else
227					begin
228						if(uart_cnt	== 20'd0)
229						begin
230							tx_data_r	<=	store[bit_cnt];
231							tx_en_r		<=	1'b1;	
232							uart_cnt	<=	uart_cnt + 1'b1;
233						end
234						else if(uart_cnt == BPS_CNT*10 - 1'b1)
235						begin
236							tx_en_r		<=	1'b0;
237							uart_cnt	<=	20'd0;
238							bit_cnt		<=	bit_cnt + 1'b1;
239						end
240						else
241						begin
242							uart_cnt	<=	uart_cnt + 1'b1;
243							tx_en_r		<=	1'b0;
244						end
245					
246					end
247				end
248				
249				3'b100:begin	//发送完成
250					uart_state	<=	3'b001;
251					data_sel	<=	1'b0;
252					tx_en_r		<=	1'b0;
253				end
254				
255				default: begin
256					uart_state	<=	3'b001;
257					tx_en_r		<=	1'b0;
258					uart_cnt	<=	20'd0;	
259					data_sel	<=	1'b0;
260					bit_cnt		<=	8'd0;
261					tx_data_r	<=	8'd0;
262				end
263				
264			endcase			
265			end
266		end
267	end
268	 
269	endmodule 

2.4顶层模块

        顶层模块uart_top用于完成uart_tx、uart_rx、uart_ctrl模块的例化。

1 	`timescale 1ns/1ps
2 	module uart_top(
3 		input			sys_clk,
4 		input			rst_n,
5 		
6 		input			uart_rxd,
7 		output			uart_txd
8 	);
9 
10	parameter  	CLK_FREQ    =   50_000_000 ;   //时钟频率
11	parameter   UART_BPS    =   9600       ;   //比特率
12
13	wire [7:0]	uart_data;
14	wire [7:0]	tx_data;
15	wire		uart_en;
16	wire		uart_tx_busy;
17	wire		rx_done;
18
19	uart_tx
20	#(
21		.CLK_FREQ(CLK_FREQ),		//系统时钟频率
22		.UART_BPS(UART_BPS)			//串口波特率
23	)
24	u_uart_tx(
25		.clk(sys_clk),
26		.rst_n(rst_n),
27		
28		.tx_data(tx_data),			//待发送数据
29		.tx_en(uart_en),			//发送使能信号
30		.uart_tx_busy(uart_tx_busy),//发送忙碌标志信号
31		.uart_txd(uart_txd)			//UART数据发送端口
32	);
33
34	uart_rx
35	#(
36		.CLK_FREQ(CLK_FREQ),		//系统时钟频率
37		.UART_BPS(UART_BPS)			//串口波特率
38	)
39	u_uart_rx(
40		.clk(sys_clk),
41		.rst_n(rst_n),
42		
43		.uart_rxd(uart_rxd),
44		.uart_rx_busy(),
45		.rx_done(rx_done),
46		.rx_data(uart_data)
47	);
48
49	uart_ctrl 
50	#(
51		.CLK_FREQ(CLK_FREQ),		//系统时钟频率
52		.UART_BPS(UART_BPS)			//串口波特率
53	)
54	u_uart_ctrl(
55		.clk(sys_clk),
56		.rst_n(rst_n),
57		
58		.rx_done(rx_done),
59		.rx_data(uart_data),
60		
61		.uart_tx_busy(uart_tx_busy),
62		.uart_en(uart_en),
63		.uart_data(tx_data)
64	);
65
66	endmodule

 仿真代码如下:

1 	`timescale  1ns/1ps
2 	module uart_top_tb();
3 
4 	reg		sys_clk;
5 	reg		rst_n;
6 	reg		uart_rxd;
7 
8 	wire	uart_txd;
9 
10	initial 
11	begin
12		sys_clk		= 	1'b1;
13		rst_n		=	1'b0;
14		uart_rxd	=	1'b1;
15		#200
16		rst_n		=	1'b1;
17	end
18
19	always #10 sys_clk	=	~sys_clk;
20
21	initial 
22	begin
23		#400
24		rx_byte();
25	end
26
27	task rx_byte();
28		integer	j;
29		for(j = 1; j < 10; j = j + 1'b1)
30			rx_bit_data(j);
31	endtask
32
33	task rx_bit_data(
34		input	[7:0]	data
35	);
36		integer i;
37		for(i = 0; i < 10; i = i + 1'b1)
38		begin
39			case(i)
40				0:uart_rxd	<=	1'b0;
41				1:uart_rxd	<=	data[0];
42				2:uart_rxd	<=	data[1];
43				3:uart_rxd	<=	data[2];
44				4:uart_rxd	<=	data[3];
45				5:uart_rxd	<=	data[4];
46				6:uart_rxd	<=	data[5];
47				7:uart_rxd	<=	data[6];
48				8:uart_rxd	<=	data[7];
49				9:uart_rxd 	<= 1'b1;
50			endcase
51			#(5208*20);
52		end	
53	endtask
54
55	uart_top u_uart_top(
56		.sys_clk(sys_clk),
57		.rst_n(rst_n),
58		
59		.uart_rxd(uart_rxd),
60		.uart_txd(uart_txd)
61	);
62
63	endmodule

仿真结果如下所示: 

UART串口通信(回环测试)UART串口通信(回环测试)        首先验证串口通信回环测试,激励模块产生数据1~9,接收模块完成数据接收后,将并行的8位1~9数据传输到uart_tx模块,uart_tx将8位数据进行串行输出,仿真结果显示,回环测试成功。当未检测到rx_done接收信号时,uart_wait计数器每计数到1s,使能rx_data_valid信号,发送store寄存的Helllo World!。

3板级验证

下载代码到Alter Cyclone IV FPGA开发板中,设置波特率为9600,打开串口调试助手,接收区每隔1s接收一个Hello World!,当手动发送123456 数据时,串口接收区显示接收123456 字符。当停止发送123456 字符时,接收区每隔1s会接收到一个Hello World!。

UART串口通信(回环测试)

 文章来源地址https://www.toymoban.com/news/detail-451434.html

 

 

到了这里,关于UART串口通信(回环测试)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 串口通信(UART)

    串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。 51单片机

    2024年02月07日
    浏览(43)
  • UART串口通信协议

    串行通信分为两种方式: 同步串行通信 和 异步串行通信 。 同步串行通信需要通信双方在同一时钟的控制下,同步传输数据。 异步串行通信是指通信双方使用各自的时钟控制数据的发送和接收过程。 通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)是一种 全双

    2024年02月03日
    浏览(38)
  • UART串口通信

    串口是“串行接口”的简称,即采用串行通信方式的接口。串行通信将数据字节分成一位一位的形式在一条数据线上逐个传送,其特点是通信线路简单,但传输速度较慢。因此串口广泛应用于嵌入式、工业控制等领域中对数据传输速度要求不高的场合。 Serial communication是一个

    2024年02月10日
    浏览(31)
  • UART串口通信实验

    不管是单片机开发还是嵌入式 Linux 开发,串口都是最常用到的外设。 可以通过串口将开发板与电脑相连,然后在电脑上通过串口调试助手来调试程序。 还有很多模块,比如蓝牙、GPS、GPRS等都使用串口与主控进行通信。 串口全称串行接口,通常也叫做COM接口,,串行接口指

    2024年02月08日
    浏览(54)
  • Verilog(1)UART串口通信

    第一部分为uart串口通信的接收部分,用pc端虚拟串口来对其发送数据。 第三部分为uart串口通信的发送部分,用此部分对pc端虚拟串口发送数据。 第二部分loop,处理数据,形成回环,使发送部分有数据来源,以此来保证实验的完成。 串口接收 :  输入: sys_clk、sys_rst_n、u

    2024年02月03日
    浏览(82)
  • FPGA入门 —— FPGA UART 串口通信

    UART 通用异步收发传输器( Universal Asynchronous Receiver/Transmitter) ,通常称作 UART。 UART 是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。 它包括了ch340、 RS232、

    2024年02月09日
    浏览(46)
  • 【FPGA】UART串口通信——奇偶校验实现

    奇偶校验位是基于uart的数据上进行一个判断 奇校验:数据1个数为奇时,校验为0,反之为1 偶校验:数据0个数为偶时,校验为0,反之为1 Uart回环在之前已经实现,现在需要基于uart增加一个奇偶校验位的需求 uart及代码:https://blog.csdn.net/weixin_59150966/article/details/128005066?spm=10

    2024年02月11日
    浏览(42)
  • 【FPGA】UART串口通信---基于FIFO

    我们在上一章完成了UART串口通信的收发模块,这一章我们将FIFO引入进来,使用FIFO进行缓存数据,来连接串口通信的收发模块 FIFO即First In First Out,是一种先进先出数据存储、缓冲器,我们知道一般的存储器是用外部的读写地址来进行读写,而FIFO这种存储器的结构并不需要外

    2023年04月14日
    浏览(85)
  • K210 UART串口通信介绍与 STM32通信

    目录 K210-UART串口通信相关函数: 使用K210串口的时候需要映射引脚: K210与STM32串口通信  发送单字节: K210端 STM32端 发送数据包 K210端 STM32端  K210的UART模块支持全双工通信,可以同时进行数据的发送和接收。在K210上使用UART串口通信,你可以连接外部设备,如传感器、显示器

    2024年03月23日
    浏览(48)
  • 【以太网通信】PHY 芯片回环测试

    PHY 芯片通常带有回环(Loopback)功能,用于 PHY 通信链路的测试。本文主要讨论三种常用 PHY 芯片的回环功能,并使用 Broadcom 的 B50612D 芯片进行 PHY 回环测试。 目录 1 常见 PHY 的回环功能 1.1 KSZ9031 1.2 RTL8211 1.3 B50610/B50612 2 PHY 回环测试         KSZ9031 芯片支持以下两种回环模

    2024年02月02日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包