计算机系统要素-从零开始构建现代计算机--第五章,03-内存/CPU/HACK计算机电路图及HDL

本节将构建内存,CPU,以及完整的HACK计算机。
画图软件为ubuntu的dia
整个计算机只有两种基本电路:组合逻辑电路和时序电路,基本构件分别是NAND和DFF,而DFF也是由NAND构建得来的,只是连接方式稍有不同(参见第三章,01-D触发器与1比特存储器实现)。
从第一章到现在,从基本的与非门开始,所有的电路的连接,都是通过布尔代数指引的。足见布尔代数在计算机发展过程中的奠基性地位。
这些电路功能上都很简单,用代码来实现是几行就可以搞定的事情,然而以此为起点,作为基本构件,可以完成不计其数的复杂任务,可见设计思想,本质把握是多么关键!

内存

HACK计算机的内存是一段包含物理内存、键盘映像、屏幕映像的连续内存地址空间,内存映像的操作与普通的内存段有所不同,因此在连接上要加以区分。

组织架构

在这里插入图片描述

电路图

在这里插入图片描述

HDL

参考https://github.com/woai3c/nand2tetris/blob/master/05/Memory.hdl

CHIP Memory {
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // 根据最大的两个地址选出对应的操作 00 01都是RAM 10是屏幕 11是键盘
    DMux4Way(in = load, sel = address[13..14], a = loadA, b = loadB, c = loadS, d = loadK);

    // 00|01 
    Or(a = loadA, b = loadB, out = loadRam);
    
    RAM16K(in = in, load = loadRam, address = address[0..13], out = outRam);
    Keyboard(out = outK);
    Screen(in = in, load = loadS, address = address[0..12], out = outS);

    // 根据最大的两个地址选出对应的操作 00 01都是RAM 10是屏幕 11是键盘
    Mux4Way16(a = outRam, b = outRam, c = outS, d = outK, sel = address[13..14], out = out);
}

CPU

CPU是最复杂的部件,其有6个控制位,有两种指令,有多个输出,因此电路上是比较复杂的

组织架构

在这里插入图片描述

电路图

本书构建的电路中最复杂的就是它了,虽然复杂,按HDL来画却并不会多花多少时间。
在这里插入图片描述

HDL

来自https://github.com/woai3c/nand2tetris/blob/master/05/CPU.hdl

CHIP CPU {

    IN  inM[16],         // M value input  (M = contents of RAM[A])
        instruction[16], // Instruction for execution
        reset;           // Signals whether to re-start the current
                         // program (reset==1) or continue executing
                         // the current program (reset==0).

    OUT outM[16],        // M value output
        writeM,          // Write to M? 
        addressM[15],    // Address in data memory (of M)
        pc[15];          // address of next instruction

    PARTS:
    // 指令的最大地址位 如果为1则是C指令 为0则是A指令
    Not(in = instruction[15], out = isA);
    // 对isC再次取返 判断是否C指令 读者可以自行用1或0代入想像一下 isC实际上就是instruction[15]的值
    Not(in = isA, out = isC);

    // 如果是C指令并且指令指定ALU输出存到AR 则将ALU的输出 输入到AR 否则将指令输入到AR
    And(a = isC, b = instruction[5], out = isLoadAluOut);
    Mux16(a = instruction, b = outALU, sel = isLoadAluOut, out = inAR);

    // 如果为A指令或指令指定输出到A处理器 则将AR的load位置1
    Or(a = isA, b = instruction[5], out = isLoadAR);
    ARegister(in = inAR, load = isLoadAR, out = outAR, out[0..14] = addressM);

    // 根据指令中的a位域判断将AR的输出或者inM输入到ALU
    Mux16(a = outAR, b = inM, sel = instruction[12], out = outAM);

    // 如果是C指令并且规定写入到M
    And(a = isC, b = instruction[3], out = writeM);

    // 如果是C指令并且规定写入到DR
    And(a = instruction[4], b = isC, out = isLoadDR); 
    DRegister(in = outALU, load = isLoadDR, out = outDR);


    And(a = isC, b = instruction[6], out = no);
    And(a = isC, b = instruction[7], out = f);
    And(a = isC, b = instruction[8], out = ny);
    And(a = isC, b = instruction[9], out = zy);
    And(a = isC, b = instruction[10], out = nx);
    And(a = isC, b = instruction[11], out = zx);

    ALU(x = outDR, y = outAM, zx = zx, nx = nx, zy = zy, ny = ny, f = f, no = no, out = outALU, out = outM, zr=zr, ng=ng);

    // 根据j位域和ALU的zr、ng位来判断跳转
    And(a = isC, b = instruction[0], out = isGT);
    And(a = isC, b = instruction[1], out = isEQ);
    And(a = isC, b = instruction[2], out = isLT);

    And(a = ng, b = isLT, out = isLtJump);
    And(a = zr, b = isEQ, out = isEqJump);

    // 输出是否大于0
    Not(in = ng, out = notNg);
    Not(in = zr, out = notZr);
    And(a = notNg, b = notZr, out = isOutGt);
    
    And(a = isOutGt, b = isGT, out = isGtJump);

    Or(a = isLtJump, b = isEqJump, out = isJump);
    Or(a = isJump, b = isGtJump, out = jump);

    PC(in = outAR, load = jump, inc = true, reset = reset, out[0..14] = pc);
}

HACK计算机

每个时钟周期内,CPU从ROM32K中取指令,从Memory取数据,输出计算结果和下一条命令所在的地址pc,同时有个reset信号表示pc是否从头开始。

组织架构

在这里插入图片描述

电路图

在这里插入图片描述

HDL

CHIP Computer {

    IN reset;

    PARTS:
    CPU(reset = reset, inM = outMemory, instruction = outROM, outM = outMvalue, writeM = isLoadValue, addressM = outAddressM, pc = outPC);
    Memory(in = outMvalue, load = isLoadValue, address = outAddressM, out = outMemory);
    ROM32K(address = outPC, out = outROM);
}
  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值