孩子都能学会的FPGA:第五课——用计数器实现UART协议的发送模块

(原创声明:该文是作者的原创,面向对象是FPGA入门者,后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门作者不光让大家知其然,还要让大家知其所以然!每个工程作者都搭建了全自动化的仿真环境,只需要双击top_tb.bat文件就可以完成整个的仿真(前提是安装了modelsim),降低了初学者的门槛。如需整个工程请留言(微信Blue23Light),不收任何费用,但是仅供参考,不建议大家获得资料后从事一些商业活动!

到目前为止,笔者讲的最多的模块就是计数器,读者可能都听的厌烦了。笔者之所以一直强调计数器,就是因为计数器是FPGA开发中的最基本的模块之一,能真正掌握了这个模块,并能把这个模块如乐高积木一样进行简单的拼搭,就可以实现复杂的功能。下面我们只是用两个计数器来实现uart的单byte发送。

讲述设计之前,先介绍一下uart协议。通用异步收发器(Universal Asynchronous Receiver/Transmitter),uart是一种通用串行数据总线,用于异步通信,该总线双向通信,可以实现全双工的发送和接收。uart在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。

由于uart采用异步通信方式,即发送端和接收端之间通过数据线进行数据传输,没有同步时钟。在异步通信中,发送端和接收端不需要同时处于激活状态,而是通过起始位停止位来标识数据帧的开始和结束。下面具体的解释uart协议的几个概念。

空闲位:uart的发送和接收线在空闲状态下是逻辑1,高电平

起始位:线上发出一个逻辑0,即低电平的信号,表示数据传输的开始;

数据位:紧接着起始位之后。 可以是5~8逻辑0或1 ,构成一个字符。从最低位开始传送,靠波特率进行定位。

奇偶校验位:在数据位加后,使得逻辑1的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。奇偶校验位可有可无。

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

波特率:是控制数据传输速率的,表示每秒钟传送的位数。常用的波特率有9600,115200等等。

本节FPGA工程的要求是:系统时钟是100MHz,低电平复位,实现uart发送,其中波特兰是115200,8个数据位,没有奇偶校验位,1个停止位。

分析一下需求,一次uart的传输是1个起始位,8个数据位和1个终止位,即一次传输需要10位。波特率是115200,系统时钟是100MHz,那传输1位需要的计数值是100_000_000/115200≈868。所以uart的发送设计就很明确了,需要两个计数器,一个计数器用于控制发送1位数据,计数868次;一个计数器用于控制发送10位数据,计数10次。

如下所示,设置了一个传输标志寄存器send_domain,当有新的数据要传输时拉高,当一次10位的传输完成后拉低;byte_cnt计数器用于计数10位数据的传输,非传输状态下清理即可;bandrate_cnt计数器用于计数1位数据传输的计数值,从0计数到867。

下面分析uart_byte_tx模块。输入信号clk和rst_n是时钟和复位。输入信号din_en是输入有效指示信号,当din_en信号拉高的时候表明输入的数据信号din有效,即要开始一次uart的发送。输入信号tx_signal即uart的输出线,输出tx_over信号用于指示一次uart传输完成。

然后定义了一次传输位数的计数值,一位传输的计数值。定义了wire类型的信号one_byte_cnt_done,用于指示1位传输完毕,拉高一个100MHz的时钟周期,用于计数器bandrate_cnt的清零;定义了wire类型的信号all_byte_cnt_done,用于指示1次uart传输完毕,用于计数器byte_cnt的清零,会拉高1位的时间。

传输标志寄存器send_domain,有新的数据要发送时拉高,一次uart传输完成拉低,有这个信号的好处是其它的控制信号都在send_domain高电平的时候变化,在send_domain低电平的时候清零或者默认值即可。

下面是两个计数器的实现,都是在send_domain拉高的时候变化,其中byte_cnt是在bandrate_cnt完成一次计数后加1,其它的清零和计数条件都很明显。

计数器都是设计好了,最后把要发送的数据在send_domain拉高的时候发出去即可,这而其实也可以用if/else if语句来实现,甚至用流水灯的移位也可以实现,只不过用case语句更直观明了而已,这儿的设计是因人而异的。

最后设置一次uart发送完成标志信号即可。

仿真是产生8bit的随机数,完成一次uart的发送就会产生一个新的随机数。仿真结果如下所示,以仿真图中的要发送的数据00100100为例,数据先发低位,加上起始位和终止位,tx_signal要发送的数据应该是0_00100100_1,仿真图中的tx_signal信号确实符合要求。

通过上面的讲解,是不是只需要两个简单的计数器就实现了uart的发送?所以FPGA的开发没有那么困难,把基本的模块合理的组合一下,这种功能就实现了。既然uart的发送设计如此简单,那uart的接收也应该不难,也是仅仅需要两个计数器即可,我们下课来实现。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值