Loading

数字电路

数字电路

通过晶体管实现0和1

数字电路是用来处理数字信号的电路, 而数字信号简单来说是指0和1这两种离散的信号.

数字信号与晶体管有关.常用的晶体管是金属-氧化物-半导体场效应晶体管 (Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET), 简称MOS管. MOS管可以分nMOS(N型MOS)和pMOS(P型MOS)两种, 两者均有三个接口.

晶体管可以理解为一个开关,连接了左右两级: 源极(source)和漏极(drain). 中间的栅极(gate)可以理解为开关, 只不过是通过电压来控制左右两级是否连通.

image

image

以nMOS为例, 根据其电气特性, nMOS的功能如下:

  • 当栅极电压与源极电压之间的差值()较大时, 源极和漏极导通, 相当于开关合上
  • 当栅极电压与源极电压之间的差值()较小时, 源极和漏极截止, 相当于开关断开

pMOS的电气特性和nMOS相反, 较大时截止, 较小时导通.

nMOS和pMOS具有两种互补的电气特性, 在半导体设计中, 通常将两者联合使用, 称为CMOS(Complementary Metal-Oxide-Semiconductor)技术.

image

当在A点通了高电压,则下方nMOS导通, 上方pMOS截止, 相当于Y接地,表示为0.

当在A点通了低电压,则上方pMOS导通, 下方nMOS截止, 相当于Y链接了电源, 表示为1.

(如下图)

image

image

通过上述条件我们把物理开关两种逻辑转换成了电压的高低.

将物理上的高电压(如)定义为逻辑1(高电平), 低电压(如)定义为逻辑0(低电平)

这就得到了数字电路中的两种基本状态.

通过晶体管搭建门电路

非门

非门, 也称为反相器. 我们会发现刚才所演示的晶体管结构图.

传输门由一对n管和p管并联组成, 其晶体管结构和电路符号如下图所示.

image

image

如何看呢?
直接看下方, 接入0则断开, 接入1则看作导线.

......

此处省略其他的了

从真值表到逻辑表达式(与或式)

有了真值表, 我们可以得到相应的逻辑表达式, 相应步骤如下:

  1. 根据输入情况描述一个表项. 对于真值表中的每个表项, 考虑每个输入信号, 若输入为1, 则取输入信号本身; 若输入为0, 则取输入信号的非. 对这些信号进行与运算, 即可得到该表项的描述. 例如, 表中A = 1, B = 0的对应描述是A & ~B.
  2. 将输出为1的表项的对应描述组合成最终的逻辑表达式. 考虑真值表中输出为1的表项, 对这些表项的描述进行或运算即可. 例如, 在异或运算的真值表中, 输出为1的情况有两种, 一种是A = 1, B = 0, 对应描述是A & ~B; 另一种是A = 0, B = 1, 对应描述是~A & B. 将这两种描述进行或运算, 得到异或运算的逻辑表达式Y = A ^ B = (A & ~B) | (~A & B).

上述步骤总是可以将一个真值表转换为一个由与运算和或运算组成的逻辑表达式. 根据这个逻辑表达式, 你可以很容易地用与门和或门搭建出相应的电路.

卡诺图化简(考试时候单独学一下)

以下是ysyx教材中的说法:

卡诺图化简

你可能会在一些数字电路的教科书上听说过这个技术; 如果你没有听说过, 那很好. 你可能需要为了考试而学习它, 但在"一生一芯"这种面向动手实践的项目中, 你几乎不会使用它.

我们想说的是, 这个技术的可扩展性非常低: 在真实的项目中, 你面对的变量数量很可能是5个以上, 甚至多达十几个, 要用卡诺图去化简这样的表达式, 效率是很低的. 事实上, 现代工具通常会采用QMC算法或者espresso算法来对逻辑表达式进行化简, 因此, 你很少需要对逻辑表达式进行手动化简, 上文介绍的方法已经足够帮助你写出一个正确的逻辑表达式, 化简的工作交给现代工具即可. 如果你感兴趣, 你可以搜索相关资料来进一步了解这些算法.

寻找更优的搭建方案搭建XOR gate

考虑使用其他门电路来搭建异或门, 尝试寻找一种晶体管数量最少的方案来实现异或门, 并在Logisim中测试你的方案是否正确.

有一种方案只需要使用14个晶体管, 因此最优方案的晶体管数量应不多于14个.

设计的第一版本异或门, 22个晶体管:

image-20261005214753592

这里距离题目给出的14个以下差太多了, 于是想有没有更简便的方式.

既然叫异或, 不妨从他的第二种理解方式来设计,以或门为基地,只改变它``1||1`的时候的结果或许会好很多.

设计的第二版本异或门, 20个晶体管:

image-20261005214731493

这里直接把下面的与非逻辑改成与非门(4个晶体管), 直接变成了16个晶体管:

image-20261005215200656

但这还是差很多, 还有没有可优化的空间了呢?

我尝试问了AI, 发现他给我的答案其实我早就探索出来了, 也就是从方案2->3的这种方式.
如何更进一步呢?

答案就是化简, 通过对当前逻辑表达式两次取反然后德摩根律化简,尽量做出更多的与非门/或非门 从而减少晶体管数量.

化简

当前的表达式为:!(A||B) && !(A && B)

最终化简后为: !(!(A || B) || (A && B))

刚好14个晶体管!!!

image-20261005222908148

搭建同或门

半定制电路思路

直接把之前搭好的异或门最后面的或非门换成或门即可:

image-20261006182525131

全定制电路

image-20261006182618102

上图是讲义中实现的异或门, 我们只需要将所有结果反转即可.

但是有限制要在6个晶体管之内, 所以排除了直接加个非门这种操作.

我想到可以直接减少一个非门, 或者是反转, 只需要将左边的非门挪到A的另一条上面的导线上即可反转结果.从而实现了同或门

全定制电路/半定制电路

半定制电路

基于常用标准单元/FPGA

相对于全定制电路来说, 成本低.

门电路的面积评估

门电路的面积可以大致用所需晶体管的数量近似表示. 但如果要考虑 对等设计原则 则会有所不同.

为了避免整个电路设计不满足对等设计原则, CMOS电路的设计者采用另一种思路: 让门电路满足对等设计原则. 这样, CMOS电路的使用者在用门电路去搭建更复杂的电路时, 就只需要关心门电路的逻辑功能, 而不必过多关心门电路的电气特性.

考虑对等设计原则的门电路面积评估

一句话来说就是: 充电回路与放电回路在最恶劣工况下的等效导通电阻, 必须小于或等于基准反相器的导通电阻(即充放电电流能力不低于反相器), 不足时需按串联倍数加宽沟道(并联晶体管).

image

一般来说, 考虑到可疑的串联电路即可考虑对等设计原则的门电路所需的晶体管数量. 如上图, P1 P2 并联, 从 Vcc -> Y 只经过一个晶体管, 电压降等同于一个反相器的压降. N1 N2 则形成了串联电路, 因此我们需要把他们分别用两个NMOS并联来代替, 使得电阻变为原来的1/2.

晶体管的数量: #T(nand) = #T(P1) + #T(P2) + #T(N1) + #T(N2) = 1 + 1 + 2 + 2 = 6

同样的, 可以得到 其他基础门电路考虑对等设计原则的晶体管数量.

如何考虑?

这里说一下我的理解:

正常的电路, 只需要分析 充电回路 放电回路即可.

这种则加上分析到可供电的输入端的充电回路, 然后看有无可以的串联回路, 分析是否不符合对等设计原则? 然后优化.

考虑从两个层次搭建N输入与非门的方案

对于多输入的门电路来说, 如果用晶体管来搭建, 其面积和输入数量呈二次关系;

如果用二输入门电路来搭建, 其面积和输入数量呈线性关系.

虽然后者的方案面积更优, 但其延迟也更大. 在一些要优化延迟的场合, 反而会选择面积更大的设计方案.

进位计数法

2进制转10进制

通常, 对于位进制数, 其真值可通过以下加权求和展开式得到:
$$
\sum_{i=0}^{n-1} a_i b^i = a_{n-1} b^{n-1} + a_{n-2} b^{n-2} + \cdots + a_1 b^1 + a_0
$$

其中$b$称为基(base), $b^i$称为每一位的权(weight).

二进制同样可以这样表示, 只需要写出加权求和式, 然后运算即可得到10进制的真值.

10进制转2进制

可以得知 按上面的展开式来看, 一个二进制数字的每一位都是 $a_{n-1}$~ $ a_0$ 排列.

那么只要求出来这些数就好了.

方法:

只需要把对应的10进制数短除法除以2, 然后余数反向写开即可得到对应2进制数.

2 | 46   -> 0          ^  低位
  +----                |
 2 | 23   -> 1         |
   +----               |
  2 | 11   -> 1        |
    +----              |
   2 | 5    -> 1       |
     +----             |
    2 | 2    -> 0      |
      +----            |
     2 | 1    -> 1     |  高位
       +----
         0 (商为0, 结束)

十六进制计数法

2进制表示虽然机器更容易处理, 但人却不好运算, 于是计算机领域通常也用16进制来表示数.

通常来说 一个16进制数可以用4位2进制数来表示,

例如二进制数0b1011111011101111可以表示为0xbeef更加简洁紧凑.

     1011 1110 1110 1111
      |    |    |    |
      b    e    e    f

八进制(octal)计数法

八进制转十进制

这里以0123为例先写出加权求和式:
$$
\sum_{i=0}^{2} a_i 8^i = 1 \times 8^2 + 2 \times 8^1 + 3 \times 8^0
$$
计算得83

十进制转八进制

继续以83为例:

短除法除以8, 然后倒序写每一步的余数即可得到123

八进制转二进制

最开始想到的是先转十进制再转二进制. 感觉太麻烦了, 肯定有更好的方式.

最直接、最标准的方法是“一位拆三位”直接映射法。因为 8=23,八进制的每一个数字码(0~7)恰好天然对应 3 位二进制数。

这里还是以0123为例:

    1    2     3
   001  010   011
   
   0b1010011
   

得到结果0b1010011

二进制转八进制

那么就和之前一样了, 直接从右到左每3位一组, 然后直接写就好了:

0b1010011
001 010 011

1 2 3
得到答案123

通过门电路搭建基本组合逻辑电路

译码器

译码器(decoder)是一种将k位输入转换成最多 $2^k$ 种不同输出的电路. 其行为如下: 将输入解析为一个二进制数值x, 并使输出的第x位为1, 其他位为0. 由于该输出仅有1位为1, 因此也称为"独热码"(One-hot).

2-4译码器

真值表如下

A1 A0 Y3 Y2 Y1 Y0
0 0 0 0 0 1
0 1 0 0 1 0
1 0 0 1 0 0
1 1 1 0 0 0

搭建2-4译码器(如何画出该译码器的电路图?)

求出逻辑表达式(与或式):

Y0 = !A1 && !A0
Y1 = !A1 && A0
Y2 = A1 && !A0
Y3 = A1 && A2

image-20261007132905498

位宽越高, 需要的晶体管数量会指数级增长, 所以不宜用位宽过大的译码器.

译码器的扩展

通过用已经搭建好的2-4decoder 作为子电路搭建 3-8decoder如下:

image-20261007162811802

思路是这样的,

  • 刚开始想到输出位宽是8, 刚好需要两个2-4 decoder, 然后我发现直接这么做却不知道如何连接导线了, 不过确定的是, 至少前四位仍然只需要按照原来的方式连接即可.

  • 但当要表示选择100, 也就是第五个的时候, 情况就会变得很糟糕, 因为A2此时为1, A1, A2 此时均为0, 导致了Y0为1, 但实际上要做到的是: 此后前四位都应该为0了.

  • 那要怎么办呢? 想到输入端只有A2会是前后的分界点(此前一直是0, 此后一直是1), 于是可以让A2为1参与运算, 使得前四位为0.
    只需要对A2取反得到0, 然后对每一位Y进行与运算即可.

  • 而后又考虑到再后四位的显示顺序和前四位是重复的, 我们可以直接复用前四位的输入和输出.

  • 但这又会导致再表示前四位的时候,后四位又不能保证全为0. 还是复用之前的处理思路, 用A2=0表示之前的状态,与后四位输出进行与运算.

搭建七段数码管译码器

过了一晚上终于做出来了!!!!

image-20261008151708123

这里简单说一下我的过程:

  • 刚开始没看懂这条hint:可以先用n选1译码器生成一组独热码, 然后再通过一层或门来分别决定每个发光二极管在哪些输入的情况下应该点亮. 后面才领悟了.

  • 需要先做用一个4-16的译码器将二进制数转成十进制, 由于每根管子都是特定的一些数才亮, 所以需要哦用到或逻辑, 直接用八个或门来对八段数码管做筛选即可.

  • 中间我到了用译码器得到16个输出之后不知道要如何再做到8位的映射了, 还傻傻的想用真值表来做, 发现太复杂就放弃了, 后面经过AI提示才意识到可以用或门来做.

  • 总之还是应该好好理解hint的深层含义的.

搭建七段数码管译码器(2)

这里要做到显示16进制数字, 只需要更改后面6根线的实现逻辑即可.

image-20261008151543535

实际做起来, 到后面线比较多的时候就有点眼瞎了.

编码器

搭建编码器

image-20261008171853555

搭建4-2优先编码器

优先编码器(priority encoder) 是指 输入不为唯一1的输入的时候, 只表示最高项的1, 全为零则表示为XX.

image-20261008183747272

输入端的X直接不用管, 输出端的任意值都可,填最方便的00就好.

然后列出逻辑表达式, 画出电路图:

image-20261008183738665

后记

寻找更优的搭建方案搭建XOR gate 这一部分后面虽然有问AI, 但实际上能从22个晶体管优化到讲义中给出的限制之内的14个还是很开心的. 居然用上了没怎么好好听课的数电课上学到的德摩根律化简来优化, 也算是学以致用了.


26/10/7 心得

搭建2-4译码器 刚开始不知道要怎么做, 后面才想明白还是要走从真值表->化简得到逻辑表达式->画出半定制电路图的流程.

以 2-4译码器 做子电路搭建 3-8译码器 的时候, 开始有些想法, 但都很难落地, 后面还是请教了AI提示了一下, 突然把我之前想的东西串起来了,于是顺利做了出来.

七段数码管译码器搭建这块, 看的我有点一头雾水. 想着还是画真值表那一套? 但发现化简 什么的要写一堆东西好麻烦, 然后hint中提到的走译码器的那条路目前还是理解思路. 想法大概是用4-16译码器把二进制转成要选择表示的数字,(第几个) 然后看对应的要亮那些数码管. 具体的今晚想想, 明天再看.


26/10/8 心得

开始感觉有点困难了,

搭建七段数码管译码器 那块卡了很久, 编码器这块也卡了很久, 后面总结, 只要是互斥输入的, 尽量从最终多个或门的思路上去设计, 而不是直接去画真值表, 那样想太复杂了.

posted @ 2026-10-06 18:21  幽暗天琴沙雕  阅读(14)  评论(0)    收藏  举报