基于Artix-7 FPGA的三级存储体系设计与实现实验

2020-11-20 03:20秦国锋秦家豪邹剑煌
实验室研究与探索 2020年10期
关键词:计算机系统寄存器指令

秦国锋, 秦家豪, 邹剑煌, 刘 鲲, 胡 岳

(同济大学计算机科学与技术系,上海201804)

0 引 言

计算机系统实验课程是计算机类专业课程的配套动手实践实验课程,它通过设置与计算机重点专业知识相适配的实验,达到帮助学生们更全面、更深入地理解计算机系统的基本组成和运作原理,培养学生们设计与开发个人计算机系统的能力。在之前“计算机系统结构”理论课程设置的基于MIPS 指令集的静态和动态流水线CPU设计与实现的同步实验中,学生们很好地完成了流水线CPU的设计与实现[1]。然而,在实际的计算机系统中不仅是CPU和内存模块的交互,需要主存、缓存和辅存形成的三级存储系统来与CPU进行数据交互,以此达到计算机的高效运行。因此,本文在实验课程中提出了一种基于Artix-7 FPGA系统的三级存储体系的设计与实现方案,该方案采用自顶向下的层次模块化设计方法,使用verilog 硬件逻辑语言进行描述。

计算机存储体系中,“三级存储”指的是高速缓冲存储器、主存储器、辅助存储器。高速缓冲存储器用来改善主存储器与中央处理器的速度匹配问题;辅助存储器用于扩大存储空间。三级存储系统解决存储器速度、容量和价格三者的矛盾,并且提升了CPU 访存速度,改善了系统的总体性能。在FPGA系统中,共有位于FPGA 系统的片内内存,位于片外的DDR 存储,以及属于外设的SD 卡3 种存储模块,分别在三级存储实验中可以模拟对应主存储器、高速缓冲存储器和辅助存储器[2]。

1 三级存储体系设计

基于FPGA系统的三级存储体系实验的总体框架分为SD 卡、DDR 和FPGA 片内内存三级,如图1 所示。系统一通电,会先执行SD 中初始部分的引导代码,从而将存储在SD中的CPU 二进制流迁移到DDR缓存中,在以此调入主存供CPU 执行,同时会将位于SD中的系统或用户程序目标代码迁移到DDR中等待CPU调用执行。

图1 三级存储总体框架

一台市场上商业发售的计算机都在它的核心硬盘(基本上都命名为C 盘)的初始地址空间固化有一段用于加载和迁移存储,在核心硬盘上的用于维护系统启动和运行的系统程序和用户程序的固定程序,常被称为BootLoader程序[3],这一加载的启动机制借助三级存储体系保证了计算机系统启动的快速和准确。

实验设计的基于Artix-7 FPGA的三级存储体系中也设计有适用于自主启动运行系统的BootLoader 程序。其实现方法是将BootLoader 程序用汇编语言和C语言联合开发,通过gcc 交叉编译后将其加载到irom里,类比于一般计算机的核心硬盘。当FPGA 板通上电后,会加载.bit 文件,然后执行irom 里的BootLoader程序[4-10]。

1.1 BootLoader启动

如图2 所示,被执行的BootLoader 程序首先会将存储于SD卡中的用户程序指令加载到iram 中(即图1 中的DDR缓存组件中),然后搬迁进板内等待被执行;在完成加载任务后修改PC 寄存器中的指令地址信息,让其指向刚被加载到板内的用户程序所在的地址空间,然后CPU按照PC 寄存器所指的指令地址空间执行该用户程序,完成一个简易计算机的启动和运行。

图2 BootLoader启动过程

1.2 程序执行的指令流和数据流

CPU在执行用户程序时指令和数据的流向如图3所示。首先CPU通过读取PC寄存器中的待执行指令地址信息,然后结合指令地址映射模块,找到存在于irom或iram地址空间的指令内容,将其加载到板内,供CPU执行。同理,在CPU 执行指令时会发生对于内存的读写需求,结合数据地址映射模块,找到存在于dram和SD卡地址空间的数据内容,将其读取到板内或者写入到这些地址空间。通过多级储存器之间相互协作,实现和保证了一台简易计算机处理效率和性能。

图3 执行程序时的指令和数据流

1.3 统一编址

在整个执行过程中,代码段地址和存储器地址进行统一编址,所有的代码、数据和存储器都在逻辑地址空间中有一个32 位的地址,C语言编写的就是对这些地址的操作。

BootLoader存储于irom 地址空间,地址为0x0000 0000,如图4 所示。在执行完BootLoader程序后,需要将PC寄存器内容改为0x00400000,指向存储加载而来的用户程序的iram地址空间中,于是在编译时需要在0x00000000 附近加上一段跳转指令到BootLoader的main 函数,以及返回时跳转回0x00400000,具体代码实现如下:

.org 0x00000000

.global _start

.set noat

.start

Lui $at,0x1000

Ori $at,$at,0x1F00

Add $sp,$zero,$at

Jal main

Nop

Lui $at,0x40 #0040 0000

Jr $at

Nop

图4 Bootloader 后指令跳转

1.4 SD卡时钟设置

依据逻辑地址的排布表,通过宏定义编写SD 卡控制管脚高低的宏函数,实现SD卡时钟设置。

#define SD_CS 0x22000000

#define SD_CLK 0x22000001

#define SD_DATAIN 0x22000002

#define SD_DATAOUT 0x22000003

#define SD_HALF_CLK_LEN 0;

#define SD_CLK_UP()*((uchar *)SD_CLK)= 1;

#define SD_CLK_DOWN()*((uchar *)SD_CLK)= 0;

#define SD_DATAIN_UP()*((uchar*)SD_ DATAIN)= 1;

#define SD _ DATAOUT _ DOWN()*((uchar *)SD _DATAOUT)= 0;

#define SD_CS_UP()*((uchar *)SD_ CS)= 1;

#define SD_ CS_DOWN()*((uchar *)SD_ CS)= 0;

如此,就可以用软件方式一一对应地写C 语言代码,实现SD卡的协议。以时钟为例如下:

Void SD_send_clk()

SD_CLK_DOWN();

DELAY_HALF_CLK();

SD_CLK_UP();

DELAY_HALF_CLK():

For (int i = 0;i <80;i + +)

SD_send_c

但仅进行上述的设置是不够的,还需将对存储单元写入0 / 1 转换成TTL高低电平的信号,通过设计的接口模块来实现电平转换,如图5 所示。

图5 SD卡接口模块

对应的Verilog代码实现如下:

module SD_soft(

input clk,/ /写入时钟

input rst,

input we,/ /写使能

input [3:0]sel_i,/ /位选信号

input [31:0]data_i,/ /写入数据

output [31:0]data_o,/ /将它视作一个4字节的输出

/ / SD相关

output reg SD_cs,/ /片选,addr = 0

output reg SD_clk,/ /时钟,addr = 1

output reg SD_datain,/ /数据输入,addr = 2

input SD_dataout / /数据输出,addr = 3

);

assign data_o = {7`b0,SD_cs,7`b0,SD_clk,7`b0,SD_datain,7`b0,SD_dataout};

always@(posedge clk or posedge rst)begin

if(rst)begin

SD_cs = 1`b0;

SD_clk = 1`b0;

SD_datain = 1`b0;

end

else if(we)begin

if(sel_i[3]= = 1`b1)begin

SD_cs <= (data_i[31:24]! = 8`b0);

end

if(sel_i[2]= = 1`b1)begin

SD_clk <= (data_i[23:16]! = 8`b0);

end

if(sel_i[1]= = 1`b1)begin

SD_datain <= (data_i[15:8]! = 8`b0);

end

end

end

SD卡作为三级存储器中离CPU最远段的一级存储器,要进行存储块和页面的地址管理,在进行数据的读写时,需要先进行初始化[11]。

2 实验验证

本次三级存储体系的设计与实现采用的CPU 是“计算机系统结构”课程中自主设计与实现的静态和动态流水线CPU[12-13]。整个三级存储体系的设计和实现采用Xilinx公司提供的vivado[14]集成开发工具和verilog[15]开发语言完成,并在Xilinx Nexys 4 Artix-7[16]开发板上进行了下板测试。

首先将整个三级存储体系实现代码生成的.bit文件写入到被格式化后的SD卡中,然后用WinHex在逻辑80 扇区(本次实验采用的SD卡对应的物理扇区是8272)写入用户指令(右键,从剪贴板写入,写入方式为16 进制)。然后放置好FPGA 板上的跳线。之后UART口连接上电源,开始启动,实现三级存储体系成功运行。

实验中,在BootLoader 程序中额外设置了开关控制Led灯的程序,以提示三级存储的建立状态,控制代码如下:

assign led = sw[0]?(sw[1]?

{debug_once_was,debug_i_data[14:0]}:inst_addr[15:

0]):inst_addr[31:16];

当sw[1:0]= = 2 时,Led 灯显示PC 寄存器内容的低16 位,sw[1:0]= = 1 时,Led 灯显示PC 寄存器的高16 位。

为避免无限循环,在测试程序末尾加入无条件跳转指令,该指令的指令代码如表1 中黄色部分标识所示。

表1 部分指令的执行过程

成功下板后,两种开关下数码管的显示如下:当sw[0]= 1,sw[1]= 0 时,Led灯显示情况如图6(a)所示,说明PC[15:0]= = 0x00a0。当sw[0]= 0,sw[1]= 1 时,Led 灯显示情况如图6(b)所示,说明PC[31:16]= = 0x0040。两者拼接组合起来就是0x0040 _00a0,即为表1 所示执行J 指令的结果。该测试结果说明三级存储体系设计与运行正确。

图6 Led灯显示情况

3 结 语

本文提出了一种基于Artix-7 FPGA的三级存储体系设计与实现方法,该方法指导学生们完成三级存储体系的设计与实现实验。此外,通过该实验,增强了学生们对于计算机的三级存储体系的结构与工作机制的深入理解和认知,是贯通后续课程实验的关键环节,为学生自主设计、实现更加完善的个人计算机系统奠定了坚实的基础[17]。

猜你喜欢
计算机系统寄存器指令
STM32和51单片机寄存器映射原理异同分析
《单一形状固定循环指令G90车外圆仿真》教案设计
Lite寄存器模型的设计与实现
关于不法分子冒充《小型微型计算机系统》名义诈骗的严正声明
IBM推出可与人类“辩论”的计算机系统
计算机系统集成实施与项目管理途径分析
移位寄存器及算术运算应用
中断与跳转操作对指令串的影响
正确书写计算机系统内部使用的二进制倍数词头符号
一种基于滑窗的余度指令判别算法