概述
本文是笔者拜读《计算机系统要素》第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触发器寄存器内存计数器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复