Nand2Tetris(计算机系统要素) Unit 1 学习笔记 - 从与非门到基础芯片设计

Nand2Tetris(计算机系统要素) Unit 1 学习笔记 - 从与非门到基础芯片设计
Xiaozhi_z起初是在CS自学指南里找到的这门课(依据基本原理构建现代计算机:从与非门到俄罗斯方块),感觉还不错而且零基础,是一个比较好的入门课程。同时全英教学可以逆向让我捉襟见肘的英语水平稍微强一点,多理解一个单词就是胜利(
Unit 1 应该都是关于电路的,爽了,正好学到电路这门课(
Unit 1.1 Boolean Logic(布尔逻辑)
这节课主要讲述逻辑
二进制听过无数遍了,但是一直没有对这个进行思考。为什么是二进制?或者说计算机是怎么通过0和1来实现计算然后一点一点设计电路组成芯片从而组合成一台真正的计算机的。
一直以来对计算机的理解就是存在即合理,从来没有细想过里面的逻辑

这就是一个比较简单的AND操作从而可以实现与逻辑 只有两个输入值都为1时 AND操作的输出值才为1
可以很详细的看出0和1的不同可能性(穷举操作),把0和1组合起来并回显结果的表格叫做真值表

这个是OR操作从而可以实现或逻辑 只要有一个值为真 结果也就为真

最后的是NOT(非)运算,仅有一个运算操作数,所以是一元逻辑运算。上方三种运算是最基本的逻辑运算。

上面的基本都是运算方法,以下为计算例子,就算是布尔计算也要遵守括号内先去计算,其余的和数学基本一致。

定义一个函数 函数内有三个变量x y z可以用以下公式来描写函数
这里应该是国外的写法,我学数电的时候似乎是用的数学运算符来表达

我们穷举所有的变量,得到一个真值表如下

然后将值代入函数进行运算,得到完整的真值表

普通数学有交换律,布尔计算也有交换律 如下

同样也适用于结合律

当然,分配律也是一样的

除去数学之外,有一个叫做德摩根定理的东西,公式如下
这个还没有学过,但是可以用真值表进行证明,稍后应该会有详细的理解?

给了一个化简的实例,使用定理进行化简
学到这里的时候其实电路学到化简了可惜没学会(至少没有特别融会贯通

Unit 1.2 Boolean Function Synthesis(布尔函数合成)
1 | 构造流程:真值表 → 析取范式 → 逻辑简化 → 门电路实现 |
课程开始回顾了上节课内容 从布尔表达式生成真值表的方法:
穷举x,y,z的可能性 得到如下表

但工程实践中更常见的是反向需求:已知电路功能(真值表),如何用基本门电路来实现?
实际情况中我们知道想让部件做什么,但不知道如何用门电路来表达,这种转换能力就显得尤为重要

将所有真值表输出值为1的标记一下 输入值为1取对应变量写入,输入值为0取变量的非(NOT)将变量之间使用AND(*)进行连接,将真值表输出值为1的每行表达式使用OR(+)连接可得到函数表达式
输入1→保留变量,输入0→取非

任何布尔函数都可用AND、OR、NOT三种基本运算实现
上一节课讲的摩根定理在这里可以直接运用,已知 AND、OR、NOT 可构造任意布尔函数,使用使用定理就可以仅用 AND 和 NOT 即可实现所有函数

还有一个NAND门运算 是由与非门(AND 和 NOT)组成的
从而延伸出仅用 NAND 门可实现所有布尔函数,计算机硬件设计仅需一种基础门(NAND)即可构建所有复杂逻辑电路。
如下图可以用NAND表示非(NOT)和与(AND)

Unit 1.3 Logic Gates(逻辑门)
逻辑门就是实现布尔运算的组件,是一种使用硬件实现布尔函数的技术。它是一种独立的、简单的芯片,旨在提供明确定义的基本功能。
基本逻辑门
逻辑门就是实现布尔运算的组件 例如Nand**(与非)**门

这个是Nand门的描述
如果输入都是1时输出0,其它情况均为1

真值表如下
| a | b | out(输出) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
当然还有三个经典的门电路:
- And(与)门:当它的两个输入都是1时输出1,在其他情况下输出0。

- Or(或)门:当其中一个输入为1时输出1,在其他情况下输出0。

- Not(非)门:它可以用作转换器,输出与输入相反。

复合逻辑门与接口
复合逻辑门是由基本逻辑门和其他复合逻辑门组成的门
这里以三输入And门为例:
- 接口:这是门的抽象描述,定义了用户能看到和使用的部分——三个输入和一个输出。它回答了门“做什么”的问题。

- 实现:这是门“怎么做”的内部构造。我们可以通过组合两个双输入And门来实现一个三输入And门的功能。

接口与实现的概念:
- 一个门的接口是唯一的,只有一种方式描述其功能。
- 但一个门的实现可以有多种(可能更节能、更便宜等),即“一个抽象规范,多种不同实现”。
硬件实现的视角
物理电路实现(电气工程视角)
举个例子 这是And(门)电路(物理实现)的样式
只有当两个开关都闭合(输入为1)时,灯泡才会亮起(输出为1)。

这个电路就是一个复合的And(与)门电路(物理实现)

逻辑门组合实现(计算机视角)
但是实际上我们不用考虑物理实现(那个应该归电气管),只需要学会对应的计算机实现即可。我们关心的是如何从最基本的Nand门开始,通过逻辑组合来构建更复杂的功能,例如下面的三输入And门。

Unit 1.4 Hardware Description Language(硬件描述语言)
这期主要是如何使用HDL,来构建逻辑门进行模拟以及测试。
HDL是一种声明性语言,没有程序执行。只是对门电路的一种描述方式。
假如说给定一个异或芯片

使用这些信息就可以写一个HDL文件 如下效果
使用CHIP关键字定义芯片名称 然后自己设置IN(INPUT 输入)名称以及OUT(OUTPUT 输出)名称即可

可以看一下Xor门的逻辑 只有两种情况下输出相等而为1 这一种逻辑不同于真值表
就是A和B非以及B和A非的时刻相同

对于普通用户来讲 只需要知道这是有两个输入 一个输出的接口就可以(不需要理解虚线中的运算逻辑),只需要知道这个接口可以用,就像我现在可以轻松的使用电脑利用Markdown编辑器直接编写文字但具体不知道它是如何和操作系统进行交互以及如何打印的屏幕上的一样,只知道这个接口提供了Xor的功能。
在HDL设计中,芯片接口是唯一的,由芯片规范确定,而实现方式可以多样化。

引出可以深入研究内部架构 逻辑图刚学可能比较难懂 没办法一眼看出来内部线是怎么走的 这时就需要给每个步骤起名 如下的效果 将所有逻辑运算组合起来就是Xor的表达式辣
HDL具有”无限扇出”特性,任何信号都可以根据需要分发到任意数量的目的地,所有连接都是同时进行的

现在就可以用HDL进行实现啦 可以通过这样的写法来描述IO接口的调用 定义为一个两入一出的芯片

刚刚只是定义了接口 但是没有具体定义接口中是如何进行逻辑运算的
首先的输入是a 输出的结果是a非
然后又描述了两个And(与)门 定义了a与b的输入(Input)以及输出(Output)
说实话有点像一种变量的映射,有点像一层一层的变量调用对应的函数(这里应该是芯片)方法

最后描述一个 Or(或)门,把之前的输出作为输出再进行下一步逻辑运算 HDL就算写完辣
这个HDL文件就是对芯片的一个结构描述方法和真值表和表达式以及逻辑图应该是一样的
其中应该最重要的就是命名了,有点像设置变量名的感觉(也有可能是变量名像这个

HDL上方的为定义接口(Interface) 下方的为具体实现(Implementation)
一遍情况下,一种相同的芯片,例如Xor。
接口都是相同的,但是具体的实现(逻辑)是可以不同的,可以用别的门电路组合成相同的效果。
HDL语句顺序无关紧要,但习惯从左到右描述以提高可读性。

不同的实现方案在成本、功耗、门数量等方面存在差异,这是硬件优化的重要考虑因素
Unit 1.5 Hardware Simulation(硬件模拟)
在上一单元中,我们学习了如何使用 HDL 实现门逻辑。但是,我们的所作所为并不能保证我们编写的 HDL 代码确实是正确的。我们不知道我们组装的这种架构能否实现我们想要设计的芯片的预期结果。
因此,在本单元中,如何使用 HDL程序,并尽我们所能验证该程序或 HDL文件是否提供了底层芯片的预期功能这件事就成为了主要学习的方向。
假如说有一个特定的HDL文件需要进行测试

可以把HDL加载到硬件模拟器的程序中 来进行测试
硬件模拟器是验证HDL代码正确性的关键工具

硬件模拟器提供了两种主要的测试模式:交互式仿真和基于脚本的仿真
可以通过加载HDL到程序实现调试测试等,可以在这个芯片中交互式的进行各种操作,这种交互方式称为交互式模拟。
除了交互式测试,还可以编写测试脚本文件,使用专门设计的测试语言来定义一组预定的、可重复的测试。这种方式称为基于脚本的模拟。
测试脚本实现了测试的自动化和可重复性
在模拟过程中,可以将仿真结果记录到输出文件中,甚至可以将仿真结果与存储在比较文件中的期望输出进行对比验证。
比较文件机制实现了自动化验证,大大提高了测试效率
硬件模拟器界面详解
课程中使用的是老版本的模拟器,这里演示的是最新的官方文档提供的Web界面模拟器(效果是一样的
最左侧显示加载的HDL代码
中间为允许交互式设置输入引脚的值(0或1)
最右侧是脚本区域(课程中没有详细说新版本的 我猜测有比对功能来判断是否编写正确

编写了一个Xor的HDL文件
那个Web端确实好用 居然还有自动补全
1 | // This file is part of www.nand2tetris.org |
使用交互式模拟可以很轻松的 看到输入输出结果

看起来功能完全正常

但是交互式模拟也有缺点 虽然非常的直观而且方便调试 对于Xor芯片来讲 真值表无非就四行 尝试四次就能出结果了
| a | b | out(输出) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
但假如说真值表有几十行甚至几百行,手动测试自然效率低下了,这时候就引出测试脚本的概念了。这是Xor的测试脚本示例

点击Run即可跑这个脚本

Output中就能看到输出的真值表啦 能看出来回显的内容和我们的需求一致 HDL写的没问题~

测试脚本的核心价值在于可重复性和自动化。当芯片设计需要反复修改时,只需重新运行测试脚本即可快速验证所有功能,无需手动重复测试
在实际项目中,测试脚本通常与比较文件(.cmp)配合使用,自动化验证输出结果是否符合预期,大大提升开发效率和代码可靠性
比较文件的作用
比较文件包含了芯片的预期输出结果,当测试脚本运行时,硬件模拟器会自动将实际输出与比较文件中的预期值进行对比,如果发现不一致就会标记错误,从而实现自动化的功能验证。

Unit 1.6 Multi-bit Buses(多位总线)
本节课主要研究如何处理一堆数据,或者说如何同时操作多个位。通过引入“总线”的概念,我们可以在更高的抽象层次上设计和思考数字电路。
什么是总线?
总线(Bus) 是一组被共同操作的硬件信号线的集合,在数字电路设计中,它让多个位(bits)能够作为一个统一的实体来传输和处理。
可以把总线想象成一条”数据高速公路”,多个位像车辆一样在这条公路上并行传输,而不是每个位都走自己独立的小路
物理层面:总线实际上还是一组独立的电线
逻辑层面:我们把这些电线看作一个完整的数据单元
例如:
- 4位总线:4根电线,可表示0-15的数值
- 16位总线:16根电线,可表示0-65535的数值
- 32位总线:32根电线,可表示0-4294967295的数值
为什么要用总线?
硬件设计时经常需要同时操作一组相关的位。不是单独处理每个位,而是把一组位当作一个完整实体来操作。
例如:设置IP地址
没有总线时:
- 就像要手动设置
192.168.1.1的每个二进制位11000000.10101000.00000001.00000001- 需要逐个设置32个开关,极其繁琐
使用总线时:
- 直接说:
IP = 192.168.1.1- 一次性完成所有32个位的设置
- 把32个独立操作变成1个整体操作
就像把32个位看作一个IP地址,而不是32根独立的电线。
总线的基本概念
总线在HDL中用数组语法表示:

1 | CHIP Add16 { |
操作总线:整体与部分
1. 将总线作为整体操作
三数相加
1 | CHIP Add3Numbers { |
2. 访问总线中的单个位
有时需要访问和操作总线中的特定位。
4位与门(And4Way)
1 | CHIP And4Way { |
索引约定:在HDL中,总线的索引从0开始:
- 4位总线:
in[0],in[1],in[2],in[3]
3. 并行位操作(按位操作)
4位按位与门
1 | CHIP BitwiseAnd4 { |
Unit 1.7 Project 1 Overview(项目 1 概述)
一开始给了一个这样的图(其实就是想说只需要Nand门就能手搓计算机

仅仅用Nand 这节课就要实现以下这么多的门
很多都不认识(

为什么要选这十五个门?
这些门(如 Not、And、Or、Mux、DMux 等)是数字逻辑设计中的基本构建块,被广泛应用于几乎所有数字设备中。它们是经过验证的、最常用且最基础的功能单元。
补充要点: 选择这15个门有两个核心原因:1. 实用性:它们被广泛用于几乎所有数字设备中。2. 基础性:它们包含了构建本课程后续计算机(Hack计算机)所需的所有基本逻辑门,为后续项目奠定基础。
十五个门电路的分类

多路复用器(Multiplexor)
比一般的输入输出电路 多一个sel(可以理解为数字选择器叭) 来选择信号
按照我上的数电课理解就是 假如有一个四选一电路 有两个选择信号 也可以称为四加二入一出电路
而且我猜测 这个多路复用器 也可以应用在片选信号上 但是只是数电课学了然后感觉可能会用到
补充要点: 多路复用器(Mux)的功能是根据选择位(sel)的值,从两个输入(a和b)中选择一个进行输出。其理想行为是:
if sel=0 then out=a else out=b。这是一种在数字设计和通信网络中非常基础且重要的数据选择操作。

AndMuxOr
这是一个AndMuxOr门 一个比较简单的使用Mux的电路
效果就是假如sel信号为0 则为与门 如果不是 则是或门

这个是门电路的真值表 和刚刚描述的一样
补充要点: 这个例子展示了多路复用器如何用于构建“可编程门”。通过一个选择位,可以动态地改变门的功能(如此处在And和Or之间切换)。实现方法是将输入同时馈送给And和Or门,然后用Mux根据选择位决定输出哪一个门的结果,这个过程也涉及了“扇出”(Fanout)概念。

这个是逻辑图
我数电好像还没有学到这个Mux门(或许见过但是没有深入学

关于这个门电路的HDL文件是这个样子的
其实主要是调用Mux模块 其他的没什么不同

多路分配器(DeMultiplexor)
多路分配器就感觉像是刚刚的逆运算吧

一个是选择 另一个就相当于分发吧 真的很像逆运算

这里还举了一个多路复用器和多路分配器在网络通信中的例子 规定了只有一条线路的情况下 如何才能同时传输两个信号 可以用这两个元器件 进行有点像编解码的功能 实现数据的传递
补充要点: 在网络通信中,Mux和DMux结合使用可以实现“时分复用”。在发送端,Mux快速交替地选择不同来源的数据位。在接收端,DMux根据同步的选择信号,将数据流分离并分发到正确的目的地。这个方案可以是异步的,非常高效。

新的门电路介绍
And16
And16长这个样子 看起来它的输出就是值同时为1时输出1 其余为0 看起来好像挺简单的 两入一出的电路
补充要点: And16是一个16位变体的门电路。它同时对两个16位输入总线的每一位执行按位与操作。这是一个并行操作,所有16位的计算是同时(在硬件中并行)完成的,而不是顺序执行。实现上可以通过16个独立的And门组合而成。

Mux4Way16
补充要点: Mux4Way16是一个多路、16位变体的复杂例子。它有四个16位输入,需要2位选择信号(因为2^2=4)来选择其中之一输出。这类芯片可以通过组合我们已经构建好的更简单的芯片(如多个Mux16)来构建。
一下子就上强度了 将Mux和带总线的一结合 变成了以下的效果
课程中就是一带而过 更多的就是认识一下

如何制作这些门电路呢?
以 Xor 为例子 会提供这个样子的图

然后还会提供HDL的基本接口文件 以及脚本文件 以及对比文件(其实就相当于真值表啦)
就相当于给了真值表答案 就看自己能不能设计出来这样的电路辣

Unit 1.8 Persectives(视角)
是一个Q&A的课 这节课的翻译不是特别好使 文档AI使用就多一点点(
是否可以从其他逻辑门开始构建计算机?
核心观点: 是的,完全可能从 NAND 以外的逻辑门开始构建计算机。
具体说明:
- 可以使用 NOR 门(非或门)作为原子构建块来构建整个计算机系统
- 也可以从 AND、OR、NOT 门组成的套件开始构建系统
现实应用:
- NAND 门在硬件系统的物理实现中非常流行
- 在许多集成电路技术中,构建 NAND 门的成本相对较低
如果真的要建一个Nand门该怎么去做?
答: 这涉及到物理层面的实现,本课程通常不深入讨论,但可以一个简单的实现方案为例(基于NMOS技术):

- 基本元件:你需要晶体管、电阻和电压源。设定正电压代表逻辑“1”,负电压(或地)代表逻辑“0”。
- 电路连接:
- 将一个电阻连接到正电压源。
- 将两个NMOS晶体管串联起来(一个接在另一个的后面),然后连接到负电压/地。
- 将电阻和晶体管串联电路的连接点作为输出端。
- 两个晶体管的栅极分别作为输入A和输入B。
- 工作原理:
- 当 A 和 B 都是 “1” (高压):两个晶体管都导通,形成一条从输出端到负电压(逻辑“0”)的低电阻通路。此时,无论连接到正电压的电阻多么“努力”,输出都会被“拉低”到“0”。这正是NAND门的功能:输入全1,输出为0。
- 当 A 或 B 是 “0” (低压):至少有一个晶体管会关闭,切断输出端到负电压的通路。此时,输出端通过电阻被“拉高”到正电压,输出为“1”。
核心要点:这个例子揭示了硬件抽象之下的物理现实。但在本课程中,我们更关心的是NAND门做什么(它的逻辑功能),而不是它具体如何实现。我们将其视为一个完美的、无需深究的黑盒,并基于此来构建整个计算机系统。
原来黑盒的概念这里就有了 我一直以为是网安的词汇
课程中使用的 HDL 和工业级的 HDL(如 Verilog/VHDL)有何异同?
- 相同点:它们都是用于描述和模拟数字硬件的真正的硬件描述语言。
- 不同点:工业级语言(如 Verilog、VHDL)功能更复杂、强大。它们的语法混合了 HDL 和 C 语言特性,包含高级编程结构(如循环),并且能够对时序、时钟等概念进行建模,这对于构建内存等时序逻辑至关重要。掌握它们通常需要数周甚至数月。
- 课程选择:为了让大家能快速上手并专注于计算机架构的核心思想,我们提供的是一个简化版的 HDL。它包含了构建本课程计算机所需的全部功能,但设计得非常简洁,可以在大约一小时内学会。
如何设计包含数百个元件的复杂芯片?
答: 设计复杂芯片没有放之四海而皆准的简单方法,它是一项需要创造力的挑战。工程师会使用各种工具和方法:
- 优化技巧:如卡诺图,用于优化门级设计。
- 自动化工具:如“硅编译器”,你可以指定所需功能,由工具内部的算法自动进行逻辑优化和布局。
Programming Assignment: Project 1(编程作业: 项目 1)
1 | 您在本项目中的工作成果将是一组 15 个文本文件,其中包含您要构建的 15 个芯片的 HDL 代码。如果您能成功构建并测试所有芯片,那就太好了。如果您只完成了部分芯片,您仍然可以提交它们以获得部分学分。 |
要做这 15个芯片的 HDL 代码
由于 Nand 被认为是基本门,无需实现它。

Not
Not门长这个样子

看见真值表为
效果为输入然后取反

我起初就是直接想的直接设计吧!然后发现没办法用自己来设计自己 因为Not本来就是一个芯片 是我要设计出来的芯片

其实自己是陷入逻辑误区了 我以为这个和编程的角度是差不多的 把这个当作函数了 但其实按照课程来讲应该用Nand来进行基础门电路的设计

Nand的真值表
将Nand当作一个基础芯片来看就好啦
| a | b | out(输出) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
如果不直接去搜索答案的话 使用这个构建Not的最大问题是 如何将二入一出的芯片 转化为一入一出的 我来观察真值表 发现当输入都为0时 输出为1 输出都为1时 输出为0 这不就恰好符合Not的效果!!!
所以我们将a与b都定义为in out定义为out(可能表述的不准确) 效果如下
1 | CHIP Not { |
测试出来效果正确

使用脚本来跑真值表也对啦 Not攻克成功!

And
And电路长这个样子

看一下And的真值表

Nand的真值表
将Nand当作一个基础芯片来看就好啦
| a | b | out(输出) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
这个其实很明显辣 就是每一个进行取反 一开始先使用一个Nand门 然后再使用一个非门(Nand实现 刚刚实现的那个) 就好啦
这里也可以直接使用Not门 以为刚刚已经设计出来了
1 | CHIP And { |
测试正常

然后来看一下最后跑出来的真值表 芯片设计完成!

Or
Or芯片的样子如下

Or的真值表如下

Nand的真值表
将Nand当作一个基础芯片来看就好啦
| a | b | out(输出) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
这个其实有难度了 因为没办法一眼设计出来了 应该就要用到之前设计的Not以及And芯片啦
这个真的给我卡住了 一瞬间不知道怎么设计这个最基础的芯片了
然后我问AI找了思路 AI让我去看一下摩根定律(没想到这个东西还能在这用


用第二条可以秒出结果啦 一下子就简单起来了
这个我是真的想不出来 我只能想出来用非和与门去构建 想不到具体的角度
1 | CHIP Or { |
成功啦

Xor
- X 代表 “Exclusive” 的缩写。“Exclusive” 的意思是 “排他的”。XOR 的全意是 “排他性或”,中文精准地翻译为 “异或”(相异则为真)。简单来说,这个 X 就指明了它与普通 OR 最关键的区别:它排除了两者同时为真的可能性。
Xor芯片的样子和真值表如下

我们已经成功设计出来了三个最基本的门电路 然后根据这个可以进行拓展啦 Xor明显就是当a和b不同时为1
1 | CHIP Xor { |
非常完美 这几个都比较简单

Mux
Mux芯片长这样 这个也叫多路复用器 有一个控制信号

逻辑如下 如果sel等于0 则输出a 如果sel等于1 则输出b

真值表如下

这实际上是一个”条件选择”的逻辑。想想看:
- 当
sel = 0时,我们想要a“通过”,b“阻断” - 当
sel = 1时,我们想要b“通过”,a“阻断”
一个与门的特性:当一个输入为0时,输出总是0;当一个输入为1时,输出等于另一个输入
那就可以使用Not门来搞出来sel的方向信号 然后使用与门特性来创造芯片!!
1 | Not(in= sel, out= Notsel); |
然后题目说 如果sel等于0 则输出a 如果sel等于1 则输出b 将a与Notsel相与 b和sel相与 最后相或就好啦
1 | CHIP Mux { |
测试成功!!!

DMux
DMux 多路分配器(DeMultiplexor)长这个样子

这个是它的描述和真值表 有两个输入端 假如sel=0 输出a=in 反之假如sel=1 输出b=in 这是第一个设计的双输出的门电路


一开始的逻辑就是使用Not来区分sel和Notsel
1 | Not(in= sel, out= Notsel); |
然后重点sel=0 输出a=in 反之假如sel=1 输出b=in
其中的重点还是与门的特性 当一个输入为0时,输出总是0;当一个输入为1时,输出等于另一个输入
这确实和数电根据真值表直接设计然后化简的想法不太一样 更多是从电路逻辑上设计然后验证的 居然没有通过真值表就能设计出这样的电路还是挺神奇的 看起来挺简洁的
1 | CHIP DMux { |
验证结果

Not16
Not16芯片的逻辑如下
输入: in[16] // 一个16位引脚
输出: out[16]
功能: 对于 i=0..15,out[i] = Not(in[i])。

效果很不一样了 现在就像是变成了一条数据 而不是单独的bit

初步验证设想是 使用16个Not门 明显是可以的 使用两个Not门进行验证出来了

然后其实失败了 我问AI也没有什么好的方法 HDL并不支持for循环 最后使用十六个非门做出来的、
1 | CHIP Not16 { |
这样的百分百也可以验证通过啦

And16
And16的芯片逻辑如下

这个其实我也没有什么好的方法了(问遍了AI And门只能一个输入一个输出属实想不到了) 十六个芯片直接实现叭
1 | CHIP And16 { |
测试成功

Or16
Or16芯片的逻辑如下

还是和前面两位一样的实现方法
1 | CHIP Or16 { |
测试成功

Mux16
Mux16芯片逻辑如下

除了多一个控制芯片之外 依旧一样的设计思路
1 | CHIP Mux16 { |
测试成功

Or8Way
Or8Way芯片逻辑如下
输入: in[8]
输出: out功能: out = Or(in[0], in[1], …, in[7])

其实也比较简单 含义就是输出八个门 结果是八个门相互或
也就是四个一组Or门 然后输出四个新的信号 之后再使用两个Or门 最后时候一个Or门即可
让AI生成了一个比较易懂的图
1 | 层级 0 (输入层): |
然后写hdl文件就好啦 就是Or递归吧
1 | CHIP Or8Way { |
验证结果 成功!

Mux4Way16
Mux4Way16芯片逻辑如下 这一次上强度了
输入: a[16], b[16], c[16], d[16], sel[2]
输出: out[16]
功能: 如果 sel=00 则 out=a,否则如果 sel=01 则 out=b,否则如果 sel=10 则 out=c,否则如果 sel=11 则 out=d
注释: 上述赋值操作都是16位的。例如,”out=a” 表示 “对于 i=0..15,out[i]=a[i]”。

其实看到这个描述 感觉就和数电里面的那个74LS153特别像
Mux4Way16芯片长这个样子

起初我的想法是一个一个实现 就如同下面的样子
1 | CHIP Mux4Way16 { |
然后我突然发现我设计过Mux16 就不用这样再造轮子了 可以用现有的工具直接写啦 但是这里有错误的点
1 | CHIP Mux4Way16 { |
真正正确的思路表是这个样子的
AI帮忙生成的
1 | SEL[1]=0 (走上面) SEL[1]=1 (走下面) |
正确的hdl文件
1 | CHIP Mux4Way16 { |
测试成功啦

Mux8Way16
Mux8Way16芯片的逻辑如下
芯片名称: Mux8Way16
输入: a[16], b[16], c[16], d[16], e[16], f[16], g[16], h[16],
sel[3]
输出: out[16]
功能: 若 sel=000 则 out=a,否则若 sel=001 则 out=b,
若 sel=010 则 out=c … 否则若 sel=111 则 out=h
注释: 上述赋值操作均为 16 位。例如,”out=a” 表示
“对于 i=0..15,out[i]=a[i]”

这个就不用讲啦 和刚刚一模一样 就是多了一层嵌套而已
第一层(处理 sel[0] 最低位):
Mux16(a,b,sel[0])→ 输出ab:选择 a 或 bMux16(c,d,sel[0])→ 输出cd:选择 c 或 dMux16(e,f,sel[0])→ 输出ef:选择 e 或 fMux16(g,h,sel[0])→ 输出gh:选择 g 或 h第二层(处理 sel[1] 中间位):
Mux16(ab,cd,sel[1])→ 输出abcd:选择 ab 或 cd(即前四个输入)Mux16(ef,gh,sel[1])→ 输出efgh:选择 ef 或 gh(即后四个输入)第三层(处理 sel[2] 最高位):
Mux16(abcd,efgh,sel[2])→ 输出out:选择 abcd 或 efgh(最终输出)
1 | CHIP Mux8Way16 { |
测试成功!

DMux4Way
DMux4Way长这个样子

DMux4Way逻辑如下
芯片名称: DMux4Way
输入: in, sel[2]
输出: a, b, c, d功能: 如果 sel=00 则 {a=in, b=c=d=0}
否则如果 sel=01 则 {b=in, a=c=d=0}
否则如果 sel=10 则 {c=in, a=b=d=0}
否则如果 sel=11 则 {d=in, a=b=c=0}。

这里主要是复用Dmux门电路 实现这样的功能
sel[1]=0 → 左组(a,b) → sel[0]=0→a, sel[0]=1→b
sel[1]=1 → 右组(c,d) → sel[0]=0→c, sel[0]=1→d
1 | CHIP DMux4Way { |
来测试一下 测试成功!

DMux8Way
这个芯片的逻辑如下
芯片名称: DMux8Way
输入: in, sel[3]
输出: a, b, c, d, e, f, g, h功能: 如果 sel=000 则 {a=in, b=c=d=e=f=g=h=0}
否则如果 sel=001 则 {b=in, a=c=d=e=f=g=h=0}
否则如果 sel=010 …
否则如果 sel=111 则 {h=in, a=b=c=d=e=f=g=0}。

和刚刚一样 也只是嵌套一下递归就好啦
1 | CHIP DMux8Way { |

测试一下

然后打包提交就好啦

