当前位置:首页 > 后端开发 > 正文内容

串口收发UART(Verilog HDL)

邻居的猫1个月前 (12-09)后端开发394

UART(Universal Asynchronous Receiver Transmitter,通用异步收发器)是一种异步串行通讯协议,首要用于计算机和嵌入式体系之间的数据交换。

完结UART通讯的接口规范和总线规范包含RS-232、RS449、RS423和RS485等,接口规范规则了通讯规范的电气特性、传输速率、衔接特性和机械特性。

文章摘要:本篇文章方针规划一个格局为开端位+8位数据(无校验)+中止位的串口收发,接纳PC上位机RS232总线信号后,从头打包转发至PC端显现(构成回环),数据完好无错码状况。

要害词: 异步时钟;亚稳态;异步串行通讯;Verilog HDL

方针规划框图:

image

【串行帧格局】

UART通讯运用两条信号线进行数据传输:发送数据线(TX)和接纳数据线(RX)。数据以数据帧的方法传输,每个数据帧由开端位、数据位(一般为5到9位)、校验位(可选)和中止位(一般为1到2位)组成。

发送方在发送数据之前,会先发送一个开端位(一般为低电平),然后依照设定的数据位和校验位发送数据,最终发送一个或多个中止位(一般为高电平)以标识数据传输的结束。接纳方在检测到开端位后,会开端接纳数据,直到检测到中止位中止(起止式协议)。一起,接纳方会根据约好的校验方法对数据进行校验。

image

1、开端位(Start Bit):一般是一个独自的位,逻辑值为0(低电平),表明字符开端,接纳端同步到发送端的数据流。

2、数据位(Data Bits):帧的主体部分,包含传输信息,数据位数量能够根据需求进行装备,常见的有5位、6位、7位、8位等。

3、校验位(Parity Bit):可选位,校验位能够是偶校验(Even Parity)、奇校验(Odd Parity)或无校验(No Parity),偶校验意味着数据位中1的个数(包含校验位)应该是偶数;奇校验则是奇数。

4、中止位(Stop Bits):标志字符的结束,并答应接纳器在接纳下一个字符之前有时刻复位。中止位的数量能够是1位、1.5位或2位。

5、闲暇位(Idle Line):在两个字符之间,线路一般坚持在高电平状况(逻辑值为1)称为闲暇线状况,它答应接纳端在字符之间有时刻来检测和呼应线路状况的改变。


数据传输中,波特率(Baud rate)是一个重要的参数,表明单位时刻内传输的码元符号的个数(一般指二进制位)。波特率并不直接等同于比特率(bit rate),因为每个码元符号或许包含多个比特。但在许多状况下,特别是在串行通讯中,一个码元符号便是一个比特,此刻波特率就等于比特率。

传送速率为960字符/秒,而每个字符为10位(或许是1个开端位、8个数据位和1个中止位)。总的二进制位数传送速率是960字符/秒 × 10位/字符 = 9600位/秒,所以波特率便是9600。

【异步传输存在亚稳态】

在数字电路规划中同步树立至关重要,异步时钟域之间的信号通讯不可防止存在亚稳态问题。UART接纳进程,开端位的检测尤为要害,过错的开端位检测或许导致整个数据包的接纳失利。为了防止因亚稳态导致的采样过错和电路毛病,规划者必须在接口处采纳牢靠的同步化办法。

亚稳态:简略来说,亚稳态是指触发器(Flip-Flop)或其他数字电路元件无法在某个规则的时刻段内到达一个可承认的安稳状况。

发生原因:首要因为违反了触发器的树立和坚持时刻(Setup and Hold Time)要求。在时钟上升沿前后的特定时刻窗口内,假如数据输入端口上的数据发生改变,就会发生时序违规,然后导致亚稳态的呈现,如下图。

image

体现特征:在安稳期间,触发器或许输出一些中间级电平,或许处于振动状况。而且,这种无用的输出电平能够沿信号通道上的各个触发器级联式传达下去,导致整个体系的不安稳。

轿车芯片的牢靠性规划:操控亚稳态,提高安稳性 - 知乎

削减亚稳态影响:

亚稳态震动时刻(Tmet)关系到后级寄存器的收集安稳问题,Tmet影响要素包含器材的生产工艺、温度、环境等。

当Tmet1时刻长到大于一个采样周期后,那第二级寄存器就会收集到亚稳态,可是从第二级寄存器输出的信号便是相对安稳的了。因为寄存器自身就有减小Tmet时刻让数据快速安稳的作用,第二级寄存器的Tmet2的持续时刻持续延长到大于一个采样周期这种状况虽然会存在,可是其概率是极小的。在第三级寄存器时,数据传输简直到达稳态。

image

单比特信号从慢速时钟域同步到快速时钟域需求运用打两拍的方法消除亚稳态。榜首级寄存器发生亚稳态并经过自死后能够安稳输出的概率为70%~80%,第二级寄存器能够安稳输出的概率为99%左右,再多加寄存器的级数改进作用就不显着了,Verilog HDL程序如下。

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	rx_reg1 <= 1'b1;
    else	rx_reg1 <= rx;
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	rx_reg2 <= 1'b1;
    else    rx_reg2 <= rx_reg1;
end

always @(posedge sys_clk or negedge sys_rst)begin
    if(!sys_rst)	rx_reg3 <= 1'b1;
    else    rx_reg3 <= rx_reg2;
end

【接纳端处理逻辑】

在本篇中,通讯格局:开端位+8位数据+无校检+1位中止位。sys_clk为体系时钟(在这里仅作为时钟参阅)设置为50Mhz(20ns),异步通讯的波特率设定为9600Baud,则波特率计数器Baud_cnt最大值 = 1/9600x50_000_000 ≈ 5208。

bit_flagbit_cnt:位标志和位计数器,用于盯梢当时接纳到的位的数量和状况。rx_reg1, rx_reg2, rx_reg3:接纳寄存器,用于暂存接纳到的数据,rx_flagpo_flag:接纳和发送的标志,用于指示接纳或发送进程的状况。rxrx_data_out:接纳到的数据和输出数据。详细UART接纳端时序图如下。

image

数据流:start信号被触发时,UART开端接纳数据,并使能work_en信号,数据位(XData[0]XData[7])被接连接纳并存储在rx_reg1rx_reg2rx_reg3等寄存器中。在数据接纳进程中,Baud_cnt[12:0]bit_flagbit_cnt 用于确保数据以正确的波特率接纳,并盯梢当时位的状况。一旦一切数据位和中止位(Xstop)都被接纳,UART将rx_data_out设置为接纳到的数据,并或许设置rx_flag以指示数据已预备好。

根据时序图,接续完结其他类型信号时序程序逻辑:

always @(posedge sys_clk or negedge sys_rst)begin//处理start_flag逻辑
    if(!sys_rst)	 start_flag <= 1'b0;
    else if((rx_reg3 == 1'b1)&&(rx_reg2 == 1'b0)&&(work_en == 1'b0))start_flag <= 1'b1;
    else start_flag <= 1'b0;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理work_en逻辑
    if(!sys_rst)	work_en <= 1'b0;
    else if(start_flag)		work_en <= 1'b1;
    else if((bit_cnt == 4'd8)&&(bit_flag == 1'b1))	work_en <= 1'b0;
    else work_en <= work_en;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理baud_cnt逻辑
    if(!sys_rst)	baud_cnt <= 13'd0;
    else if((baud_cnt == BAUD_CNT_MAX - 1'b1)||(work_en == 1'b0))baud_cnt <= 13'd0;
    else 	baud_cnt <= baud_cnt + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理bit_flag逻辑
    if(!sys_rst)	bit_flag <= 1'b0;
    else if(baud_cnt == BAUD_CNT_MAX/2 - 1'b1)	bit_flag <= 1'b1;
    else bit_flag <= 1'b0;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理bit_cnt逻辑
    if(!sys_rst)	 bit_cnt <= 4'd0;
    else if((bit_cnt == 4'd8)&&(bit_flag == 1'b1))	 bit_cnt <= 4'd0;
    else if(bit_flag)	bit_cnt <= bit_cnt + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理rx_data逻辑
    if(!sys_rst)	rx_data <= 8'b0;
    else if((bit_cnt >= 4'd1)&&(bit_cnt<= 4'd8)&&(bit_flag))
        rx_data <= {rx_reg3,rx_data[7:1]};
end

always @(posedge sys_clk or negedge sys_rst)begin//处理rx_flag逻辑
    if(!sys_rst)	rx_flag <= 1'd0;
    else if((bit_cnt == 4'd8)&&(bit_flag))	rx_flag <= 1'b1;
    else 	rx_flag <= 1'd0;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理po_data逻辑
    if(!sys_rst)	po_data <= 8'd0;
    else if(rx_flag)	po_data <= rx_data;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理po_flag逻辑
    if(!sys_rst)	po_flag <= 1'b0;
    else	po_flag <= rx_flag;
end

齐备后,编写了一个简略的仿真程序,验证接纳的时序状况。从下图可知,三级寄存器顺次往后延迟了一个时钟周期,即20ns,这完结了方针希望,用于减小亚稳态影响,确保时序精确。
image

再看接纳rx信号线数据的处理状况,待一轮字符数据处理完结后,po_data得到了正确的串行输入数据。波特率计数器在计数到13’d5027后归零,等候使能信号拉高。

image

【发送端处理逻辑】

较于接纳端,发送端逻辑比较简略。pi_data :输入的8位数据信号,pi_flag:输入信号标志。Baud_cnt为波特率计数器。输入发送标志为高电平,发送端将预备的数据,按位计数输出到串行信号总线tx,顺次拉低信号线,发送开端标志+8位数据信号。比特计数器计数到4'd9拉低使能线,表明单个字符数据输出结束,拉高信号线标志中止至闲暇状况。

image

always @(posedge sys_clk or negedge sys_rst)begin//处理work_en逻辑
    if(!sys_rst)	 work_en <= 1'b0;
    else if((bit_cnt == 4'd9)&&bit_flag)	work_en <= 1'b0;
    else if(pi_flag)	work_en <= 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理baud_cnt逻辑
    if(!sys_rst)	 baud_cnt <= 13'b0;
    else if((baud_cnt == BAUD_CNT_MAX - 1'b1)||(!work_en))	 baud_cnt <= 13'b0;
    else if(work_en)	baud_cnt <= baud_cnt + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理bit_cnt逻辑
    if(!sys_rst)	bit_cnt <= 4'd0;
    else if((bit_cnt == 4'd9)&&(bit_flag == 1'b1))	bit_cnt <= 4'd0;
    else if((work_en == 1'b1)&&(bit_flag == 1'b1))	bit_cnt <= bit_cnt + 1'b1;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理bit_flag逻辑
    if(!sys_rst)	 bit_flag <= 1'b0;
    else if(baud_cnt == 13'd1)	bit_flag <= 1'd1;
    else 	bit_flag <= 1'b0;
end

always @(posedge sys_clk or negedge sys_rst)begin//处理tx发送逻辑
    if(!sys_rst)	 tx <= 1'b0;
    else if(bit_flag == 1'b1)begin
            case(bit_cnt)
            0   :tx <= 1'b0;
            1   :tx <= pi_data[0];
            2   :tx <= pi_data[1];
            3   :tx <= pi_data[2];
            4   :tx <= pi_data[3];
            5   :tx <= pi_data[4];
            6   :tx <= pi_data[5];
            7   :tx <= pi_data[6];
            8   :tx <= pi_data[7];
            9   :tx <= 1'b1;
            default: tx<= 1'b1;
            endcase
        end
end

齐备后,编写了仿真程序,验证发送的时序状况。检测到输入标志为高电平,work_en使能有用,波特率计数器开端计数,比特位计数器待其计数到13'd1时计数加1,这样防止比特错判。

image

从下面仿真图能够看到,tx发送输出的串行信号时序是与pi_data坚持一致的。

image

【全体验证UART】

首要,树立五组恣意字符数据,经UART发送端向UART接纳端转发。经过仿真程序进行剖析,因为接纳端与PC源数据比较,对数据的处理要迟后一个字符周期,即5208x20x10ns,从下图可得到,数据处理串行数据tran_data后坚持正确,而且输出数据out_data与源数据坚持一致,即可验证模块规划暂时是没有大问题。

image

最终,将UART接纳端和发送端模块实例化为文章最初的规划结构。在PC端发送恣意三组数据后,如下图COM11端口接纳数据而且正确,规划到此验证成功,满意希望。

image

文献参阅:

[1] 野火]FPGA Verilog开发实战攻略——根据Altera EP4CE10 征程Pro开发板 文档 (embedfire.com);

[2] FPGA中亚稳态——让你无处可逃 - 屋檐下的龙卷风 - 博客园 (cnblogs.com);

[3] ww1.microchip.com/downloads/en/DeviceDoc/70000582e.pdf;

[4]万敏. 异步时序电路中的亚稳态规划与剖析[D]. 上海:上海交通大学,2008.


本篇文章中运用的Verilog程序模块,若有需见网页左栏Gitee库房链接:憨大头的妙妙屋: 真美妙! (gitee.com)

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=260

标签: FPGA-Verilog类
分享给朋友:

“串口收发UART(Verilog HDL)” 的相关文章

rbenv:Ruby 多版别办理利器

rbenv:Ruby 多版别办理利器

在 Ruby 开发的国际中,常常需求面临不同项目运用不同 Ruby 版别的状况。这时,一个高效、灵敏且易于运用的 Ruby 版别办理东西就显得尤为重要。 rbenv 正是这样一个东西,它答应开发者在同一台核算机上轻松装置、切换和办理多个 Ruby 版别。本文将具体介绍 rbenv 的装置、根本运用...

关于Validation的办法运用

关于Validation的办法运用

acceptance验证 acceptance 是 Rails 中的一个验证器(validator),用于验证一个布尔类型的特点是否被承受。在表单中,一般会有一些复选框或单选按钮,用户需求勾选或挑选才干提交表单。acceptance 验证器用于保证这些复选框或单选按钮现已被选中或勾选。 当一个特点被...

母亲的回头

母亲的回头

写在前面 392 字 | 亲情 | 考虑 | 陪同 | 细节 | 情感 | 感受 | 体会 | 时刻 正文   等车。   我说,自己一个人就可以了,都等,空耗两个人的时刻。母亲不愿。   司机迟到了十多分钟。这过程中,母亲很着急。   我上了车。   母亲敲了敲司机的车窗。司机将窗摇下来,听见...

java开源项目,助力开发者高效编程的利器

java开源项目,助力开发者高效编程的利器

1. JavaGuide 提供了丰富的Java开源项目资源,包括框架、工具和教程等,灵感来源于 awesomejava 项目。你可以访问以下链接了解 2. CSDN 上有多篇文章介绍了基于Spring Boot的优质Java开源项目,涵盖了电商、微服务、支付、秒杀、博客、管理后台等多个...

有关go的短语,go的短语归纳大全初中

有关go的短语,go的短语归纳大全初中

1. Go ahead 请继续,往前走2. Go for it 尽管去做,试试看3. Go with the flow 顺其自然,随波逐流4. Go the extra mile 额外努力,做得更多5. Go out on a limb 冒险尝试,承担风险6. Go back to squ...

python和c语言的区别,深入探讨两种编程语言的差异

python和c语言的区别,深入探讨两种编程语言的差异

Python 和 C 语言是两种非常不同的编程语言,它们各自有不同的用途、设计理念和编程范式。以下是它们之间的一些主要区别:1. 类型系统: Python 是一种动态类型语言,这意味着你不需要在声明变量时指定它们的类型。Python 会在运行时推断变量的类型。 C 是一种静态类型语言,这...