附录A RTL图A1. 控制器的RTL图
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
图A.1 控制器的RTL图
A2. CPU的RTL图
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
图A.2 CPU的RTL图
附录B VHDL程序清单
(1)CPU.vhd文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
----头文件
PACKAGE cpu_defs IS
TYPE opcode IS(load,sta,add,sub,and1,jmp1,nop); ----枚举,七组唯一的二进制数值,0-6
CONSTANT word_w : NATURAL := 8;
CONSTANT op_w : NATURAL := 3;
CONSTANT rfill:STD_LOGIC_VECTOR(op_w-1 downto0):= ( others => '0');----三位零常量
--FUNCTIOn slv2op(slv:IN STD_LOGIC_VECTOR)RETURNopcode;
FUNCTION op2slv(op:in opcode)RETURNSTD_LOGIC_VECTOR;
END PACKAGE cpu_defs;
PACKAGE BODY cpu_defs IS
TYPE optable IS ARRAY(opcode) OFSTD_LOGIC_VECTOR(op_w-1 DOWNTO 0);---具有opcode个元素的数组,三位数据
CONSTANTtrans_table:optable:=("000","001","010","011","100","101","110");---七组二进制数与七个操作符一一对应
FUNCTION op2slv(op:IN opcode)RETURNSTD_LOGIC_VECTOR IS
BEGIN
RETURN trans_table(op);
END FUNCTION op2slv;----------输入操作符对应的无符号整数0-6,输出相对应的二进制编码
END PACKAGE BODY cpu_defs;
----源文件
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_unsigned.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE WORK.CPU_DEFS.ALL;
ENTITY CPU IS
PORT( clock:IN STD_LOGIC;-----------时钟输入
reset:IN STD_LOGIC;-----------置位输入
mode:IN STD_LOGIC_VECTOR(2 DOWNTO 0);--------三位模式输入
mem_addr:OUT UNSIGNED(word_w-op_w-3 DOWNTO 0);-------三位内存地址的输入
output: OUT STD_LOGIC_VECTOR(word_w-1DOWNTO 0);-------八位数据输出
data_r_out : OUT STD_LOGIC_VECTOR(23DOWNTO 0);--------24位微指令输出
reg_out:OUT STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
regg_out: OUT STD_LOGIC_VECTOR(word_w-1 DOWNTO0);
op_out: OUT STD_LOGIC_VECTOR(op_w-1DOWNTO 0);----------三位操作码输出
add_r_out:OUT UNSIGNED(4 DOWNTO 0); ----------五位地址输出
segctl:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
segout:OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
);
END ENTITY;
ARCHITECTURE rtl OF CPU IS
TYPE mem_array IS ARRAY (0 To2**(word_w-op_w-2)-1) OF STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);----八位数组,每个元素为八位二进制数
SIGNALmem : mem_array;--------------------------------存储器内存储的内容,程序和数据
CONSTANTprog: mem_array:=(
0=>op2slv(load)&STD_LOGIC_VECTOR(TO_UNSIGNED(7,word_w-op_w-2))&"00", --00011100 4-2加载的对象 ---------load内存中内容存到acc
1=>op2slv(sta)&"001"&"01", --00100101 4-2无作用 ---------sta把acc中内容存到reg1
2=>op2slv(add)&STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w-2))&"00", --01011000 ---------add把acc与内存中数据相加给acc
3=>op2slv(sub)&"001"&"01", --01100101 4-2无作用 ---------sub acc中内容减去reg1中内容 给acc
4=>op2slv(sta)&"010"&"10", --00101010 4-2无作用 ---------sta把acc中内容存到men(7)
--5=> op2slv(and1) &"010" & "10",
5=>op2slv(jmp1)&STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w-2))&"00", --10111000 ---------acc结果为零,跳到空操作,否则跳到第二条指令
6=>STD_LOGIC_VECTOR(TO_UNSIGNED(4,word_w)), --00000010
7=>STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w))); --00000011
--7-5本条程序的功能 --4-2下一条程序的位置(具体三位二进制数) 或 本条程序的对象
-----------------------事先编好的存入存储器的内容
TYPE microcode_array IS ARRAY (0 To 20) OF STD_LOGIC_VECTOR(23 DOWNTO0);
CONSTANT code:microcode_array:=(
0=> "000000001001010000000001",
1=> "000000000000000110000010",
2=> "000000000110000000000011",
3=> "000000000001001000011111",
4=>"000000010010000000000000",
5=>"000100000000000000000000",
6=>"100000000000000000000111",
7=>"000010000001000000001111",
8=> "000000000000000110000100",
9=>"010000000000000000011110",
10=> "000000000000000110010000",
11=> "000001000000100000100000",
12=> "000010000001000000010001",
13=> "000000000000000110011100",
14=> "000000000000000000000000",
15=> "000000000000000100000000",
16=> "000000000010100001000000",
17=> "000000000000000110010010",
18=> "001000000010100000000000",
19=> "000000100010000000000000",
20=>"000000000000000000000000");-------------21个元素,24位二进制操作码数组
SIGNAL count:UNSIGNED(word_w-op_w-1 DOWNTO0);--------五位计数值
SIGNAL op:STD_LOGIC_VECTOR(op_w-1 DOWNTO0);------三位指令码
SIGNAL z_flag:STD_LOGIC;------ZF
SIGNAL mdr_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);---------八位数据寄存器DR的输出
SIGNAL mar_out:UNSIGNED(word_w-op_w-3 DOWNTO0);----------三位地址寄存器MAR的输出
SIGNAL IR_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);----------指令寄存器的八位输出(指令或译码后的操作码)--------波形未输出
SIGNAL acc_out:UNSIGNED(word_w-1 DOWNTO0);----------八位累加器输出
SIGNAL reg1_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
SIGNAL reg2_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);
SIGNAL sysbus_out:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);--------八位数据总线输出
SIGNAL mem_addr_r:UNSIGNED(word_w-op_w-3DOWNTO 0);
SIGNAL inclock:STD_LOGIC;-----------内部时钟
SIGNAL period:integer:=50000000;
SIGNAL hcnt:integer:=25000000;
--SIGNAL period:integer:=16;
--SIGNAL hcnt:integer:=8;
SIGNAL cnt:integer:=0;
SIGNAL inclock_c:STD_LOGIC;-----------内部时钟
SIGNAL period_c:integer:=125000;
SIGNAL hcnt_c:integer:=62500;
--SIGNAL period_c:integer:=2;
--SIGNAL hcnt_c:integer:=1;
SIGNAL cnt_c:integer:=0;
SIGNAL databuf:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL datain:STD_LOGIC_VECTOR(15 DOWNTO 0);
SIGNAL cnt_show:STD_LOGIC_VECTOR(1 DOWNTO0):="00";
BEGIN
PROCESS(clock)
BEGIN
IFRISING_EDGE(clock) THEN
IF cnt>period THEN
cnt<=0;
inclock<='1';
ELSIF cnt<hcnt THEN
inclock<='1';
cnt<=cnt+1;
ELSE
inclock<='0';
cnt<=cnt+1;
END IF;
ENDIF;
END PROCESS;
PROCESS(clock)
BEGIN
IFRISING_EDGE(clock) THEN
IF cnt_c>period_c THEN
cnt_c<=0;
inclock_c<='1';
ELSIF cnt_c<hcnt_c THEN
inclock_c<='1';
cnt_c<=cnt_c+1;
ELSE
inclock_c<='0';
cnt_c<=cnt_c+1;
END IF;
ENDIF;
END PROCESS;
PROCESS(reset,inclock)
BEGIN
IFreset='0' THEN
mem_addr<=(OTHERS =>'0');
mem_addr_r<=(OTHERS =>'0');
ELSIFRISING_EDGE(inclock) THEN
mem_addr_r<=mem_addr_r+1;
mem_addr<=mem_addr_r;
endif;
END PROCESS;
PROCESS(reset,inclock)
VARIABLE instr_reg:STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);-----------指令寄存器中的内容
VARIABLE acc:UNSIGNED(word_w-1 DOWNTO0);----------累加器
CONSTANT zero:UNSIGNED(word_w-1 DOWNTO 0):=(OTHERS =>'0');----------八位零常量
VARIABLE mdr:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);----------数据寄存器
VARIABLE reg1:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);-------------?
VARIABLE reg2:STD_LOGIC_VECTOR(word_w-1DOWNTO 0);------------?
VARIABLE mar:UNSIGNED(word_w-op_w-3DOWNTO 0);---------三位地址寄存器
VARIABLE sysbus : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE microcode :microcode_array;------------24位指令码数组
VARIABLE add_r: UNSIGNED(4 DOWNTO 0);
VARIABLE data_r: STD_LOGIC_VECTOR(23 DOWNTO 0);--------------24位指令码
VARIABLE temp: STD_LOGIC_VECTOR(4 DOWNTO0);-----------五位临时变量
BEGIN
reg2:="00000111";
IFreset='0' THEN-------------置位端清零
add_r:=(OTHERS =>'0');
count<= (OTHERS =>'0');
instr_reg:=(OTHERS =>'0');
acc:= (OTHERS =>'0');
mdr:= (OTHERS =>'0');
reg1:= (OTHERS =>'0');
reg2 := (OTHERS =>'0');
mar := (OTHERS =>'0');
z_flag<='0';
mem <= prog;
sysbus :=(OTHERS=>'0');
ELSIFRISING_EDGE(inclock) THEN --microprogram controller 指令控制器
data_r:=code(TO_INTEGER(add_r));
IF data_r(4 DOWNTO 0)="11111"THEN --判断地址
temp:="01"&op(2DOWNTO 0);
add_r:=UNSIGNED(temp);
ELSIF data_r(4 DOWNTO0)="11110" THEN
IFIR_out(1 downto 0)="10" THEN
add_r :="00110";
ELSIFIR_out(1 downto 0)="01" THEN
add_r :="00101";
ENDIF;
ELSIF data_r(4 DOWNTO 0)="11100"THEN
IFz_flag='0' THEN
add_r:="10011";
ELSE
add_r:="10100";
ENDIF;
ELSE
add_r:=UNSIGNED(data_r(4 DOWNTO 0));
END IF;
data_r_out<=data_r;
add_r_out<=add_r;
--PC 程序计数器----确定下一条指令的地址
IF data_r(15)='1' THEN --PC_bus='T'
sysbus:=rfill & STD_LOGIC_VECTOR(count);
END IF;
IF data_r(17)='1'THEN --load_PC='l' count置数
count<= UNSIGNED(mdr(word_w-op_w-1 DOWNTO 0));----------data_r(17)==?
ELSIF data_r(10)='1' THEN --INC_PC='l' ---------data_r(10)=IPC 决定计数器是否加一
count<= count+1;
ELSE
count<= count;
END IF;
--IR 指令寄存器---用来保存当前正在执行的指令,如果是操作码就进行译码
IF data_r(14)='1'THEN --load_ IR data_r(14)==IIR
instr_reg:=mdr;
END IF; -----------------------------------------保存当前正在执行的指令(mdr是计算的数据)
IF data_r(9)='1'THEN --Addr_ bus='l' 判断是否是操作码
sysbus:="00"& rfill & instr_reg(word_w-op_w-1 DOWNTO 2);
END IF;---------------------------------------------------译操作码
op <= instr_reg(word_w-1 DOWNTO word_w-op_w); -----------第七位到第五位 当前三位操作码
IR_out<=instr_reg;
op_out<=op;
--ALU 算术逻辑单元
IF data_r(16)='1'THEN --load_ACC='l' ------------data_r(16)==ESUM 判断是否给acc
acc:=UNSIGNED(mdr);------------计算数据结果给acc
ENd if;
IF data_r(22)='1'THEN --ACC_bus='l'
sysbus:=STD_LOGIC_VECTOR(acc);-------------判断是否累加结果acc给数据总线
END IF;
IF data_r(18)='1'THEN --REG1_ bus='l'
sysbus:=STD_LOGIC_VECTOR(reg1);---------------寄存器reg1的结果给数据总线
END IF;
IF data_r(19)='1'THEN --REG2_ bus='l'
sysbus:= STD_LOGIC_VECTOR(reg2);---------------寄存器reg2的结果给数据总线
END IF;
If data_r(20)='1'then --load_ regl='l'
reg1:=sysbus;
reg_out<=reg1;----------------reg1获得数据总线上的值并输出
END IF;
IF IR_out(1 downto 0)="00" THEN
IFdata_r(11)='1'THEN --ALU_ ACC='l' data_r(11)==IA
IF data_r(6)='1'THEN --ALU__add='l' data_r(6) == Iadd
acc:=acc+UNSIGNED(mdr);
END IF;
ENDIF;
ELSIF IR_out(1 downto 0)="01"THEN
IFdata_r(11)='1'THEN --ALU_ ACC='l'
IF data_r(5)='1'THEN --ALU_ _sub='l' data_r(5) == Isub
acc:=acc-UNSIGNED(reg1_out);
END IF;
ENDIF;
ELSIF IR_out(1 downto0)="10"THEN
IFdata_r(11)='1' THEN --ALU_ ACC='l'
IF data_r(21)='1'THEN --ALU_ and='1' ata_r(21) == Iand
acc:= acc and UNSIGNED(mdr);
END IF;
ENDIF;
END IF;
IF acc=zero THEN --根据结果acc设计ZF
z_flag<='1';
ELSE
z_flag<='0';
END IF;
acc_out<=acc;
--RAM 存储器
IF data_r(12)='1'THEN --load_MAR='l' data_r(12) = IMAR 是否工作
mar:=UNSIGNED(sysbus(word_w-op_w-3dOWNTO 0)); ----------获得地址信息
ELSIF data_r(23)='1' THEN --load_ MDR='1' data_r(23) = IMDR
mdr:=sysbus;--------------指令或数据给MDR
ELSIF data_r(8)='1'THEN --CS='l'
IFdata_r(7)='1' THEN --R_NW='l'读
mdr:= mem(TO_INTEGER(mar));
ELSE
mem(TO_INTEGER(mar)) <= mdr; -- 写数据或指令
ENDIF;
END IF;
IF data_r(13)='1'THEN --MDR_bus='l' data_r(13) = EMDR
sysbus:=mdr;
END IF;
mdr_out<= mdr;
mar_out<= mar;
ENDIF;
sysbus_out <= sysbus;
reg1_out<= reg1;
reg2_out<= reg2;
regg_out <= reg2_out;
END PROCESS;
PROCESS(mode,inclock)
VARIABLE output_t:STD_LOGIC_VECTOR(15 DOWNTO0);
BEGIN
--mode=0-> sysbus
--mode=1-> PC
--mode=2-> result of ALU
--mode=3-> IR
--mode=4-> MAR
--mode=5-> MDR
--mode=6 -> mem
output_t := (OTHERS =>'0');
CASE mode is
WHEN "000" =>output_t(7 downto 0):=sysbus_out;
WHEN "001" =>output_t(word_w-op_w-1 DOWNTO 0):=STD_LOGIC_VECTOR(count);
WHEN "010" =>output_t(7downto 0):=STD_LOGIC_VECTOR(acc_out);
WHEN "011" =>output_t(7downto 0):= IR_out;
WHEN "100"=>output_t(word_w-op_w-3 DOWNTO 0):=STD_LOGIC_VECTOR(mar_out);
WHEN "101" =>output_t(7downto 0) := mdr_out;
WHEN "110" =>output_t(7downto 0):= mem(TO_INTEGER(mem_addr_r));
WHEN others =>output_t(7 downto 0):=(OTHERS=>'Z');
END CASE;
output<=output_t(7 downto 0);
datain<=output_t;
END PROCESS;
PROCESS(inclock_c)
BEGIN
IF RISING_EDGE(inclock_c) THEN
cnt_show<= cnt_show + "01";
END IF;
END PROCESS;
PROCESS(inclock_c)
BEGIN
IF RISING_EDGE(inclock_c) THEN
casecnt_show IS
when"00"=>
databuf<=datain(3 downto 0);
segctl<="1110";
when"01"=>
databuf<=datain(7 downto 4);
segctl<="1101";
when"10"=>
databuf<=datain(11 downto 8);
segctl<="1011";
when"11"=>
databuf<=datain(15 downto 12);
segctl<="0111";
WHENothers =>segctl<="0000";
ENDCASE;
END IF;
END PROCESS;
PROCESS(databuf)
BEGIN
casedatabuf IS
when"0000"=>
segout<="0000001";
when"0001"=>
segout<="1001111";
when"0010"=>
segout<="0010010";
when"0011"=>
segout<="0000110";
when"0100"=>
segout<="1001100";
when"0101"=>
segout<="0100100";
when"0110"=>
segout<="0100000";
when"0111"=>
segout<="0001111";
when"1000"=>
segout<="0000000";
when"1001"=>
segout<="0000100";
when"1010"=>
segout<="0001000";
when"1011"=>
segout<="1100000";
when"1100"=>
segout<="0110001";
when"1101"=>
segout<="1000010";
when"1110"=>
segout<="0110000";
when"1111"=>
segout<="0111000";
WHENothers =>segout<= (OTHERS=>'0');
end case;
END PROCESS;
END ARCHITECTURE;
附录C 微指令解析
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
图C.121微指令解析
file:///C:/Users/Quan/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png
图C.2 21条微指令的作用 |