编写fpga的串口代码时遇到的一个大坑!
- 1 warning 10240!!!
- 2 代码
- 2.1 uart_tx.v
- 2.2 send_freq.v
- 2.3 send_freq_top.v
1 warning 10240!!!
在调试串口时遇到一个很诡异的问题。我打算用串口循环发送一个频率值,间隔为1s,然而下载到板子后只能发一次。我反复地检查我的时序设计图,然后用testbench仿真观察波形,都没有错!第一次遇到仿真正确然而下板验证时却出错的情况,值得纪念一下。不过难受的是我为这件事卡了一个星期,这一个星期里我反复地修改串口模块、发送频率模块和顶层模块,然而都无济于事,甚至还出现很多莫名其妙的情况,比如发送间隔为1s时只发了一次,改为10ms时就发送了两次,再改为1us时就什么也收不到了,完全不知道里面发生了什么……
转机出现在今晚,我想起了以前看过的fpga开发分享贴,里面提到调试fpga时如果实在找不出bug所在,就看看warning。这一看不得了了!当我把下面这条10240警告改掉之后,程序就跑通了!!!
1
210240 Verilog HDL Always Construct warning at send_freq.v(38): inferring latch(es) for variable "r_next_state", which holds its previous value in one or more paths through the always construct
这一条警告出现的原因是写了if没写else,或者写了case没写default,产生了锁存器。我在send_freq.v里面是这样写的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_cur_state <= S_IDLE; else r_cur_state <= r_next_state; end always @(*) begin case(r_cur_state) S_IDLE: if(i_freq_send_req) r_next_state <= S_SEND_TENTH; S_SEND_TENTH: ... default: r_next_state <= S_IDLE; endcase end
我没有给r_next_state赋初值,复位后r_cur_state为S_IDLE,如果在紧接着的时钟沿到来前i_freq_send_req没有出现,那么r_cur_state就被赋值为r_next_state,一个未初始化的值。然后再次进入case判断时,因为有default的存在,r_next_state第一次被赋值为S_IDLE。接着r_cur_state又被赋值为S_IDLE,这个时候程序才走上正轨,该赋值的变量都赋值了。按理说不应该出现我遇到的问题,所以这个玄学我暂时没法解释。先记录在此,以后回过头来看也许就能一目了然。如果各位看官知道其中道理的,还望不吝赐教。
以后要是要重视编程规范呀。
2 代码
这部分是可以运行的代码,分别是串口发送模块,频率发送控制模块和顶层模块。
2.1 uart_tx.v
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
115
116module uart_tx( input i_clk, input i_rst_n, input i_uart_send_req, input[7:0] i_uart_send_byte, output o_uart_send_ack, output o_uart_tx_pin ); localparam C_CYCLE = 50 * 1000000 / 115200; localparam S_IDLE = 5'b00001; localparam S_START = 5'b00010; localparam S_DATA = 5'b00100; localparam S_STOP = 5'b01000; localparam S_ACK = 5'b10000; reg[4:0] r_cur_state; reg[4:0] r_next_state; reg[31:0]r_cycle_cnt; reg[2:0] r_bit_cnt; reg[7:0] r_uart_send_byte; reg r_uart_send_ack; reg r_uart_tx_pin; assign o_uart_tx_pin = r_uart_tx_pin; assign o_uart_send_ack = r_uart_send_ack; always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_cur_state <= S_IDLE; else r_cur_state <= r_next_state; end always @(*) begin case(r_cur_state) S_IDLE: if(i_uart_send_req) r_next_state <= S_START; else r_next_state <= S_IDLE; S_START: if(r_cycle_cnt == C_CYCLE - 1) r_next_state <= S_DATA; else r_next_state <= S_START; S_DATA: if((r_cycle_cnt == C_CYCLE - 1) && r_bit_cnt == 3'd7) r_next_state <= S_STOP; else r_next_state <= S_DATA; S_STOP: if(r_cycle_cnt == C_CYCLE - 1) r_next_state <= S_ACK; else r_next_state <= S_STOP; S_ACK: r_next_state <= S_IDLE; default: r_next_state <= S_IDLE; endcase end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_uart_tx_pin <= 1'b1; else case(r_next_state) S_IDLE: r_uart_tx_pin <= 1'b1; S_START: r_uart_tx_pin <= 1'b0; S_DATA: r_uart_tx_pin <= r_uart_send_byte[r_bit_cnt]; S_STOP, S_ACK: r_uart_tx_pin <= 1'b1; default: r_uart_tx_pin <= 1'b1; endcase end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_cycle_cnt <= 32'd0; else if(r_cur_state != r_next_state || (r_next_state == S_DATA && r_cycle_cnt == C_CYCLE - 1)) r_cycle_cnt <= 32'd0; else r_cycle_cnt <= r_cycle_cnt + 32'd1; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_bit_cnt <= 3'd0; else if(r_cur_state == S_DATA) if(r_cycle_cnt == C_CYCLE - 1) r_bit_cnt <= r_bit_cnt + 3'd1; else r_bit_cnt <= r_bit_cnt; else r_bit_cnt <= 3'd0; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_uart_send_byte <= 8'd0; else if(i_uart_send_req) r_uart_send_byte <= i_uart_send_byte; else r_uart_send_byte <= r_uart_send_byte; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_uart_send_ack <= 1'b0; else if(r_next_state == S_ACK) r_uart_send_ack <= 1'b1; else r_uart_send_ack <= 1'b0; end endmodule
2.2 send_freq.v
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
115
116
117
118
119
120
121
122
123
124
125
126module send_freq( input i_clk, input i_rst_n, input i_freq_send_req, input[9:0] i_freq, output o_freq_send_ack, output o_uart_tx_pin ); localparam S_IDLE = 6'b000001; localparam S_SEND_TENTH = 6'b000010; localparam S_SEND_DOT = 6'b000100; localparam S_SEND_INT = 6'b001000; localparam S_WAIT = 6'b010000; localparam S_ACK = 6'b100000; reg[5:0] r_cur_state; reg[5:0] r_next_state; reg[5:0] r_last_state; reg[9:0] r_freq; reg[7:0] r_uart_send_byte; reg r_freq_send_ack; reg r_uart_send_req; wire r_uart_send_ack; assign o_freq_send_ack = r_freq_send_ack; always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_cur_state <= S_IDLE; else r_cur_state <= r_next_state; end always @(*) begin case(r_cur_state) S_IDLE: if(i_freq_send_req) r_next_state <= S_SEND_TENTH; else // important!! r_next_state <= S_IDLE; S_SEND_TENTH,S_SEND_DOT,S_SEND_INT: r_next_state <= S_WAIT; S_WAIT: if(r_uart_send_ack) begin if(r_last_state == S_SEND_TENTH) r_next_state <= S_SEND_DOT; else if(r_last_state == S_SEND_DOT) r_next_state <= S_SEND_INT; else if(r_last_state == S_SEND_INT && (|r_freq)) r_next_state <= S_SEND_INT; else r_next_state <= S_ACK; end else r_next_state <= S_WAIT; S_ACK: r_next_state <= S_IDLE; default: r_next_state <= S_IDLE; endcase end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_freq_send_ack <= 1'b0; else if(r_next_state == S_ACK) r_freq_send_ack <= 1'b1; else r_freq_send_ack <= 1'b0; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_last_state <= S_IDLE; else if(r_next_state == S_SEND_TENTH || r_next_state == S_SEND_DOT || r_next_state == S_SEND_INT) r_last_state <= r_next_state; else r_last_state <= r_last_state; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_uart_send_req <= 1'b0; else if(r_next_state == S_SEND_TENTH) r_uart_send_req <= 1'b1; else if(r_next_state == S_ACK) r_uart_send_req <= 1'b0; else r_uart_send_req <= r_uart_send_req; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_freq <= 10'd0; else if(r_next_state == S_SEND_TENTH) r_freq <= i_freq / 10'd10; else if(r_next_state == S_SEND_INT && (|r_freq)) r_freq <= r_freq / 10'd10; else r_freq <= r_freq; end always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) r_uart_send_byte <= 8'hff; else if(r_next_state == S_SEND_TENTH) r_uart_send_byte <= i_freq % 10'd10 + "0"; else if(r_next_state == S_SEND_DOT) r_uart_send_byte <= "."; else if(r_next_state == S_SEND_INT && (|r_freq)) r_uart_send_byte <= r_freq % 10'd10 + "0"; else r_uart_send_byte <= r_uart_send_byte; end uart_tx uart_tx_inst( .i_clk (i_clk), .i_rst_n (i_rst_n), .i_uart_send_req (r_uart_send_req), .i_uart_send_byte (r_uart_send_byte), .o_uart_send_ack (r_uart_send_ack), .o_uart_tx_pin (o_uart_tx_pin) ); endmodule
2.3 send_freq_top.v
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
56module send_freq_top( input i_clk, input i_rst_n, output o_uart_tx_pin ); localparam S_IDLE = 4'b0001; localparam S_SEND = 4'b0010; localparam S_WAIT = 4'b0100; localparam S_SEND2= 4'b1000; reg[3:0] r_next_state; reg[31:0] r_clk_cnt; reg[9:0] r_freq; reg r_freq_send_req; wire r_freq_send_ack; always @(posedge i_clk or negedge i_rst_n) begin if(!i_rst_n) begin r_next_state <= S_IDLE; r_freq <= 10'd1021; r_freq_send_req <= 1'b0; r_clk_cnt <= 32'd0; end else case(r_next_state) S_IDLE: r_next_state <= S_SEND; S_SEND: begin r_clk_cnt <= 32'd0; if(r_freq_send_req && r_freq_send_ack) begin r_freq_send_req <= 1'b0; r_next_state <= S_WAIT; end else if(!r_freq_send_req) r_freq_send_req <= 1'b1; end S_WAIT: begin r_clk_cnt <= r_clk_cnt + 32'd1; if(r_clk_cnt >= 32'd50000000) r_next_state <= S_SEND; end default: r_next_state <= S_IDLE; endcase end send_freq send_freq_inst( .i_clk (i_clk), .i_rst_n (i_rst_n), .i_freq_send_req (r_freq_send_req), .i_freq (r_freq), .o_freq_send_ack (r_freq_send_ack), .o_uart_tx_pin (o_uart_tx_pin) ); endmodule
最后
以上就是孝顺康乃馨最近收集整理的关于编写fpga的串口代码时遇到的一个大坑!1 warning 10240!!!2 代码的全部内容,更多相关编写fpga的串口代码时遇到的一个大坑!1内容请搜索靠谱客的其他文章。
发表评论 取消回复