1.简介
(1)UART一种通用异步串口数据总线,最低采用两路信号(TX/RX)即可实现全双工通信,十分简单;
(2)UART采用LSB模式传输,串口数据传输格式如下图所示:
起始位:长度为1位的时间,用于表示发送字符的开始;
数据位:长度长度不固定,一般是8位;
校验位:可以加也可以不加。
停止位:一般是1位、1.5位、2位长度,用于告知接收端字符传输结束;
(3)每个字符的发送都需要有起始位和停止位,对于连续数据也是如此;
2.内部结构
3.实现
发送模块代码如下:
1 module uart_tx_path # 2 ( 3 parameter BAUD_DIV = 13'd9, //baud 4 parameter BAUD_DIV_CAP = 13'd4 //baud capture point 5 ) 6 ( 7 input clk, //main clk 8 input rst_n, //reset 9 input uart_tx_en, //send one byte data enable 10 input[7:0] uart_tx_byte, //one byte data 11 output uart_txd, //the txd pin 12 output uart_tx_done //send one byte data done 13 ); 14 15 //------------------------- Baud rate generator ------------------------- 16 reg[12:0] cnt_baud_div; 17 reg baud_cap; 18 reg baud_start; 19 20 always@(posedge clk or negedge rst_n) 21 begin 22 if(!rst_n) begin 23 cnt_baud_div <= 13'd0; 24 end 25 else begin 26 if(baud_start) begin 27 if(cnt_baud_div >= BAUD_DIV) begin 28 cnt_baud_div <= 13'd0; 29 end 30 else begin 31 cnt_baud_div <= cnt_baud_div + 1'b1; 32 end 33 end 34 else begin 35 cnt_baud_div <= 13'd0; 36 end 37 end 38 end 39 40 always@(posedge clk or negedge rst_n) 41 begin 42 if(!rst_n) begin 43 baud_cap <= 1'b0; 44 end 45 else begin 46 if(cnt_baud_div==BAUD_DIV_CAP) begin 47 baud_cap <= 1'b1; 48 end 49 else begin 50 baud_cap <= 1'b0; 51 end 52 end 53 end 54 55 //-------------------------capture the uart_tx_en posedge------------------------- 56 reg uart_tx_en_r0,uart_tx_en_r1; 57 wire uart_tx_en_p; 58 59 always@(posedge clk or negedge rst_n) 60 begin 61 if(!rst_n) begin 62 uart_tx_en_r0 <= 1'b0; //uart_tx_en of the idle state is low 63 uart_tx_en_r1 <= 1'b0; 64 end 65 else begin 66 uart_tx_en_r0 <= uart_tx_en; 67 uart_tx_en_r1 <= uart_tx_en_r0; 68 end 69 end 70 71 assign uart_tx_en_p = (~uart_tx_en_r1 & uart_tx_en_r0)? 1'b1:1'b0; //capture the uart_tx_en posedge 72 73 //------------------------- capture the txd data ------------------------- 74 localparam TX_IDLE = 1'b0; 75 localparam TX_WORK = 1'b1; 76 77 reg state_tx; 78 reg uart_tx_done_r; 79 reg[9:0] send_data; 80 reg[3:0] tx_bit; 81 82 always@(posedge clk or negedge rst_n) 83 begin 84 if(!rst_n) begin 85 state_tx <= TX_IDLE; 86 send_data <= 10'b1111_1111_11; 87 uart_tx_done_r <= 1'b0; 88 end 89 else begin 90 case(state_tx) 91 TX_IDLE: if(uart_tx_en_p) begin 92 baud_start <= 1'b1; 93 send_data <= {1'b1,uart_tx_byte,1'b0}; 94 state_tx <= TX_WORK; 95 uart_tx_done_r <= 1'b0; 96 end 97 else begin 98 baud_start <= 1'b0; 99 send_data <= 10'b1111_1111_11; 100 state_tx <= TX_IDLE; 101 uart_tx_done_r <= 1'b0; 102 end 103 TX_WORK: if(tx_bit == 4'd10) begin 104 baud_start <= 1'b1; 105 send_data <= 10'b1111_1111_11; 106 state_tx <= TX_WORK; 107 uart_tx_done_r <= 1'b0; 108 end 109 else if(tx_bit>=4'd11) begin 110 baud_start <= 1'b0; 111 send_data <= 10'b1111_1111_11; 112 state_tx <= TX_IDLE; 113 uart_tx_done_r <= 1'b1; 114 end 115 else begin 116 baud_start <= 1'b1; 117 send_data <= send_data; 118 state_tx <= TX_WORK; 119 uart_tx_done_r <= 1'b0; 120 end 121 default: ; 122 endcase 123 end 124 end 125 //------------------------- the uart txd work ------------------------- 126 reg uart_txd_r; 127 128 always@(posedge clk or negedge rst_n) 129 begin 130 if(!rst_n) begin 131 uart_txd_r <= 1'b1; //uart_txd of the idle state is high 132 tx_bit <= 4'd0; 133 end 134 else begin 135 if(state_tx == TX_WORK) begin 136 if(baud_cap) begin 137 if (tx_bit <= 4'd9) 138 uart_txd_r <= send_data[tx_bit]; 139 else 140 uart_txd_r <= 1'b1; 141 tx_bit <= tx_bit + 1'b1; 142 end 143 else begin 144 uart_txd_r <= uart_txd_r; 145 tx_bit <= tx_bit; 146 end 147 end 148 else begin 149 uart_txd_r <= 1'b1; 150 tx_bit <= 4'd0; 151 end 152 end 153 end 154 155 assign uart_tx_done = uart_tx_done_r; 156 assign uart_txd = uart_txd_r; 157 158 endmodule