0295-Nand-时序逻辑

环境

  • Time 2023-07-07

前言

说明

参考:https://www.nand2tetris.org/
参考:《编码:隐匿在计算机背后的语言》

目标

接上一节,实现 Bit、Register、RAM8、RAM64、RAM512、RAM4K、RAM16K、PC。

Bit

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

CHIP Bit {
    IN in, load;
    OUT out;

    PARTS:
    // Put your code here:
    Mux(a = d, b = in, sel = load, out = o);
    DFF(in = o, out = out, out = d);
}

Register

/**
 * 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:
    // Put your code here:
    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

/**
 * 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 = la, b = lb, c = lc, d = ld,
        e = le, f = lf, g = lg, h = lh);

    Register(in = in, load = la, out = oa);
    Register(in = in, load = lb, out = ob);
    Register(in = in, load = lc, out = oc);
    Register(in = in, load = ld, out = od);
    Register(in = in, load = le, out = oe);
    Register(in = in, load = lf, out = of);
    Register(in = in, load = lg, out = og);
    Register(in = in, load = lh, out = oh);

    Mux8Way16(a = oa, b = ob, c = oc, d = od, e = oe, f = of, g = og,
        h = oh, sel = address, out = out);
}

RAM64

/**
 * Memory of 64 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 RAM64 {
    IN in[16], load, address[6];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in = load, sel = address[0..2], a = ra, b = rb, c = rc,
        d = rd, e = re, f = rf, g = rg, h = rh);

    RAM8(in = in, load = ra, address = address[3..5], out = oa);
    RAM8(in = in, load = rb, address = address[3..5], out = ob);
    RAM8(in = in, load = rc, address = address[3..5], out = oc);
    RAM8(in = in, load = rd, address = address[3..5], out = od);
    RAM8(in = in, load = re, address = address[3..5], out = oe);
    RAM8(in = in, load = rf, address = address[3..5], out = of);
    RAM8(in = in, load = rg, address = address[3..5], out = og);
    RAM8(in = in, load = rh, address = address[3..5], out = oh);

    Mux8Way16(a = oa, b = ob, c = oc, d = od, e = oe, f = of, g = og,
        h = oh, sel = address[0..2], out = out);
}

RAM512

/**
 * 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 = ra, b = rb, c = rc,
        d = rd, e = re, f = rf, g = rg, h = rh);

    RAM64(in = in, load = ra, address = address[3..8], out = oa);
    RAM64(in = in, load = rb, address = address[3..8], out = ob);
    RAM64(in = in, load = rc, address = address[3..8], out = oc);
    RAM64(in = in, load = rd, address = address[3..8], out = od);
    RAM64(in = in, load = re, address = address[3..8], out = oe);
    RAM64(in = in, load = rf, address = address[3..8], out = of);
    RAM64(in = in, load = rg, address = address[3..8], out = og);
    RAM64(in = in, load = rh, address = address[3..8], out = oh);

    Mux8Way16(a = oa, b = ob, c = oc, d = od, e = oe, f = of, g = og,
        h = oh, sel = address[0..2], out = out);
}

RAM4K

/**
 * Memory of 4K 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 RAM4K {
    IN in[16], load, address[12];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in = load, sel = address[0..2], a = ra, b = rb, c = rc,
        d = rd, e = re, f = rf, g = rg, h = rh);

    RAM512(in = in, load = ra, address = address[3..11], out = oa);
    RAM512(in = in, load = rb, address = address[3..11], out = ob);
    RAM512(in = in, load = rc, address = address[3..11], out = oc);
    RAM512(in = in, load = rd, address = address[3..11], out = od);
    RAM512(in = in, load = re, address = address[3..11], out = oe);
    RAM512(in = in, load = rf, address = address[3..11], out = of);
    RAM512(in = in, load = rg, address = address[3..11], out = og);
    RAM512(in = in, load = rh, address = address[3..11], out = oh);

    Mux8Way16(a = oa, b = ob, c = oc, d = od, e = oe, f = of, g = og,
        h = oh, sel = address[0..2], out = out);
}

RAM16K

/**
 * 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 = ra, b = rb, c = rc, d = rd);

    RAM4K(in = in, load = ra, address = address[2..13], out = oa);
    RAM4K(in = in, load = rb, address = address[2..13], out = ob);
    RAM4K(in = in, load = rc, address = address[2..13], out = oc);
    RAM4K(in = in, load = rd, address = address[2..13], out = od);

    Mux4Way16(a = oa, b = ob, c = oc, d = od, sel = address[0..1], out = out);
}

PC


/**
 * 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:
    /** 如果inc为1,将之前输出的值加1 */
    Inc16(in = ao, out = o);
    Mux16(a = ao, b = o, sel = inc, out = o1);

    /** 如果load为1,从输入读取地址 */
    Mux16(a = o1, b = in, sel = load, out = o2);
    /** 如果reset为1,从直接为0 */
    Mux16(a = o2, b = false, sel = reset, out = o3);

    /** 使用寄存器保存之前的值 */
    Register(in = o3, load = true, out = out, out = ao);
}

总结

通过之前建立起来的逻辑门,实现了算术逻辑单元 ALU。

附录

posted @ 2025-10-30 17:47  jiangbo4444  阅读(6)  评论(0)    收藏  举报