UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器,是设备间进行异步通信的关键模块。UART负责处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式;通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用两根信号线(Rx 和Tx)就可以完成通信过程,因此也称为异步串行通信。

                          

起始位:每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。

数据位:起始位之后就是我们所要传输的数据,数据位可以是5、6、7、8位等,构成一个字符(一般都是8位)。如ASCII码(7位),扩展BCD码(8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。

奇偶校验位:

   数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。校验位其实是调整个数,串口校验分几种方式:

  1、奇校验(odd parity):如果数据位中“1”的数目是偶数,则校验位为“1”,如果“1”的数目是奇数,校验位为“0”。

  2、偶校验(even parity):如果数据为中“1”的数目是偶数,则校验位为“0”,如果为奇数,校验位为“1”。

  3、mark parity:校验位始终为1。

  4、parity:校验位始终为0。

  5、无校验(no parity)。

停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备之间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟的机会。停止位个数越多,数据传输越稳定,但是数据传输速度也越慢。

空闲位:UART协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据传输。

波特率:数据传输速率使用波特率来表示。单位bps(bits per second),常见的波特率9600bps、115200bps等等,其他标准的波特率是1200,2400,4800,19200,38400,115200等等。

  代码如下:

  顶层文件AXI4_UART.v

  1 //**************************************************************************
2 // *** file name : AXI4_UART.v
3 // *** version : 1.0
4 // *** Description : AXI4_UART
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.09.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module AXI4_UART
12 #(
13 parameter SYS_FRE = 100_000_000 ,
14 parameter TX_FIFO_DEPTH = 2048 ,
15 parameter RX_FIFO_DEPTH = 2048
16 )
17 (
18 input wire i_s_axi_aclk ,
19 input wire i_s_axi_aresetn ,
20 input wire [31:0] i_s_axi_awaddr ,
21 input wire [2:0] i_s_axi_awprot ,
22 input wire i_s_axi_awvalid ,
23 output wire o_s_axi_awready ,
24 input wire [31:0] i_s_axi_wdata ,
25 input wire [3:0] i_s_axi_wstrb ,
26 input wire i_s_axi_wvalid ,
27 output wire o_s_axi_wready ,
28 output wire [1:0] o_s_axi_bresp ,
29 output wire o_s_axi_bvalid ,
30 input wire i_s_axi_bready ,
31 input wire [31:0] i_s_axi_araddr ,
32 input wire [2:0] i_s_axi_arprot ,
33 input wire i_s_axi_arvalid ,
34 output wire o_s_axi_arready ,
35 output wire [31:0] o_s_axi_rdata ,
36 output wire [1:0] o_s_axi_rresp ,
37 output wire o_s_axi_rvalid ,
38 input wire i_s_axi_rready ,
39 input wire i_uart_rx ,
40 output wire o_uart_tx
41 );
42
43 wire w_module_en ;
44 wire [31:0] w_fre_cnt ;
45 wire [3:0] w_uart_data_bit ;
46 wire [2:0] w_uart_parity_mode ;
47 wire [2:0] w_uart_stop_bit ;
48 wire [7:0] w_tx_fifo_din ;
49 wire w_tx_fifo_wr ;
50 wire [8:0] w_rx_fifo_dout ;
51 wire w_rx_fifo_rd ;
52 wire [15:0] w_uart_wr_cnt ;
53 wire [15:0] w_uart_rd_cnt ;
54 wire w_fifo_rest ;
55 wire w_fifo_clr ;
56 wire [7:0] w_tx_data ;
57 wire w_tx_valid ;
58 wire w_tx_req ;
59 wire [8:0] w_rx_data ;
60 wire w_rx_valid ;
61 wire w_tx_fifo_empty ;
62
63 /******************************************************************************\
64 Uart control
65 \******************************************************************************/
66 Uart_ctrl
67 #(
68 .SYS_FRE (SYS_FRE )
69 )
70 u_Uart_ctrl
71 (
72 .i_s_axi_aclk (i_s_axi_aclk ),
73 .i_s_axi_aresetn (i_s_axi_aresetn ),
74 .i_s_axi_awaddr (i_s_axi_awaddr ),
75 .i_s_axi_awprot (i_s_axi_awprot ),
76 .i_s_axi_awvalid (i_s_axi_awvalid ),
77 .o_s_axi_awready (o_s_axi_awready ),
78 .i_s_axi_wdata (i_s_axi_wdata ),
79 .i_s_axi_wstrb (i_s_axi_wstrb ),
80 .i_s_axi_wvalid (i_s_axi_wvalid ),
81 .o_s_axi_wready (o_s_axi_wready ),
82 .o_s_axi_bresp (o_s_axi_bresp ),
83 .o_s_axi_bvalid (o_s_axi_bvalid ),
84 .i_s_axi_bready (i_s_axi_bready ),
85 .i_s_axi_araddr (i_s_axi_araddr ),
86 .i_s_axi_arprot (i_s_axi_arprot ),
87 .i_s_axi_arvalid (i_s_axi_arvalid ),
88 .o_s_axi_arready (o_s_axi_arready ),
89 .o_s_axi_rdata (o_s_axi_rdata ),
90 .o_s_axi_rresp (o_s_axi_rresp ),
91 .o_s_axi_rvalid (o_s_axi_rvalid ),
92 .i_s_axi_rready (i_s_axi_rready ),
93 .o_module_en (w_module_en ),
94 .o_fifo_clr (w_fifo_clr ),
95 .o_fre_cnt (w_fre_cnt ),
96 .o_uart_data_bit (w_uart_data_bit ),
97 .o_uart_parity_mode (w_uart_parity_mode ),
98 .o_uart_stop_bit (w_uart_stop_bit ),
99 .o_tx_data (w_tx_fifo_din ),
100 .o_tx_valid (w_tx_fifo_wr ),
101 .i_rx_data (w_rx_fifo_dout ),
102 .o_rx_req (w_rx_fifo_rd ),
103 .i_tx_fifo_wr_cnt (w_uart_wr_cnt ),
104 .i_rx_fifo_rd_cnt (w_uart_rd_cnt )
105
106 );
107
108 assign w_fifo_rest = w_fifo_clr & (~i_s_axi_aresetn);
109 /******************************************************************************\
110 Uart tx
111 \******************************************************************************/
112 Uart_tx u_Uart_tx
113 (
114 .i_sys_clk (i_s_axi_aclk ),
115 .i_sys_rstn (i_s_axi_aresetn & w_module_en),
116 .i_fre_cnt (w_fre_cnt ),
117 .i_tx_data_bit (w_uart_data_bit ),
118 .i_parity_mode (w_uart_parity_mode ),
119 .i_stop_bit (w_uart_stop_bit ),
120 .i_tx_data (w_tx_data ),
121 .i_tx_valid (w_tx_valid ),
122 .o_tx_req (w_tx_req ),
123 .o_uart_tx (o_uart_tx )
124 );
125
126 /******************************************************************************\
127 Uart rx
128 \******************************************************************************/
129 Uart_rx u_Uart_rx
130 (
131 .i_sys_clk (i_s_axi_aclk ),
132 .i_sys_rstn (i_s_axi_aresetn & w_module_en),
133 .i_fre_cnt (w_fre_cnt ),
134 .i_rx_data_bit (w_uart_data_bit ),
135 .i_parity_mode (w_uart_parity_mode[2] ),
136 .i_stop_bit (w_uart_stop_bit ),
137 .o_rx_data (w_rx_data ),
138 .o_rx_valid (w_rx_valid ),
139 .i_uart_rx (i_uart_rx )
140 );
141 /******************************************************************************\
142 Uart tx fifo
143 \******************************************************************************/
144 xpm_fifo_sync
145 #(
146 .DOUT_RESET_VALUE ("0" ),
147 .ECC_MODE ("no_ecc" ),
148 .FIFO_MEMORY_TYPE ("block" ),
149 .FIFO_READ_LATENCY (1 ),
150 .FIFO_WRITE_DEPTH (TX_FIFO_DEPTH ),
151 .FULL_RESET_VALUE (0 ),
152 .PROG_EMPTY_THRESH (10 ),
153 .PROG_FULL_THRESH (10 ),
154 .RD_DATA_COUNT_WIDTH (1 ),
155 .READ_DATA_WIDTH (8 ),
156 .READ_MODE ("fwft" ),
157 .SIM_ASSERT_CHK (0 ),
158 .USE_ADV_FEATURES ("0707" ),
159 .WAKEUP_TIME (0 ),
160 .WRITE_DATA_WIDTH (8 ),
161 .WR_DATA_COUNT_WIDTH (1 )
162 )
163 u_uart_tx_fifo
164 (
165 .wr_clk (i_s_axi_aclk ),
166 .rst (w_fifo_rest ),
167 .rd_en (w_tx_req ),
168 .dout (w_tx_data ),
169 .din (w_tx_fifo_din ),
170 .wr_en (w_tx_fifo_wr ),
171 .wr_data_count (w_uart_wr_cnt ),
172 .rd_data_count ( ),
173 .empty (w_tx_fifo_empty ),
174 .almost_empty ( ),
175 .almost_full ( ),
176 .data_valid ( ),
177 .dbiterr ( ),
178 .full ( ),
179 .overflow ( ),
180 .prog_empty ( ),
181 .prog_full ( ),
182 .rd_rst_busy ( ),
183 .sbiterr ( ),
184 .underflow ( ),
185 .wr_ack ( ),
186 .wr_rst_busy ( ),
187 .injectdbiterr ( ),
188 .injectsbiterr ( ),
189 .sleep (1'b0 )
190
191 );
192 assign w_tx_valid = ~w_tx_fifo_empty;
193 /******************************************************************************\
194 Uart rx fifo
195 \******************************************************************************/
196 xpm_fifo_sync
197 #(
198 .DOUT_RESET_VALUE ("0" ),
199 .ECC_MODE ("no_ecc" ),
200 .FIFO_MEMORY_TYPE ("block" ),
201 .FIFO_READ_LATENCY (1 ),
202 .FIFO_WRITE_DEPTH (RX_FIFO_DEPTH ),
203 .FULL_RESET_VALUE (0 ),
204 .PROG_EMPTY_THRESH (10 ),
205 .PROG_FULL_THRESH (10 ),
206 .RD_DATA_COUNT_WIDTH (1 ),
207 .READ_DATA_WIDTH (9 ),
208 .READ_MODE ("fwft" ),
209 .SIM_ASSERT_CHK (0 ),
210 .USE_ADV_FEATURES ("0707" ),
211 .WAKEUP_TIME (0 ),
212 .WRITE_DATA_WIDTH (9 ),
213 .WR_DATA_COUNT_WIDTH (1 )
214 )
215 u_uart_rx_fifo
216 (
217 .wr_clk (i_s_axi_aclk ),
218 .rst (w_fifo_rest ),
219 .rd_en (w_rx_fifo_rd ),
220 .dout (w_rx_fifo_dout ),
221 .din (w_rx_data ),
222 .wr_en (w_rx_valid ),
223 .wr_data_count ( ),
224 .rd_data_count (w_uart_rd_cnt ),
225 .almost_empty ( ),
226 .almost_full ( ),
227 .data_valid ( ),
228 .dbiterr ( ),
229 .empty ( ),
230 .full ( ),
231 .overflow ( ),
232 .prog_empty ( ),
233 .prog_full ( ),
234 .rd_rst_busy ( ),
235 .sbiterr ( ),
236 .underflow ( ),
237 .wr_ack ( ),
238 .wr_rst_busy ( ),
239 .injectdbiterr ( ),
240 .injectsbiterr ( ),
241 .sleep (1'b0 )
242 );
243
244 endmodule

Uart_ctrl.v

  1 //**************************************************************************
2 // *** file name : Uart_ctrl.v
3 // *** version : 1.0
4 // *** Description : Uart_ctrl
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.09.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Uart_ctrl
12 #(
13 parameter SYS_FRE = 100_000_000
14 )
15 (
16 input wire i_s_axi_aclk ,
17 input wire i_s_axi_aresetn ,
18 input wire [31:0] i_s_axi_awaddr ,
19 input wire [2:0] i_s_axi_awprot ,
20 input wire i_s_axi_awvalid ,
21 output wire o_s_axi_awready ,
22 input wire [31:0] i_s_axi_wdata ,
23 input wire [3:0] i_s_axi_wstrb ,
24 input wire i_s_axi_wvalid ,
25 output wire o_s_axi_wready ,
26 output wire [1:0] o_s_axi_bresp ,
27 output wire o_s_axi_bvalid ,
28 input wire i_s_axi_bready ,
29 input wire [31:0] i_s_axi_araddr ,
30 input wire [2:0] i_s_axi_arprot ,
31 input wire i_s_axi_arvalid ,
32 output wire o_s_axi_arready ,
33 output wire [31:0] o_s_axi_rdata ,
34 output wire [1:0] o_s_axi_rresp ,
35 output wire o_s_axi_rvalid ,
36 input wire i_s_axi_rready ,
37 output reg o_module_en ,
38 output reg o_fifo_clr ,
39 output reg [31:0] o_fre_cnt ,
40 output reg [3:0] o_uart_data_bit ,
41 output reg [2:0] o_uart_parity_mode ,
42 output reg [2:0] o_uart_stop_bit ,
43 output wire [7:0] o_tx_data ,
44 output wire o_tx_valid ,
45 input wire [8:0] i_rx_data ,
46 input wire o_rx_req ,
47 input wire [15:0] i_tx_fifo_wr_cnt ,
48 input wire [15:0] i_rx_fifo_rd_cnt
49 );
50
51 wire [31:0] w_ctrl_wr_addr ;
52 wire w_ctrl_wr_en ;
53 wire [31:0] w_ctrl_wr_data ;
54 wire [3:0] w_ctrl_wr_mask ;
55 wire [31:0] w_ctrl_rd_addr ;
56 reg [31:0] w_ctrl_rd_data ;
57 wire w_fifo_rstn ;
58
59 wire [31:0] w_reg_00_rd ;
60 wire [31:0] w_reg_01_rd ;
61 wire [31:0] w_reg_02_rd ;
62 wire [31:0] w_reg_03_rd ;
63 wire [31:0] w_reg_04_rd ;
64 wire [31:0] w_reg_05_rd ;
65
66
67 /******************************************************************************\
68 Axi4_lite_slave interface
69 \******************************************************************************/
70 Uart_Axi4_lite_slave u_Uart_Axi4_lite_slave
71 (
72 .i_s_axi_aclk (i_s_axi_aclk ),
73 .i_s_axi_aresetn (i_s_axi_aresetn ),
74 .i_s_axi_awaddr (i_s_axi_awaddr ),
75 .i_s_axi_awprot (i_s_axi_awprot ),
76 .i_s_axi_awvalid (i_s_axi_awvalid ),
77 .o_s_axi_awready (o_s_axi_awready ),
78 .i_s_axi_wdata (i_s_axi_wdata ),
79 .i_s_axi_wstrb (i_s_axi_wstrb ),
80 .i_s_axi_wvalid (i_s_axi_wvalid ),
81 .o_s_axi_wready (o_s_axi_wready ),
82 .o_s_axi_bresp (o_s_axi_bresp ),
83 .o_s_axi_bvalid (o_s_axi_bvalid ),
84 .i_s_axi_bready (i_s_axi_bready ),
85 .i_s_axi_araddr (i_s_axi_araddr ),
86 .i_s_axi_arprot (i_s_axi_arprot ),
87 .i_s_axi_arvalid (i_s_axi_arvalid ),
88 .o_s_axi_arready (o_s_axi_arready ),
89 .o_s_axi_rdata (o_s_axi_rdata ),
90 .o_s_axi_rresp (o_s_axi_rresp ),
91 .o_s_axi_rvalid (o_s_axi_rvalid ),
92 .i_s_axi_rready (i_s_axi_rready ),
93 .o_ctrl_wr_addr (w_ctrl_wr_addr ),
94 .o_ctrl_wr_en (w_ctrl_wr_en ),
95 .o_ctrl_wr_data (w_ctrl_wr_data ),
96 .o_ctrl_wr_mask (w_ctrl_wr_mask ),
97 .o_ctrl_rd_addr (w_ctrl_rd_addr ),
98 .i_ctrl_rd_data (w_ctrl_rd_data )
99 );
100 /******************************************************************************\
101 Register 0x00~0x03
102 \******************************************************************************/
103 assign w_reg_00_rd = SYS_FRE;
104 /******************************************************************************\
105 Register 0x04~0x07
106 \******************************************************************************/
107 always @ (posedge i_s_axi_aclk)
108 begin
109 if(~i_s_axi_aresetn)
110 begin
111 o_module_en <= 'd0;
112 end
113 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h01) & w_ctrl_wr_mask[0])
114 begin
115 o_module_en <= w_ctrl_wr_data[0];
116 end
117 end
118
119 always @ (posedge i_s_axi_aclk)
120 begin
121 if(~i_s_axi_aresetn)
122 begin
123 o_fifo_clr <= 'd0;
124 end
125 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h01) & w_ctrl_wr_mask[1])
126 begin
127 o_fifo_clr <= w_ctrl_wr_data[8];
128 end
129 else
130 begin
131 o_fifo_clr <= 'd0;
132 end
133 end
134
135 always @ (posedge i_s_axi_aclk)
136 begin
137 if(~i_s_axi_aresetn)
138 begin
139 o_uart_data_bit <= 'd0;
140 o_uart_parity_mode <= 'd0;
141 end
142 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h01) & w_ctrl_wr_mask[2])
143 begin
144 o_uart_data_bit <= w_ctrl_wr_data[23:20];
145 o_uart_parity_mode <= w_ctrl_wr_data[18:16];
146 end
147 end
148
149 always @ (posedge i_s_axi_aclk)
150 begin
151 if(~i_s_axi_aresetn)
152 begin
153 o_uart_stop_bit <= 'd0;
154 end
155 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h01) & w_ctrl_wr_mask[3])
156 begin
157 o_uart_stop_bit <= w_ctrl_wr_data[26:24];
158 end
159 end
160
161 assign w_reg_01_rd = {{5'd0,o_uart_stop_bit},{o_uart_data_bit,1'b0,o_uart_parity_mode},8'd0,{7'd0,o_module_en}};
162 /******************************************************************************\
163 Register 0x08~0x0b
164 \******************************************************************************/
165 always @ (posedge i_s_axi_aclk)
166 begin
167 if(~i_s_axi_aresetn)
168 begin
169 o_fre_cnt[7:0] <= 'd0;
170 end
171 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h02) & w_ctrl_wr_mask[0])
172 begin
173 o_fre_cnt[7:0] <= w_ctrl_wr_data[7:0];
174 end
175 end
176 always @ (posedge i_s_axi_aclk)
177 begin
178 if(~i_s_axi_aresetn)
179 begin
180 o_fre_cnt[15:8] <= 'd0;
181 end
182 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h02) & w_ctrl_wr_mask[1])
183 begin
184 o_fre_cnt[15:8] <= w_ctrl_wr_data[15:8];
185 end
186 end
187 always @ (posedge i_s_axi_aclk)
188 begin
189 if(~i_s_axi_aresetn)
190 begin
191 o_fre_cnt[23:16] <= 'd0;
192 end
193 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h02) & w_ctrl_wr_mask[2])
194 begin
195 o_fre_cnt[23:16] <= w_ctrl_wr_data[23:16];
196 end
197 end
198 always @ (posedge i_s_axi_aclk)
199 begin
200 if(~i_s_axi_aresetn)
201 begin
202 o_fre_cnt[31:24] <= 'd0;
203 end
204 else if(w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h02) & w_ctrl_wr_mask[3])
205 begin
206 o_fre_cnt[31:24] <= w_ctrl_wr_data[31:24];
207 end
208 end
209
210 assign w_reg_02_rd = o_fre_cnt;
211
212 /******************************************************************************\
213 Register 0x0c~0x0f
214 \******************************************************************************/
215 assign o_tx_valid = (w_ctrl_wr_en & (w_ctrl_wr_addr[7:2] == 6'h03) & w_ctrl_wr_mask[0]);
216 assign o_tx_data = w_ctrl_wr_data[7:0];
217
218 /******************************************************************************\
219 Register 0x10~0x13
220 \******************************************************************************/
221 assign o_rx_req = i_s_axi_arvalid & o_s_axi_arready & (i_s_axi_araddr[11:0] == 12'h010);
222 assign w_reg_04_rd = {23'd0,i_rx_data};
223
224 /******************************************************************************\
225 缓存状态 0x14~0x17
226 \******************************************************************************/
227 assign w_reg_05_rd = {i_tx_fifo_wr_cnt,i_rx_fifo_rd_cnt};
228 /******************************************************************************\
229 Read Register
230 \******************************************************************************/
231 always @ (*)
232 begin
233 case(w_ctrl_rd_addr[7:2])
234 6'h00 : w_ctrl_rd_data = w_reg_00_rd ;
235 6'h01 : w_ctrl_rd_data = w_reg_01_rd ;
236 6'h02 : w_ctrl_rd_data = w_reg_02_rd ;
237 6'h04 : w_ctrl_rd_data = w_reg_04_rd ;
238 6'h05 : w_ctrl_rd_data = w_reg_05_rd ;
239 default : w_ctrl_rd_data = 32'h0000;
240 endcase
241 end
242
243 endmodule

Uart_tx.v

  1 //**************************************************************************
2 // *** file name : Uart_tx.v
3 // *** version : 1.0
4 // *** Description : Uart_tx
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.09.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Uart_tx
12 (
13 input i_sys_clk ,
14 input i_sys_rstn ,
15
16 input [31:0] i_fre_cnt ,
17 input [3:0] i_tx_data_bit ,
18 input [2:0] i_parity_mode ,
19 input [2:0] i_stop_bit ,
20 input [7:0] i_tx_data ,
21 input i_tx_valid ,
22 output reg o_tx_req ,
23 output reg o_uart_tx
24 );
25 localparam S_IDLE = 5'h01;
26 localparam S_START = 5'h02;
27 localparam S_DATA = 5'h04;
28 localparam S_PARITY = 5'h08;
29 localparam S_STOP = 5'h10;
30
31 reg [31:0] r_fre_cnt ;
32 reg [3:0] r_tx_data_bit ;
33 reg [2:0] r_parity_mode ;
34 reg [2:0] r_stop_bit ;
35 reg [31:0] r_fre_sum ;
36 reg r_baud_fre ;
37 reg [4:0] r_cur_state ;
38 reg [4:0] r_next_state ;
39 reg [7:0] r_uart_tx_data ;
40 reg [7:0] r_tx_data ;
41 reg [3:0] r_cnt_tx_bit ;
42 reg [2:0] r_cnt_stop_bit ;
43 reg r_parity ;
44 reg r_tx_data_en ;
45 wire w_baud_pos ;
46 wire w_baud_neg ;
47 wire w_tx_start_en ;
48 wire w_tx_data_en ;
49 wire w_tx_data_end ;
50 wire w_parity_end ;
51 wire w_tx_stop_en ;
52 wire w_tx_stop_end ;
53
54
55 function oneadd;
56 input [7:0] i_data;
57 begin
58 oneadd = i_data[7] + i_data[6] + i_data[5] + i_data[4] + i_data[3] + i_data[2] + i_data[1] + i_data[0];
59 end
60 endfunction
61 /******************************************************************************\
62 Synchronous signal
63 \******************************************************************************/
64 always@(posedge i_sys_clk)
65 begin
66 if(~i_sys_rstn)
67 begin
68 r_fre_cnt <= 'd0;
69 r_tx_data_bit <= 'd0;
70 r_parity_mode <= 'd0;
71 r_stop_bit <= 'd0;
72 end
73 else
74 begin
75 r_fre_cnt <= i_fre_cnt ;
76 r_tx_data_bit <= i_tx_data_bit ;
77 r_parity_mode <= i_parity_mode ;
78 r_stop_bit <= i_stop_bit ;
79 end
80 end
81 /******************************************************************************\
82 Generate sample baud rate signal
83 \******************************************************************************/
84 always@(posedge i_sys_clk)
85 begin
86 if(~i_sys_rstn)
87 begin
88 r_fre_sum <= 32'hffffffff;
89 end
90 else
91 begin
92 r_fre_sum <= r_fre_sum + r_fre_cnt;
93 end
94 end
95 always@(posedge i_sys_clk)
96 begin
97 r_baud_fre <= r_fre_sum[31];
98 end
99
100 assign w_baud_pos = ~r_baud_fre & r_fre_sum[31];
101 assign w_baud_neg = ~r_fre_sum[31] & r_baud_fre ;
102
103 /******************************************************************************\
104 State machine
105 \******************************************************************************/
106 always@(posedge i_sys_clk)
107 begin
108 if(~i_sys_rstn)
109 begin
110 r_cur_state <= S_IDLE;
111 end
112 else
113 begin
114 r_cur_state <= r_next_state;
115 end
116 end
117
118 always@(*)
119 begin
120 r_next_state = 'd1;
121 case(r_cur_state)
122 S_IDLE:
123 begin
124 if(i_tx_valid & w_baud_neg)
125 begin
126 r_next_state = S_START;
127 end
128 else
129 begin
130 r_next_state = S_IDLE;
131 end
132 end
133 S_START:
134 begin
135 if(w_tx_start_en)
136 begin
137 r_next_state = S_DATA;
138 end
139 else
140 begin
141 r_next_state = S_START;
142 end
143 end
144 S_DATA:
145 begin
146 if(w_tx_data_end)
147 begin
148 if(r_parity_mode[2])
149 begin
150 r_next_state = S_STOP;
151 end
152 else
153 begin
154 r_next_state = S_PARITY;
155 end
156 end
157 else
158 begin
159 r_next_state = S_DATA;
160 end
161 end
162 S_PARITY:
163 begin
164 if(w_parity_end)
165 begin
166 r_next_state = S_STOP;
167 end
168 else
169 begin
170 r_next_state = S_PARITY;
171 end
172 end
173 S_STOP:
174 begin
175 if(w_tx_stop_end)
176 begin
177 r_next_state = S_IDLE;
178 end
179 else
180 begin
181 r_next_state = S_STOP;
182 end
183 end
184 default: r_next_state = S_IDLE;
185 endcase
186 end
187
188 /******************************************************************************\
189 Uart tx data
190 \******************************************************************************/
191 assign w_tx_start_en = (r_cur_state == S_START) & w_baud_neg;
192 assign w_tx_data_en = (r_cur_state == S_DATA) & w_baud_neg;
193 assign w_tx_data_end = (r_cur_state == S_DATA) & (r_cnt_tx_bit == r_tx_data_bit);
194 assign w_parity_end = (r_cur_state == S_PARITY) & w_baud_neg;
195 assign w_tx_stop_en = (r_cur_state == S_STOP) & (w_baud_neg | w_baud_pos);
196 assign w_tx_stop_end = (r_cur_state == S_STOP) & (r_cnt_stop_bit == r_stop_bit);
197
198 always@(posedge i_sys_clk)
199 begin
200 r_tx_data_en <= w_tx_data_en;
201 end
202
203 always@(posedge i_sys_clk)
204 begin
205 if(~i_sys_rstn)
206 begin
207 r_uart_tx_data <= 8'hff;
208 end
209 else if(w_tx_start_en)
210 begin
211 r_uart_tx_data <= r_tx_data;
212 end
213 else if(r_tx_data_en)
214 begin
215 r_uart_tx_data <= {1'b1,r_uart_tx_data[7:1]};
216 end
217 end
218
219 always@(posedge i_sys_clk)
220 begin
221 if(~i_sys_rstn | w_tx_data_end)
222 begin
223 r_cnt_tx_bit <= 'd0;
224 end
225 else if(w_tx_data_en)
226 begin
227 r_cnt_tx_bit <= r_cnt_tx_bit + 1'b1;
228 end
229 end
230
231 always@(posedge i_sys_clk)
232 begin
233 if(~i_sys_rstn | w_tx_stop_end)
234 begin
235 r_cnt_stop_bit <= 'd0;
236 end
237 else if(w_tx_stop_en)
238 begin
239 r_cnt_stop_bit <= r_cnt_stop_bit + 1'b1;
240 end
241 end
242
243 always@(*)
244 begin
245 case(r_cur_state)
246 S_START:
247 if(w_baud_pos & i_tx_valid)
248 o_tx_req = 1'b1;
249 else
250 o_tx_req = 1'b0;
251 default:
252 o_tx_req = 1'b0;
253 endcase
254 end
255 assign w_deal_en = i_tx_valid & o_tx_req;
256
257 /******************************************************************************\
258 Uart tx parity
259 \******************************************************************************/
260 always@(posedge i_sys_clk)
261 begin
262 if(w_deal_en)
263 begin
264 r_tx_data <= i_tx_data;
265 end
266 end
267
268 always@(*)
269 begin
270 case(r_parity_mode)
271 3'd0 : r_parity = oneadd(r_tx_data) ? 1'b0 : 1'b1; //Odd parity
272 3'd1 : r_parity = oneadd(r_tx_data) ? 1'b1 : 1'b0; //Even parity
273 3'd2 : r_parity = 'd1; //Mark parity
274 3'd3 : r_parity = 'd0; //Space parity
275 default : r_parity = 'd0; //No parity
276 endcase
277 end
278 /******************************************************************************\
279 Uart tx serial port
280 \******************************************************************************/
281 always@(*)
282 begin
283 case(r_cur_state)
284 S_START : o_uart_tx = 'd0;
285 S_DATA : o_uart_tx = r_uart_tx_data[0];
286 S_PARITY : o_uart_tx = r_parity;
287 S_STOP : o_uart_tx = 'd1;
288 default : o_uart_tx = 'd1;
289 endcase
290 end
291
292 endmodule

Uart_rx.v

  1 //**************************************************************************
2 // *** file name : Uart_tx.v
3 // *** version : 1.0
4 // *** Description : Uart_tx
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.09.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Uart_rx
12 (
13 input i_sys_clk ,
14 input i_sys_rstn ,
15
16 input [31:0] i_fre_cnt ,
17 input [3:0] i_rx_data_bit ,
18 input i_parity_mode ,
19 input [2:0] i_stop_bit ,
20 output [8:0] o_rx_data ,
21 output o_rx_valid ,
22 input i_uart_rx
23
24 );
25 localparam S_IDLE = 6'h01;
26 localparam S_START = 6'h02;
27 localparam S_DATA = 6'h04;
28 localparam S_PARITY = 6'h08;
29 localparam S_STOP = 6'h10;
30 localparam S_END = 6'h20;
31
32 reg [31:0] r_fre_cnt ;
33 reg [3:0] r_rx_data_bit ;
34 reg r_parity_mode ;
35 reg [2:0] r_stop_bit ;
36 reg [2:0] r_uart_rx ;
37 reg [31:0] r_fre_sum ;
38 reg r_rx_enable ;
39 reg [1:0] r_baud_fre ;
40 reg [5:0] r_current_state ;
41 reg [5:0] r_next_state ;
42 reg [3:0] r_cnt_rx_bit ;
43 reg [7:0] r_rx_data ;
44 reg [7:0] r_rx_data1 ;
45 reg r_cnt_parity_bit ;
46 reg r_parity_er ;
47 reg r_parity_er1 ;
48 reg [2:0] r_cnt_stop_bit ;
49
50 wire w_uart_rx_pos ;
51 wire w_uart_rx_neg ;
52 wire w_data_sample_en ;
53 wire w_data_sample_end ;
54 wire w_parity_sample_en ;
55 wire w_parity_sample_end;
56 wire w_stop_sample_en ;
57 wire w_stop_sample_end ;
58 /******************************************************************************\
59 Synchronous signal
60 \******************************************************************************/
61 always@(posedge i_sys_clk)
62 begin
63 if(~i_sys_rstn)
64 begin
65 r_fre_cnt <= 'd0;
66 r_rx_data_bit <= 'd0;
67 r_parity_mode <= 'd0;
68 r_stop_bit <= 'd0;
69 end
70 else
71 begin
72 r_fre_cnt <= i_fre_cnt ;
73 r_rx_data_bit <= i_rx_data_bit;
74 r_parity_mode <= i_parity_mode;
75 r_stop_bit <= i_stop_bit ;
76 end
77 end
78
79 always@(posedge i_sys_clk)
80 begin
81 if(~i_sys_rstn)
82 begin
83 r_uart_rx <= 'd0;
84 end
85 else
86 begin
87 r_uart_rx <= {r_uart_rx[1:0],i_uart_rx};
88 end
89 end
90
91 assign w_uart_rx_pos = ~r_uart_rx[2] & r_uart_rx[1];
92 assign w_uart_rx_neg = ~r_uart_rx[1] & r_uart_rx[2];
93
94 /******************************************************************************\
95 Generate sample baud rate signal
96 \******************************************************************************/
97 always@(posedge i_sys_clk)
98 begin
99 if(~i_sys_rstn)
100 begin
101 r_fre_sum <= 'd0;
102 end
103 else if(r_rx_enable)
104 begin
105 r_fre_sum <= r_fre_sum + r_fre_cnt;
106 end
107 end
108 always@(posedge i_sys_clk)
109 begin
110 r_baud_fre <= {r_baud_fre[0],r_fre_sum[31]};
111 end
112
113 assign w_baud_pos = ~r_baud_fre[1] & r_baud_fre[0];
114 assign w_baud_neg = ~r_baud_fre[0] & r_baud_fre[1];
115
116 always@(*)
117 begin
118 case(r_current_state)
119 S_IDLE: r_rx_enable <= 'd0;
120 S_END : r_rx_enable <= 'd0;
121 default:r_rx_enable <= 1'b1;
122 endcase
123 end
124
125 /******************************************************************************\
126 State machine
127 \******************************************************************************/
128 always@(posedge i_sys_clk)
129 begin
130 if(~i_sys_rstn)
131 begin
132 r_current_state <= S_IDLE;
133 end
134 else
135 begin
136 r_current_state <= r_next_state;
137 end
138 end
139
140 always@(*)
141 begin
142 r_next_state <= 'd1;
143 case(r_current_state)
144 S_IDLE:
145 begin
146 if(w_uart_rx_neg)
147 begin
148 r_next_state <= S_START;
149 end
150 else
151 begin
152 r_next_state <= S_IDLE;
153 end
154 end
155 S_START:
156 begin
157 if(w_baud_pos & (r_uart_rx[2] == 1'b0))
158 begin
159 r_next_state <= S_DATA;
160 end
161 else if(w_baud_pos & (r_uart_rx[2] == 1'b1))
162 begin
163 r_next_state <= S_IDLE;
164 end
165 else
166 begin
167 r_next_state <= S_START;
168 end
169 end
170 S_DATA:
171 begin
172 if(w_data_sample_end)
173 begin
174 if(r_parity_mode)
175 begin
176 r_next_state <= S_STOP;
177 end
178 else
179 begin
180 r_next_state <= S_PARITY;
181 end
182 end
183 else
184 begin
185 r_next_state <= S_DATA;
186 end
187 end
188 S_PARITY:
189 begin
190 if(w_parity_sample_end)
191 begin
192 r_next_state <= S_STOP;
193 end
194 else
195 begin
196 r_next_state <= S_PARITY;
197 end
198 end
199 S_STOP:
200 begin
201 if(w_stop_sample_end)
202 begin
203 r_next_state <= S_END;
204 end
205 else
206 begin
207 r_next_state <= S_STOP;
208 end
209 end
210 S_END:
211 begin
212 r_next_state <= S_IDLE;
213 end
214 default: r_next_state <= S_IDLE;
215 endcase
216 end
217 /******************************************************************************\
218 Uart rx data sample
219 \******************************************************************************/
220 assign w_data_sample_en = (r_current_state == S_DATA) && w_baud_pos;
221 assign w_data_sample_end = (r_current_state == S_DATA) && (r_cnt_rx_bit == r_rx_data_bit);
222
223 always@(posedge i_sys_clk)
224 begin
225 if(~i_sys_rstn | w_data_sample_end)
226 begin
227 r_cnt_rx_bit <= 'd0;
228 end
229 else if(w_data_sample_en)
230 begin
231 r_cnt_rx_bit <= r_cnt_rx_bit + 1'b1;
232 end
233 end
234
235 always@(posedge i_sys_clk)
236 begin
237 if(~i_sys_rstn | w_data_sample_end)
238 begin
239 r_rx_data <= 'd0;
240 end
241 else if(w_data_sample_en)
242 begin
243 r_rx_data <= {r_uart_rx[2],r_rx_data[7:1]};
244 end
245 end
246
247 always@(posedge i_sys_clk)
248 begin
249 if(~i_sys_rstn)
250 begin
251 r_rx_data1 <= 'd0;
252 end
253 else if(w_data_sample_end)
254 begin
255 r_rx_data1 <= r_rx_data;
256 end
257 end
258
259 /******************************************************************************\
260 Uart rx parity sample
261 \******************************************************************************/
262 assign w_parity_sample_en = (r_current_state == S_PARITY) && w_baud_pos;
263 assign w_parity_sample_end = (r_current_state == S_PARITY) && (r_cnt_parity_bit == 1'b1);
264
265 always@(posedge i_sys_clk)
266 begin
267 if(~i_sys_rstn | w_parity_sample_end)
268 begin
269 r_cnt_parity_bit <= 'd0;
270 r_parity_er <= 'd0;
271 end
272 else if(w_parity_sample_en)
273 begin
274 r_cnt_parity_bit <= r_cnt_parity_bit + 1'b1;
275 r_parity_er <= r_uart_rx[2];
276 end
277 end
278
279 always@(posedge i_sys_clk)
280 begin
281 if(~i_sys_rstn)
282 begin
283 r_parity_er1 <= 'd0;
284 end
285 else if(w_parity_sample_end)
286 begin
287 r_parity_er1 <= r_parity_er;
288 end
289 end
290 /******************************************************************************\
291 Uart rx stop sample
292 \******************************************************************************/
293 assign w_stop_sample_en = (r_current_state == S_STOP) && (w_baud_pos | w_baud_neg);
294 assign w_stop_sample_end = (r_current_state == S_STOP) && (r_cnt_stop_bit == r_stop_bit);
295
296 always@(posedge i_sys_clk)
297 begin
298 if(~i_sys_rstn | w_stop_sample_end)
299 begin
300 r_cnt_stop_bit <= 'd0;
301 end
302 else if(w_stop_sample_en)
303 begin
304 r_cnt_stop_bit <= r_cnt_stop_bit + 1'b1;
305 end
306 end
307
308 assign o_rx_data = {r_rx_data1,r_parity_er1};
309 assign o_rx_valid = w_stop_sample_end;
310
311 endmodule

  以上是笔者根据时序写的代码,只是简单的跑了下仿真,没有实际上板调试。笔者是比较懒的人,因此以上代码也只是仅供参考的

仿真代码Uart_sim.v,这里把UART的tx,rx引脚直接相连。对于收发数据的位宽处理以及接收的校验位这里都应当交由软件驱动来处理。

  1 //**************************************************************************
2 // *** file name : Uart_sim.v
3 // *** version : 1.0
4 // *** Description : Uart_sim
5 // *** Blogs : https://www.cnblogs.com/WenGalois123/
6 // *** Author : Galois_V
7 // *** Date : 2022.09.14
8 // *** Changes : Initial
9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Uart_sim();
12
13 /******************************************************************************\
14 Define AXI4-lite interface port
15 \******************************************************************************/
16 wire w_axi_aclk ;
17 wire w_axi_aresetn ;
18
19 wire [31:0] w_axi_awaddr ;
20 wire w_axi_awvalid ;
21 wire w_axi_awready ;
22
23 wire [31:0] w_axi_wdata ;
24 wire [3:0] w_axi_wstrb ;
25 wire w_axi_wvalid ;
26 wire w_axi_wready ;
27
28 wire [1:0] w_axi_bresp ;
29 wire w_axi_bvalid ;
30 wire w_axi_bready ;
31
32 wire [31:0] w_axi_araddr ;
33 wire w_axi_arvalid ;
34 wire w_axi_arready ;
35
36 wire [31:0] w_axi_rdata ;
37 wire [1:0] w_axi_rresp ;
38 wire w_axi_rvalid ;
39 wire w_axi_rready ;
40
41 /******************************************************************************\
42 Instantiate AXI4-lite master module
43 \******************************************************************************/
44 m_axi4_lite_if u_m_axi4_lite_if
45 (
46 .o_sys_clk (w_axi_aclk ),
47 .o_sys_rstn (w_axi_aresetn ),
48 .o_m_axi_awaddr (w_axi_awaddr ),
49 .o_m_axi_awvalid (w_axi_awvalid ),
50 .i_m_axi_awready (w_axi_awready ),
51 .o_m_axi_wdata (w_axi_wdata ),
52 .o_m_axi_wstrb (w_axi_wstrb ),
53 .o_m_axi_wvalid (w_axi_wvalid ),
54 .i_m_axi_wready (w_axi_wready ),
55 .i_m_axi_bresp (w_axi_bresp ),
56 .i_m_axi_bvalid (w_axi_bvalid ),
57 .o_m_axi_bready (w_axi_bready ),
58 .o_m_axi_araddr (w_axi_araddr ),
59 .o_m_axi_arvalid (w_axi_arvalid ),
60 .i_m_axi_arready (w_axi_arready ),
61 .i_m_axi_rdata (w_axi_rdata ),
62 .i_m_axi_rresp (w_axi_rresp ),
63 .i_m_axi_rvalid (w_axi_rvalid ),
64 .o_m_axi_rready (w_axi_rready )
65 );
66
67 /******************************************************************************\
68 Instantiate AXI4-lite slave IP core
69 \******************************************************************************/
70 wire w_uart_data;
71
72 AXI4_UART
73 #(
74 .SYS_FRE (100_000_000 ),
75 .TX_FIFO_DEPTH (2048 ),
76 .RX_FIFO_DEPTH (2048 )
77 )
78 u_AXI4_UART
79 (
80 .i_s_axi_aclk (w_axi_aclk ),
81 .i_s_axi_aresetn (w_axi_aresetn ),
82 .i_s_axi_awaddr (w_axi_awaddr ),
83 .i_s_axi_awprot ('d0 ),
84 .i_s_axi_awvalid (w_axi_awvalid ),
85 .o_s_axi_awready (w_axi_awready ),
86 .i_s_axi_wdata (w_axi_wdata ),
87 .i_s_axi_wstrb (w_axi_wstrb ),
88 .i_s_axi_wvalid (w_axi_wvalid ),
89 .o_s_axi_wready (w_axi_wready ),
90 .o_s_axi_bresp (w_axi_bresp ),
91 .o_s_axi_bvalid (w_axi_bvalid ),
92 .i_s_axi_bready (w_axi_bready ),
93 .i_s_axi_araddr (w_axi_araddr ),
94 .i_s_axi_arprot ('d0 ),
95 .i_s_axi_arvalid (w_axi_arvalid ),
96 .o_s_axi_arready (w_axi_arready ),
97 .o_s_axi_rdata (w_axi_rdata ),
98 .o_s_axi_rresp (w_axi_rresp ),
99 .o_s_axi_rvalid (w_axi_rvalid ),
100 .i_s_axi_rready (w_axi_rready ),
101 .i_uart_rx (w_uart_data ),
102 .o_uart_tx (w_uart_data )
103 );
104
105 /******************************************************************************\
106 Perform the steps of IP core in sequence
107 \******************************************************************************/
108 reg [31:0] r_cpu_rd_data;
109 initial r_cpu_rd_data = 0;
110
111
112 initial
113 begin
114 $display("start");
115 #2000;
116 u_m_axi4_lite_if.arm_write_data(32'h00000004,32'h00810101,4'hf);//set stop bit 1/set data bit 8/set parity_mode odd/ clear fifo/enable the IP module
117 #200;
118 u_m_axi4_lite_if.arm_write_data(32'h00000008,32'd4947802,4'hf);//set the clk as 115200
119 #200;
120 u_m_axi4_lite_if.arm_write_data(32'h0000000c,{28'd0,8'h5a},4'hf);//tx data 8'h5a
121 #200;
122 u_m_axi4_lite_if.arm_write_data(32'h0000000c,{28'd0,8'h85},4'hf);//tx data 8'h85
123 #200;
124 u_m_axi4_lite_if.arm_write_data(32'h0000000c,{28'd0,8'h6f},4'hf);//tx data 8'h6f
125 #200000;
126 u_m_axi4_lite_if.arm_read_data(32'h00000010,r_cpu_rd_data);
127
128 $display("sim complete");
129 end
130
131
132 endmodule

仿真结果如下:

tx:

rx:这里的接收数据把校验位也包括了,因此这里输出的数据为9bit,实际的接收数据可以看r_rx_data1。

最新文章

  1. Ajax浅学习
  2. jQuery里ajax的用法
  3. uva 1368
  4. wap手机端解决返回上一页,js
  5. 我的PHP之旅--XML初步
  6. php5.6解决curl扩展不生效的问题
  7. 其他—cooki和session
  8. mutex,thread
  9. FPGA笔试必会知识点2—FPGA器件
  10. Jquery Post提交时Content-Type的不同取值详解
  11. 查看Windows版本号
  12. SQL server学习(五)T-SQL编程之存储过程
  13. 创建py模板
  14. Centos7部署kubectl命令行工具(五)
  15. [转]分析MySQL数据类型的长度【mysql数据字段 中length和decimals的作用!熟悉mysql必看】
  16. C# 调用dephi dll 实例
  17. Android 框架
  18. Thread(线程)和ThreadPool(线程池) Thread回调与返回值
  19. C++中常函数内部的this指针也是const类型的
  20. java编写简单的语法分析预测程序

热门文章

  1. JZOJ 5350. 【NOIP2017提高A组模拟9.7】陶陶摘苹果
  2. GPT接入飞书
  3. 跳板攻击之:frp代理转发
  4. 02#Web 实战:实现树形控件
  5. TextBox 事件
  6. (四)Mysql之索引介绍
  7. wwise 音频引擎介绍
  8. 【C/C++】main函数中的argc和argv
  9. python读取Excel指定单元格的值
  10. Object.defineProperty(定义试添加json对象的属性)