504-访存指令的控制信号
# 504-访存指令的控制信号
对于MIPS这样的指令系统来说, 其运算指令是不能直接访问存储器的, 因此,我们还需要设计单独的访存指令, 用来完成寄存器和存储器之间的数据传输。 在这一节,我们就来看一看这一类访存指令是如何生成控制信号的。
对于我们要实现的这个处理器,访存指令都是属于I型指令, 一条是load,一条是store,我们分别来进行分析。
# load指令
对于load指令, 首先当然也是取指;然后根据运算出的地址,访问数据存储器,并将读出的内容写入到rt指定的寄存器中; 最后,是更新PC寄存器。 那第一步和第三步,与运算指令都是一样的,在这里,我们就只讲解第二步相关的操作。
这是我们的数据通路,如果当前IFU 取回的是一条load指令,那这些控制信号将会如何设置呢? 首先,下一条指令的地址应该还是采用PC+4的方式。 然后我们来看寄存器堆这一边,rs和rt都是固定连接到了指令编码的对应位域, 因此,busA和busB这两组信号上,分别是由rs和rt所指定的寄存器的内容。 但我们要注意,对于这条指令,我们想要运算的是rs寄存器中的内容和立即数的符号扩展进行加法。 因此,对于ALU的第二个操作数的来源, 我们应该通过这个多选器,选择通道1,并且设置扩展部件为符号扩展的功能。 这样,指令位域中的16位立即数就会经过符号扩展,最终连接到了ALU的第二个输入端, 而我们发送到ALU的控制信号,则是要设置为加法运算。 这样,ALU就会完成了访存地址的运算, 并将地址信号送到数据存储器的地址输入端。
同时我们也要注意,busB上的信号,也会被连接到数据存储器的数据输入端, 虽然我们并不需要它,但是这根信号仍然会把Rp所指定的寄存器的内容送过来。 所以我们需要设置数据存储器的写使能信号, 把它设为0,保证了数据存储器的内容不会发生改变。
然后我们来看最后这个多选器, 这个多选器的两个输入,一个是ALU的运算结果,就是访存的地址; 另一个是从数据存储器当中,读出的数据。 那么对于这条指令,我们显然希望把后者送到寄存器堆当中去, 因此对于这个多选器来说,我们需要设置它的选择信号为1, 这样我们就可以把数据存储器的输出传送到寄存器堆的数据输入端, 而且因为我们要写入rt所指定的寄存器, 所以我们需要设置寄存器堆的写使能信号为有效, 并把写入寄存器编号的来源设置为rt, 这样,在下一个时钟上升沿到来的时候, 数据存储器输出的内容,就会被写入到rt所指定的寄存器当中去了,而且在同样的这个时钟上升沿,PC寄存器的内容也不会被更新为PC+4, 这就是load指令所完成的操作。
# store指令
然后我们来看store指令, store指令也分为三步,同样,我们也只看其中的第二步。 对于store指令,我们也需要将rs寄存器中的内容和立即数的符号扩展进行加法运算,并以此作为地址访问数据存储器, 不过不是读出,而是写入,
因此,对应到数据通路上,我们就直接标出了对于store指令,有效的这些信号。 那这些控制信号又该如何设置呢? 那你不妨自己想一想,然后我们一起快速地浏览一遍。
对于IFU,我们要选择下一条指令的地址, 仍然是PC+4,我们要选择ALU的数据的输入, 现在我们选的是立即数的符号扩展, 而对于ALU,我们依然要选择加法的运算类型, ALU的运算结果,依然是一个地址,会被送到数据存储器上, 但是与之前不同的是,这条指令要完成向数据存储器的写操作, 所以在这里,我们会把数据存储器的写使能信号置为有效。 这样,在下一个时钟的上升沿,数据存储器 就会采样其数据输入端的信号,但这个输入端的信号又是什么呢? 我们可以看一看,实际上它连到了busB,而 busB是由rt这个信号所指定的寄存器中的内容。 因此,在下一个时钟上升沿到来的时候, 数据存储器会根据ALU算出来的地址,选中对应的存储单元, 并采样这个来自rt寄存器当中的内容, 将它存到对应的存储单元中去。 对于store指令来说,它就完成了它所需要做的主体的操作, 但是对于这个数据通路,我们必须要把剩下的控制信号都设置完整。 我们来看后面这个多选器,因为对store指令,我们不需要改写寄存器堆的内容, 所以无论选择哪个通路,都是没有意义的。 在这里,我们就设置这个控制信号,可以是0,也可以是1,就用x来进行标记。 那这样,这个多选器总会选出一组信号, 最终送到寄存器堆的数据输入端。 不过,这没有关系,我们只需要设置寄存器堆的写使能信号为无效, 在时钟上升沿到来的时候,寄存器堆的内容就不会发生改变。也正因为如此, 这个要写入的寄存器编号,无论设成rb还是rt,也都是可以的, 这就是对于store指令的控制信号的设置方法。
# 小结
现在,我们已经掌握了访存指令是如何生成控制信号的, 再加上之前的运算指令,我们就可以编写程序,让计算机完成相应的任务了。 不过,如果我们想编写出功能更为强大的程序, 那只有运算指令和访存指令是不够的,我们还需要改变程序流向的分支指令, 这一点,我们在下一节继续分析。