Skip to content

Latest commit

 

History

History
887 lines (702 loc) · 25.9 KB

readme.md

File metadata and controls

887 lines (702 loc) · 25.9 KB

基于Vivado平台使用VHDL设计实现一个单周期CPU(HBU硬件描述语言实验大作业)

CPU架构

基本架构

参考课程给出的推荐架构,具体如下:

  • 哈佛结构RISC,字长为16位
  • 单周期
  • 指令字长为16位
  • 数据字长为16位
  • 程序存储空间为65536字
  • 数据存储空间为65536字

寄存器

  • 16个16位通用寄存器r0-r15 ,r0总为零,r15为链接寄存器;
  • 1个4位标志寄存器,V溢出,C进位,N负,Z零;

指令集说明

指令集分类如下:

  • 立即寻址加载指令
  • 寄存器寻址运算指令
  • 立即寻址跳转指令
  • 偏移寻址条件分支指令
  • 寄存器间接寻址加载/存储指令
  • 链接寄存器寻址跳转指令

立即寻址加载指令

指令中的8位立即数加载到指定的通用寄存器低8位。 Imm8为8位立即数,rd为通用寄存器。

LI rd, Imm8

寄存器寻址运算指令

通用寄存器rs和rd中的两个操作数进行运算操作码alu_op指定运算Fx ,结果赋值到寄存器rd中。寄存器寻址运算指令的运算操作码为4位,可以指定16种运算。每种运算都将改变标志位寄存器的内容。

Fx rd, rs

运算指令 操作码 说明
ADD 0000 加法
SUB 0001 减法
MOV 0100 拷贝
AND 0101 与运算
OR 1010 或运算
NOT 0111 非运算
XOR 1000 异或运算
SLL 1001 逻辑左移
SRL 1010 逻辑右移
SRA 1011 算数右移
SCC 1100 带进位循环一位右移
TST 1101 比较运算,仅改变标志位
RDF 1110 读标志位
WRF 1111 写标志位

立即寻址跳转指令

跳转指令

14位立即数地址送PC低14位(程序跳转), PC高2位不变。

JMP addr14

带链接的跳转指令

当前 PC值送r15 ,14为立即数地址送 PC低14位。

JL addr14

偏移寻址条件分支指令

若指定条件为真,当前 PC 值加上有符号相对偏移地址立即数 addr8 送给 PC,程序跳转。条件码为4位,对应4位标志位,产生4个执行跳转条件。条件码某位为1,所对应的标志位为1,则该执行跳转条件为真。条件码某位为0,则该执行跳转条件总为真。

BX addr8

条件码 说明
0000 直接跳转
0001 Z为1(相等)则跳转
0010 标志位 N为1(小于)则跳转
0100 标志位 C为1(有进位或借位)则跳转
1000 标志位 V为1(溢出)则跳转

寄存器间接寻址

寄存器间接寻址加载指令

将 rs 所存的地址值指定的数据存储器单元中的数据加载到 rd

LM rd, rs

存器间接寻址存储指令

将 rd 中的数据保存到 rs 所存的地址值指定的数据存储器单元。

SM rd, rs

链接寄存器寻址跳转指令

r15送 PC,程序跳转

JR

设计框架

该CPU主要组成部件如下:

  • 寄存器堆
  • 标志寄存器
  • ALU
  • 译码器
  • 数据存储器
  • 指令存储器

组件设计

寄存器组

共16个16位寄存器,设置一个读端口和一个读写端口

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity My_register is
    Port ( 
        clk : in STD_LOGIC;
        ra1 : in STD_LOGIC_VECTOR(3 downto 0); -- 端口1 地址
        ra2 : in STD_LOGIC_VECTOR(3 downto 0); -- 端口2 地址
        rwd2 : in STD_LOGIC_VECTOR(15 downto 0); -- 端口2 写数据
        rwe2 : in  STD_LOGIC;                       -- 端口2 写数据使能
        rrd1 : out STD_LOGIC_VECTOR(15 downto 0); -- 端口1 读数据
        rrd2 : out STD_LOGIC_VECTOR(15 downto 0) -- 端口2 读数据
    );
end My_register;

architecture Behavioral of My_register is
    -- 16个16位通用寄存器
    type type_reg is array (15 downto 0) of std_logic_vector(15 downto 0);
    signal reg : type_reg;
begin
    process (clk) is
    begin 
        if clk'event and clk = '1' then
            if rwe2 = '1' then
                reg(conv_integer(ra2)) <= rwd2;
            end if;
        end if;
    end process;
    rrd1 <= X"0000" when ra1="0000" else reg(conv_integer(ra1));
    rrd2 <= X"0000" when ra2="0000" else reg(conv_integer(ra2));
end Behavioral;

标志位寄存器

ALU 算数逻辑运算单元

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity My_alu is
    Port ( 
        vcnz    : in STD_LOGIC_VECTOR(3 downto 0);
        aluop   : in STD_LOGIC_VECTOR(3 downto 0);
        od1     : in STD_LOGIC_VECTOR(15 downto 0);
        od2     : in STD_LOGIC_VECTOR(15 downto 0);
        aluout : inout STD_LOGIC_VECTOR(15 downto 0);
        fout    : out STD_LOGIC_VECTOR(3 downto 0)
    );
end My_alu;

architecture Behavioral of My_alu is
    signal add_result : STD_LOGIC_VECTOR(16 downto 0);
    signal minus_result : STD_LOGIC_VECTOR(16 downto 0);
    signal shift_number : integer range 0 to 31;
    signal sll_result : STD_LOGIC_VECTOR(15 downto 0);
    signal srl_result : STD_LOGIC_VECTOR(15 downto 0);
    signal sra_result : STD_LOGIC_VECTOR(15 downto 0);
    signal scc_result : STD_LOGIC_VECTOR(15 downto 0);
    signal flag_v : STD_LOGIC;
    signal c_result : STD_LOGIC;
    signal flag_c : STD_LOGIC;
    signal flag_n : STD_LOGIC;
    signal flag_z : STD_LOGIC;
    signal temp_fout:STD_LOGIC_VECTOR(3 downto 0);
begin
-- 加法  
add_result <= ("0" & od1) + ("0" & od2);
-- 减法
minus_result <= ("0" & od1) - ("0" & od2);
-- 移位数目
shift_number <= conv_integer(od2);
-- 逻辑左移
sll_result <= to_stdlogicvector(to_bitvector(od1) sll Shift_Number);

-- 逻辑右移
srl_result <= to_stdlogicvector(to_bitvector(od1) srl Shift_Number);

-- 算数右移
sra_result <= to_stdlogicvector(to_bitvector(od1) sra Shift_Number);

-- 带进位循环一位右移
scc_result(15) <= od1(0);
scc_result(14 downto 0) <= od1(15 downto 1) ;

-- 标志位输出
temp_fout(3) <= add_result(16); -- 溢出标志
temp_fout(2) <= add_result(16); -- 进位标志
temp_fout(1) <= aluout(15) ; -- 负数标志
temp_fout(0) <= '1' when minus_result(15 downto 0) = X"000" else
            '0' ;  -- 零标志

fout <= od1(3 downto 0) when aluop="1111" else
        temp_fout;

aluout <= add_result(15 downto 0)     when aluop = "0000" else  -- ADD
            minus_result(15 downto 0)  when aluop = "0001" else   -- SUB
            od2                            when aluop = "0100" else   -- MOV  ?
            od1 and od2                   when aluop = "0101" else   -- AND
            od1 or od2                    when aluop = "0110" else -- OR
            not od2                       when aluop = "0111" else -- NOT
            od1 xor od2                  when aluop = "1000" else -- XOR
            sll_result                   when aluop = "1001" else
            srl_result                   when aluop = "1010" else
            sra_result                   when aluop = "1011" else
            scc_result                   when aluop = "1100" else
            od1                           when aluop = "1101" else -- TST 比较
            X"000" & vcnz               when aluop = "1110" else 
            od2;
end Behavioral;

数据存储器

基于IP核blk_mem_gen_0封装

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Mem_data is
    port(
                clk		:	in	STD_LOGIC;
                ma 		:	in	STD_LOGIC_VECTOR(15 downto 0);
                mrd		:	out	STD_LOGIC_VECTOR(15 downto 0);
                mwe		:	in	STD_LOGIC;
                mwd		:	in	STD_LOGIC_VECTOR(15 downto 0)
        );
end Mem_data;

architecture Behavioral of Mem_data is
    component blk_mem_gen_0 is
	  Port ( 
	    clka : in STD_LOGIC;
	    wea : in STD_LOGIC_VECTOR ( 0 to 0 );
	    addra : in STD_LOGIC_VECTOR ( 15 downto 0 );
	    dina : in STD_LOGIC_VECTOR ( 15 downto 0 );
	    douta : out STD_LOGIC_VECTOR ( 15 downto 0 )
	  );
	end component blk_mem_gen_0;

	signal	wea		:	STD_LOGIC_VECTOR ( 0 to 0 );

begin
    wea		<=	(others => mwe);
	u0:	blk_mem_gen_0	port map(
									clka	=>	clk,
									wea		=>	wea,
									addra	=>	ma,
									dina	=>	mwd,
									douta	=>	mrd	
								);
end Behavioral;

指令存储器

基于IP核dist_mem_gen_0封装

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity Mem_inst is
    port(
                pc		:	in	STD_LOGIC_VECTOR(15 downto 0);
                instr	:	out	STD_LOGIC_VECTOR(15 downto 0)
        );
end Mem_inst;

architecture Behavioral of Mem_inst is
    component dist_mem_gen_0 is
	  Port ( 
	    a : in STD_LOGIC_VECTOR ( 15 downto 0 );
	    spo : out STD_LOGIC_VECTOR ( 15 downto 0 )
	  );
	end component dist_mem_gen_0;
begin

u0:	dist_mem_gen_0	port map(
									a	=>	pc,
									spo	=>	instr	
								);

end Behavioral;

控制器

主要完成指令译码,生成控制信号,计算PC值等任务

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity My_cpu is
	port(
			clk			:	in STD_LOGIC; -- 时钟信号
			rst			:	in STD_LOGIC; -- 复位信号

			pc			:	buffer	STD_LOGIC_VECTOR(15 downto 0); -- 程序指针
			instr		:	in	STD_LOGIC_VECTOR(15 downto 0); -- 指令

			ma 			:	out	STD_LOGIC_VECTOR(15 downto 0); -- 地址
			mrd			:	in	STD_LOGIC_VECTOR(15 downto 0); -- 读数据
			mwe			:	out	STD_LOGIC; -- 写使能
			mwd			:	out	STD_LOGIC_VECTOR(15 downto 0) -- 写数据
	);
end My_cpu;

architecture Behavioral of My_cpu is
    signal	ra1			:	STD_LOGIC_VECTOR(3 downto 0);
	signal	ra2			:	STD_LOGIC_VECTOR(3 downto 0);
	signal	rrd1		:	STD_LOGIC_VECTOR(15 downto 0);
	signal	rrd2		:	STD_LOGIC_VECTOR(15 downto 0);
	signal	rwd2		:	STD_LOGIC_VECTOR(15 downto 0);
	signal	rwe2		:	STD_LOGIC; -- rd寄存器写使能

	signal	fi			:	STD_LOGIC_VECTOR(3 downto 0);
	signal	fwe			:	STD_LOGIC; -- 标志寄存器写使能

	signal	npcs		: STD_LOGIC_VECTOR(1 downto 0);  -- 下一条程序地址选择
	signal	rdas		: STD_LOGIC; -- rd寄存器地址选择
	signal	rdwds		: STD_LOGIC_VECTOR(1 downto 0); -- rd寄存器写数据选择

	signal	fo		: STD_LOGIC_VECTOR(3 downto 0); -- 标志位寄存器输出
	signal	rs			: STD_LOGIC_VECTOR(3 downto 0);
	signal	rd			: STD_LOGIC_VECTOR(3 downto 0); -- 目标寄存器
	signal	imm8		: STD_LOGIC_VECTOR(7 downto 0); -- 8位立即数
	signal	op			: STD_LOGIC_VECTOR(3 downto 0); -- 操作码
	signal	aluop		: STD_LOGIC_VECTOR(3 downto 0); -- alu操作码
	signal	fcond		: STD_LOGIC_VECTOR(3 downto 0); -- 条件码
	signal	aluout		: STD_LOGIC_VECTOR(15 downto 0);
	signal	fout		: STD_LOGIC_VECTOR(3 downto 0);
	signal	od1			: STD_LOGIC_VECTOR(16 downto 0);
	signal	od2			: STD_LOGIC_VECTOR(16 downto 0);
	signal	addr8		: STD_LOGIC_VECTOR(7 downto 0); -- 目的地址(指令)	
	signal	addr14		: STD_LOGIC_VECTOR(13 downto 0);
	signal	ja			: STD_LOGIC_VECTOR(15 downto 0);
	signal	ba			: STD_LOGIC_VECTOR(15 downto 0);
	signal flag         : STD_LOGIC; -- 标志寄存器flag

	component	My_register	is
		port(
				clk : in STD_LOGIC;
				ra1 : in STD_LOGIC_VECTOR(3 downto 0); -- 端口1 地址
				ra2 : in STD_LOGIC_VECTOR(3 downto 0); -- 端口2 地址
				rwd2 : in STD_LOGIC_VECTOR(15 downto 0); -- 端口2 写数据
				rwe2 : in  STD_LOGIC; -- 端口2 写数据使能
				rrd1 : out STD_LOGIC_VECTOR(15 downto 0); -- 端口1 读数据
				rrd2 : out STD_LOGIC_VECTOR(15 downto 0) -- 端口2 读数据
			);
	end component My_register;

	component	My_flag_register	is
		Port ( 
			clk : in STD_LOGIC;
			fi  : in STD_LOGIC_VECTOR(3 downto 0);
			fwe : in STD_LOGIC;
			fo  : out STD_LOGIC_VECTOR(3 downto 0)
    	);
	end component My_flag_register;	

	component	My_alu	is
		port (
			vcnz    : in STD_LOGIC_VECTOR(3 downto 0);
			aluop   : in STD_LOGIC_VECTOR(3 downto 0);
			od1     : in STD_LOGIC_VECTOR(15 downto 0);
			od2     : in STD_LOGIC_VECTOR(15 downto 0);
			aluout : inout STD_LOGIC_VECTOR(15 downto 0);
			fout    : out STD_LOGIC_VECTOR(3 downto 0)
		);
	end component My_alu;	

begin
	-- 寄存器堆
	register1:	My_register		port map(
									clk			=>	clk,
									ra1			=>	ra1,
									ra2			=>	ra2,
									rwd2		=>	rwd2,
									rwe2 			=>	rwe2,
									rrd1			=>	rrd1,
									rrd2			=>	rrd2
								);
	-- 标志寄存器
	flag_register: My_flag_register 	port map(
									clk			=>	clk,
									fi			=>	fi,
									fwe			=>	fwe,
									fo		=>	fo
								);
	-- alu
	alu: My_alu port map(
			vcnz    => fo,
			aluop   => aluop,
			od1     => rrd2,
			od2     => rrd1,
			aluout  => aluout,
			fout    => fi
	);
-- ——————————————————————————————————————————————
-- 译码
	op <= instr(15 downto 12);
	rs <= instr(7 downto 4);
	rd <= instr(3 downto 0);
	imm8 <= instr(11 downto 4);
	aluop <= instr(11 downto 8);
	addr8 <= instr(7 downto 0);
	fcond <= instr(11 downto 8);
	addr14 <= instr(13 downto 0);
-- ——————————————————————————————————————————————


-- begin——————————————————————————————————————————————
-- 寄存区写数据选择
	-- 寄存器写数据来源选择
	rdwds <= "00" when op = "0000" else
			  "01" when op = "0001" else
			  "10" when op(3 downto 2) = "11" else
			  "11" when op = "0100" else 
			  "XX";


	rwd2 <= X"00" & imm8 when rdwds = "00" else
			aluout 	   	   when rdwds = "01" else
			pc              when rdwds = "10" else
			mrd             when rdwds = "11" else
			X"0000";

	-- 寄存器写使能
	rwe2 <= '1' when op ="0000" or op="0001" or op(3 downto 2) = "11" or op= "0100" else
			 '0' when op(3 downto 2) = "10" or op = "0010" or op = "0101" or op = "0011" else
			 'X';

-- end——————————————————————————————————————————————


	-- 读写寄存器端口地址选择
	rdas <= '1' when op = "0000" or op ="0001" or op = "0100" or op ="0101" else 
			 '0' when op(3 downto 2) = "11" or op = "0011" else
			 'X';

	ra2 <=  rd when rdas = '1' else
			 "1111" when rdas = '0' else
			 "XXXX";
	-- 读寄存器端口地址选择
	ra1 <= rs;

	-- 标志寄存器写使能
	fwe <= '1' when op = "0001" else
			'0';
	
	flag <= '1' when fcond = "0000" else
			 fo(0) when fcond = "0001" else
			fo(1) when fcond = "0010" else
			fo(2) when fcond = "0100" else
			fo(3) when fcond = "1000" else
			'0';

	mwe <= '1' when op = "0101" else
			'0';

	mwd<=rrd2;

	ma<=rrd1;
-- begin——————————————————————————————————————————————
-- 下一条指令选择
	ja <="00" & instr(13 downto 0);
	ba <= X"00" & instr(7 downto 0) when instr(7)='0' else
		   X"ff" & instr(7 downto 0);

	npcs <= "00" when op = "0000" or op ="0001" or op = "0100" or op="0101" else
			 "01" when op(3 downto 2) = "10" or  op(3 downto 2) = "11" else
			 "10" when op = "0010" and flag = '1' else
			 "00" when op = "0010" and flag = '0' else
			 "11" when op = "0011"  else
			 "XX";
	process (clk) is
	begin
		if clk'event and clk='1' then
			if rst='1' then
				pc <= X"0000";
			else
		case npcs is
			when "00" => pc <= pc + '1'; -- 顺序执行
			when "01" => pc <= ja; -- 寻址跳转
			when "10" => pc <= pc + ba; -- 跳转
			when "11" => pc <= rrd2; -- 链接跳转
			when others => pc <= pc;
		end case;
		end if;
		end if;
end process;
-- end——————————————————————————————————————————————




end Behavioral;

整体封装

将CPU、数据存储器、指令存储器封装到一起

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity My_computer is
    port(
            clk				:	in STD_LOGIC;
            rst				:	in STD_LOGIC;

            ma_io 			:	buffer	STD_LOGIC_VECTOR(15 downto 0);
            mrd_io			:	buffer		STD_LOGIC_VECTOR(15 downto 0);
            mwe_io			:	buffer	STD_LOGIC;
            mwd_io			:	buffer	STD_LOGIC_VECTOR(15 downto 0)
        );
end My_computer;

architecture Behavioral of My_computer is

    component	My_cpu	is
		port(
				clk			:	in STD_LOGIC;
				rst			:	in STD_LOGIC;

				pc			:	buffer	STD_LOGIC_VECTOR(15 downto 0);
				instr		:	in	STD_LOGIC_VECTOR(15 downto 0);

				ma 			:	out	STD_LOGIC_VECTOR(15 downto 0);
				mrd			:	in	STD_LOGIC_VECTOR(15 downto 0);
				mwe			:	out	STD_LOGIC;
				mwd			:	out	STD_LOGIC_VECTOR(15 downto 0)
		);
	end component My_CPU;

    component	Mem_inst	is
    port(
            pc		:	in	STD_LOGIC_VECTOR(15 downto 0);
            instr	:	out	STD_LOGIC_VECTOR(15 downto 0)
    );
	end component Mem_inst;

	component	Mem_data	is
		port(
				clk		:	in	STD_LOGIC;
				ma 		:	in	STD_LOGIC_VECTOR(15 downto 0);
				mrd		:	out	STD_LOGIC_VECTOR(15 downto 0);
				mwe		:	in	STD_LOGIC;
				mwd		:	in	STD_LOGIC_VECTOR(15 downto 0)
		);
	end component Mem_data;

	signal 			pc			:	STD_LOGIC_VECTOR(15 downto 0);
	signal 			instr		:	STD_LOGIC_VECTOR(15 downto 0);

	signal 			ma 			:	STD_LOGIC_VECTOR(15 downto 0);
	signal 			mrd			:	STD_LOGIC_VECTOR(15 downto 0);
	signal 			mwe			:	STD_LOGIC;
	signal 			mwd			:	STD_LOGIC_VECTOR(15 downto 0);

begin
	ma_io <=ma;
	mrd_io<=mrd;
	mwe_io<=mwe;
	mwd_io<=mwd;
    u0:	My_CPU		port map(
									clk			=>	clk,
									rst			=>	rst,

									pc			=>	pc,
									instr		=>	instr,

									ma 			=>	ma,
									mrd			=>	mrd,
									mwe			=>	mwe,
									mwd			=>	mwd
								);

	u1:	Mem_inst	port map(
									pc		=>	pc,
									instr	=>	instr
								);

	u2:	Mem_data	port map(
									clk		=>	clk,
									ma		=>	ma,
									mrd		=>	mrd,
									mwe		=>	mwe,
									mwd		=>	mwd
								);

end Behavioral;

测试验证

编写顶层仿真模块

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity First_TestBanch is
end First_TestBanch;

architecture Behavioral of First_TestBanch is
	component My_computer is
		port(
				clk				:	in STD_LOGIC;
				rst				:	in STD_LOGIC;

				ma_io 			:	buffer	STD_LOGIC_VECTOR(15 downto 0);
				mrd_io			:	buffer		STD_LOGIC_VECTOR(15 downto 0);
				mwe_io			:	buffer	STD_LOGIC;
				mwd_io			:	buffer	STD_LOGIC_VECTOR(15 downto 0)
		);
	end component My_computer;

	signal	clk				:	STD_LOGIC;
	signal	rst				:	STD_LOGIC;

	signal	ma_io 			:	STD_LOGIC_VECTOR(15 downto 0);
	signal	mrd_io			:	STD_LOGIC_VECTOR(15 downto 0);
	signal	mwe_io			:	STD_LOGIC;
	signal	mwd_io			:	STD_LOGIC_VECTOR(15 downto 0);
begin
	computer:	My_computer	port map(
									clk			=>	clk,			
									rst			=>	rst,

									ma_io 		=>	ma_io,
									mrd_io		=>	mrd_io,
									mwe_io		=>	mwe_io,
									mwd_io		=>	mwd_io			
								);

	process is
	begin
		rst		<=	'1';
		wait for	5 ps;
		rst		<=	'0';
		wait;
	end process;

	process is
	begin
		clk		<=	'0';
		wait for	1 ps;
		clk		<=	'1';
		wait for	1 ps;
	end process;
end Behavioral;

初步仿真测试

使用老师给出的测试指令进行仿真

memory_initialization_radix = 16;
memory_initialization_vector =
0121    ;   LI      r1, #12h
0082    ;   LI      r2, #08h
1921    ;   SLL     r1, r2 
0343    ;   LI      r3, #34h
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0561    ;   LI      r1, #56h
1921    ;   SLL     r1, r2 
0783    ;   LI      r3, #78h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1154    ;   SUB     r4, r5              ;sub
0121    ;   LI      r1, #12h
1921    ;   SLL     r1, r2 
0343    ;   LI      r3, #34h
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0561    ;   LI      r1, #56h
1921    ;   SLL     r1, r2 
0783    ;   LI      r3, #78h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1145    ;   SUB     r5, r4             ;sub
07f1    ;   LI      r1, #7fh
1921    ;   SLL     r1, r2 
0ff3    ;   LI      r3, #ffh
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0001    ;   LI      r1, #00h
1921    ;   SLL     r1, r2 
0023    ;   LI      r3, #02h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1054    ;   ADD     r4, r5             ;add
c028    ;   JL      0028h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0046    ;   LI      r6, #04h
1f06    ;   WRF     r6
0a07    ;   LI      r7, #a0h
1c07    ;   SCC     r7
0018    ;   LI      r8, #01h
108f    ;   ADD     r15, r8             ;add
3000    ;   JR

经过不断地调试改错后,完成了此测试,整个测试过程中的寄存器值变化如下表:

寄存器 数据
0 00h
1 12h->1200h->1234h->56h->5600h->5678h->12h->1200h->1234h->56h->5600h->5678h->7fh->7f00h->7fffh->00h->02h
2 08h
3 34h->78h->34h->78h->ffh->02h
4 1234h->bbbch->1234h->7fffh->8001h
5 5678h->5678h->4444h->02h
6 04h
7 a0h->50h
8 01h
9
10
11
12
13
14
15 22h->23h

仿真结果与人工计算结果完全一致,仿真如下:

但分析发现,此测试集中缺少分支跳转、数据存储等指令,因此在此基础上进行了修改,增加了TST,BS,SM 指令,以测试相关指令的执行。

改进仿真测试

memory_initialization_radix = 16;
memory_initialization_vector =
0121    ;   LI      r1, #12h
0082    ;   LI      r2, #08h
1921    ;   SLL     r1, r2  左移八位
0343    ;   LI      r3, #34h
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0561    ;   LI      r1, #56h
1921    ;   SLL     r1, r2 
0783    ;   LI      r3, #78h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1154    ;   SUB     r4, r5              ;sub
0121    ;   LI      r1, #12h
1921    ;   SLL     r1, r2 
0343    ;   LI      r3, #34h
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0561    ;   LI      r1, #56h
1921    ;   SLL     r1, r2 
0783    ;   LI      r3, #78h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1145    ;   SUB     r5, r4             ;sub
07f1    ;   LI      r1, #7fh
1921    ;   SLL     r1, r2 
0ff3    ;   LI      r3, #ffh
1631    ;   OR      r1, r3
1414    ;   MOV     r4, r1
0001    ;   LI      r1, #00h
1921    ;   SLL     r1, r2 
0023    ;   LI      r3, #02h
1631    ;   OR      r1, r3
1415    ;   MOV     r5, r1
1054    ;   ADD     r4, r5             ;add
c028    ;   JL      0028h              
0ff3    ;   LI      r3, #ffh           ;跳到这里 pc:0023
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0000    ;   LI      r0, #00h
0046    ;   LI      r6, #04h
1f06    ;   WRF     r6
0a07    ;   LI      r7, #a0h
1c07    ;   SCC     r7
0018    ;   LI      r8, #01h
108f    ;   ADD     r15, r8            ;add
1d35    ;   TST     r3,r5  ;002e
21f4    ;   BX      #f4                 ;pc:002f -13
5013    ;   SM      r3,r1               ;存储指令

1d35指令处,进行相等判断,写入标志寄存器,21f4处根据标志位寄存器进行跳转,第一次经过时由于r3r5均为02h 所以进行跳转,PC在原基础上减13实际是加上-13(注意应该写成补码!),跳转到0ff3指令处 ,修改r3为ffh。第二次经过分支跳转时,不满足相等条件,继续执行最后一条存储指令。

仿真结果与预期一致,如下:

代码地址

https://github.com/qy-liuhuo/My_CPU