基本门电路的verilog实现

293 阅读8分钟

这一节来介绍一下基本门电路的实现,首先看一下最基本的与非门。

与非门特性是跟与门相反,与门是当A B输入为1的时候输出为1其他情况输出为0,而与非门正好相反,当A B输入为1的时候输出为0其他情况输出为1。

我们可以使用继电器来实现,如下图,当左边的两个开关闭合的时候,相当于A B输入为1,两个弹片都被拉下来,那么灯泡这边输出的是0,灯会变灭,其他A B的输入情况总有一个弹片没有被拉下来,那么这时候电源跟输出导通,输出的就是1,灯亮。

也可以使用晶体管来实现,如下图,它由两个NMOS管串联跟两个PMOS管并联构成,NMOS管是当gate输入高电压的时候导通,PMOS管是当gate输入低电压的时候导通,

这两个NMOS管它的源极是接地输入的是0,这两个PMOS管它的源极是接电源的所以输入的是1,右边Y是输出。(不清楚晶体管特性可以看上一篇文章:计算机系统概述)

我们来推导一下,当A B都为1的时候那么两个NMOS管是导通的,所以它们的输出就跟接地是一样,输出的是0,然后当A B为1的时候,两个PMOS管是没有导通的,所以它们的输出对最终的输出Y就不会产生影响,那么输出就是0。

其他情况就是当A B其中一个为0的时候,那么这两个PMOS管总有一个是导通的,那么Y输出的就是1,然后当A B其中一个为0的时候,那么这两个NMOS管总有一个是不导通的,所以它们的输出就不是通的,那么对最终的输出Y就不会产生影响,所以输出最终是1。

除了与非门,还有其他的一些门电路,与(AND),或(OR),非(NOT),或非门(NOR),异或门(XOR),我们稍微在这里记一下这些门电路的符号,我们后面会直接使用符号。

与非门就是在与门后面加一个圆圈,或非门是在或门后面加一个圆圈,

或非门特性是跟或门正好相反,或门是当A B其中一个为1的时候输出为1,其他情况输出0,而或非门正好相反,当A B其中一个为1的时候输出是0,其他情况输出为1。

异或门是在或门前面加一个半圆,异或门的特性是当A B相同时输出为0,当A B不同时输出为1。

这些基本的门电路都可以使用与非门来构造,我们稍后会看到。

那我们这里思考一下,为什么两个输入0 0能够输出1呢,输入0就代表没有电流,输出1就代表有电流,那么两个输入都没有电流怎么会凭空产生电流呢?

最早之前设计电路都是通过焊接的方式把多个晶体管连接起来,如果晶体管的数量比较少,几百个,几千个这样做还可以实现,但现在CPU中有几十亿个晶体管,如果还采用这种方式就不太现实。

所以现在设计电路跟设计软件一样都使用编程语言来设计,然后把语言再转换成实际的硬件电路,那么设计硬件电路的语言被称为硬件描述语言HDL。

常见的HDL有verilog跟VHDL,我们会使用verilog来设计电路,下面就是verilog例子,首先定义一个模块test,定义输入a,b,c和输出sum,然后在模块内部使用门电路的组合来描述这个模块的结构,

在verilog里面语句的前后顺序是没有关系的,它只是描述这些门电路之间是怎么连接的,比如下面的代码,g1这个异或门,它的输入是a b输出是s1,g1是连接到g4这个与门的,g1的输出s1作为g4的输入,然后g4是连接到g5的,g4的输出c2是作为g5的输入,所以你去改变这些语句的前后顺序是不会去改变这种连接顺序的。

除了使用这种门电路来描述,还可以使用更高级的语言,类似c语言的语法来描述,这样你编写代码效率就会更高一些,但是这种c语言的描述最终也是转换成门电路的描述形式。

因为我们主要是学习原理,并且我们设计的CPU也不复杂,所以我们只会使用门电路来描述。

verilog代码编写完成以后我们可以使用仿真软件模拟电路的运行情况,验证电路的正确性,我们会使用iverilog这个比较轻量级的软件来仿真验证,通过sudo apt-get install iverilog安装。

仿真验证完成以后我们就使用综合器把verilog代码转换成实际的电路表示,也称为网表,然后烧写到FPGA开发板中去验证,从而检查我们的代码是否有正确的转换成硬件电路的结构和行为,是否满足实际的需求和性能要求。

FPGA的全称是现场可编程门阵列,也就是说它可以通过编程来改变硬件的结构,一般电路在设计好以后就不能再改变了,除非你手动再去焊接,那么这就不叫可编程了。

比如下面的电路,当a b c输入为0的时候,它经过一些门电路输出为0,那么设计好以后你就无法再去改变这个逻辑,

而FPGA是基于一种查找表的结构,叫做LUT, LUT本质上是一个RAM,RAM的内容是可以修改的,可以通过地址来寻址,我们可以把a b c的输入比如都输入0作为RAM的地址,

下图在000这个地方存储的是0,那么它输出out就是0,然后我们可以改变000这个地址存储的值,把它改成1,那么它输出就是1。

前面通过verilog转换成的网表就是下载到LUT中,去配置LUT里面的内容,这样我们就可以在不改变硬件焊接结构的情况下去实现不同的逻辑,然后我们把多个LUT跟寄存器组合起来叫做CLB,再把多个CLB组合起来构成的就是FPGA内部的大致结构。

我们看怎么使用verilog来实现与非门,首先定义一个与非门的模块Nand,定义输入是a b输出是out,

它有两个NMOS管串联跟两个PMOS管并联构成,看代码第1个NMOS管它的gate输入是b,源极接地所以输入是0,然后输出是o1,第2个NMOS管它的gate接的是a,源极是上一个NMOS管的输出o1,然后输出是out,

这两个PMOS管它的gate分别接的是a b,然后源极接的是电源,所以输入的是1, 输出的是out。

然后对每一个模块,我们都要定义一个对应的测试模块如下面的nand_tb.v,在测试模块首先include被测试的模块nand.v,定义输入值a b,然后调用被测试的模块,

上面的测试代码就模拟了不同的时间阶段,把a b设成不同的值,初始的时候a b是0,过10个时间段,可能是10毫秒10纳秒,把b的值设成1,再过10个时间段把a设成1 b设成0,然后$monitor就是监控输入和输出的值,当a b out其中一个值发生变化的时候就会打印出来。

我们使用iverilog编译运行一下,这里要编译测试模块,测试模块会调用被测试的模块,看一下在不同的输入情况下,他的输出是否是满足与非门的特性。

然后其他的门电路都可以使用与非门来实现,比如下面这个与门and gate它就是有两个与非门来连接,第一个与非门的输入是A B输出是AnandB,然后第一个与非门的输出作为第二个与非门的输入,第二个与非门的两个输入都是AnandB然后输出是out。

实现完成就编译验证一下,每个模块它都会有一个对应的测试模块,然后其他的模块大家就可以自己去实现一下,就根据上面的电路描述去实现一下也不会太难,

这里只是说这些门电路可以使用与非门来实现,实际中也可以使用更少的晶体管来实现,比如下面这个非门就可以使用两个晶体管来实现。

觉得不错点赞关注一下,跟我一起学习计算机科学!

CS入门指南:手写操作系统,数据库,TCP/IP协议栈,GUI库,编译器