一、实验原理
RISC即精简指令集计算机(ReducedInstructionSetComputer)的缩写。RISC-CPU与一般的CPU相比,通过简化指令系统使计算机的结构更加简单合理,从而提高了运算速度。本文对RISC-CPU的架构进行了分析,并使用VHDL语言设计了8位RISC-CPUIP软核。SAP-1CPU部分:程序计数器、MAR、指令寄存器、控制器/序列发生器、累加器、加减法器、B寄存器、输出寄存器。
1.1SAP-1CPU及计算机的组成架构简介
1.程序计数器
它是一个4Bits的计数器,计数范围由0~15。主要功用是记录下每个执行的指令地址,并把这个地址传送至MAR寄存器存放。
2.输入与MAR(MemoryAccessRegister)
这个方块应分成两个部分,一个是接受由“输入”部分输入到RAM内存的外部程序和数据,另一部分“MAR”是用来在CPU执行上述所加载的程序时,暂存下一个要执行的指令地址。
3.16_8RAM
这个RAM有16个存储单元,每个单元为1字节,即8bits。所以这个RAM的地址总线是4bit,地址编码是由0000,0001,0010…1111,这个地址内容是由上述MAR传送过来,然后通过译码将地址存放的8位数据或指令输出至Wbus。
4.指令寄存器
属于CPU内的控制单元,主要是将在RAM的8位数据,通过Wbus后读入指令寄存器,然后再把数据一分为二,较高的4位属于指令部分,送至下一级的“控制器”,而较低的4位属于数据部分,将会被送至Wbus。
5.控制器/序列发生器
这个模块也是属于CPU内控制单元的一部分,这个控制器在程序执行时,负责送出整个计算机的时序信号CLK,而且会把指令寄存器送来的4位指令,解译成12位的控制信号,由这组控制信号指挥其它的功能方块,完成该指令的运作。由于使用VHDL语言设计整个SAR-1,依照语法的使用,这部分会被省略,而且不会影响整个CPU运作。
6.累加器
累加器是个8位的缓冲寄存器,它是存放目前计算机执行的实时数据地方。不同的指令也将使它产生不同的工作方式。
7.加减法器
这个加减法器负责执行数学的加法和减法运算,而且运算的结果会放回“累加器”暂存。
8.B寄存器
这个寄存器用来配合“累加器”、“加减法器”,执行“加法”或“减法”的工作。
9.输出寄存器
这个输出寄存器的用途是,CPU执行到“输出结果”的指令时,便将“累加器”的结果传至“输出寄存器”,所以它是负责存放输出结果,当然这个存放的结果是二进制形式的。
1.2SAP-1CPU指令.寻址法.程序设计
SAP-1的CPU指令,共有5个且可分成两种类型,如表
直接寻址法(DirectAddressing)
二、实验要求
配合SAP-1指令,设计16(Word)_8(Bit)的ROM,使其能够执行如下预算:
三、实验设计与过程
3.1SAP-1CPU设计
SAP-CPU在前面所提的指令,它们执行的指令周期总长度基本上都是6个脉冲长度,这可以用下图说明
SAP-1指令周期(InstructionCycle)
时序状态S0-S2范围为取指令周期,而时序状态S3-S5为指令执行周期.下面是每个时序状态下,SAP-1CPU的工作任务:
1.取指令周期(FetchCycle)
(1)状态S0:(寻址状态,AddressState)
这个状态下,“程序计数器”负责将所要执行的指令地址值传递至MAR存放.
(2)状态S2:(增加状态,IncrementState)
这个状态下,“程序计数器”的值加1,代表计数器将指针指向下一个要执行的指令地址值.
原先在状态S0时,“程序计数器”的值是01H,它会传递01H给“MAR”,然后在这个状态S1时,将内容值加1后变成02H,这样以便记录下次要执行的指令地址值.
(3)状态S2:(记忆状态,MemoryState)
这个状态下,将把记录在“MAR”里的指令地址值,送入“RAM”里后,由“RAM”读出该地址的指令码,再将该指令放入“指令寄存器”.
有一点必须强调的是,不论是执行哪个指令,它们的状态S0-S2的动作方式都是相同的,不过状态S3-S5的动作方式就会因执行对那个指令而有所不同.
2.指令执行周期
(1)LDA指令
状态S3:
这个状态下,上述的09H数据传入MAR,以便下个状态能取出该数值所代表的地址里的值,比如20H.
状态S4:
这个状态是将存放在“MAR”里的09数据,通过RAM读出09H地址的数据,比如是数值20H数值至“累加器”
状态S5:
这个状态下的LDA指令并没有作用
(2)ADD指令
状态S3:
这个状态下,上述的AH数据将传入MAR,以便下个状态取出该数值所代表地址里的内容值,比如是数值14H
状态S4:
这个状态是将存放“MAR”里的AH数据,通过RAM读出AH地址内的数据,放到B寄存器中
状态S5:
这个状态是将存在“累加器”和“B寄存器”的数值内容存放入“加减法器”相加后,再将相加结果放回“累加器”
(3)SUB指令
状态S3:
这个状态下,上述的BH数据传入MAR,以便下个状态能取出该数值所代表地址里的值
状态S4:
这个状态是将存放在“MAR”的BH数据,通过RAM读出BH地址内的数据,并放到B寄存器中
状态S5:
这个状态是将存放在“累加器”和“B寄存器”的数值放入“加减法器”相减后,再将相减后结果放回“累加器”
(4)OUT指令
状态S3:
这个状态下,累加器的内容将经Wbus传至“输出寄存器”,然后显示在二进制显示装置.
状态S4:
这个状态OUT指令没有作用.
状态S5:
这个状态OUT指令没有作用
(5)HLT指令
状态S3:
这个状态下“控制器/序列发生器”将停止送出脉冲信号CLK,这时SAP-1CPU会停止执行工作.
状态S4:
这个状态HLT指令没有作用
状态S5:
这个状态HLT指令没有作用
3.2设计思路
使用三个IO端口,分别为时钟输入clk,复位使能rst,及结果输出端口output_data。
使用portmap语句进行了元件例化,将CPU与ROM相连接了。
XXX程序
LIBRARYIEEE;
XXX.ALL;
XXX.ALL;
XXXXXX;
ENTITYROM16_8is
PORT(
DATAOUT:OUTSTD_LOGIC_VECTOR(7DOWNTO0);--DataOutputADDR:INSTD_LOGIC_VECTOR(3DOWNTO0);--ADDRESSCE:INSTD_LOGIC--ChipEnable
ENDROM16_8;
ARCHITECTUREaOFROM16_8IS
BEGIN
DATA<=“1”WHENADDR=“0000”ANDCE=‘0’--LDA9H
“0”WHENADDR=“0001”ANDCE=‘0’ELSE--ADDAH“1”WHENADDR=“0010”ANDCE=‘0’ELSE--ADDBH“0”WHENADDR=“0011”ANDCE=‘0’ELSE--SUBCH“0”WHENADDR=“0100”ANDCE=‘0’ELSE--OUT“0”WHENADDR=“0101”ANDCE=‘0’ELSE--HLT“0”WHENADDR=“1001”ANDCE=‘0’ELSE
“0”WHENADDR=“1010”ANDCE=‘0’ELSE
“0”WHENADDR=“1011”ANDCE=‘0’ELSE
“0”WHENADDR=“1100”ANDCE=‘0’ELSE
“0”;
ENDa;
XXX程序
ARCHITECTUREaOFSAP1IS
TYPESTATEIS(SO,S1,S2,S3,S4,S5);--statetypedeclare
SIGNALPState:STATE;--presentstateSIGNALNState:STATE;--ne_tstate……
BEGIN
ChangeStateMode:PROCESS(CR,RST)--states0~s5
BEGIN
IFRST=‘1’THEN--resetcpu
PC<=“0000”;--pogram
counter=0H
ACC<=“0”;--accumulator=0H
RUN<=‘1’;--CPUrunprogramenable
PState<=S0;--Initialcpupresentstate
ELSIFCP’EVENTANDCP=‘0’THEN--clocknegativeedage
IFRUN=‘1’THEN--runprogrameanble
CASEPStateIS--checkcpupresentstate
WHENS0=>--(addressstatefetchcycle-1)
NState<=S1;--cpune_tstate
WHENS1=>--(incrementstatefetchcycle-2)
NState<=S2;--cpune_tstate
WHENS2=>--(memorystatefetchcycle-3)
NState<=S3;--cpune_tstate
WHENS3=>--STATES3(E_ecutioncycle-1)
NState<=S4;--cpune_tstate
WHENS4=>--STATES4(E_ecutioncycle-2)
NState<=S5;--cpune_tstate
WHENS5=>--STATES5(E_ecutioncycle-3)
NState<=S0;--cpune_tstate
ENDCASE;
PState<=NState;--切换状态
ENDIF;
ENDIF;
ENDPROCESSChangeStateMode;
ENDa;
3.5指令捕捉周期(fetchcycle)
Changestatemode:process(cp,rst)--states0~s5
variableflag,f1:boolean;
begin
ifrst=‘1’then
Pstate<=s0;
flag:=ture;---PC指针允许加1标志打开
elsifcp’eventandcp=‘0’then
ifrun=‘1’then
casepstateis
whenso=>
nstate<=s1;
mar<=std_logic_vector(pc);
whens1=>
nstate<=s2;
ifflag=turethen
pc<=pc+1;
flag:=false;
endif;
Whens2=>
Nastate<=s3;
Flag:ture;
Ir<=databus;
Whens3=>
Endcase;
3.6指令执行周期(fetchcycle)
在CaseWhen语句的状态S3处,加入下面粗体字命令,将“指令寄存器”
(IR)截取高4位指令至TMP里
Elsifcp’eventandcp=‘0’then
whens2=>
Whens3=>
nstate<=s4;
temp<=ir(7downto4),
whens4=>
其余指令执行周期的命令,不放入CASEWHEN语句里,而改以IF-ELSE将状态S3~S5命令出来,这么做只是不希望CASEWHEN语句太过冗长。
changestatemode:process(cp,rst)
variableflag,F1:boolean;
Begin
Ifrst=‘1’then
Elsifcp’eventandcp=‘0’then
Ifrun=‘1’then
casepstateis
whens0=>
nstate<=s1;
endcase;
pstate<=nstate;
Endif;
Ifpstate=s3then
If(tmp=“0000”)or(tmp=“0001”)or(tmp=“0010”)then
Mar<=ir(3downto0);
elsiftmp=“1110”then
outreg<=acc;
elsiftmp=“1111”then
run<=‘0’;
Endif
Elsifpstate=s4then
iftmp=“0000”then
acc<=databus;
elsiftmp=“0001”then
breg<=databus;
elsiftmp=“0010”then
breg<=databus;
endif;
Elsifpstate=s5then
iftmp=“0001”andf1=turethenNum<=unsigned(acc)+unsigend(breg);
Acc<=std_logic_vector(num);F1:=false;
Elsiftmp=“0010”andf1=truethennum<=unsigned(acc)-unsigned(breg);Acc<=std_logic_vector(num);F1:false;
Endif;
Endif;
Endif;Endprocesschangestatemode;
四、实验结果及仿真
4.1软件仿真结果
4.2硬件仿真结果
五、实验总结
如果要对程序运行的指令进行更改,需要改变s5中的计算whens5=>ne_t_state<=s0;
iftemp="0001"andf1='1'then
a_<=a_b_;--执行位与指令,将结果存入a_f1<='0';
elsiftemp="0010"andf1='1'then
a_<=a_||b_;--执行或指令,将结果存入a_f1<='0';
endif;