我是靠谱客的博主 鲜艳蚂蚁,最近开发中收集的这篇文章主要介绍【计算机系统要素】使用D触发器实现寄存器、内存和计数器D触发器寄存器内存计数器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文是笔者拜读《计算机系统要素》第3章(时序逻辑)的实践项目。
本文的HDL程序所调用的组合逻辑模块来自前几篇博客。

目录

  • D触发器
  • 寄存器
    • 1比特位寄存器
    • 多比特位寄存器
  • 内存
    • 8字内存
    • 64字内存
    • 512字内存
    • 4K字内存
    • 16K字内存
  • 计数器

D触发器

在这里插入图片描述
在这里插入图片描述
DFF的输出被赋予了上个时钟周期的输入,所有的DFF门都连接同一个主时钟,所有时序芯片都在主时钟频率的协调下共同工作。

Nand门一样,DFF门在计算机体系中处于非常底层的位置,计算机中的所有时序芯片(寄存器、内存、计数器)都基于大量的DFF门。

DFF的物理实现是个复杂的任务,它使用反馈电路(仅基于Nand门)连接几个基本的逻辑门。

寄存器

1比特位寄存器

在这里插入图片描述
如果希望寄存器开始存储一个新值,可以把这个值置于in输入口,然后将load位设为1;如果希望寄存器一直存储它的内部值直到新的指令到来,就将load设置为0
在这里插入图片描述
在这里插入图片描述

CHIP Bit {
    IN in, load; // t
    OUT out; // t+1

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

内部接线o1的默认初值是false,即低电平。
输入是t时刻的,输出是t+1时刻的,该输出又是t+2时刻输出的一部分。

多比特位寄存器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
读:要读取寄存器的内容,只需获取它的输出。
写:要将新数据d写入寄存器,只需将d置于in输入管脚,并将load输入管脚的值设为1,这样,在下一个时钟周期,寄存器被赋予新的数据值,输出变成了d

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]);
}

一个寄存器的大小就是一个的宽度。

内存

在这里插入图片描述
随机访问存储器(RAM),是由n(表示内存尺寸)个w(表示内存宽度)位寄存器组成的阵列。
在这里插入图片描述
在这里插入图片描述

k是地址总线的个数。

读:要读取编号为m的寄存器,我们先将m置于address输入管脚。RAM的直接存取逻辑将选中编号为m的寄存器,于是该寄存器将它的输出发送到RAM的输出管脚,这是个不涉及时间的组合逻辑操作。

写:要将新的数据值d写入编号为m的寄存器,我们同样将m置于address输入管脚,并将d置于in管脚,然后确认load1。这样使得RAM的直接存取逻辑去选中m号寄存器,load位来使能写操作,在下一个时钟周期里,被选中的寄存器将会被赋予新的数据值dRAM的输出值也变成了d

8字内存

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

    PARTS:
    // Put your code here:
    DMux8Way(in = true, sel = address, a = ram0, b = ram1, c = ram2, d = ram3, e = ram4, f = ram5, g = ram6, h = ram7);
    // 寻址,写/读数据
    // 每个寄存器要么将数据置为in,要么维持原值不变
    And(a = ram0, b = load, out = s0);
    Register(in = in, load = s0, out = o0);
    And(a = ram1, b = load, out = s1);
    Register(in = in, load = s1, out = o1);
    And(a = ram2, b = load, out = s2);
    Register(in = in, load = s2, out = o2);
    And(a = ram3, b = load, out = s3);
    Register(in = in, load = s3, out = o3);
    And(a = ram4, b = load, out = s4);
    Register(in = in, load = s4, out = o4);
    And(a = ram5, b = load, out = s5);
    Register(in = in, load = s5, out = o5);
    And(a = ram6, b = load, out = s6);
    Register(in = in, load = s6, out = o6);
    And(a = ram7, b = load, out = s7);
    Register(in = in, load = s7, out = o7);
    // 通过八选一选择器,输出数据
    Mux8Way16(a = o0, b = o1, c = o2, d = o3, e = o4, f = o5, g = o6, h = o7, sel = address, out = out);
}

仅当某个寄存器被选中且load1,才改变该寄存器的值。
在时序逻辑中,需要经过一定的时钟周期数才能使输入流到输出;而在组合逻辑中,输入一瞬间就能流到输出。

64字内存

CHIP RAM64 {
    IN in[16], load, address[6];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in = true, sel = address[3..5], a = ram0, b = ram1, c = ram2, d = ram3, e = ram4, f = ram5, g = ram6, h = ram7);
    And(a = ram0, b = load, out = s0);
    RAM8(in = in, load = s0, address = address[0..2], out = o0);
    And(a = ram1, b = load, out = s1);
    RAM8(in = in, load = s1, address = address[0..2], out = o1);
    And(a = ram2, b = load, out = s2);
    RAM8(in = in, load = s2, address = address[0..2], out = o2);
    And(a = ram3, b = load, out = s3);
    RAM8(in = in, load = s3, address = address[0..2], out = o3);
    And(a = ram4, b = load, out = s4);
    RAM8(in = in, load = s4, address = address[0..2], out = o4);
    And(a = ram5, b = load, out = s5);
    RAM8(in = in, load = s5, address = address[0..2], out = o5);
    And(a = ram6, b = load, out = s6);
    RAM8(in = in, load = s6, address = address[0..2], out = o6);
    And(a = ram7, b = load, out = s7);
    RAM8(in = in, load = s7, address = address[0..2], out = o7);

    Mux8Way16(a = o0, b = o1, c = o2, d = o3, e = o4, f = o5, g = o6, h = o7, sel = address[3..5], out = out);
}

3位寻址芯片,低3位在芯片里寻址字。

512字内存

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

    PARTS:
    // Put your code here:
    DMux8Way(in = true, sel = address[6..8], a = ram0, b = ram1, c = ram2, d = ram3, e = ram4, f = ram5, g = ram6, h = ram7);
    And(a = ram0, b = load, out = s0);
    RAM64(in = in, load = s0, address = address[0..5], out = o0);
    And(a = ram1, b = load, out = s1);
    RAM64(in = in, load = s1, address = address[0..5], out = o1);
    And(a = ram2, b = load, out = s2);
    RAM64(in = in, load = s2, address = address[0..5], out = o2);
    And(a = ram3, b = load, out = s3);
    RAM64(in = in, load = s3, address = address[0..5], out = o3);
    And(a = ram4, b = load, out = s4);
    RAM64(in = in, load = s4, address = address[0..5], out = o4);
    And(a = ram5, b = load, out = s5);
    RAM64(in = in, load = s5, address = address[0..5], out = o5);
    And(a = ram6, b = load, out = s6);
    RAM64(in = in, load = s6, address = address[0..5], out = o6);
    And(a = ram7, b = load, out = s7);
    RAM64(in = in, load = s7, address = address[0..5], out = o7);

    Mux8Way16(a = o0, b = o1, c = o2, d = o3, e = o4, f = o5, g = o6, h = o7, sel = address[6..8], out = out);
}

4K字内存

CHIP RAM4K {
    IN in[16], load, address[12];
    OUT out[16];

    PARTS:
    // Put your code here:
    DMux8Way(in = true, sel = address[9..11], a = ram0, b = ram1, c = ram2, d = ram3, e = ram4, f = ram5, g = ram6, h = ram7);
    And(a = ram0, b = load, out = s0);
    RAM512(in = in, load = s0, address = address[0..8], out = o0);
    And(a = ram1, b = load, out = s1);
    RAM512(in = in, load = s1, address = address[0..8], out = o1);
    And(a = ram2, b = load, out = s2);
    RAM512(in = in, load = s2, address = address[0..8], out = o2);
    And(a = ram3, b = load, out = s3);
    RAM512(in = in, load = s3, address = address[0..8], out = o3);
    And(a = ram4, b = load, out = s4);
    RAM512(in = in, load = s4, address = address[0..8], out = o4);
    And(a = ram5, b = load, out = s5);
    RAM512(in = in, load = s5, address = address[0..8], out = o5);
    And(a = ram6, b = load, out = s6);
    RAM512(in = in, load = s6, address = address[0..8], out = o6);
    And(a = ram7, b = load, out = s7);
    RAM512(in = in, load = s7, address = address[0..8], out = o7);

    Mux8Way16(a = o0, b = o1, c = o2, d = o3, e = o4, f = o5, g = o6, h = o7, sel = address[9..11], out = out);
}

16K字内存

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

    PARTS:
    // Put your code here:
    DMux4Way(in = true, sel = address[12..13], a = ram0, b = ram1, c = ram2, d = ram3);
    
    And(a = ram0, b = load, out = s0);
    RAM4K(in = in, load = s0, address = address[0..11], out = o0);
    And(a = ram1, b = load, out = s1);
    RAM4K(in = in, load = s1, address = address[0..11], out = o1);
    And(a = ram2, b = load, out = s2);
    RAM4K(in = in, load = s2, address = address[0..11], out = o2);
    And(a = ram3, b = load, out = s3);
    RAM4K(in = in, load = s3, address = address[0..11], out = o3);

    Mux4Way16(a = o0, b = o1, c = o2, d = o3, sel = address[12..13], out = out);
}

计数器

指令地址计数器:内容是计算机下一时钟周期要读取和执行的指令地址。大多数情况下,计数器在每个时钟周期内做简单的加1操作,其它情况下要进行跳转,甚至置0(重新执行程序)。

我们需要一个可重载、可重置的计数器。

inc=1时,计数器在每个时钟周期自加,输出值out(t)=out(t-1)+1;如果想要将计数器重置为0,就将reset置为1;如果想要将其初始化为某个计数值d,就将d置于in输入管脚然后将load位置1
在这里插入图片描述
在这里插入图片描述

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

    PARTS:
    // Put your code here:
    Xor16(a = in, b = in, out = reseto); //reset输出
    Inc16(in = ot, out = inco); // inc输出
    
    Mux16(a = in, b = reseto, sel = reset, out = o1);
    Or(a = reset, b = load, out = or1);
    Mux16(a = inco, b = o1, sel = or1, out = o2);

    Or(a = or1, b = inc, out = or2);
    Register(in = o2, load = or2, out = out);
    Register(in = o2, load = or2, out = ot);
}

注意loadincreset的优先级不一样。

最后

以上就是鲜艳蚂蚁为你收集整理的【计算机系统要素】使用D触发器实现寄存器、内存和计数器D触发器寄存器内存计数器的全部内容,希望文章能够帮你解决【计算机系统要素】使用D触发器实现寄存器、内存和计数器D触发器寄存器内存计数器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部