孩子都能学会的FPGA:第四课——组合逻辑和时序逻辑

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

上课讲了阻塞赋值和非阻塞赋值,很多人可能会有疑问,为什么要分阻塞赋值和非阻塞赋值,合并成一种赋值不可以吗?这不是增加了开发的难度吗?说实话,还真的的不能合并,因为学习过数字电路的人都知道,数字电路的根据触发器有没有时钟可以分为组合电路和时序电路,那对应到FPGA开发上就是组合逻辑和时序逻辑,说白了FPGA的开发就是组合逻辑和时序逻辑的开发,大家去看看所有的FPGA工程,都是组合逻辑和时序逻辑的有机组合。下面详细的介绍这两种逻辑。

组合逻辑,反应在硬件电路上就是没有时钟的锁存和控制,组合电路任意时刻的输出仅仅取决于当前时刻的输入,与电路原本的状态无关,就是组合电路没有任何的记忆功能。可以把组合电路想象成《水浒传》中的李逵,无组织无纪律,李逵的行为(输出)只与当前的环境(输入)有关,根本不去管出发前宋江大哥的命令(以前时刻的输入),所以李逵才会惹出来那么多的麻烦来。组合逻辑的这种性质,注定了要用阻塞赋值来实现,因为阻塞赋值不消耗仿真时间,当前输入的变化马上反应到输出的变化,所以阻塞赋值就是为组合逻辑量身定制的!

时序逻辑,反应在硬件电路上就是有时钟可以进行锁存和控制,时序电路任意时刻的输出不仅取决于当前时刻的输入,而且还和电路原来的状态有关,就是时序电路是有记忆功能的。可以把时序电路想象成《水浒传》中的108将,上梁山前大家各自为战,但是上了梁山就要统一行动听指挥,不能私自行动,就像李逵私自下山就要受到惩罚。时序逻辑的性质,决定要用非阻塞赋值来实现,因为非阻塞赋值是让所有的寄存器在特定的时刻统一变化,其它时刻大家保持当前的状态即可。

大家常用照镜子来比喻用阻塞赋值实现组合逻辑,只要你站在镜子前面,镜子里面马上就可以出现你的样貌,但是只要你离开镜子,镜子里面马上就没有了你的样貌。常用手机拍照来比喻用非阻塞赋值实现时序逻辑,比如自拍,只有按了拍照按钮,你的样貌才会被保存成图片,当前图片可以保存到下一次按动拍照按钮为止,图片就会更新为新的一副图片,在这期间,无论你的表情和动作如何变化,图片上的内容都不会变化。

下面我们用实例来说明,还是用第二课的流水灯为例说明,当时我们把one_second_done信号定义成了wire,然后用assign进行赋值(为了快速仿真SYS_CLK设置为10),这就是阻塞赋值,实现的就是组合逻辑。

添加图片注释,不超过 140 字(可选)

看看仿真结果,在one_second_cnt由8变化成9的时刻one_second_done拉高,在one_second_cnt由9变化成0的时刻one_second_done拉低,就是one_second_cnt的变化马上会引起one_second_done的变化。

添加图片注释,不超过 140 字(可选)

阻塞赋值的信号一定要定义成wire类型吗?其实不是的,也可以定义成reg类型,不过实现组合逻辑的方式要改变一下,如下所示。@(*)的意思是模块中所有信号的变化都是同时引起one_second_done的变化。

添加图片注释,不超过 140 字(可选)

仿真结果和用assign的仿真结果是一样的,如下所示。

添加图片注释,不超过 140 字(可选)

那one_second_done可不可以用时序逻辑来实现,在本例中是可以的,修改FPGA程序如下:

添加图片注释,不超过 140 字(可选)

然后再看看仿真解决,比较一下和组合逻辑实现的有什么不同。如下所示,结果很明显,计数器one_second_cnt多计数了一次,计数器one_second_cnt是10的时候one_second_done才拉高。具体分析一下,时序逻辑的计数器one_second_cnt由8变成9是在clk上升沿再往后Δt的时间,就是在clk上升沿的时候计数器的值还是8,所以此时one_second_done不会拉高。计数器one_second_cnt由9变成10是在clk上升沿再往后Δt的时间,就是在clk上升沿的时候计数器的值还是9,所以此时one_second_done才会被拉高!one_second_done拉低也是相同的分析思路。

添加图片注释,不超过 140 字(可选)

从功能上分析,上面的FPGA程序其实是错误的,本来预期的是每计数10次one_second_done拉高一次,现在变成了每计数11次one_second_done拉高一次,所以在时序逻辑中,要把修改计数的值,才能保证功能的正确,如下所示。

添加图片注释,不超过 140 字(可选)

在看看仿真结果,功能就是正确的了。

添加图片注释,不超过 140 字(可选)

大家可能会说,你口口声声说要大家尽快入门FPGA,但是连续几课只讲计数器和流水灯,要是别人早就讲到各个IP的设计了。我想说的是:开始慢一点,是为了后面的快一些!下课让大家看看仅仅使用计数器就可以实现UART的协议!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值