我是靠谱客的博主 玩命板栗,这篇文章主要介绍Uart串口收发回环验证,现在分享给大家,希望可以做个参考。

Uart串口收发回环验证

    • 接受模块
    • 发送模块
    • 波特率设置模块
    • 顶层模块
    • TB
    • Modelsim仿真结果
    • 板级验证
    • 总结

本次所做的项目比较复杂(对我本人来讲),设计一个Uart IP核,在其基础,封装axi接口,使其成为面向AXI口的IP,再例化个microblaze作为主机,使microblaze与Uart之间通过AXI总线进行通信。具体模块图如下,包含主机microblaze,主接口模块,从接口模块,从机Uart。

在这里插入图片描述
本文首先介绍Uart基本模块。该顶层模块包含接受模块、发送模块、发送波特率设置模块、接受波特率设置模块。为了方便验证,我们将接受模块与发送模块连接,采用回环的形式。

接受模块

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2019/05/24 16:58:41 // Design Name: // Module Name: uart_rx // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_rx( clk, rst_n, Rs232_rx, bps_clk, rx_data, rx_int, bps_start ); input clk; input rst_n; input bps_clk; input Rs232_rx; output [7:0] rx_data; output reg rx_int; output reg bps_start; reg Rs232_rx0,Rs232_rx1,Rs232_rx2,Rs232_rx3; wire neg_edge; reg [3:0] num; reg [7:0] rx_data_t1; reg [7:0] rx_data_t2; always@(posedge clk or negedge rst_n) if(!rst_n) begin Rs232_rx0 <= 1'b1; Rs232_rx1 <= 1'b1; Rs232_rx2 <= 1'b1; Rs232_rx3 <= 1'b1; end else begin Rs232_rx0 <= Rs232_rx; Rs232_rx1 <= Rs232_rx0; Rs232_rx2 <= Rs232_rx1; Rs232_rx3 <= Rs232_rx2; end assign neg_edge = Rs232_rx3 & Rs232_rx2 & ~Rs232_rx1 & ~Rs232_rx0; always@(posedge clk or negedge rst_n) if(!rst_n) begin bps_start <= 1'b0; rx_int <= 1'b0; end else if (neg_edge) begin bps_start <= 1'b1; rx_int <= 1'b1; end else if (num == 4'd10) begin bps_start <= 1'b0; rx_int <= 1'b0; end always@(posedge clk or negedge rst_n) if(!rst_n) begin rx_data_t1 <= 8'd0; rx_data_t2 <=8'd0; num <= 4'd0; end else if(rx_int) begin if (bps_clk) begin num <= num+1'b1; case(num) 4'd1: rx_data_t1[0] <= Rs232_rx; 4'd2: rx_data_t1[1] <= Rs232_rx; 4'd3: rx_data_t1[2] <= Rs232_rx; 4'd4: rx_data_t1[3] <= Rs232_rx; 4'd5: rx_data_t1[4] <= Rs232_rx; 4'd6: rx_data_t1[5] <= Rs232_rx; 4'd7: rx_data_t1[6] <= Rs232_rx; 4'd8: rx_data_t1[7] <= Rs232_rx; default:; endcase end end else if(num >= 4'd9) begin num <= 4'd0; rx_data_t2 <= rx_data_t1; end assign rx_data = rx_data_t2; endmodule

发送模块

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2019/05/24 15:39:09 // Design Name: // Module Name: uart_tx // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_tx( clk, rst_n, tx_int, rx_data, bps_clk, Rs232_tx, bps_start ); input clk; input rst_n; input tx_int; input [7:0] rx_data; input bps_clk; output Rs232_tx; output bps_start; reg tx_int0; reg tx_int1; reg tx_int2; wire neg_edge; (* keep = "true" *) reg en; reg [3:0] num; reg bps_start_t; //reg [7:0] rx_data_t; reg Rs232_tx_t; always@(posedge clk or negedge rst_n) if(!rst_n) begin tx_int0 <= 1'b0; tx_int1 <= 1'b0; tx_int2 <= 1'b0; end else begin tx_int0 <= tx_int; tx_int1 <= tx_int0; tx_int2 <= tx_int1; end assign neg_edge = tx_int2 & ~tx_int1; always@(posedge clk or negedge rst_n) if(!rst_n) begin en <= 1'b0; bps_start_t <= 1'b0; end else if (neg_edge) begin en <= 1'b1; bps_start_t <= 1'b1; //rx_data_t <= rx_data; end else if (num == 4'd10) begin en <= 1'b0; bps_start_t <= 1'b0; end assign bps_start = bps_start_t; always@(posedge clk or negedge rst_n) if(!rst_n) begin Rs232_tx_t <= 1'b1; num <= 12'd0; end else if (en) begin if (bps_clk) begin case (num) 4'd0: Rs232_tx_t <= 1'b0; 4'd1: Rs232_tx_t <= rx_data[0]; 4'd2: Rs232_tx_t <= rx_data[1]; 4'd3: Rs232_tx_t <= rx_data[2]; 4'd4: Rs232_tx_t <= rx_data[3]; 4'd5: Rs232_tx_t <= rx_data[4]; 4'd6: Rs232_tx_t <= rx_data[5]; 4'd7: Rs232_tx_t <= rx_data[6]; 4'd8: Rs232_tx_t <= rx_data[7]; 4'd9: Rs232_tx_t <= 1'b1; default: Rs232_tx_t <= 1'b1; endcase num <= num +1'b1; end end else if(num == 4'd10) begin num <= 1'b0; end assign Rs232_tx = Rs232_tx_t; endmodule

波特率设置模块

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2019/05/24 15:06:47 // Design Name: // Module Name: speed_set // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module speed_set( bps_start, clk, rst_n, bps_clk ); input bps_start; input clk; input rst_n; output reg bps_clk; (* keep = "true" *) reg [12:0] cnt; `define BPS_NUM 5207 `define BPS_NUM_2 2306 always@(posedge clk or negedge rst_n) if (!rst_n) cnt <= 13'd0; else if (cnt == `BPS_NUM || !bps_start) cnt <= 13'd0; else cnt <= cnt + 1'b1; always@(posedge clk or negedge rst_n) if(!rst_n) bps_clk <= 1'b0; else if (cnt == `BPS_NUM_2) bps_clk <= 1'b1; else bps_clk <= 1'b0; endmodule

顶层模块

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2019/05/27 10:00:56 // Design Name: // Module Name: uart_top // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_top( clk_p, clk_n, rst_n, Rx, Tx ); input clk_p; input clk_n; input rst_n; input Rx; output Tx; wire clk_50m; wire bps_clk_tx; wire bps_clk_rx; wire bps_start_tx; wire bps_start_rx; wire [7:0] rx_data; wire int; clk_wiz_0 instance_name ( // Clock out ports .clk_50m(clk_50m), // output clk_50m // Status and control signals .resetn(rst_n), // input resetn // Clock in ports .clk_in1_p(clk_p), // input clk_in1_p .clk_in1_n(clk_n)); // input clk_in1_n speed_set speed_tx( .bps_start(bps_start_tx), .clk(clk_50m), .rst_n(rst_n), .bps_clk(bps_clk_tx) ); uart_tx uart_tx( .clk(clk_50m), .rst_n(rst_n), .tx_int(int), .rx_data(rx_data), .bps_clk(bps_clk_tx), .Rs232_tx(Tx), .bps_start(bps_start_tx) ); speed_set speed_rx( .bps_start(bps_start_rx), .clk(clk_50m), .rst_n(rst_n), .bps_clk(bps_clk_rx) ); uart_rx uart_rx( .clk(clk_50m), .rst_n(rst_n), .Rs232_rx(Rx), .bps_clk(bps_clk_rx), .rx_data(rx_data), .rx_int(int), .bps_start(bps_start_rx) ); endmodule

TB

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
`timescale 1ns / 1ps `define clock_period 20 // // Company: // Engineer: // // Create Date: 2019/05/27 10:38:22 // Design Name: // Module Name: uart_tb // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module Uart_tb; reg clk_p; reg clk_n; reg rst_n; reg Rx; wire Tx; uart_top uart_top( .clk_p(clk_p), .clk_n(clk_n), .rst_n(rst_n), .Rx(Rx), .Tx(Tx) ); initial clk_p = 0; always #2.5 begin clk_p = ~clk_p; clk_n = ~clk_p; end initial begin Rx = 1'b1; rst_n = 1'b0; #(`clock_period*20); rst_n = 1'b1; #(`clock_period*52080); //起始位 Rx = 1'b0; #(`clock_period*5208); //数据位 Rx = 1'b1; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); Rx = 1'b1; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); Rx = 1'b0; #(`clock_period*5208); //停止位 Rx = 1'b1; #(`clock_period*5208); Rx = 1'b1; #(`clock_period*52080); end endmodule

Modelsim仿真结果

在这里插入图片描述

板级验证

在这里插入图片描述在这里插入图片描述

总结

本项目Uart设计没有什么难度,基本原理在看完Uart之后spe之后基本了解,再加上之前有点底子,在代码表写上很快完成。但由于Vivado工具使用不熟练,导致花费大量时间,尤其在debug调试之后生成ILA核,抓取的波形不知道怎么看,自己摸索始终不会,最终还是在 老同志的帮助下知道了怎么回事,一方面感谢,另一发方面感概其其奇妙之后,感觉在数字芯片这么难之下下,我们工程师(妄称)还是要多多交流,这样才能共同进步。终极学习法费曼学习法不是说了吗,学习最快的途径是教会一个外行人,你教别人的同时自己也在快速成长。另外自身而言,实在琢磨不出在,还是问问别人,又是你半天搞不出来,一问就回了,提高效率不是。
扯哪去了,回归正题。在前期写好代码之后,兴致勃勃地仿真还通过了,感觉没啥问题,直接上板子烧入,之后崩了,没有结果。前期以为串口工具有问题,想不到还真有问题,板子上USB口接错了,COM口出错,小白尽是犯这种低级错误啊。改完之后重新烧入,还是不行,心态有点炸。实在没办法请教了大神,让我用debug来找出代码那不对,刚开始我始终不以为意,认为仿真通过我写的代码肯定没问题,肯定是其他硬件问题。再加上我debug不会用,浪费了大量时间。在慢慢琢磨与请教之后,发现了问题(前方高能):
1.我在一个always进程中对一个变量赋值之前,没有对其进行复位(TX模块的bps_start_t),导致仿真出现红线未知态。不过这不是主要问题
2.也是tx模块中我竟然多num信号在两个进程中同时对其赋值,明显不过的代码错误,但是综合尽然通过了,什么鬼
总结:
在那个alway进程中间对所有变量赋值之前,现在Rst中对所有进行复位
不要感觉没有错误仿真通过就感觉代码没问题,万事大吉EDA也不是万能的,错误看完的看看警告。
对变量进行暂存再赋值是将reg型变量变为wire型。如果其他进程用到了就不需要转变,只是偶尔输出时需要转变。

最后

以上就是玩命板栗最近收集整理的关于Uart串口收发回环验证的全部内容,更多相关Uart串口收发回环验证内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(84)

评论列表共有 0 条评论

立即
投稿
返回
顶部