组合逻辑电路combinational logic out[t] = function(in[t])

时序逻辑电路clock-based sequential logic out[t] = function(in[t-1])

作业顺序

image-20210102103914837.png

1位寄存器 Bit

根据作业的Given,可以看到可以直接使用D触发器(Data Flip-Flop, DFF gate)。

D触发器 DFF

image-20210102113648602.png

DFF的作用,out[t+1] = in[t]
image-20210102120030632.png

  1. // This file is part of www.nand2tetris.org
  2. // and the book "The Elements of Computing Systems"
  3. // by Nisan and Schocken, MIT Press.
  4. // File name: projects/03/a/Bit.hdl
  5. /**
  6. * 1-bit register:
  7. * If load[t] == 1 then out[t+1] = in[t]
  8. * else out does not change (out[t+1] = out[t])
  9. */
  10. CHIP Bit {
  11. IN in, load;
  12. OUT out;
  13. PARTS:
  14. // Put your code here:
  15. Mux(a=dffin, b=in, sel=load, out=nowin);
  16. DFF(in=nowin, out=out, out=dffin);
  17. }

出现的主要问题还是HDL不熟悉,不知道可以直接将一个临时变量(不是从已知输入计算得来的)直接作为输入。花了半天,一直在想如何处理一开始没有dffin的问题。最后还是看了论坛的中帖子,才解决。

16位寄存器 Register

1位寄存器进行16位并行处理。

// 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/03/a/Register.hdl

/**
 * 16-bit register:
 * If load[t] == 1 then out[t+1] = in[t]
 * else out does not change
 */

CHIP Register {
    IN in[16], load;
    OUT out[16];

    PARTS:
    Bit(in=in[0], load=load, out=out[0]);
    Bit(in=in[1], load=load, out=out[1]);
    Bit(in=in[2], load=load, out=out[2]);
    Bit(in=in[3], load=load, out=out[3]);
    Bit(in=in[4], load=load, out=out[4]);
    Bit(in=in[5], load=load, out=out[5]);
    Bit(in=in[6], load=load, out=out[6]);
    Bit(in=in[7], load=load, out=out[7]);
    Bit(in=in[8], load=load, out=out[8]);
    Bit(in=in[9], load=load, out=out[9]);
    Bit(in=in[10], load=load, out=out[10]);
    Bit(in=in[11], load=load, out=out[11]);
    Bit(in=in[12], load=load, out=out[12]);
    Bit(in=in[13], load=load, out=out[13]);
    Bit(in=in[14], load=load, out=out[14]);
    Bit(in=in[15], load=load, out=out[15]);
}

RAM8

image-20210102205743611.png
image-20210102222432137.png

没有提示,真的挺难想的。又花了一个晚上,最后还是参考别人的代码

看着似乎和上面的Implementation tips有些出入,其实主要是没有Dmux8way16这个组件的原因,这一点论坛中也有很多人这么认为。

我看了通过的代码,逻辑是先用Dmux8way根据address标记每个寄存器的状态,load=1表示写入,load=0表示读出(输出与上次相同)。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/03/a/RAM8.hdl

/**
 * Memory of 8 registers, each 16 bit-wide. Out holds the value
 * stored at the memory location specified by address. If load==1, then 
 * the in value is loaded into the memory location specified by address 
 * (the loaded value will be emitted to out from the next time step onward).
 */

CHIP RAM8 {
    IN in[16], load, address[3];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in=load, sel=address, a=loada, b=loadb, c=loadc, d=loadd, e=loade, f=loadf, g=loadg, h=loadh);

    Register(in=in, load=loada, out=out0);
    Register(in=in, load=loadb, out=out1);
    Register(in=in, load=loadc, out=out2);
    Register(in=in, load=loadd, out=out3);
    Register(in=in, load=loade, out=out4);
    Register(in=in, load=loadf, out=out5);
    Register(in=in, load=loadg, out=out6);
    Register(in=in, load=loadh, out=out7);

    Mux8Way16(a=out0, b=out1, c=out2, d=out3, e=out4, f=out5, g=out6, h=out7, sel=address, out=out);
}

RAM512

其他RAM都是类似的,高位作为选择下一级RAM的选择器,低位作为下一级RAM内的地址。

// This file is part of the materials accompanying the book 
// "The Elements of Computing Systems" by Nisan and Schocken, 
// MIT Press. Book site: www.idc.ac.il/tecs
// File name: projects/03/b/RAM512.hdl

/**
 * Memory of 512 registers, each 16 bit-wide. Out holds the value
 * stored at the memory location specified by address. If load==1, then 
 * the in value is loaded into the memory location specified by address 
 * (the loaded value will be emitted to out from the next time step onward).
 */

CHIP RAM512 {
    IN in[16], load, address[9];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in=load, sel=address[0..2], a=loada, b=loadb, c=loadc, d=loadd, e=loade, f=loadf, g=loadg, h=loadh);
    RAM64(in=in, load=loada, address=address[3..8], out=outa);
    RAM64(in=in, load=loadb, address=address[3..8], out=outb);
    RAM64(in=in, load=loadc, address=address[3..8], out=outc);
    RAM64(in=in, load=loadd, address=address[3..8], out=outd);
    RAM64(in=in, load=loade, address=address[3..8], out=oute);
    RAM64(in=in, load=loadf, address=address[3..8], out=outf);
    RAM64(in=in, load=loadg, address=address[3..8], out=outg);
    RAM64(in=in, load=loadh, address=address[3..8], out=outh);
    Mux8Way16(a=outa, b=outb, c=outc, d=outd, e=oute, f=outf, 
              g=outg, h=outh, sel=address[0..2], out=out);
}

RAM16K

这个提一下,其他的其实都是一个模子,换几个参数,最后一个是由4个RAM4K构成的,也应该使用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/03/b/RAM16K.hdl

/**
 * Memory of 16K registers, each 16 bit-wide. Out holds the value
 * stored at the memory location specified by address. If load==1, then 
 * the in value is loaded into the memory location specified by address 
 * (the loaded value will be emitted to out from the next time step onward).
 */

CHIP RAM16K {
    IN in[16], load, address[14];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux4Way(in=load, sel=address[0..1], a=loada, b=loadb, c=loadc, d=loadd);
    RAM4K(in=in, load=loada, address=address[2..13], out=outa);
    RAM4K(in=in, load=loadb, address=address[2..13], out=outb);
    RAM4K(in=in, load=loadc, address=address[2..13], out=outc);
    RAM4K(in=in, load=loadd, address=address[2..13], out=outd);
    Mux4Way16(a=outa, b=outb, c=outc, d=outd, sel=address[0..1], out=out);
}

程序计数器 PC

image-20210103140937625.png

我感觉对这个给出的if-else太具有迷惑性了。自己有两个想法,一是选出优先级最高的if-else,把其他的屏蔽掉;另一个思路,就是从后向前判断,前面的优先级高,后计算,把优先级低的覆盖掉了。

但都是因为Register没处理好,没做出来正确结果。感觉上类似1位寄存器,但没写出来这种循环的效果。

这里说一下我对Register作用的理解:为了实现out[t+1] = x,前面的操作都是在选择x最符合哪一个条件。最后再去”访问寄存器”,修改结果。

最终还是参考设计图,才写出来。

// 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/03/a/PC.hdl

/**
 * A 16-bit counter with load and reset control bits.
 * if      (reset[t] == 1) out[t+1] = 0
 * else if (load[t] == 1)  out[t+1] = in[t]
 * else if (inc[t] == 1)   out[t+1] = out[t] + 1  (integer addition)
 * else                    out[t+1] = out[t]
 */

CHIP PC {
    IN in[16],load,inc,reset;
    OUT out[16];

    PARTS:
    // Put your code here:
    Inc16(in=lastout, out=outinc);
    Mux16(a=lastout, b=outinc, sel=inc, out=ininc);
    Mux16(a=ininc, b=in, sel=load, out=inload);
    Mux16(a=inload, b=false, sel=reset, out=inreset);
    Register(in=inreset, load=true, out=out, out=lastout);
}

作业提交

image-20210103201417279.png

花了三天,才算提上交,很多并不是自己想出来的。可能是因为有些类似if-else的处理有很多技巧。

总结

第三周的作业费时较久,一方面是因为自己确实对组合逻辑电路和时序逻辑电路等相关概念和基本的组件等不熟悉,对中文的概念就不熟悉,对英文的就更头痛,想到去年写数据库的那些作业时也是很头疼,可能一晚才能写出来一问。

不过,能给自己带来启发,带来收获,这已经很开心了。😄