在单周期数据路径中加载半字和加载字节

ahe*_*ang 5 verilog mips cpu-architecture vhdl

有一个问题已经被问到将负载字节实现到单周期数据路径而不必更改数据存储器,解决方案如下.

替代文字http://img214.imageshack.us/img214/7107/99897101.jpg

这实际上是一个非常现实的问题; 大多数存储器系统完全基于字,并且单个字节通常仅在处理器内部处理.当您在许多计算机上看到"总线错误"时,这通常意味着处理器尝试访问未正确字对齐的内存地址,并且内存系统引发了异常.无论如何,因为字节地址可能不是4的倍数,所以我们不能直接将它们传递给内存.但是,我们仍然可以得到任何字节,因为每个字节都可以在某个字中找到,所有字地址都是4的倍数.所以我们要做的第一件事就是确保我们得到正确的字.如果我们取地址的高30位(即ALUresult [31-2])并将它们与低端的两个0位组合(这就是"左移2"单元真正做的那样),我们有包含所需字节的字的字节地址.这只是字节自己的地址,向下舍入到4的倍数.这个改变意味着lw现在也会将地址舍入到4的倍数,但这没关系,因为非对齐地址无论如何都不适用于lw单元.好的,现在我们从内存中获取数据字.我们如何得到我们想要的字节?好吧,请注意,字中字节的字节偏移量仅由字节地址的低2位给出.因此,我们只需使用这两个位来使用多路复用器从字中选择适当的字节.注意使用big-endian字节编号,适用于MIPS.接下来,我们必须将字节零扩展到32位(即,只将其与高端的24个零组合),因为问题指定这样做.实际上,在这个问题中这是一个轻微的错误:实际上,lbu指令对字节进行零扩展,但是lb符号扩展它.那好吧.最后,我们必须扩展MemtoReg控制的多路复用器以接受一个新输入:lb情况的零扩展字节.MemtoReg控制信号必须加宽到2位.原始的0和1情况分别变为00和01,我们添加了一个新的情况10,仅用于lb的情况.

即使在阅读了解释之后,我也不太明白它是如何工作的,特别是关于左移ALU结果为2会给出字节地址......这怎么可能?所以,如果我想加载一个半字,那么我会做一个左移,我会得到半个字的地址?什么是更好的方法来加载字节,通过修改数据内存加载半字?(上面的问题提出了我们无法修改数据存储器的约束)

Cha*_*ler 3

原作者似乎只是在从内存读取的 32 位数据中添加了一个字节多路复用器。该存储器允许完整的 32 位自然对齐加载(lw 指令),并且附加字节多路复用器和零扩展也允许加载字节指令(lbu 指令)。

ALU 结果的左移产生字地址,而不是字节地址,并解释了信号路由中隐式右移两位的情况。最终结果只是 ALU 结果的低两位在发送到内存之前被屏蔽(清零)。ALU 值的两个 LSB 被馈送到存储器下游的字节多路复用器,允许字存储器读取任意字节。

所示逻辑中没有直接支持加载半字(16 位),仅支持字节和完整 32 位字。但是,您可以使用类似的方法轻松修改字节寻址逻辑以支持字而不是字节(甚至两者)。