本文是笔者拜读《计算机系统要素》第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管脚,然后确认load为1。这样使得RAM的直接存取逻辑去选中m号寄存器,load位来使能写操作,在下一个时钟周期里,被选中的寄存器将会被赋予新的数据值d,RAM的输出值也变成了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);
}
仅当某个寄存器被选中且
load为1,才改变该寄存器的值。
在时序逻辑中,需要经过一定的时钟周期数才能使输入流到输出;而在组合逻辑中,输入一瞬间就能流到输出。
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);
}
注意
load、inc和reset的优先级不一样。
最后
以上就是鲜艳蚂蚁最近收集整理的关于【计算机系统要素】使用D触发器实现寄存器、内存和计数器D触发器寄存器内存计数器的全部内容,更多相关【计算机系统要素】使用D触发器实现寄存器、内存和计数器D触发器寄存器内存计数器内容请搜索靠谱客的其他文章。
发表评论 取消回复