基于Axi4_lite的UART串口Verilog代码实现
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。