



从图3.2可知在QMEM中有一个RAM,指令与数据都存储在该RAM中。QMEM中关于该RAM的例化语句如下。
打开文件or1200_spram_2048x32.v,在其中定义具体的RAM,由于考虑了各种芯片的实际情况,所以这个文件很长,但与我们有关的很少,在or1200_defines.v中默认是GenericMemory,表示通用存储器,不考虑实际厂家,所以or1200_spram_2048x32.v文件中只有如下部分是在OR1200最小系统中使用的。
上述代码就是使用数组得到一个RAM,具体芯片的综合工具会将这个数组综合为存储单元。QMEM中的RAM例化涉及如下信号:qmem_en、qmem_we、qmem_di、qmem_addr、qmem_do和qmem_sel。在QMEM中上述信号定义如下。
(1)qmem_en:连接到RAM的ce,作为片选信号,当CPU取指令(qmemimmu_cycstb_i为1),且指令地址在QMEM地址范围内(iaddr_qmem_hit为1)时,或者CPU加载/存储数据(qmemdmmu_cycstb_i为1),且数据地址在QMEM地址范围内(daddr_qmem_hit为1)时,都会使得qmem_en为1。
(2)qmem_we:连接到RAM的we,作为写操作信号,当CPU加载/存储数据(qmemdmmu_cycstb_i为1),且数据地址在QMEM地址范围内(daddr_qmem_hit为1),且是写操作(qmemdcpu_we_i为1)时,会使得qmem_we为1。
(3)qmem_di:连接到RAM的di,作为RAM的输入数据,因为指令存储器是只读的,所以CPU的指令Wishbone总线没有WE_O、DAT_O接口,只有CPU的数据Wishbone总线有WE_O、DAT_O接口,因此qmem_di直接连接到CPU数据Wishbone总线的DAT_O接口(参考图3.11可知qmemdcpu_dat_i连接到CPU的dcpu_dat_o)。
(4)qmem_addr:连接到RAM的addr,作为地址信号,CPU是可以按字节寻址的,而QMEM中的RAM是按字寻址的,且地址宽度是11,所以只取QMEM输入地址的2~12位,比如读取0x4处的数据,实际送往RAM的地址是0x1,如图3.13所示。此外由于只有一个RAM,但是指令总线、数据总线都可能要访问该RAM,当同时访问时就有一个优先级的问题,这里采用的数据总线的优先级高于指令总线的优先级。当加载/存储数据(qmemdmmu_cycstb_i为1),且数据地址在QMEM地址范围内(daddr_qmem_hit为1)时,送到RAM的地址就是数据Wishbone总线送入的地址qmemdmmu_adr_i,反之是指令Wishbone总线送入的地址qmemimmu_adr_i。
(5)qmem_do:连接到RAM的doq,作为RAM的输出数据,在一定条件下赋值给qmemicpu_dat_o、qmemdcpu_dat_o。
(6)qmem_sel:在RAM中没有该信号,但实际上该信号在加载存储类指令执行时是有作用的,所以OR1200的rel3版本的QMEM内部RAM设计是有问题的,具体讨论及改正方法将在加载存储类指令分析时给出。
图3.13 QMEM中的RAM是按照字寻址的
CPU会在三种情况下用到QMEM:取指令、加载(Load)数据和存储(Store)数据。关于后两者将在加载存储类指令分析时进行介绍,本章只结合取指令过程分析QMEM的工作过程,取指令也分两种情况:复位后取第一条指令、正常运行过程中的指令读取。