9、P1 W1 U1.8 总结、作业1答案
视频:
如果本次课程对应的 Coursera 的视频打不开,可以点击下面链接
P1W1U1.8 - Perspectives
软件:
全课程所需软件项目包官方下载:
https://www.nand2tetris.org/software
备了一份软件项目包放在CSDN了,版本2.6支持Mac、Linux、Windows:
https://download.csdn.net/download/shazizm/11268147
本节课程实际上,是增加的答疑环节。我来用几句话总结完毕,然后写作业:
1.不光是用Nand可以完成“Hack小电脑”的制作,用其它也行,比如Nor。
2.区分一下电子工程和计算机科学的边界,课程不会去讨论逻辑门如何在物理上实现。
3.课程里的HDL是两位老师为简化学习,专门做教学目的。同学在工作上通常见到的是 Verilog,VHDL。
4.复杂的电路是如何设计的?搜索百度“IC设计专业”。
已知:
第一次作业,毕竟整个课程名叫NandtoTetris,所以一开始只有Nand能用。如下图
开始我们只有 Nand
下载 nand2tetris.zip
全课程所需软件项目包官方下载:
https://www.nand2tetris.org/software
备了一份软件项目包放在CSDN了,版本2.6支持Mac、Linux、Windows:
https://download.csdn.net/download/shazizm/11268147
启动 硬件模拟器
Windows用 HardwareSimulator.bat
下图是在Mac上启动
设计方法“三步转换”
老师推荐了一个设计方法和流程,回忆参考:
P1 W1 U1.4 硬件描述语言HDL
硬件模拟器 操作说明
写好硬件代码,如何用硬件模拟器调试,测试,对比结果,回忆参考:
P1 W1 U1.5 硬件模拟
1、Not
第一个Not 只能用Nand来设计。这个貌似没法用“三步转换”的方法。直接看着Nand的真值表发现其中包含一个Not真值表,貌似有思路了,准备工作环境。
红框内是个Not的真值表
1、写代码
我自己增加一个“作业”的目录,新建“1_Not”用来存放我的作业代码,新建一个文件叫 Not.hdl,用编辑器打开。
Hardware Simulator 硬件模拟器不能编辑Not.hdl。需要自己找个编辑器来写代码,如图用的VScode代码可以自己设计,也可以直接采用老师提供的 逻辑门接口命名(下载包/nand2tetris/projects里)然后只设计逻辑部分,我这里采取老师的命名规则,以免之后不方便用老师提供的工具排查问题。
打开/nand2tetris/projects/01里的Not.hdl,复制其中提供的代码 到我们自己的/作业/1_Not/Not.dhl里。
在 代码 PARTS:下加入自己的思考
Nand(a=true,b=in,out=out);
//下面也都行
//Nand(a=in,b=true,out=out);
//Nand(a=in,b=in,out=out);
完整代码:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not.hdl
/**
* Not gate:
* out = not in 这里已经给出布尔函数,一般用三部转换推导出来,这个not貌似不能。
*/
CHIP Not {
IN in; // 接口名称
OUT out; // 接口名称
PARTS:
// Put your code here: 自己的代码写在下面
Nand(a=true,b=in,out=out);
}
2、测试
拷贝 /nand2tetris/projects/01 里的 和 。到/作业/1_Not里准备测试。
测试结果如果没有报错,如上图 successfully 了,说明 作业写对了。可以进行下一个了。
2、And
1、真值表
先把逻辑门的符号,或者语言描述的功能等,归纳成真值表。
我们知道And 的真值表 如下图
2、三步转换
有了真值表,怎么转换成 布尔函数,回忆参考:P1 W1 U1.2 布尔函数
三步转换方法粗糙总结就是:找出真值表 out列等于 “1” 的行,a 等于 0就写 “Not(a)”, b 等于1 就写 “b”,ab用And连接。多行out等于1的,用Or连接。
如上图得 布尔函数:
这里需要布尔代数的操作再转成 只用 Not 和 Nand 的表示方式。回忆参考:P1 W1 U1.1 布尔逻辑
//只有最后一行out等于1,得:
a And b
// 可是我们没有And,我们目前只有 Nand 和 Not,因为 布尔代数?布尔恒等式? a And b = Not(a Nand b),得:
Not(a Nand b)
布尔函数Not(a Nand b) 转 HDL 代码:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/And.hdl
/**
* And gate:
* out = 1 if (a == 1 and b == 1)
* 0 otherwise
*/
CHIP And {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Nand(a=a,b=b,out=nandout);
Not(in=nandout,out=out);
}
最后跟上一个Not的操作一样,用硬件模拟器测试,没有问题,OK。之后的都按此流程就能完成本周所有的作业。
测试 And 成功
3、Or
1、真值表
2、布尔函数(三步转换)
布尔代数,在 P1 W1 U1.1 布尔逻辑 这个教程里讲的并不全。在做转换的时候参考了下面网站(有自动简化工具 和 更全的布尔恒等式)。
http://electronics-course.com/boolean-algebra
(另一个最小化工具,如果上面的打不开)
http://tma.main.jp/logic/index_en.html
//真值表里out等于“1”的行 用 Or 连接,得:
(Not(a) And b) Or (a And Not(b)) Or (a And b) // 参考:[P1 W1 U1.2 布尔函数](https://www.jianshu.com/p/a7c784aa3224)
// 目前我们有 Nand、Not、And了。上行 进过 布尔恒等式 简化如下:
(Not(a) And b) Or ( (a And Not(b)) Or (a And b) )
(Not(a) And b) Or ( a And (Not(b) Or b) )
(Not(a) And b) Or a
a Or (Not(a) And b)
( a Or Not(a) ) And ( a Or b)
1 And (a Or b)
a Or b // 貌似绕了一大圈,获得了一个本来就知道的答案。。。也许只是验证三步转换法。。。
Not(Not(a Or b)) // 把 Or 用 Not 和 And 表示
Not( Not(a) And Not(b) )
布尔函数Not( Not(a) And Not(b) )转 HDL 代码:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or.hdl
/**
* Or gate:
* out = 1 if (a == 1 or b == 1)
* 0 otherwise
*/
CHIP Or {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Not(in = a,out = nota);
Not(in = b,out = notb);
And(a = nota, b = notb, out = andout);
Not(in = andout, out = out);
}
最后 用 硬件模拟器,测试设计结果
现在有Nand、Not、And、Or了
4、Xor
0、描述
Xor 异或: 如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
1、真值表
根据描述:推出真值表
2、布尔函数
( Not(a) And b) Or ( a And Not(b) ) //貌似没法简化了
3、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Xor.hdl
/**
* Exclusive-or gate:
* out = not (a == b)
*/
CHIP Xor {
IN a, b;
OUT out;
PARTS:
// Put your code here:
Not(in = a,out = notaout);
Not(in = b,out = notbout);
And(a = notaout ,b = b ,out = notaandbout);
And(a = a ,b = notbout ,out = aandnotbout );
Or(a = notaandbout, b = aandnotbout, out = out );
}
4、测试
硬件模拟器测试成功。
5、Mux
0、描述
Multiplexor(多路选择器)用 Mux 表示
sel 设置为0 时,out 输出 是 a 的内容。
sel 设置为1 时,out 输出 是 b 的内容。
1、真值表
根据描述:推出真值表
2、布尔函数
(a And ( Not(b) ) And Not(sel) ) Or
(a And b And Not(sel) ) Or
(Not(a) And b And sel ) Or
(a And b And sel )
// 有时候打不开:http://electronics-course.com/boolean-algebra
//(a * ( ~b ) * (~sel) ) +
//(a * b * (~sel) ) +
//((~a) * b * sel ) +
//(a * b * sel )
// 用另一个在线简化工具(推荐):http://tma.main.jp/logic/index_en.html
// (A(~B)(~C))+(AB(~C))+((~A)BC)+(ABC) => a~c + bc => a And Not(sel) Or b And sel
//优先级:()> not > and > or
( a And (Not sel) ) Or ( b And sel)
3、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux.hdl
/**
* Multiplexor:
* out = a if sel == 0
* b otherwise
*/
CHIP Mux {
IN a, b, sel;
OUT out;
PARTS:
// Put your code here:
Not( in = sel , out = notselout);
And( a = a , b = notselout , out = aandnotselout);
And( a = b, b = sel, out = aandselout);
Or( a = aandnotselout, b = aandselout, out = out);
}
4、测试
硬件模拟器 测试成功
6、DMux
0、描述
Demultiplexor(反向多路选择器?)用 DMux 表示
当sel = 0 ,a = in ,b=0
当sel = 1 ,a = 0 , b =in
貌似功能和Mux 正相反。
1、真值表
根据描述:推出真值表
2、布尔函数
这个怎么用“三步转换” ?两个输出。。。
//貌似不用 Or 连接了,分别写两个
//a
in And Not(sel)
//b
in And sel
3、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux.hdl
/**
* Demultiplexor:
* {a, b} = {in, 0} if sel == 0
* {0, in} if sel == 1
*/
CHIP DMux {
IN in, sel;
OUT a, b;
PARTS:
// Put your code here:
Not(in=sel, out=nsel);
And(a=in, b=nsel, out=a);
And(a=in, b=sel, out=b);
}
4、测试
硬件模拟器 测试成功
7、Not16
这个可以理解为 16 个 Not ,Not16 能一次处理 16个输入同时进行Not逻辑运算。
1、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not16.hdl
/**
* 16-bit Not:
* for i=0..15: out[i] = not in[i]
*/
CHIP Not16 {
IN in[16];
OUT out[16];
PARTS:
// Put your code here:
Nand(a=in[0], b=in[0], out=out[0]);
Nand(a=in[1], b=in[1], out=out[1]);
Nand(a=in[2], b=in[2], out=out[2]);
Nand(a=in[3], b=in[3], out=out[3]);
Nand(a=in[4], b=in[4], out=out[4]);
Nand(a=in[5], b=in[5], out=out[5]);
Nand(a=in[6], b=in[6], out=out[6]);
Nand(a=in[7], b=in[7], out=out[7]);
Nand(a=in[8], b=in[8], out=out[8]);
Nand(a=in[9], b=in[9], out=out[9]);
Nand(a=in[10], b=in[10], out=out[10]);
Nand(a=in[11], b=in[11], out=out[11]);
Nand(a=in[12], b=in[12], out=out[12]);
Nand(a=in[13], b=in[13], out=out[13]);
Nand(a=in[14], b=in[14], out=out[14]);
Nand(a=in[15], b=in[15], out=out[15]);
}
2、测试
硬件模拟器测试成功
8、And16
同理
1、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/And16.hdl
/**
* 16-bit bitwise And:
* for i = 0..15: out[i] = (a[i] and b[i])
*/
CHIP And16 {
IN a[16], b[16];
OUT out[16];
PARTS:
// Put your code here:
And(a=a[0], b=b[0], out=out[0]);
And(a=a[1], b=b[1], out=out[1]);
And(a=a[2], b=b[2], out=out[2]);
And(a=a[3], b=b[3], out=out[3]);
And(a=a[4], b=b[4], out=out[4]);
And(a=a[5], b=b[5], out=out[5]);
And(a=a[6], b=b[6], out=out[6]);
And(a=a[7], b=b[7], out=out[7]);
And(a=a[8], b=b[8], out=out[8]);
And(a=a[9], b=b[9], out=out[9]);
And(a=a[10], b=b[10], out=out[10]);
And(a=a[11], b=b[11], out=out[11]);
And(a=a[12], b=b[12], out=out[12]);
And(a=a[13], b=b[13], out=out[13]);
And(a=a[14], b=b[14], out=out[14]);
And(a=a[15], b=b[15], out=out[15]);
}
2、测试
硬件模拟器测试成功
9、Or16
同理
1、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or16.hdl
/**
* 16-bit bitwise Or:
* for i = 0..15 out[i] = (a[i] or b[i])
*/
CHIP Or16 {
IN a[16], b[16];
OUT out[16];
PARTS:
// Put your code here:
Or(a=a[0], b=b[0], out=out[0]);
Or(a=a[1], b=b[1], out=out[1]);
Or(a=a[2], b=b[2], out=out[2]);
Or(a=a[3], b=b[3], out=out[3]);
Or(a=a[4], b=b[4], out=out[4]);
Or(a=a[5], b=b[5], out=out[5]);
Or(a=a[6], b=b[6], out=out[6]);
Or(a=a[7], b=b[7], out=out[7]);
Or(a=a[8], b=b[8], out=out[8]);
Or(a=a[9], b=b[9], out=out[9]);
Or(a=a[10], b=b[10], out=out[10]);
Or(a=a[11], b=b[11], out=out[11]);
Or(a=a[12], b=b[12], out=out[12]);
Or(a=a[13], b=b[13], out=out[13]);
Or(a=a[14], b=b[14], out=out[14]);
Or(a=a[15], b=b[15], out=out[15]);
}
2、测试
硬件模拟器测试成功
10、Mux16
同理
1、HDL
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux16.hdl
/**
* 16-bit multiplexor:
* for i = 0..15 out[i] = a[i] if sel == 0
* b[i] if sel == 1
*/
CHIP Mux16 {
IN a[16], b[16], sel;
OUT out[16];
PARTS:
// Put your code here:
Mux(a=a[0], b=b[0], sel=sel, out=out[0]);
Mux(a=a[1], b=b[1], sel=sel, out=out[1]);
Mux(a=a[2], b=b[2], sel=sel, out=out[2]);
Mux(a=a[3], b=b[3], sel=sel, out=out[3]);
Mux(a=a[4], b=b[4], sel=sel, out=out[4]);
Mux(a=a[5], b=b[5], sel=sel, out=out[5]);
Mux(a=a[6], b=b[6], sel=sel, out=out[6]);
Mux(a=a[7], b=b[7], sel=sel, out=out[7]);
Mux(a=a[8], b=b[8], sel=sel, out=out[8]);
Mux(a=a[9], b=b[9], sel=sel, out=out[9]);
Mux(a=a[10], b=b[10], sel=sel, out=out[10]);
Mux(a=a[11], b=b[11], sel=sel, out=out[11]);
Mux(a=a[12], b=b[12], sel=sel, out=out[12]);
Mux(a=a[13], b=b[13], sel=sel, out=out[13]);
Mux(a=a[14], b=b[14], sel=sel, out=out[14]);
Mux(a=a[15], b=b[15], sel=sel, out=out[15]);
}
2、测试
硬件模拟器测试成功
11、Or8Way
这个应该用在 满足 8种情况,有一种为true。输出就为true的情况
搞明白这个Or8Way,要先搞明白老师的命名规则,我推断是:
Or16:Or 的2way 16bit?(输入 a[16] ,b[16], 输出 out[16] )
Or8Way :Or 的 8way?1bit? (输入 in[8](可以看作 a,b,c,d,e,f,g,h), 输出out)
Or4Way16 :Or 的 4way? 16bit? (输入 a[16], b[16], c[16], d[16], 输出 out[16] ?)
Mux4Way16 : Mux 的 4way 16bit(输入 a[16], b[16], c[16], d[16], sel[2],输出 out[16] )
我分析这个逻辑门 应该用在 “有8种情况下,有一种为true。输出就为true”的情况
这里“三步转换”从老师提供的接口得知:
8-way Or gate: out = in[0] Or in[1] Or ... Or in[7].
利用 2 Associative Law 可以推导:
in[0] Or in[1] Or in[2] Or in[3] Or in[4] Or in[5] Or in[6] Or in[7]
( in[0] Or in[1] ) Or ( in[2] Or in[3] ) Or ( in[4] Or in[5] ) Or ( in[6] Or in[7] )
( ( in[0] Or in[1] ) Or ( in[2] Or in[3] ) ) Or ( ( in[4] Or in[5] ) Or ( in[6] Or in[7] ) )
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or8Way.hdl
/**
* 8-way Or gate: out = in[0] Or in[1] Or ... Or in[7].
*/
CHIP Or8Way {
IN in[8];
OUT out;
PARTS:
Or(a=in[0], b=in[1], out=c1);
Or(a=in[2], b=in[3], out=c2);
Or(a=in[4], b=in[5], out=c3);
Or(a=in[6], b=in[7], out=c4);
Or(a=c1, b=c2, out=c5);
Or(a=c3, b=c4, out=c6);
Or(a=c5, b=c6, out=out);
}
12、Mux4Way16
命名定义:
Mux4Way16 : Mux 的 4way 16bit(输入 a[16], b[16], c[16], d[16], sel[2],输出 out[16] )
我分析这个用在 “比如有 4路 16bit 输入,需要从中选择一种”的情况。
sel[2] = 00,01,10,11分别可以代表 4 路选择
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux4Way16.hdl
/**
* 4-way 16-bit multiplexor.
* out = a if sel == 00
* b if sel == 01
* c if sel == 10
* d if sel == 11
*/
CHIP Mux4Way16 {
IN a[16], b[16], c[16], d[16], sel[2];
OUT out[16];
PARTS:
Mux16(a=a, b=b, sel=sel[0], out=c1);
Mux16(a=c, b=d, sel=sel[0], out=c2);
Mux16(a=c1, b=c2, sel=sel[1], out=out);
}
13、Mux8Way16
命名定义:
Mux8Way16 : Mux 的 8way 16bit(输入 a[16], b[16], c[16], d[16],e[16],f[16],g[16],h[16], sel[3],输出 out[16] )
我分析这个用在 “比如有 8路 16bit 输入,需要从中选择一种”的情况。
sel[3] = 000,001,010,011,100,101,110,111,分别可以代表 8 路选择
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux8Way16.hdl
/**
* 8-way 16-bit multiplexor.
* out = a if sel == 000
* b if sel == 001
* etc.
* h if sel == 111
*/
CHIP Mux8Way16 {
IN a[16], b[16], c[16], d[16],
e[16], f[16], g[16], h[16],
sel[3];
OUT out[16];
PARTS:
Mux4Way16(a=a, b=b, c=c, d=d, sel[0]=sel[0], sel[1]=sel[1], out=c1);
Mux4Way16(a=e, b=f, c=g, d=h, sel[0]=sel[0], sel[1]=sel[1], out=c2);
Mux16(a=c1, b=c2, sel=sel[2], out=out);
}
14、DMux4Way
这个东西,跟 Mux 是反正着的。估计用在跟Mux4Way 相反的作用上。
1bit “进” 4路选择后 1bit “出”
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux4Way.hdl
/**
* 4-way demultiplexor.
* {a,b,c,d} = {in,0,0,0} if sel == 00
* {0,in,0,0} if sel == 01
* {0,0,in,0} if sel == 10
* {0,0,0,in} if sel == 11
*/
CHIP DMux4Way {
IN in, sel[2];
OUT a, b, c, d;
PARTS:
DMux(in=in, sel=sel[1], a=c1, b=c2);
DMux(in=c1, sel=sel[0], a=a, b=b);
DMux(in=c2, sel=sel[0], a=c, b=d);
}
15、DMux8Way
1bit “进” 8路选择后 1bit “出”
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux8Way.hdl
/**
* 8-way demultiplexor.
* {a,b,c,d,e,f,g,h} = {in,0,0,0,0,0,0,0} if sel == 000
* {0,in,0,0,0,0,0,0} if sel == 001
* etc.
* {0,0,0,0,0,0,0,in} if sel == 111
*/
CHIP DMux8Way {
IN in, sel[3];
OUT a, b, c, d, e, f, g, h;
PARTS:
DMux(in=in, sel=sel[2], a=c1, b=c2);
DMux4Way(in=c1, sel[0]=sel[0], sel[1]=sel[1], a=a, b=b, c=c, d=d);
DMux4Way(in=c2, sel[0]=sel[0], sel[1]=sel[1], a=e, b=f, c=g, d=h);
}