📄 control.vhd
字号:
----------------------------------------------------------------------- TITLE: Controller / Opcode Decoder-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)-- DATE CREATED: 2/8/01-- FILENAME: control.vhd-- PROJECT: Plasma CPU core-- COPYRIGHT: Software placed into the public domain by the author.-- Software 'as is' without warranty. Author liable for nothing.-- NOTE: MIPS(tm) is a registered trademark of MIPS Technologies.-- MIPS Technologies does not endorse and is not associated with-- this project.-- DESCRIPTION:-- Controls the CPU by decoding the opcode and generating control -- signals to the rest of the CPU.-- This entity decodes the MIPS(tm) opcode into a -- Very-Long-Word-Instruction. -- The 32-bit opcode is converted to a -- 6+6+6+16+4+2+4+3+2+2+3+2+4 = 60 bit VLWI opcode.-- Based on information found in:-- "MIPS RISC Architecture" by Gerry Kane and Joe Heinrich-- and "The Designer's Guide to VHDL" by Peter J. Ashenden---------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;use work.mlite_pack.all;entity control is port(opcode : in std_logic_vector(31 downto 0); intr_signal : in std_logic; rs_index : out std_logic_vector(5 downto 0); rt_index : out std_logic_vector(5 downto 0); rd_index : out std_logic_vector(5 downto 0); imm_out : out std_logic_vector(15 downto 0); alu_func : out alu_function_type; shift_func : out shift_function_type; mult_func : out mult_function_type; branch_func : out branch_function_type; a_source_out : out a_source_type; b_source_out : out b_source_type; c_source_out : out c_source_type; pc_source_out: out pc_source_type; mem_source_out:out mem_source_type; exception_out: out std_logic);end; --entity controlarchitecture logic of control isbegincontrol_proc: process(opcode, intr_signal) variable op, func : std_logic_vector(5 downto 0); variable rs, rt, rd : std_logic_vector(5 downto 0); variable rtx : std_logic_vector(4 downto 0); variable imm : std_logic_vector(15 downto 0); variable alu_function : alu_function_type; variable shift_function : shift_function_type; variable mult_function : mult_function_type; variable a_source : a_source_type; variable b_source : b_source_type; variable c_source : c_source_type; variable pc_source : pc_source_type; variable branch_function: branch_function_type; variable mem_source : mem_source_type; variable is_syscall : std_logic;begin alu_function := ALU_NOTHING; shift_function := SHIFT_NOTHING; mult_function := MULT_NOTHING; a_source := A_FROM_REG_SOURCE; b_source := B_FROM_REG_TARGET; c_source := C_FROM_NULL; pc_source := FROM_INC4; branch_function := BRANCH_EQ; mem_source := MEM_FETCH; op := opcode(31 downto 26); rs := '0' & opcode(25 downto 21); rt := '0' & opcode(20 downto 16); rtx := opcode(20 downto 16); rd := '0' & opcode(15 downto 11); func := opcode(5 downto 0); imm := opcode(15 downto 0); is_syscall := '0'; case op is when "000000" => --SPECIAL case func is when "000000" => --SLL r[rd]=r[rt]<<re; a_source := A_FROM_IMM10_6; c_source := C_FROM_SHIFT; shift_function := SHIFT_LEFT_UNSIGNED; when "000010" => --SRL r[rd]=u[rt]>>re; a_source := A_FROM_IMM10_6; c_source := C_FROM_shift; shift_function := SHIFT_RIGHT_UNSIGNED; when "000011" => --SRA r[rd]=r[rt]>>re; a_source := A_FROM_IMM10_6; c_source := C_FROM_SHIFT; shift_function := SHIFT_RIGHT_SIGNED; when "000100" => --SLLV r[rd]=r[rt]<<r[rs]; c_source := C_FROM_SHIFT; shift_function := SHIFT_LEFT_UNSIGNED; when "000110" => --SRLV r[rd]=u[rt]>>r[rs]; c_source := C_FROM_SHIFT; shift_function := SHIFT_RIGHT_UNSIGNED; when "000111" => --SRAV r[rd]=r[rt]>>r[rs]; c_source := C_FROM_SHIFT; shift_function := SHIFT_RIGHT_SIGNED; when "001000" => --JR s->pc_next=r[rs]; pc_source := FROM_BRANCH; alu_function := ALU_ADD; branch_function := BRANCH_YES; when "001001" => --JALR r[rd]=s->pc_next; s->pc_next=r[rs]; c_source := C_FROM_PC_PLUS4; pc_source := FROM_BRANCH; alu_function := ALU_ADD; branch_function := BRANCH_YES; when "001010" => --MOVZ if(!r[rt]) r[rd]=r[rs]; /*IV*/-- c_source := C_FROM_REG_SOURCE_EQZ; when "001011" => --MOVN if(r[rt]) r[rd]=r[rs]; /*IV*/-- c_source := FROM_REG_SOURCE_NEZ; when "001100" => --SYSCALL is_syscall := '1'; when "001101" => --BREAK s->wakeup=1; is_syscall := '1'; when "001111" => --SYNC s->wakeup=1; when "010000" => --MFHI r[rd]=s->hi; c_source := C_FROM_MULT; mult_function := MULT_READ_HI; when "010001" => --FTHI s->hi=r[rs]; mult_function := MULT_WRITE_HI; when "010010" => --MFLO r[rd]=s->lo; c_source := C_FROM_MULT; mult_function := MULT_READ_LO; when "010011" => --MTLO s->lo=r[rs]; mult_function := MULT_WRITE_LO; when "011000" => --MULT s->lo=r[rs]*r[rt]; s->hi=0; mult_function := MULT_SIGNED_MULT; when "011001" => --MULTU s->lo=r[rs]*r[rt]; s->hi=0; mult_function := MULT_MULT; when "011010" => --DIV s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; mult_function := MULT_SIGNED_DIVIDE; when "011011" => --DIVU s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; mult_function := MULT_DIVIDE; when "100000" => --ADD r[rd]=r[rs]+r[rt]; c_source := C_FROM_ALU; alu_function := ALU_ADD; when "100001" => --ADDU r[rd]=r[rs]+r[rt]; c_source := C_FROM_ALU; alu_function := ALU_ADD; when "100010" => --SUB r[rd]=r[rs]-r[rt]; c_source := C_FROM_ALU; alu_function := ALU_SUBTRACT; when "100011" => --SUBU r[rd]=r[rs]-r[rt]; c_source := C_FROM_ALU; alu_function := ALU_SUBTRACT; when "100100" => --AND r[rd]=r[rs]&r[rt]; c_source := C_FROM_ALU; alu_function := ALU_AND; when "100101" => --OR r[rd]=r[rs]|r[rt]; c_source := C_FROM_ALU; alu_function := ALU_OR; when "100110" => --XOR r[rd]=r[rs]^r[rt]; c_source := C_FROM_ALU; alu_function := ALU_XOR; when "100111" => --NOR r[rd]=~(r[rs]|r[rt]); c_source := C_FROM_ALU; alu_function := ALU_NOR; when "101010" => --SLT r[rd]=r[rs]<r[rt]; c_source := C_FROM_ALU; alu_function := ALU_LESS_THAN_SIGNED; when "101011" => --SLTU r[rd]=u[rs]<u[rt]; c_source := C_FROM_ALU; alu_function := ALU_LESS_THAN; when "101101" => --DADDU r[rd]=r[rs]+u[rt]; c_source := C_FROM_ALU; alu_function := ALU_ADD; when "110001" => --TGEU when "110010" => --TLT when "110011" => --TLTU when "110100" => --TEQ when "110110" => --TNE when others => end case; when "000001" => --REGIMM rt := "000000"; rd := "011111"; a_source := A_FROM_PC; b_source := B_FROM_IMMX4; alu_function := ALU_ADD; pc_source := FROM_BRANCH; branch_function := BRANCH_GTZ; --if(test) pc=pc+imm*4 case rtx is when "10000" => --BLTZAL r[31]=s->pc_next; branch=r[rs]<0; c_source := C_FROM_PC_PLUS4; branch_function := BRANCH_LTZ; when "00000" => --BLTZ branch=r[rs]<0; branch_function := BRANCH_LTZ; when "10001" => --BGEZAL r[31]=s->pc_next; branch=r[rs]>=0; c_source := C_FROM_PC_PLUS4; branch_function := BRANCH_GEZ; when "00001" => --BGEZ branch=r[rs]>=0; branch_function := BRANCH_GEZ; when "10010" => --BLTZALL r[31]=s->pc_next; lbranch=r[rs]<0; c_source := C_FROM_PC_PLUS4; pc_source := FROM_LBRANCH; branch_function := BRANCH_LTZ; when "00010" => --BLTZL lbranch=r[rs]<0; pc_source := FROM_LBRANCH; branch_function := BRANCH_LTZ; when "10011" => --BGEZALL r[31]=s->pc_next; lbranch=r[rs]>=0; c_source := C_FROM_PC_PLUS4; pc_source := FROM_LBRANCH; branch_function := BRANCH_GEZ; when "00011" => --BGEZL lbranch=r[rs]>=0; pc_source := FROM_LBRANCH; branch_function := BRANCH_GEZ; when others => end case;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -