简单组合逻辑——半加器
在前面两小节当中,我们设计并实现了简单组合逻辑中的多路选择器和3-8译码器。
那么本小节我们将使用 Verilog 语言描绘一个具有半加器功能的电路,同样使用的是简单组合逻辑,为什么要实现半加器功能呢?我们是想通过半加器引入我们的全加器,进而引入层次化设计的方法。
本小节的主要内容分为两个部分:第一部分是理论学习,第二部分是实战演练。
在理论学习部分,我们会讲解一下半加器的相关内容;在实战演练部分,我们会设计并实现一个半加器。
首先开始理论学习
文章目录
1 理论学习
半加器
加法器是我们数字电路中经常用到的一种基本器件,它主要用于两个数或多个数的相加。加法器又分为半加器和全加器:半加器电路是指对两个输入数据位相加,输出一个结果位和一个进位,它没有进位的输入,它是实现一位二进制数的加法运算电路;全加器是半加器的升级版,除了加数和被加数之外,还要加上上一级传进来的进位信号。
以上就是理论知识的讲解,下面进入实战演练。
2 实战演练
2.1 实验目标
首先搞清楚我们的实验目标:我们希望使用简单组合逻辑,实现一个半加器,功能怎么实现呢?
2.2 硬件资源
同样的,我们使用按键和 LED 灯。我们可以使用我们开发板上的 KEY1 和 KEY2 两个按键,作为两个加数,然后使用 LED 灯 D6,表示相加和的输出,然后使用 D7 表示进位的输出。
那么功能的实现方法已经明确了,接下来就正式开始我们的实战。
2.3 程序设计
首先要新建工程存放位置,新建一个文件夹,文件体系的建立我们已经设置了很多次,这儿应该是轻车熟路。
2.3.1 模块框图
文件体系建立完成之后,打开 doc 文件夹,然后新建 Visio 文件,打开 Visio 文件,开始我们的模块框图的绘制以及波形图的绘制。然后 取消 放大,添加我们的波形工具箱
首先是模块框图的绘制,那么输入信号有两个,就是两个被加数
输出信号也是有两个:一个是结果位,一个是进位。结果位用 sum 表示,进位用 cout 表示
2.3.2 波形绘制
2.3.2.1 真值表
模块框图已经绘制完成,下面开始设计我们的真值表
当两个按键都被按下时,输入的都是 0,两个 0 相加,结果位也是 0,进位也是 0;那么如果只按下 KEY1 松开 KEY2,就是 KEY1 输入的是 0, KEY2 输入的是 1,那么 0 和 1 相加,得到的结果位是 1,进位也是 0;如果只按下 KEY2,松开 KEY1,结果位也是 1,进位还是 0;如果两个按键都不按下时,输入的都是高电平 1,那么结果位就是 0,进位就是 1
下面就可以参照真值表进行波形图的绘制。
2.3.2.2 波形图
首先是两路输入信号,我们填充为绿色;然后是两路输出信号,我们填充为红色
下面就是参照着真值表进行波形图的绘制。用这个符号表示数据变化,为了方便绘制我们添加一个参考线,对它进行一个颜色的区分,然后变成虚线,将它拉长
两路输入信号初始值都是未知,用 X 表示。输入信号未知,得到的进位和结果位也是未知的
那么参照真值表的第一行:输入信号是 0,得到的结果位和进位也是 0。然后参照着真值表,继续进行波形的绘制
那么这样就完成了波形图的绘制。
2.4 代码编写
下面就开始参照着波形图进行代码的编写,首先来新建我们的 .v 文件
我们前面部分的章节它的内容是比较简单的,所以说波形图也比较简单,那么参照着波形图就可以很快的进行代码的编写。
首先是模块的开始,然后是模块名,然后是 端口列表
输入信号,然后是 输出信号,那么输入信号和输出信号之间,我们习惯隔开一行,这样在实例化的时候,方便输入信号和输出信号的区分。上面是输入信号,下面是输出信号输出信号的类型我们也使用 wire 型,因为后面我们使用 assign 语句对它们进行赋值
那么端口列表编写完成,接下来就开始对它们进行赋值。
我们使用 assign 语句,然后使用位拼接的方式,将进位放在高位,结果位放在低位,这样就完成了输出信号的赋值
将输入信号相加,相加之和的低位赋值给结果位,高位赋值给进位。
我们这里编写的代码比较简单,大家也可以使用其他的组合逻辑对他们进行赋值。
2.5 编译代码
我们对文件进行保存,然后回到桌面,建立我们的实验工程。下一步 文件命名 下一步 下一步,选择我们的芯片,这儿都已经是轻车熟路了
然后添加我们的 .v 文件,然后编译,查找语法错误,点击 OK
接下来可以查看一下 RTL 视图,点击这个位置,按住 Ctrl 并滚动鼠标滚轮可以对它进行缩放
我们可以看到,我们的代码应该是出现了错误,回到代码文件,更正后保存并且重新编译
我们的代码已经被综合成了一个加法器:ADDER
下面就是仿真验证。
2.6 逻辑仿真
找到我们的文件夹,找到 sim 文件夹,建立一个仿真文件,双击打开
现在就可以开始仿真文件的编写。
首先是时间参数,然后是时间单位、时间尺度,然后是模块、模块名、端口列表
然后定义两个模拟输入信号,然后定义两个 wire 型的输出信号
下面就是我们的输入信号的初始化,使用 initial 语句
然后是模 2 取余法
然后是模块的实例化
然后将信号相连接
同样为了便于观察,使用一些系统函数。
仍然使用 initial 语句,首先是时间格式的设置,这个我们也已经编写了很多次了,大家应该很熟悉了,然后是纳秒、小数位数,然后单位,然后是打印字节数
这样时间格式就编写完成,开始监测函数
那么这样,监测函数也已经编写完成,对文件进行保存
然后回到我们的实验工程,添加我们的测试文件
然后进行仿真设置
然后开始仿真
那么编译通过了,现在可以开始仿真。
我们可以找到我们的 sim 选项卡,把我们的被仿真模块添加到波形当中,选中它,可以使用快捷键 Ctrl+W,然后将它的波形添加到波形窗口,然后使用 Ctrl+A 进行波形的全选,然后使用 Ctrl+G 可以进行分组,然后点击左下角这个位置,可以进行路径的屏蔽
我们在这儿再教大家一些 ModelSim 使用的一些技巧,比如说我们意外的关闭了这个波形窗口,怎样把它调出来呢?我们可以使用 View,然后在我们这个位置 勾选,我们的波形窗口又重新回到了界面
我们再添加我们的模块,选中它使用快捷键,然后对它们进行分组
我们还可以点击右上角这个位置,将它单独拉出来,然后再次点击这个位置又可以把它锁定回去
如果说你的 ModelSim 界面,因为你的误操作发生了混乱,我们可以把它们初始化,点击这个位置,然后选择 Reset,它就会回到最初的模样,我们可以选择任意窗口的界面,点击它们右上角的 +,就可以把所有的选项卡放在下面,这样方便操作,而且更加清晰
接下来开始波形的查看,我们使用 Restart 清除所有的波形,然后输入参数 100us,然后运行一次
进行全局视图,添加我们的参考线,然后以参考线为中心进行放大,下面将我们的仿真波形与我们绘制的波形图进行比较
我们任选一个位置,比如说这个位置,输入信号 1 是高电平,输入信号 2 是低电平,结果位就是 1,进位是 0,这种情况与我们波形图中这种情况是对应的
然后我们再选取一个位置,比如说这个位置,两个输入信号都是高电平,结果位是低电平,进位是高电平,与这个位置对应了
然后查看打印列表,将打印列表与我们的真值表进行比对。我们随便选择一组数据,选择这一组。输入信号 1 为高电平,输入信号 2 为低电平,那么结果位是 1,进位是 0 与真值表之中的这个是对应的
再随便选取一组数据,比如说这个位置,那么输入信号 1 和输入信号 2 都是高电平,结果位是 0,进位是 1,那么与最后一行是对应的
仿真波形与我们绘制波形图是一致的,而且打印列表与真值表也是一致的,所以说仿真验证通过。
那么下面就可以进行上板验证
2.7 管脚绑定
上板验证之前是管脚的绑定。我们在我们的实验工程中,点击这个位置,绑定我们的管脚,那么进位是与 D7——LED 灯相连,它与 FPGA 的物理连接是 M6,点击回车;那么按键 1 是 M2 回车,按键 2 是 M1 回车;然后结果位是 L7 回车,这样管脚绑定完成
进行一次全编译,编译完成之后有 7 个警告,我们点击 OK
2.8 上板验证
按照下图所示,连接我们的板卡与下载器还有电源,下载器的另一端连接电脑,我们为它上电
点击工具栏上的 Programmer 图标,选择 Add File…(添加文件),找到 output_files 文件夹,选择我们的 led.sof 文件,点击 Open,点击 Start(开始),文件下载完成
程序下载完成,我们打开摄像头
当按键 KEY1、KEY2 都没有被按下时,它们输入的都是高电平,那么结果位就是 0,进位就是 1,表示结果位的 LED 灯被点亮;如果说按下按键 KEY1 或者按下按键 KEY2,它们两者之中有一个是高电平,有一个是低电平,那么结果位就是高电平,进位就是 0,所以说表示进位的 LED 灯被点亮;如果 KEY1、KEY2 两个按键同时被按下,这就表示输入信号都为 0,那么进位也为 0,结果位也为 0,所以说两个 LED 灯都被点亮
半加器 上板验证
那么上板验证通过
参考资料: