赞
踩
通用异步收发器(Universal Asynchronous Receiver/Transmitter,UART)可以和各种标准串行接口,如RS 232和RS 485等进行全双工异步通信,具有传输距离远、成本低、可靠性高等优点。一般UART由专用芯片如8250,16450来实现,但专用芯片引脚都较多,内含许多辅助功能,在实际使用时往往只需要用到UART的基本功能,使用专用芯片会造成资源浪费和成本提高。
UART只需要两条信号线:RXD和TXD,其中RXD是UART的接收端,TXD是UART的发送端,接收与发送是全双工形式。下图为UART的工作原理如下
如上图所示,uart是将传输数据的每个字符一位接一位地传输。
其中每一位(Bit)的意义如下:
空闲位:高电平,表明当前无传输事务。
起始位:一位低电平信号,标志着数据传输的开始。
数据位:紧接着起始位之后。数据位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。
奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。
停止位:一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
uart数据传输的速率用波特率表示,其含义为从一设备发到另一设备,每秒钟可以通信的数据比特个数。典型的波特率有300, 1200, 2400, 9600, 19200, 115200等。一般通信两端设备都要设为相同的波特率,但有些设备也可设置为自动检测波特率。
uart的设计分为两个部分,一部分为发送模块,另一部分为接收模块。程序设计主要通过状态机实现,在本设计中,我们略去了奇偶校验位,每次传输8bit数据,且停止位为1位。
我们共设置了如下几个状态:
IDLE:空闲状态,电平恒为1;
START:起始位,电平为0,1位;
DATA:数据位,共8位,先发送低比特;
STOP:停止位,高电平,共1位。
其中,发送模块在上一状态向下一状态切换时,改变电平,而接收模块,则在状态的中间位置进行采样,如下图所示:
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2022/02/26 15:27:26 // Design Name: // Module Name: uart_tx_sim // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_tx_sim #(parameter BPS=5208) ( input clk, input rst_n, input start, input [7:0] send_data, output reg rs232_tx ); // // parameter BPS=5208; //计算传输一次的计数时间: // //计数时间 = 1000000000ns/9600 = 104166.7ns // //50MHz的时钟周期为20ns,所以计数传输一个比特的次数为104166.7 / 20 = 5208 parameter IDLE = 0; parameter START = 1; //起始位 parameter SEND = 2; //8bit数据发送,最低位开始传送,靠时钟定位。 parameter STOP =3; //停止位 reg [2:0] cur_state; reg [2:0] next_state; reg [31:0] count; //计数器 reg [31:0] send_cnt; //发送bit计数器 //三段式状态机 always@(posedge clk,negedge rst_n) if(~rst_n) cur_state<=IDLE; else cur_state<=next_state; // always@(*) case(cur_state) IDLE:if(start) next_state=START; else next_state=IDLE; START:if(count==BPS-1) next_state=SEND; else next_state=START; SEND:if(send_cnt==8-1&&count==BPS-1) next_state=STOP; else next_state=SEND; STOP:if(count==BPS-1) next_state=IDLE; else next_state=STOP; default:next_state=IDLE; endcase //count always@(posedge clk,negedge rst_n) if(~rst_n) count<=0; else if(cur_state!=IDLE) begin if(count==BPS-1) count<=0; else count<=count+1; end else count<=0; //send_cnt always@(posedge clk,negedge rst_n) if(~rst_n) send_cnt<=0; else if(cur_state==SEND&&count==BPS-1) send_cnt<=send_cnt+1; else if(cur_state!=SEND) send_cnt<=0; //rs232_tx always@(*) case(cur_state) IDLE:rs232_tx=1; START:rs232_tx=0; SEND:begin case(send_cnt) 0:rs232_tx=send_data[0]; 1:rs232_tx=send_data[1]; 2:rs232_tx=send_data[2]; 3:rs232_tx=send_data[3]; 4:rs232_tx=send_data[4]; 5:rs232_tx=send_data[5]; 6:rs232_tx=send_data[6]; 7:rs232_tx=send_data[7]; default:rs232_tx=1; endcase end STOP:rs232_tx=1; default:rs232_tx=1; endcase endmodule
`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2022/02/26 16:25:38 // Design Name: // Module Name: uart_rx_sim // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module uart_rx_sim #(parameter BPS=5208) ( input clk, input rst_n, input rs232_rx, output reg valid, output reg [7:0] recv_data ); parameter IDLE = 0; parameter START = 1; parameter RECV = 2; parameter STOP =3; //parameter BPS=5208; // reg sample_edge; reg [2:0] cur_state; reg [2:0] next_state; reg [31:0] count; reg [2:0] recv_cnt; //0-7 reg rs232_rx_ff1; //检测到IDLE状态下tx信号拉低 //rs232_tx_ff1 always@(posedge clk) rs232_rx_ff1<=rs232_rx; // always@(posedge clk,negedge rst_n) if(~rst_n) cur_state<=IDLE; else cur_state<=next_state; // always@(*) begin case(cur_state) IDLE:if(~rs232_rx&&rs232_rx_ff1) //检测到下降沿 next_state=START; else next_state=IDLE; START:if(count==BPS-2) //检测到下降沿占去一个周期 next_state=RECV; else next_state=START; RECV:if(recv_cnt==8-1&&count==BPS-1) next_state=STOP; else next_state=RECV; STOP:if(count==BPS-1) next_state=IDLE; else next_state=STOP; default:next_state=IDLE; endcase end //count always@(posedge clk,negedge rst_n) if(~rst_n) count<=0; else case(cur_state) IDLE:count<=0; START:if(count==BPS-2) count<=0; else count<=count+1; RECV:if(count==BPS-1) count<=0; else count<=count+1; STOP:if(count==BPS-1) count<=0; else count<=count+1; default:count<=0; endcase //recv_cnt always@(posedge clk,negedge rst_n) if(~rst_n) recv_cnt<=0; else if(cur_state==RECV&&count==BPS-1) recv_cnt<=recv_cnt+1; else if(cur_state==STOP) recv_cnt<=0; //sample_edge always@(posedge clk,negedge rst_n) if(~rst_n) sample_edge<=0; else if(cur_state==RECV&&count==BPS/2-1) //在数据最中间采用 sample_edge<=1; else sample_edge<=0; //recv_data always@(posedge clk) if(cur_state==RECV&&sample_edge) begin case(recv_cnt) 0:recv_data[0]<=rs232_rx; 1:recv_data[1]<=rs232_rx; 2:recv_data[2]<=rs232_rx; 3:recv_data[3]<=rs232_rx; 4:recv_data[4]<=rs232_rx; 5:recv_data[5]<=rs232_rx; 6:recv_data[6]<=rs232_rx; 7:recv_data[7]<=rs232_rx; default:; endcase end //valid always@(posedge clk,negedge rst_n) if(~rst_n) valid<=0; else if(cur_state==STOP) valid<=1; else if(~rs232_rx&&rs232_rx_ff1&&cur_state==IDLE) valid<=0; endmodule
见链接:https://pan.baidu.com/s/1TdDGv-eiPZ91tepzJGSvhg
提取码:zdfw
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。