📄 cpu.vhd
字号:
--实验11 组合逻辑控制器实验
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL,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); --used to select the content of output
mem_addr : IN UNSIGNED(word_w-op_w-1 DOWNTO 0);
PC_bus : INOUT STD_LOGIC; -- signal of PC
load_PC : INOUT STD_LOGIC; -- signal of PC
INC_PC : INOUT STD_LOGIC; -- signal of PC
Addr_bus : INOUT STD_LOGIC; -- signal of IR
load_IR : INOUT STD_LOGIC; -- signal of IR
ACC_bus : INOUT STD_LOGIC; -- signal of ALU
load_ACC : INOUT STD_LOGIC; -- signal of ALU
ALU_ACC : INOUT STD_LOGIC; -- signal of ALU
ALU_add : INOUT STD_LOGIC; -- signal of ALU
ALU_sub : INOUT STD_LOGIC; -- signal of ALU
z_flag : INOUT STD_LOGIC; -- signal of ALU
MDR_bus : INOUT STD_LOGIC; -- signal of RAM
load_MDR : INOUT STD_LOGIC; -- signal of RAM
load_MAR : INOUT STD_LOGIC; -- signal of RAM
CS : INOUT STD_LOGIC; -- signal of RAM
R_NW : INOUT STD_LOGIC; -- signal of RAM
sysbus_out : OUT STD_LOGIC_VECTOR(word_w-1 DOWNTO 0); --output of bus
present_out: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --the output of C,Z,V,S
output : OUT STD_LOGIC_VECTOR(word_w-1 DOWNTO 0) --output of PC,opcode,mdr,mar,IR,acc,mem
);
END ENTITY;
ARCHITECTURE rtl OF CPU IS
TYPE state IS (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10);
TYPE mem_array IS ARRAY (0 TO 2**(word_w-op_w)-1) OF STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
SIGNAL mem : mem_array;
CONSTANT prog : mem_array:=(
0=> op2slv(load) & STD_LOGIC_VECTOR(TO_UNSIGNED(4,word_w-op_w)),
1=> op2slv(add) & STD_LOGIC_VECTOR(TO_UNSIGNED(5,word_w-op_w)),
2=> op2slv(store) & STD_LOGIC_VECTOR(TO_UNSIGNED(6,word_w-op_w)),
3=> op2slv(bne) & STD_LOGIC_VECTOR(TO_UNSIGNED(7,word_w-op_w)),
4=> STD_LOGIC_VECTOR(TO_UNSIGNED(2,word_w)),
5=> STD_LOGIC_VECTOR(TO_UNSIGNED(3,word_w)),
OTHERS => (OTHERS =>'0'));
SIGNAL present_state,next_state:state;
SIGNAL mdr_out : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0); --output of mdr
SIGNAL mar_out : UNSIGNED(word_w-op_w-1 DOWNTO 0); --output of mar
SIGNAL IR_out : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0); --output of Instruction Register
--SIGNAL present_out: STD_LOGIC_VECTOR(3 DOWNTO 0); --output of current state
SIGNAL acc_out : UNSIGNED(word_w-1 DOWNTO 0); --output of acc
SIGNAL count : UNSIGNED(word_w-op_w-1 DOWNTO 0);
SIGNAL op : STD_LOGIC_VECTOR(op_w-1 DOWNTO 0);
BEGIN
PROCESS(clock,reset)
VARIABLE instr_reg : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE acc : UNSIGNED(word_w-1 DOWNTO 0);
CONSTANT zero : UNSIGNED(word_w-1 DOWNTO 0):=(others =>'0');
VARIABLE mdr : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
VARIABLE mar : UNSIGNED(word_w-op_w-1 DOWNTO 0);
VARIABLE sysbus : STD_LOGIC_VECTOR(word_w-1 DOWNTO 0);
BEGIN
IF reset='0' THEN
count <= (OTHERS =>'0');
instr_reg := (OTHERS =>'0');
acc := (OTHERS =>'0');
mdr := (OTHERS =>'0');
mar := (OTHERS =>'0');
z_flag <='0';
mem <= prog;
sysbus :=(OTHERS =>'0');
present_state <=s0;
ELSIF RISING_EDGE(clock) THEN
--PC
IF PC_bus='1' THEN
sysbus := rfill & STD_LOGIC_VECTOR(count);
END IF;
IF load_PC='1' THEN
--count <= UNSIGNED(sysbus(word_w-op_w-1 DOWNTO 0));
count <= UNSIGNED(mdr(word_w-op_w-1 DOWNTO 0));
ELSIF INC_PC='1' THEN
count <= count+1;
ELSE
count <= count;
END IF;
--IR
IF load_IR='1' THEN
instr_reg := mdr;
END IF;
IF Addr_bus='1' THEN
sysbus := rfill & instr_reg(word_w-op_w-1 DOWNTO 0);
END IF;
op <= instr_reg(word_w-1 DOWNTO word_w-op_w);
IR_out <= instr_reg;
--ALU
IF load_ACC='1' THEN
acc:=UNSIGNED(mdr);
END IF;
IF ALU_ACC='1' THEN
IF ALU_add='1' THEN
acc := acc + UNSIGNED(mdr);
ELSIF ALU_sub='1' THEN
acc := acc - UNSIGNED(mdr);
END IF;
END IF;
IF ACC_bus='1' THEN
sysbus := STD_LOGIC_VECTOR(acc);
END IF;
IF acc=zero THEN
z_flag <='1';
ELSE
z_flag <='0';
END IF;
acc_out<= acc;
--RAM
IF load_MAR='1' THEN
mar := UNSIGNED(sysbus(word_w-op_w-1 DOWNTO 0));
ELSIF load_MDR='1' THEN
mdr := sysbus;
ELSIF CS='1' THEN
IF R_NW='1' THEN
mdr := mem(TO_INTEGER(mar));
ELSE
mem(TO_INTEGER(mar))<=mdr;
END IF;
END IF;
IF MDR_bus='1' THEN
sysbus:=mdr;
END IF;
mdr_out <= mdr;
mar_out <= mar;
--sequencer
present_state <= next_state;
END IF;
sysbus_out <=sysbus;
END PROCESS;
PROCESS(present_state,op,z_flag)
BEGIN
ACC_bus <= '0';
load_ACC <= '0';
PC_bus <= '0';
load_PC <= '0';
load_IR <= '0';
load_MAR <= '0';
MDR_bus <= '0';
load_MDR <= '0';
ALU_ACC <= '0';
ALU_add <= '0';
ALU_sub <= '0';
INC_PC <= '0';
Addr_bus <= '0';
CS <= '0';
R_NW <= '0';
CASE present_state IS
WHEN s0 =>
PC_bus <= '1';
load_MAR <= '1';
INC_PC <= '1';
next_state <= s1;
present_out<= "0000";
WHEN s1 =>
CS <= '1';
R_NW <= '1';
next_state <= s2;
present_out<= "0001";
WHEN s2 =>
MDR_bus <= '1';
load_IR <= '1';
next_state <= s3;
present_out<= "0010";
WHEN s3 =>
Addr_bus <= '1';
load_MAR <= '1';
present_out<= "0011";
IF op="001" THEN --op=store
next_state <=s4;
ELSE
next_state <=s6;
END IF;
WHEN s4 =>
ACC_bus <= '1';
load_MDR <= '1';
next_state <= s5;
present_out<= "0100";
WHEN s5 =>
CS <= '1';
r_NW <= '0';
next_state <= s0;
present_out<= "0101";
WHEN s6 =>
CS <= '1';
R_NW <= '1';
present_out<= "0110";
IF op="000" THEN --op=load
next_state <=s7;
ELSIF op="100" THEN --op=bne
IF z_flag='0' THEN
next_state <=s9;
ELSE
next_state <=s10;
END IF;
ELSE
next_state <=s8;
END IF;
WHEN s7=>
MDR_bus <= '1';
load_ACC <= '1';
next_state <= s0;
present_out<= "0111";
WHEN s8 =>
MDR_bus <= '1';
ALU_ACC <= '1';
present_out<= "1000";
IF op="010" THEN --op=add
ALU_add <='1';
ELSIF op="011" THEN --op=sub
ALU_sub <='1';
END IF;
next_state <=s0;
WHEN s9=>
MDR_bus <= '1';
load_PC <= '1';
next_state <= s0;
present_out<= "1001";
WHEN s10=>
next_state <= s0;
present_out<= "1010";
END CASE;
END PROCESS;
PROCESS(mode,mem_addr)
BEGIN
--mode=0 -> PC
--mode=1 -> opcode
--mode=2 -> mdr
--mode=3 -> mar
--mode=4 -> IR
--mode=5 -> result of ALU
--mode=6 -> mem
output <= (OTHERS =>'0');
CASE mode is
WHEN "000" =>
output(word_w-op_w-1 downto 0)<= STD_LOGIC_VECTOR(count);
WHEN "001" =>
output(op_w-1 downto 0) <= op;
WHEN "010" =>
output <= mdr_out;
WHEN "011" =>
output(word_w-op_w-1 downto 0) <= STD_LOGIC_VECTOR(mar_out);
WHEN "100" =>
output <= IR_out;
WHEN "101" =>
output <= STD_LOGIC_VECTOR(acc_out);
WHEN "110" =>
output <= mem(TO_INTEGER(mem_addr));
WHEN others =>
output <= (others =>'Z');
END CASE;
END PROCESS;
END ARCHITECTURE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -