美文网首页From Nand To Tetris 从与非门到俄罗斯方块
21、P1 W3 U3.6 总结、作业3答案(待深入)

21、P1 W3 U3.6 总结、作业3答案(待深入)

作者: shazizm | 来源:发表于2019-08-06 23:25 被阅读0次

    视频:
    如果本次课程对应的 Coursera 的视频打不开,可以点击下面链接
    P1W3U3.6 - Perspectives

    1. DFF没有实现,在实际中是怎么回事呢?
      没太明白,视频 00:40 到 5:45 (待深入研究)

    2. RAM 在电脑是唯一的存储吗?
      RAM是最重要的。存数据和命令。断电丢失存储。

    ROM只读存储单元。断电不丢失存储。一般用来启动系统的程序存在这里。

    Flash存储单元。集合了RAM和ROM的有点。

    Cache存储。这里有一种取舍,更大更便宜更慢的存储(比如硬盘)。还有一种离CPU很近,不仅小而且贵不过速度奇快。Cache就是后者。

    物理角度,各种存储的实现可能不同。但是从逻辑的角度来看。他们都是寻址,然后从寄存器里读数据。这个规律是不变的。

    求:
    1bit Register
    16-bit Register
    RAM8
    RAM64
    RAM512
    RAM4k
    RAM16k
    PC

    一、 Bit (1bit 寄存器)

    1、分析

    回顾17、P1 W3 U3.2 触发器(Flip-Flops)

    DFF硬件模拟器已给,Mux第一周作业

    利用一个mux 和一个 dff

    2、HDL

    如上图DFF图标有倒三角,是一个时序电路,写法貌似软件模拟上跟普通写逻辑没啥区别。

    //注:Mux里sel = 0,out = a。对应load = 0 ,输出上一步的dffout(读操作)
    Mux(a = dffout, b = a, sel = load, out = muxout); 
    
    //这种out 多赋值的情况第二周作业里应该就见到了。
    DFF(in = muxout, out = dffout, 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/03/a/Bit.hdl
    
    /**
     * 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里sel = 0,out = a,对应load = 0 ,还是输出上一步的dffout(读操作)
        Mux(a = dffout, b = in, sel = load, out = muxout); 
    
        //这种out 多赋值的情况第二周作业里应该就见到了。
        DFF(in = muxout, out = dffout, out = out); 
    }
    
    

    3、测试

    测试成功

    PS:第一周作业详情说了如何用 Hardware Simulator 硬件模拟器 进行测试。这里就贴一张图

    Hardware_Simulator 本文最开始 软件处下载



    二、Register(16-bit 寄存器)

    1、分析

    貌似就是串16个bit,类似第一周的And16.


    2、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/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:
        // 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]);
    }
    
    

    3、测试

    测试成功



    三、RAM8(8个 16-bit 寄存器)

    1、分析

    因为后面几个RAMxxx都类似,就在这一起分析了,后面就省略了

    选 RAM8 里的 一个 Register 进行设置数据

    load 为1 时,addr 给一个 sel[k],选择出一个寄存器,写

    //伪代码
    // in 输入 1bit、sel[3] 输入选项。 
    // 输出 8路1bit,被sel选中的路,输出in的状态。其它7路还输出之前的状态。
    DMux8Way { 
        IN in=load, sel[3] = addr[k];
        OUT a, b, c, d, e, f, g, h; // 输出决定哪个寄存器 进行 load操作
    }
    
    Register(in = in,load = DMux8Way输出的out ,out = outa)
    Register(in = in, load = b, out = outb)
    Register(in = in, load = c, out = outc)
    ...
    

    选 RAM8 里的 一个 Register 进行读数据

    8个 Register 需要用 address 来选择,选择就用Mux,有8路要选择来操作读。第一周作业貌似做过一个 Mux8Way16。

    //伪代码
    Mux8Way16(
    a = 1路[16], // 代表第0个寄存器的状态,outa
    b = 2路[16], // outb
    c = 3路[16], // outc
    d = ...,
    e = ...,
    f = ...,
    g = ...,
    h = 8路[16], 
    sel=addr[k], 
    out = out[16])
    

    2、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/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=outa);
        Register(in=in, load=loadb, out=outb);
        Register(in=in, load=loadc, out=outc);
        Register(in=in, load=loadd, out=outd);
        Register(in=in, load=loade, out=oute);
        Register(in=in, load=loadf, out=outf);
        Register(in=in, load=loadg, out=outg);
        Register(in=in, load=loadh, out=outh);
    
        Mux8Way16(a=outa, b=outb, c=outc, d=outd,
                  e=oute, f=outf, g=outg, h=outh, sel=address, out=out);
    }
    



    四、RAM64(8个 RAM8)

    那以此类推,这个就把上一个的Register换成RAM8,不过RAM8上比Register多一个address[3],而RAM64也需要3位来选择8个RAM8。
    这里需要把RAM64的 address[6],拆分一下

    2、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/03/a/RAM64.hdl
    
    /**
     * 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:
        // RAM64 八选一 RAM8 ,用 address 的[0][1][2]
        DMux8Way(in=load, sel=address[0..2], a=loada, b=loadb, c=loadc, d=loadd,
                                             e=loade, f=loadf, g=loadg, h=loadh);
    
        // RAM8 里的3位,用 address的[3][4][5]
        RAM8(in=in, load=loada, address=address[3..5], out=outa);
        RAM8(in=in, load=loadb, address=address[3..5], out=outb);
        RAM8(in=in, load=loadc, address=address[3..5], out=outc);
        RAM8(in=in, load=loadd, address=address[3..5], out=outd);
        RAM8(in=in, load=loade, address=address[3..5], out=oute);
        RAM8(in=in, load=loadf, address=address[3..5], out=outf);
        RAM8(in=in, load=loadg, address=address[3..5], out=outg);
        RAM8(in=in, load=loadh, address=address[3..5], 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);
    }
    



    五、RAM512(8个 RAM64)

    同理上面RAM64

    2、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/03/b/RAM512.hdl
    
    /**
     * Memory of 512 registers, each 16-bit wide.  
     * The chip facilitates read and write operations, as follows:
     *     Read:  out(t) = RAM512[address(t)](t)
     *     Write: If load(t-1) then RAM512[address(t-1)](t) = in(t-1)
     * In words: the chip always outputs the value stored at the memory 
     * location specified by address. If load == 1, the in value is loaded 
     * into the memory location specified by address.  This value becomes 
     * available through the out output starting from the next time step.
     */
    
    CHIP RAM512 {
        IN in[16], load, address[9];
        OUT out[16];
    
        PARTS:
    
        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);
    }
    



    六、RAM4k(8个 RAM512)

    同理上面

    2、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/03/b/RAM4K.hdl
    
    /**
     * 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=loada, b=loadb, c=loadc, d=loadd,
                                             e=loade, f=loadf, g=loadg, h=loadh);
    
        RAM512(in=in, load=loada, address=address[3..11], out=outa);
        RAM512(in=in, load=loadb, address=address[3..11], out=outb);
        RAM512(in=in, load=loadc, address=address[3..11], out=outc);
        RAM512(in=in, load=loadd, address=address[3..11], out=outd);
        RAM512(in=in, load=loade, address=address[3..11], out=oute);
        RAM512(in=in, load=loadf, address=address[3..11], out=outf);
        RAM512(in=in, load=loadg, address=address[3..11], out=outg);
        RAM512(in=in, load=loadh, address=address[3..11], 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)

    稍微有点小变化,其它同理上面

    2、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/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

    1、分析

    计数器的逻辑描述如下:
    如果 reset[t] == 1 那么 PC 的 out[t+1] = 0 (out 重置到 0步)
    如果 reset[t] !== 1
    那么再判断
    如果 load[t] ==1 那么 PC 的 out[t+1] = in[t] (out 跳转到 in步)
    如果 load[t] !==1
    那么再判断
    如果 inc[t] == 1 那么 PC 的 out[t+1] = out[t] + 1 (out 下一步)
    如果以上都不是 那么 out[t+1] = out[t] (out 保持不变)

    解题思路:
    可以想到依次用3 个 Mux 表示 reset、load、inc的选择
    HDL的顺序可能得反着写。
    先做 inc 自增1, Inc(in = feedback,out = outinc)
    再做inc ,Mux(...)
    再做load, Mux(a = outinc,b = in[16], sel = load ,out = outload )
    最后判断清零reset Mux(...,out= feadback, out = out)
    最后容易忽略的是要加入合适的时序逻辑。来使PC具有时序性。

    计数器

    2、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/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=feedback, out=incout);
    
        Mux16(a=feedback, b=incout, sel=inc, out=m1); //sel为1时,做加1操作
        Mux16(a=m1, b=in, sel=load, out=m2); //sel(load)为1时,out = in
        Mux16(a=m2, b=false, sel=reset, out=m3); //sel为0时,选a。reset=1,选b
    
        //加寄存器的目的是为了引入时序,上面的Inc和Mux都是没有时序的。
        //有了时序,feedback估计才能起作用。
        Register(in=m3, load=true, out=feedback, out=out); //load =true时,out=in。反之out等于上一个clock的out
    }
    
    

    3、测试

    测试成功。

    这周课,引入了时序逻辑,由于老师隐藏了DFF和时钟脉冲这些影响学习的因素。使我们更容易理解。但同时这里的时序逻辑电路在物理上真正是如何的实现的,就有待之后去发现了。你满足这样虚拟的CPU实现方式嘛?

    不,你不满足。

    相关文章

      网友评论

        本文标题:21、P1 W3 U3.6 总结、作业3答案(待深入)

        本文链接:https://www.haomeiwen.com/subject/pxogdctx.html