实验解析¶
接下来,让我们用刚学习的知识来分析实验的设计。
点亮数字人生¶
题目要求显示三个数列:从 0 到 9、从 1 到 9 的奇数数列和从 0 到 8 的偶数数列。
这个实验主要是考察组合逻辑和时序逻辑的应用。
由于这里的数列显示输出是内部状态,所以应该用寄存器来分别保存三个数列的当前取值,也就是用 时序逻辑 。在时序逻辑中,所有的更新都应该在时钟上升沿。在上升沿的时候,如果数列要取下一项,就根据当前的结果,计算出下一个结果。为了解决溢出的问题,可以用 if
来实现。
最后,为了要输出到不带译码的数码管上,要在 CPLD 内部实现译码。译码的输出完全取决于输出,因此是 组合逻辑 。考虑到这里的输入情况从 0 到 9 比较多,可以用 case
语句来实现。在组合逻辑中,所有的情况下输出信号都要有取值,因此不要忘记 case
的 default
情况。
四位加法器设计¶
题目要求实现一个四位的加法器。
这个实验主要是考察组合逻辑和模块化编程的应用。
本题比较特殊,要求同学例化半加器来实现全加器,再用全加器来实现一个四位的加法器。在这里,半加器和全加器就是子模块,因此我们要先编写子模块,再用子模块实现最后的四位加法器设计。
这个题目里,输出完全由输入决定,因此是 组合逻辑 。半加器比较简单,按照真值表可以推导出表达式。把两个半加器拼起来,就可以得到全加器。把四个全加器拼接起来,就可以得到四位加法器。
计数器设计¶
题目要求显示两位数的计数器。
这个实验主要是考察组合逻辑和时序逻辑的应用。
遇到计数的问题,首先要考虑到 时序逻辑 ,因为需要保存内部状态。第一个想法是直接用一组寄存器来保存整个计数,然后输出的时候,再使用 组合逻辑,采用除法和取模的方式把十位数和个位数取出来。但是在硬件上,我们要避免除法和取模的操作,因为其面积消耗比较大,延迟也比较大。
考虑到这里每次计数器只会加一,那么可以把个位数和十位数分别存储,当个位数要溢出的时候,再对十位数加一。这样就免去了除法和取模的操作。
最后,输出的时候,要将数字译码为数码管的输出,这时候就可以用前面实验编写好的译码器。这就是模块化设计的好处。
串行密码锁¶
题目要求实现一个密码锁。
这个实验主要是考察组合逻辑、时序逻辑和状态机的应用。
首先要分析,内部需要存储哪些东西,这样就知道哪些是 时序逻辑,哪些是 组合逻辑。首先,肯定要保存密码,还有当前正在输入的密码,由于密码输入是一位一位输入的,还需要记录当前输入密码的进度,还有目前是解锁还是失败的状态。具体实现的时候,可以用状态机来记录当前输入密码的进度,例如正在输入的是第一位密码、正在输入的是第二位密码、密码错误、成功解锁等。
进一步思考,这里的输出比较简单,因此除了寄存器之间的组合逻辑,没有额外的从寄存器到输出、从输入到输出的组合逻辑。所以如果你发现写了很多逻辑,却没有出现时钟的时候,可能就说明实现出了错误。
最后,这个题目要求在复位的时候,根据不同的输入设定不同的复位值,这个功能在编写的时候,在 FPGA 上可能会因为复位不是常数而产生锁存器(latch)。这个问题可以通过换一种写法来解决。