实验八 16位CPU验证性设计
一、实验目的
1. 理解16位CPU的结构和功能;
2.学习各类典型指令的执行流程;
3. 学习掌握部件单元电路的设计技术;
4. 掌握应用程序在用FPGA所设计的CPU上仿真和软硬件综合调试方法。
二、实验设备
1.装有quartus Ⅱ 9.0的pc一台;
2.Cyclone Ⅲ 实验箱一台。
三、实验原理
使用VHDL语言编写CPU所要具备的寄存器、存储器、ALU(运算器)、比较器、移位寄存器和控制器。最后将各模块连接起来,受控制器控制各模块的工作状态。
四、实验内容和步骤
1.编写移位器SFT4的VHDL代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
entity SFT4 is
port (a:in std_logic_vector (15 downto 0);
sel:in std_logic_vector (2 downto 0);
y:out std_logic_vector (15 downto 0));
end SFT4;
architecture rtl of SFT4 is
constant shftpass: std_logic_vector (2 downto 0):="000";
constant sftl: std_logic_vector (2 downto 0):="001";
constant sftr: std_logic_vector (2 downto 0):="010";
constant rotl: std_logic_vector (2 downto 0):="011";
constant rotr: std_logic_vector (2 downto 0):="100";
begin
process(a,sel)begin
case sel is
when shftpass => y <=a;
when sftl => y <=a(14 downto 0) & '0';
when sftr => y <='0' & a(15 downto 1);
when rotl => y <=a(14 downto 0) & a(15) ;
when rotr => y <=a(0) & a(15 downto 1);
when others => y <="0000000000000000";
end case;
end process;
end rtl;
2.编写缓冲寄存器REGT的VHDL代码
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity REGT is
port(a:in std_logic_vector (15 downto 0);
clk,RST,en :in std_logic;
q:out std_logic_vector (15 downto 0));
end REGT;
architecture bhv of REGT is
signal v1 : std_logic_vector (15 downto 0);
begin
process (clk,a,RST) begin
if RST='1'then v1<="0000000000000000";
elsif rising_edge(clk) then v1<=a;end if;
end process;
process(en,v1) begin
if en ='1'then q<=v1; else q<="ZZZZZZZZZZZZZZZZ";end if;
end process;
end bhv;
3.编写输出锁存器和指令寄存器REG16A的VHDL代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG16A IS
PORT(A:IN STD_LOGIC_VECTOR(15 DOWNTO 0);CLK:IN STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR(15 DOWNTO 0));
END REG16A;
ARCHITECTURE BHV OF REG16A IS
BEGIN
PROCESS(CLK,A) BEGIN
IF RISING_EDGE(CLK) THEN Q<=A;END IF;
END PROCESS;
END BHV;
4.编写R7-R0寄存器阵列REG_AR8的VHDL代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY REG_AR8 IS
PORT(DATA:IN STD_LOGIC_VECTOR(15 DOWNTO 0);
SEL :IN STD_LOGIC_VECTOR(2 DOWNTO 0);
CLK: IN STD_LOGIC;Q: OUT STD_LOGIC_VECTOR(15 DOWNTO 0));
END REG_AR8;
ARCHITECTURE RTL OF REG_AR8 IS
TYPE T_RAM IS ARRAY (0 TO 7) OF STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL RAMDATA:T_RAM;
SIGNAL TEMP_DATA: STD_LOGIC_VECTOR(15 DOWNTO 0);
BEGIN
PROCESS (CLK,SEL) BEGIN
IF RISING_EDGE(CLK) THEN RAMDATA(CONV_INTEGER(SEL))<=DATA;END IF;
END PROCESS;
PROCESS(SEL) BEGIN
TEMP_DATA<=RAMDATA(CONV_INTEGER(SEL));END PROCESS;
Q<=TEMP_DATA;
END RTL;
5.编写地址寄存器REG_A的VHDL代码
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY REG_A IS
PORT(RST,CLK,LOAD:IN STD_LOGIC;
D:IN STD_LOGIC_VECTOR(15 DOWNTO 0);
Q:OUT STD_LOGIC_VECTOR(15 DOWNTO 0));
END REG_A;
ARCHITECTURE BEHAVIORAL OF REG_A IS
BEGIN
PROCESS (CLK,RST) BEGIN
IF RST='1' THEN Q<=(OTHERS=>'0');
ELSIF RISING_EDGE(CLK) THEN
IF LOAD='1' THEN Q<=D; END IF;
END IF ;
END PROCESS;
END BEHAVIORAL;
6.编写比较器comp的VHDL代码
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity comp is
port(a,b:in std_logic_vector(15 downto 0);
sel:in std_logic_vector(2 downto 0);
compout:out std_logic);
end comp;
architecture rtl of comp is
constant eq :std_logic_vector(2 downto 0):="000";
constant neq:std_logic_vector(2 downto 0):="001";
constant gt :std_logic_vector(2 downto 0):="010";
constant gte:std_logic_vector(2 downto 0):="011";
constant lt :std_logic_vector(2 downto 0):="100";
constant lte:std_logic_vector(2 downto 0):="101";
begin
process(a,b,sel) begin
case sel is
when eq=>if a=b then compout<='1';else compout<='0';end if;
when neq=>if a/=b then compout<='1';else compout<='0';end if;
when gt =>if a>b then compout<='1';else compout<='0';end if;
when gte =>if a>=b then compout<='1';else compout<='0';end if;
when lt =>if a<b then compout<='1';else compout<='0';end if;
when lte =>if a<=b then compout<='1';else compout<='0';end if;
when others => compout<='0';
end case;
end process;
end rtl;
7.编写运算器ALU的VHDL代码
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ALU_V IS
PORT(a,b:in std_logic_vector(15 downto 0);
sel:in std_logic_vector(3 downto 0);
c:out std_logic_vector(15 downto 0));
end ALU_V;
architecture rtl of ALU_V IS
constant alupass:std_logic_vector(3 downto 0):="0000";
constant andOp:std_logic_vector(3 downto 0):="0001";
constant orOp:std_logic_vector(3 downto 0):="0010";
constant notOp:std_logic_vector(3 downto 0):="0011";
constant xorOp:std_logic_vector(3 downto 0):="0100";
constant plus:std_logic_vector(3 downto 0):="0101";
constant alusub:std_logic_vector(3 downto 0):="0110";
constant inc:std_logic_vector(3 downto 0):="0111";
constant dec:std_logic_vector(3 downto 0):="1000";
constant zero:std_logic_vector(3 downto 0):="1001";
begin
process(a,b,sel) begin
case sel is
when alupass=>c<=a;
when andOp=>c<=a and b;
when orOp=>c<=a and b;
when xorOp=>c<=a xor b;
when notOp=>c<=not a;
when plus =>c<=a+b;
when alusub=>c<=a-b;
when inc=>c<=a+"0000000000000001";
when dec=>c<=a-"0000000000000001";
when zero=>c<="0000000000000000";
when others=>c<="0000000000000000";
end case ;end process;
end rtl;
8.编写控制器CONTRAL的VHDL代码
library ieee;
use ieee.std_logic_1164.all;
entity contrla is
port(clock:in std_logic;reset:in std_logic;
instrreg:in std_logic_vector(15 downto 0);
compout:in std_logic;
progcntrwr:out std_logic;
progcntrrd:out std_logic;
addrregwr:out std_logic;
addrregrd:out std_logic;
outregwr:out std_logic;
outregrd:out std_logic;
shiftsel:out std_logic_vector(2 downto 0);
alusel:out std_logic_vector(3 downto 0);
compsel:out std_logic_vector(2 downto 0);
opregrd:out std_logic;
opregwr:out std_logic;
instrwr:out std_logic;
regsel:out std_logic_vector(2 downto 0);
regrd:out std_logic;
regwr:out std_logic;
rw:out std_logic;
vma:out std_logic);
end contrla;
architecture rtl of contrla is
constant shftpass:std_logic_vector(2 downto 0):="000";
constant alupass :std_logic_vector(3 downto 0):="0000";
constant zero :std_logic_vector(3 downto 0):="1001";
constant inc :std_logic_vector(3 downto 0):="0111";
constant plus :std_logic_vector(3 downto 0):="0101";
type state is (reset1,reset2,reset3,execute,nop,load,store,
load2,load3,load4,store2,store3,store4,incpc,incpc2,incpc3,loadi2,loadi3,loadi4,loadi5,loadi6,inc2,inc3,inc4,move1,move2,
add2,add3,add4);
signal current_state, next_state : state;
begin
com:process(current_state,instrreg,compout) begin
progcntrwr<='0';progcntrrd<='0';addrregwr<='0';addrregrd<='0';
outregwr<='0';outregrd<='0';shiftsel<=shftpass;alusel<=alupass;
opregrd<='0';opregwr<='0';instrwr<='0';regsel<="000";
regrd<='0';regwr<='0';rw<='0';vma<='0';
case current_state is
when reset1=>alusel<=zero;shiftsel<=shftpass;
outregwr<='1';next_state<=reset2;
when reset2=>outregrd<='1';progcntrwr<='1';
addrregwr<='1';next_state<=reset3;
when reset3=>vma<='1';rw<='0';instrwr<='1';next_state<=execute;
when execute=>
case instrreg(15 downto 11) is
when"00000"=>next_state<=incpc;
when"00001"=>next_state<=load2;
when"00010"=>next_state<=store2;
when"00100"=>progcntrrd<='1';alusel<=inc;
shiftsel<=shftpass;next_state<=loadi2;
when"00111"=>next_state<=inc2;
when"01101"=>next_state<=add2;
when"00011"=>next_state<=move1;
when others=>next_state<=incpc;
end case;
when load2=>regsel<=instrreg(5 downto 3);regrd<='1';
addrregwr<='1';next_state<=load3;
when load3=>vma<='1';rw<='0';regsel<=instrreg(2 downto 0);
regwr<='1';next_state<=incpc;
when add2=>regsel<=instrreg(5 downto 3);
regrd<='1';
next_state<=add3;opregwr<='1';
when add3=>regsel<=instrreg(2 downto 0);
regrd<='1';alusel<=plus;
shiftsel<=shftpass;outregwr<='1';
next_state<=add4;
when add4=>regsel<="011";
outregrd<='1';regwr<='1';
next_state<= incPc;
when move1=>regsel<=instrreg(5 downto 3);regrd<='1';alusel<=alupass;
shiftsel<=shftpass;outregwr<='1';next_state<=move2;
When move2 => regsel <=instrReg(2 downto 0); outregrd<='1';
Regwr <='1'; next_state<=incpc;
When store2 => regsel <=instrReg(2 downto 0); regrd<='1';
addrRegwr <= '1'; next_state<=store3;
When store3 => regsel <=instrReg(5 downto 3); regrd<='1';
rw<='1'; next_state<=incpc;
When loadi2 => progcntrrd<='1';alusel<=inc; shiftsel<=shftpass;
Outregwr <='1';next_state<=loadi3;
When loadi3 =>Outregrd <='1';next_state <= loadi4;
When loadi4 =>Outregrd <= '1';progcntrwr<='1'; addrregwr<='1';next_state <= loadi5;
When loadi5 => vma <= '1'; rw <= '0'; next_state <= loadi6;
When loadi6 => vma <= '1'; rw <= '0'; regsel<=instrreg (2 downto 0);
Regwr <= '1'; next_state <= incpc;
When inc2 =>regSel<=instrReg(2 downto 0) ; regrd<='1'; alusel<=inc;
shiftsel<=shftpass;Outregwr <= '1';next_state <=inc3;
When inc3 => Outregrd <= '1';next_state <= inc4;
When inc4 =>outregrd<='1';regsel <= instrreg (2 downto 0) ;
Regwr <='1'; next_state <= incpc;
When incpc => progcntrrd<='1';alusel<=inc; shiftsel<=shftpass;
Outregwr <= '1';next_state<=incpc2;
When incpc2 => outregrd<='1'; progcntrwr <= '1'; addrregwr<='1';
Next_state <= incpc3;
When incpc3 => outregrd<='0'; vma<='1'; rw<='0'; instrwr<='1';
next_state<=execute;
When others => next_state <= incpc;
End case;
End process;
reg: process (clock, reset) begin
If reset = '1' then current_state <= reset1 ;
Elsif rising_edge(clock) then current_state<=next_state ; end if;
End process;
End rtl;
9.使用原理图生成节拍脉冲发生器STEP
10.使用LPM调用生成RAMK和三态门lpm_bustri0
11.编写测试程序cx.mif并使用它初始化RAM
12.由以上模块画出总电路原理图如下所示
13.仿真调试
实现了将立即数0032H存放到R1,将立即数0011H存放到R2,并将R1和R2的数据之和0043H存放在R3的功能。
14.设计新指令
①新增指令及其功能表
②修改控制器contrla.vhd的代码
library ieee;
use ieee.std_logic_1164.all;
entity contrla is
port(clock:in std_logic;reset:in std_logic;
instrreg:in std_logic_vector(15 downto 0);
compout:in std_logic;
progcntrwr:out std_logic;
progcntrrd:out std_logic;
addrregwr:out std_logic;
addrregrd:out std_logic;
outregwr:out std_logic;
outregrd:out std_logic;
shiftsel:out std_logic_vector(2 downto 0);
alusel:out std_logic_vector(3 downto 0);
compsel:out std_logic_vector(2 downto 0);
opregrd:out std_logic;
opregwr:out std_logic;
instrwr:out std_logic;
regsel:out std_logic_vector(2 downto 0);
regrd:out std_logic;
regwr:out std_logic;
rw:out std_logic;
vma:out std_logic;
we1:out std_logic);
end contrla;
architecture rtl of contrla is
constant shftpass:std_logic_vector(2 downto 0):="000";
constant alupass :std_logic_vector(3 downto 0):="0000";
constant zero :std_logic_vector(3 downto 0):="1001";
constant inc :std_logic_vector(3 downto 0):="0111";
constant plus :std_logic_vector(3 downto 0):="0101";
constant notOp :std_logic_vector(3 downto 0):="0011";type state is (reset1,reset2,reset3,execute,nop,load,store,
load2,load3,load4,store2,store3,store4,incpc,incpc2,incpc3,
loadi2,loadi3,loadi4,loadi5,loadi6,inc2,inc3,inc4,move1,move2,
add2,add3,add4,in0,in1,in2,in3,in4,out0,out1,out2,out3);
signal current_state, next_state : state;
begin
com:process(current_state,instrreg,compout) begin
progcntrwr<='0';progcntrrd<='0';addrregwr<='0';addrregrd<='0';
outregwr<='0';outregrd<='0';shiftsel<=shftpass;alusel<=alupass;
opregrd<='0';opregwr<='0';instrwr<='0';regsel<="000";
regrd<='0';regwr<='0';rw<='0';vma<='0';we1<='0';
case current_state is
when reset1=>alusel<=zero;shiftsel<=shftpass;
outregwr<='1';next_state<=reset2;
when reset2=>outregrd<='1';progcntrwr<='1';
addrregwr<='1';next_state<=reset3;
when reset3=>vma<='1';rw<='0';instrwr<='1';next_state<=execute;
when execute=>
case instrreg(15 downto 11) is
when"00000" => next_state<=incpc;
when"00001" => next_state<=load2;
when"00010" => next_state<=store2;
when"00100" => progcntrrd<='1'; alusel<=inc;
shiftsel<=shftpass;next_state<=loadi2;
when"00111" => next_state<=inc2;
when"01101" => next_state<=add2;
when"00011" => next_state<=move1;
--新定义指令:IN 从输入端口读外设数据,OUT 从端口向外设输出数据
when"01111" => next_state<=in0;--IN,从端口读外设数据到寄存器Rn
when"10010" => next_state<=out0; --OUT 向端口输出数据
when others=>next_state<=incpc;
end case;
when load2=>regsel<=instrreg(5 downto 3);regrd<='1';
addrregwr<='1';next_state<=load3;
when load3=>vma<='1';rw<='0';
regsel<=instrreg(2 downto 0);regwr<='1';
next_state<=incpc;
when add2=>regsel<=instrreg(5 downto 3);
regrd<='1'; next_state<=add3;opregwr<='1';
when add3=>regsel<=instrreg(2 downto 0);
regrd<='1';alusel<=plus;shiftsel<=shftpass;
outregwr<='1'; next_state<=add4;
when add4=>regsel<="011"; outregrd<='1';regwr<='1';
next_state<= incPc;
when move1=>regsel<=instrreg(5 downto 3);regrd<='1';
alusel<=alupass;shiftsel<=shftpass;outregwr<='1';
next_state<=move2;
When move2 => regsel <=instrReg(2 downto 0);
outregrd<='1';Regwr <='1'; next_state<=incpc;
When store2 => regsel <=instrReg(2 downto 0);
regrd<='1';addrRegwr <= '1'; next_state<=store3;
When store3 => regsel <=instrReg(5 downto 3);
regrd<='1';rw<='1'; next_state<=incpc;
When loadi2 => progcntrrd<='1';alusel<=inc;
shiftsel<=shftpass;Outregwr <='1';next_state<=loadi3;
When loadi3 =>Outregrd <='1';next_state <= loadi4;
When loadi4 =>Outregrd <= '1';progcntrwr<='1';
addrregwr<='1';next_state <= loadi5;
When loadi5 => vma <= '1'; rw <= '0';
next_state <= loadi6;
When loadi6 => vma <= '1'; rw <= '0';
regsel<=instrreg (2 downto 0);Regwr <= '1';
next_state <= incpc;
When inc2 =>regSel<=instrReg(2 downto 0) ;
regrd<='1'; alusel<=inc; shiftsel<=shftpass;
Outregwr <= '1';next_state <=inc3;
When inc3 => Outregrd <= '1';next_state <= inc4;
When inc4 =>outregrd<='1';
regsel <= instrreg (2 downto 0) ;Regwr <='1';
next_state <= incpc;
When incpc => progcntrrd<='1';alusel<=inc;
shiftsel<=shftpass;Outregwr <= '1';next_state<=incpc2;
When incpc2 => outregrd<='1'; progcntrwr <= '1';
addrregwr<='1'; Next_state <= incpc3;
When incpc3 => outregrd<='0'; vma<='1'; rw<='0';
instrwr<='1';next_state<=execute;
--以下为新的指令状态
when in0 => progCntrRd <= '1' ; aluSel<= notOp;
shiftsel<=shftpass; Outregwr <= '1';next_state <=in1;
when in1 => outregrd<='1';addrRegwr <= '1';
next_state <=in2;
when in2 => opRegRd<='1';
regSel<=instrReg(2 downto 0) ; regWr <='1';
next_state <= incpc;
when out0 => progCntrRd <= '1' ; aluSel<= notOp;
shiftsel<=shftpass;we1<='0';Outregwr <= '1';
next_state <=out1;
when out1 => outregrd<='1';addrRegwr <= '1';we1<='0';
next_state <=out2;
when out2 => we1<='0';regSel<=instrReg(2 downto 0);
RegRd<='1'; next_state <= out3; --功能仿真代码
when out3 => we1<='1'; next_state <= incpc; --功能仿真代码
--时序仿真代码 when out2 => we1<='1'; regSel<=instrReg(2 downto 0);
RegRd<='1'; next_state <= incpc;
When others => next_state <= incpc;
End case;
End process;
reg: process (clock, reset) begin
If reset = '1' then current_state <= reset1 ;
Elsif rising_edge(clock) then current_state<=next_state ;
end if;
End process;
End rtl;
③编写存储器RAMK初始化文件,该程序执行的功能是:(7802H)从输入端口读数据并存放到寄存器R2;(2001H、0001H)将立即数0001H送寄存器R1;680AH将寄存器R1和R2的内容相加后送R3;9003H将寄存器R3的内容向输出端口输出到外设。
④仿真测试(基于ModelSim-Alera的功能仿真)
程序运行总体图
7802H、2001H和0001H程序运行图
680AH执行过程图
9003H执行过程图