Skip to content

Instantly share code, notes, and snippets.

@zhanghuimeng
Last active February 3, 2018 04:04
Show Gist options
  • Save zhanghuimeng/5e6db5ed9ef1abaf4316ac28476b28ec to your computer and use it in GitHub Desktop.
Save zhanghuimeng/5e6db5ed9ef1abaf4316ac28476b28ec to your computer and use it in GitHub Desktop.
NewThinpadProject/simulation/srcs
/* DIV Module */
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.INCLUDE.ALL;
entity DIV is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
signed_i: in STD_LOGIC;
start_i: in STD_LOGIC;
cancel_i: in STD_LOGIC;
operand_1_i: in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
operand_2_i: in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
ready_o: out STD_LOGIC;
result_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0));
end DIV;
architecture Behavioral of EX is
begin
process (clk'event)
variable div_temp_result: STD_LOGIC(DATA_LEN downto 0); -- 临时保存除法结果
variable cnt: STD_LOGIC_VECTOR(DIV_CNT_LEN-1 downto 0); -- 试商法进行了几轮
-- dividend的低32位保存的是被除数和中间结果
-- 第k次迭代结束时dividend[k..0]保存的是当前得到的中间结果
-- dividend[31..k+1]保存的是被除数中还没有参与运算的数据
-- dividend的高32位是每次迭代时的被减数
variable dividend: STD_LOGIC_VECTOR(DOUBLE_DATA_LEN downto 0);
variable divisor: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
variable operand_1: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
variable operand_2: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
signal state: STD_LOGIC_VECTOR(1 downto 0); -- 自动机状态
begin
if (rising_edge(clk)) then
if rst = RST_ENABLE then
state <= DIV_STATE_FREE;
ready_o <= DIV_RESULT_READY_NOT;
result_o <= DOUBLE_ZERO_DATA;
else
div_state: case state is
-- FREE状态
-- 若start_i置位,分成3种情况:
-- (1)开始除法运算但除数为0,进入BY0状态
-- (2)开始除法运算但除数不为0,进入ON状态
-- (3)没有开始除法运算,维持FREE状态
when DIV_STATE_FREE =>
if (start_i = DIV_START) AND (cancel_i = '0') then
if (operand_1_i = ZERO_DATA) then
state <= DIV_START_BY0;
else
state <= DIV_STATE_ON;
cnt := "000000";
if (signed_i = '1') AND (operand_1_i(DATA_LEN-1) = '1') then -- 被除数取补码
operand_1 := (NOT operand_1_i) + '1';
else
operand_1 := operand_1_i;
end if;
if (signed_i = '1') AND (operand_2_i(DATA_LEN-1) = '1') then -- 除数取补码
operand_2 := (NOT operand_2_i) + '1';
else
operand_2 := operand_2_i;
end if;
dividend := DOUBLE_ZERO_DATA:
dividend(DATA_LEN downto 1) := operand_1;
divisor := operand_2;
else -- 没有开始除法运算
ready_o <= DIV_RESULT_READY_NOT;
result_o <= DOUBLE_ZERO_DATA;
end if;
-- BY0状态
-- 直接进入END状态,除法结束,结果为0
when DIV_START_BY0 =>
dividend := DOUBLE_ZERO_DATA:
state <= DIV_STATE_END;
-- ON状态
-- 分为3种情况:
-- (1)若cancel_i置位,则直接回到FREE状态
-- (2)若不取消且cnt不为32,则继续进行试商法
-- (3)若不取消且cnt为32,则试商法结束,保存结果,进入END状态
when DIV_STATE_ON =>
if cancel_i = '1' then
state <= DIV_STATE_FREE;
else
if NOT (cnt = "100000") then -- 继续进行试商法
if (div_temp_result(DATA_LEN) = '1') then
dividend := dividend(DOUBLE_DATA_LEN-1 downto 1) & '0';
else
dividend := div_temp_result(DATA_LEN-1 downto 0) & dividend(DATA_LEN-1 downto 1) & '0';
end if;
cnt <= cnt + '1';
else -- 试商法结束
-- 求补码
if (signed_i = '1') AND ((operand_1_i(DATA_LEN-1) ^ operand_2_i(DATA_LEN-1)) = '1') then
dividend(DATA_LEN-1 downto 0) := (~dividend(DATA_LEN-1 downto 0)) + '1';
end if;
-- 求补码
if (signed_i = '1') AND ((operand_1_i(DATA_LEN-1) ^ dividend(DOUBLE_DATA_LEN)) = '1') then
dividend(DOUBLE_DATA_LEN downto DATA_LEN+1) := (~dividend(DOUBLE_DATA_LEN downto DATA_LEN+1)) + '1';
end if;
state <= DIV_STATE_END;
cnt := "000000";
end if;
end if;
-- 除法运算结束
when DIV_STATE_END =>
ready_o <= DIV_RESULT_READY;
result_o <= dividend(DOUBLE_DATA_LEN downto DATA_LEN+1) & dividend(DATA_LEN-1 downto 0);
if (start_i = DIV_STOP) then
state <= DIV_STATE_FREE;
ready_o <= DIV_RESULT_READY_NOT;
result_o <= DOUBLE_ZERO_DATA;
end if;
end case div_state;
end if;
end if;
end process;
end Behavioral;
/* EX Module */
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use STD.TEXTIO.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
-- use work.fixed_generic_pkg_mod.all; TODO
use WORK.INCLUDE.ALL;
entity EX is
Port ( rst: in STD_LOGIC; -- Reset
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input 当前指令 from ID/EX for 异常处理
op_i: in STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- input 自定义操作码 from ID/EX
funct_i: in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input 自定义指令功能 from ID/EX
operand_1_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input 操作数1 from ID/EX
operand_2_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input 操作数2 from ID/EX
extended_offset_i: in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input 扩展后的偏移 from ID/EX
reg_wt_en_i: in STD_LOGIC; -- input 寄存器写使能 from ID/EX for 在WB阶段写入
reg_wt_addr_i: in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input 寄存器写地址 from ID/EX for 在WB阶段写入
hi_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input HI寄存器内容 from HI_LO for 在本阶段读HILO寄存器
lo_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input LO寄存器内容 from HI_LO for 在本阶段读HILO寄存器
clock_cycle_cnt_i: in STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- input 累加指令时钟周期计数 from EX/MEM
mul_cur_result_i: in STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- input 累加指令当前结果 from EX/MEM
div_ready_i: in STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- input 除法运算是否结束 from DIV for 除法指令
div_result_i: in STD_LOGIC; -- input 除法运算结果 from DIV for 除法指令
is_in_delayslot_i: in STD_LOGIC; -- input 当前指令是否在延迟槽中 from ID/EX
link_addr_i: in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input the 保存返回地址的寄存器的地址 from ID/EX
cp0_reg_data_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input CP0寄存器 from CP0
pc_i: in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input 指令地址 from ID/EX for 异常处理
except_type_i: in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0); -- input 异常类型 from ID/EX for 异常处理
reg_wt_en_o: out STD_LOGIC; -- output register write enable to EX/MEM
reg_wt_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to EX/MEM
reg_wt_data_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output register write data to EX/MEM
is_load_store_o: out STD_LOGIC; -- output load/store to EX/MEM, ID
funct_o: out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output load/store type to EX/MEM, ID
load_store_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output load/store memory address to EX/MEM
store_data_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output store data to EX/MEM
hilo_en_o: out STD_LOGIC; -- output HI_LO write enable to EX/MEM
hi_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output HI data to EX/MEM
lo_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output LO data to EX/MEM
pause_o: out STD_LOGIC; -- output pause information to PAUSE_CTRL
clock_cycle_cnt_o: out STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- output 累加指令周期数 to EX/MEM for
mul_cur_result_o: out STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- output 当前累加结果 to EX/MEM
div_start_o: out STD_LOGIC; -- output 是否开始除法运算 to DIV for 除法指令
div_signed_i: out STD_LOGIC; -- output 是否为带符号除法,1表示带 to DIV for 除法指令
is_in_delayslot_o: out STD_LOGIC; -- output (is in delay slot) to EX/MEM for exception handling
cp0_reg_read_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output (which CP0 register to read) to CP0
cp0_reg_we_o: out STD_LOGIC; -- output (CP0 write register enable) to EX/MEM
cp0_reg_write_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output (CP0 write register address) to EX/MEM
cp0_reg_data_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output (CP0 write register data) to EX/MEM
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0));
end EX;
architecture Behavioral of EX is
begin
process (all)
variable output: LINE;
variable operand_1: UNSIGNED(DATA_LEN-1 downto 0);
variable operand_2: UNSIGNED(DATA_LEN-1 downto 0);
variable sum_result: UNSIGNED(DATA_LEN downto 0); -- 加减法和比较结果
variable overflow: STD_LOGIC;
variable compare_result: STD_LOGIC;
variable operand_mul_1: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
variable operand_mul_2: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
variable mul_sign: STD_LOGIC;
variable mult_result: STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0);
variable mult_accum_result: UNSIGNED(DOUBLE_DATA_LEN downto 0);
variable hi: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
variable lo: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
variable trap_assert : STD_LOGIC;
variable over_assert : STD_LOGIC;
-- TODO Add division support
-- variable dividend_float: sfixed(REG_DATA_LEN-1 downto 0);
-- variable divisor_float: sfixed(REG_DATA_LEN-1 downto 0);
-- variable quotient_float: sfixed(DOUBLE_DATA_LEN-1 downto 0);
begin
if rst = RST_ENABLE then
reg_wt_data_o <= REG_ZERO_DATA;
reg_wt_addr_o <= REG_ZERO_ADDR;
reg_wt_en_o <= REG_WT_DISABLE;
is_load_store_o <= NOT_LOAD_STORE;
funct_o <= FUNCT_TYPE_NOP;
load_store_addr_o <= ZERO_ADDR;
store_data_o <= ZERO_DATA;
hilo_en_o <= CHIP_DISABLE;
hi_o <= REG_ZERO_DATA;
lo_o <= REG_ZERO_DATA;
pause_o <= PAUSE_NOT;
clock_cycle_cnt_o <= b"00";
mul_cur_result_o <= DOUBLE_ZERO_DATA;
cp0_reg_write_addr_o <= REG_ZERO_ADDR;
cp0_reg_we_o <= REG_WT_DISABLE;
cp0_reg_data_o <= ZERO_DATA;
current_inst_address_o <= INST_ZERO_ADDR;
except_type_o <= ZERO_DATA;
is_in_delayslot_o <= DELAYSLOT_NOT;
trap_assert := TRAP_FALSE;
else
reg_wt_addr_o <= reg_wt_addr_i;
reg_wt_en_o <= reg_wt_en_i;
is_load_store_o <= NOT_LOAD_STORE;
funct_o <= FUNCT_TYPE_NOP;
load_store_addr_o <= ZERO_ADDR;
store_data_o <= ZERO_DATA;
pause_o <= PAUSE_NOT;
clock_cycle_cnt_o <= b"00";
mul_cur_result_o <= DOUBLE_ZERO_DATA;
hilo_en_o <= CHIP_DISABLE;
cp0_reg_write_addr_o <= REG_ZERO_ADDR;
cp0_reg_we_o <= REG_WT_DISABLE;
cp0_reg_data_o <= ZERO_DATA;
trap_assert := TRAP_FALSE;
over_assert := TRAP_FALSE;
-- 加减法和带符号比较指令
-- 转化为无符号数加减,本质与补码相同
operand_1 := UNSIGNED(operand_1_i);
-- 减法和比较时,取第二个操作数的补码
if (funct_i = FUNCT_TYPE_SUB) OR (funct_i = FUNCT_TYPE_SUBU) OR (funct_i = FUNCT_TYPE_SLT) OR(funct_i = FUNCT_TYPE_SLTI)
OR (funct_i = FUNCT_TYPE_TLT) OR (funct_i = FUNCT_TYPE_TLTI) OR (funct_i = FUNCT_TYPE_TGE) OR (funct_i = FUNCT_TYPE_TGEI)
OR (funct_i = FUNCT_TYPE_TLTU) OR (funct_i = FUNCT_TYPE_TLTIU) OR (funct_i = FUNCT_TYPE_TGEU) OR (funct_i = FUNCT_TYPE_TGEIU)
then
operand_2 := UNSIGNED((not operand_2_i) + b"1");
else
operand_2 := UNSIGNED(operand_2_i);
end if;
-- 计算结果
sum_result := UNSIGNED(b"0" & operand_1) + UNSIGNED(b"0" & operand_2);
overflow := '0';
-- 判断是否溢出
if (operand_1(REG_DATA_LEN-1) = '0') AND (operand_2(REG_DATA_LEN-1) = '0') AND (sum_result(REG_DATA_LEN) = '1') then
overflow := '1';
end if;
if (operand_1(REG_DATA_LEN-1) = '1') AND (operand_2(REG_DATA_LEN-1) = '1') AND (sum_result(REG_DATA_LEN) = '0') then
overflow := '1';
end if;
-- 计算比较的结果
compare_result := '0';
-- 带符号比较
if (funct_i = FUNCT_TYPE_SLT) OR (funct_i = FUNCT_TYPE_SLTI) OR (funct_i = FUNCT_TYPE_TLT) OR (funct_i = FUNCT_TYPE_TLTI)
OR (funct_i = FUNCT_TYPE_TGE) OR (funct_i = FUNCT_TYPE_TGEI) then
if (operand_1_i(DATA_LEN-1) = '1') AND (operand_2_i(DATA_LEN-1) = '0') then
compare_result := '1';
elsif (operand_1_i(DATA_LEN-1) = operand_2_i(DATA_LEN-1)) AND (sum_result(DATA_LEN-1) = '1') then
compare_result := '1';
end if;
-- 无符号比较
elsif (funct_i = FUNCT_TYPE_SLTU) OR (funct_i = FUNCT_TYPE_SLTIU) OR (funct_i = FUNCT_TYPE_TLTU) OR (funct_i = FUNCT_TYPE_TLTIU)
OR (funct_i = FUNCT_TYPE_TGEU) OR (funct_i = FUNCT_TYPE_TGEIU) then
if UNSIGNED(operand_1_i) < UNSIGNED(operand_2_i) then
compare_result := '1';
end if;
end if;
-- 带符号乘法指令
-- 不要直接把补码相乘!
mul_sign := '0';
if operand_1_i(DATA_LEN-1) = '1' then
operand_mul_1 := (NOT operand_1_i) + b"1";
mul_sign := NOT mul_sign;
else
operand_mul_1 := operand_1_i;
end if;
if operand_2_i(DATA_LEN-1) = '1' then
operand_mul_2 := (NOT operand_2_i) + b"1";
mul_sign := NOT mul_sign;
else
operand_mul_2 := operand_2_i;
end if;
mult_result := std_logic_vector(unsigned(operand_mul_1) * unsigned(operand_mul_2));
if mul_sign = '1' then
mult_result := (NOT mult_result) + b"1";
end if;
-- 开始进行实际计算
op_code: case op_i is
-- NOP指令
-- 什么也不做
when OP_TYPE_NOP =>
-- 算术指令
when OP_TYPE_ARITH =>
arith_funct: case funct_i is
-- 加法(有异常)
when FUNCT_TYPE_ADD | FUNCT_TYPE_ADDI =>
if overflow = '1' then
reg_wt_en_o <= REG_WT_DISABLE;
over_assert := TRAP_TRUE;
else
reg_wt_data_o <= STD_LOGIC_VECTOR(sum_result(REG_DATA_LEN-1 downto 0));
end if;
-- 加法(无异常)
when FUNCT_TYPE_ADDIU | FUNCT_TYPE_ADDU =>
reg_wt_data_o <= STD_LOGIC_VECTOR(sum_result(REG_DATA_LEN-1 downto 0));
-- 减法(有异常)
when FUNCT_TYPE_SUB =>
if overflow = '1' then
reg_wt_en_o <= REG_WT_DISABLE;
over_assert := TRAP_TRUE;
else
reg_wt_data_o <= STD_LOGIC_VECTOR(sum_result(REG_DATA_LEN-1 downto 0));
end if;
-- 减法(无异常)
when FUNCT_TYPE_SUBU =>
reg_wt_data_o <= STD_LOGIC_VECTOR(sum_result(REG_DATA_LEN-1 downto 0));
-- 前导1个数
when FUNCT_TYPE_CLO =>
reg_wt_data_o <= STD_LOGIC_VECTOR(to_unsigned(count_leading_ones(operand_1_i), REG_DATA_LEN));
-- 前导0个数
when FUNCT_TYPE_CLZ =>
reg_wt_data_o <= STD_LOGIC_VECTOR(to_unsigned(count_leading_zeros(operand_1_i), REG_DATA_LEN));
-- 比较指令
when FUNCT_TYPE_SLT | FUNCT_TYPE_SLTI | FUNCT_TYPE_SLTIU | FUNCT_TYPE_SLTU =>
reg_wt_data_o <= zero_extend(compare_result, DATA_LEN);
-- 乘法
when FUNCT_TYPE_MUL =>
reg_wt_data_o <= mult_result(DATA_LEN-1 downto 0);
-- 写HILO
when FUNCT_TYPE_MULT =>
hilo_en_o <= CHIP_ENABLE;
hi := mult_result(DOUBLE_DATA_LEN-1 downto DATA_LEN);
lo := mult_result(DATA_LEN-1 downto 0);
-- 无符号乘法,重新计算乘法结果,存入HILO中
when FUNCT_TYPE_MULTU =>
mult_result := STD_LOGIC_VECTOR(UNSIGNED(operand_1_i) * UNSIGNED(operand_2_i));
hilo_en_o <= CHIP_ENABLE;
hi := mult_result(DOUBLE_DATA_LEN-1 downto DATA_LEN);
lo := mult_result(DATA_LEN-1 downto 0);
-- 乘累加/累减指令
when FUNCT_TYPE_MADD | FUNCT_TYPE_MADDU | FUNCT_TYPE_MSUB | FUNCT_TYPE_MSUBU =>
if (funct_i = FUNCT_TYPE_MADDU) or (funct_i = FUNCT_TYPE_MSUBU) then
mult_result := std_logic_vector(unsigned(operand_1_i) * unsigned(operand_2_i));
end if;
-- 第一个循环:乘法
if (clock_cycle_cnt_i = "00") then
mul_cur_result_o <= mult_result;
clock_cycle_cnt_o <= "01";
pause_o <= PAUSE; -- 暂停流水线
-- 第二个循环:累加到HILO
elsif clock_cycle_cnt_i = "01" then
mult_accum_result := UNSIGNED('0' & hi & lo); -- 当前累加结果
if (funct_i = FUNCT_TYPE_MADD) or (funct_i = FUNCT_TYPE_MADDU) then
mult_accum_result := UNSIGNED('0' & mul_cur_result_i) + mult_accum_result;
else
mult_accum_result := UNSIGNED('0' & ((not mul_cur_result_i) + '1')) + mult_accum_result;
end if;
hilo_en_o <= CHIP_ENABLE;
hi := STD_LOGIC_VECTOR(mult_accum_result(DOUBLE_DATA_LEN-1 downto DATA_LEN));
lo := STD_LOGIC_VECTOR(mult_accum_result(DATA_LEN-1 downto 0));
mul_cur_result_o <= DOUBLE_ZERO_DATA;
clock_cycle_cnt_o <= "10"; -- 如果直接置为00,下一个循环会重复本步
pause_o <= PAUSE_NOT; -- 取消流水线暂停
end if;
-- 除法指令
when FUNCT_TYPE_DIV =>
-- TODO
when others =>
end case arith_funct;
when OP_TYPE_LOGIC =>
logic_funct: case funct_i is
-- or instructions
when FUNCT_TYPE_AND =>
reg_wt_data_o <= (operand_1_i and operand_2_i);
-- or instructions
when FUNCT_TYPE_OR =>
reg_wt_data_o <= (operand_1_i or operand_2_i);
-- or instructions
when FUNCT_TYPE_XOR =>
reg_wt_data_o <= (operand_1_i xor operand_2_i);
-- or instructions
when FUNCT_TYPE_NOR =>
reg_wt_data_o <= (operand_1_i nor operand_2_i);
when others =>
end case logic_funct;
when OP_TYPE_SHIFT =>
shift_funct: case funct_i is
-- shift left logic instructions
when FUNCT_TYPE_SHIFT_LEFT_LOGIC =>
reg_wt_data_o <= (operand_2_i sll to_integer(unsigned(operand_1_i(4 downto 0))));
-- shift right logic instructions
when FUNCT_TYPE_SHIFT_RIGHT_LOGIC =>
reg_wt_data_o <= (operand_2_i srl to_integer(unsigned(operand_1_i(4 downto 0))));
-- shift right arithmetic instructions
when FUNCT_TYPE_SHIFT_RIGHT_ARITH =>
reg_wt_data_o <= ((to_stdlogicvector(to_bitvector(std_logic_vector(operand_2_i)) sra to_integer(unsigned(operand_1_i(4 downto 0))))));
when others =>
end case shift_funct;
when OP_TYPE_MOVE =>
move_funct: case funct_i is
-- MOVZ
when FUNCT_TYPE_MOVE_ZERO =>
if operand_2_i = REG_ZERO_DATA then
reg_wt_en_o <= REG_WT_ENABLE;
end if;
reg_wt_data_o <= operand_1_i;
-- MOVN
when FUNCT_TYPE_MOVE_NOT_ZERO =>
if not(operand_2_i = REG_ZERO_DATA) then
reg_wt_en_o <= REG_WT_ENABLE;
end if;
reg_wt_data_o <= operand_1_i;
-- MFHI
-- Solve data conflict issue
when FUNCT_TYPE_MOVE_FROM_HI =>
reg_wt_data_o <= hi_o;
-- MTHI
when FUNCT_TYPE_MOVE_TO_HI =>
hilo_en_o <= CHIP_ENABLE;
hi := operand_1_i;
-- MFLO
when FUNCT_TYPE_MOVE_FROM_LO =>
reg_wt_data_o <= lo_o;
-- MTLO
when FUNCT_TYPE_MOVE_TO_LO =>
hilo_en_o <= CHIP_ENABLE;
lo := operand_1_i;
when others =>
end case move_funct;
when OP_TYPE_BRANCH =>
branch_funct: case funct_i is
when FUNCT_TYPE_JAL | FUNCT_TYPE_JALR | FUNCT_TYPE_BAL | FUNCT_TYPE_BGEZAL | FUNCT_TYPE_BLTZAL =>
reg_wt_data_o <= link_addr_i;
when others =>
end case branch_funct;
when OP_TYPE_LOAD_STORE =>
load_store_funct: case funct_i is
-- Load: operand1 = base, offset = extended_offset
when FUNCT_TYPE_LB | FUNCT_TYPE_LBU | FUNCT_TYPE_LH | FUNCT_TYPE_LHU | FUNCT_TYPE_LW | FUNCT_TYPE_LWL| FUNCT_TYPE_LWR =>
is_load_store_o <= IS_LOAD_STORE;
funct_o <= funct_i;
load_store_addr_o <= operand_1_i + extended_offset_i;
-- store_data_o <= ZERO_DATA;
store_data_o <= operand_2_i; -- for LWL and LWR instructions
-- Store: operand1 = base, operand2 = rt, offset = extended_offset
when FUNCT_TYPE_SB | FUNCT_TYPE_SH | FUNCT_TYPE_SW | FUNCT_TYPE_SWL | FUNCT_TYPE_SWR =>
is_load_store_o <= IS_LOAD_STORE;
funct_o <= funct_i;
load_store_addr_o <= operand_1_i + extended_offset_i;
store_data_o <= operand_2_i;
when others =>
end case load_store_funct;
when OP_TYPE_CP0 =>
cp0_func: case( funct_i ) is
when FUNCT_TYPE_MFC0 =>
cp0_reg_read_addr_o <= inst_i(15 downto 11);--rd的地?????? 5??????
if (mem_cp0_reg_we_i = REG_WT_ENABLE) and (mem_cp0_reg_write_addr_i = inst_i(15 downto 11)) then
reg_wt_data_o <= mem_cp0_reg_data_i; --数据冲突:访存阶段要写的寄存器地?????? = 要读的寄存器地址
elsif (wb_cp0_reg_we_i = REG_WT_ENABLE)and (wb_cp0_reg_write_addr_i = inst_i(15 downto 11))then
reg_wt_data_o <= wb_cp0_reg_data_i; --数据冲突:写回阶段要写的寄存器地?????? = 要读的寄存器地址
else
reg_wt_data_o <= cp0_reg_data_i;--读取到的cp0中指定寄存器的???
end if;
when FUNCT_TYPE_MTC0 =>
cp0_reg_write_addr_o <= inst_i(15 downto 11);
cp0_reg_we_o <= REG_WT_ENABLE;
cp0_reg_data_o <= operand_2_i;
when others =>
end case cp0_func;
when OP_TYPE_TRAP =>
trap_func: case( funct_i ) is
when FUNCT_TYPE_TEQ | FUNCT_TYPE_TEQI =>
if operand_1_i = operand_2_i then
trap_assert := TRAP_TRUE;
end if ;
when FUNCT_TYPE_TGE | FUNCT_TYPE_TGEI | FUNCT_TYPE_TGEU | FUNCT_TYPE_TGEIU =>
if compare_result = '0' then
trap_assert := TRAP_TRUE;
end if ;
when FUNCT_TYPE_TLT | FUNCT_TYPE_TLTI | FUNCT_TYPE_TLTIU | FUNCT_TYPE_TLTU =>
if compare_result = '1' then
trap_assert := TRAP_TRUE;
end if ;
when FUNCT_TYPE_TNE | FUNCT_TYPE_TNEI =>
if operand_1_i /= operand_2_i then
trap_assert := TRAP_TRUE;
end if ;
when others =>
end case ;
when others =>
end case op_code;
-- Use signal to give hi/lo output a correct value
hi_o <= hi;
lo_o <= lo;
except_type_o <= except_type_i(31 downto 12) & over_assert & trap_assert & except_type_i(9 downto 8) & x"00";
is_in_delayslot_o <= is_in_delayslot_i;
current_inst_address_o <= current_inst_address_i;
end if;
end process;
end Behavioral;
/**
ID模块
Encoding: UTF-8
此模块中不读HILO寄存器
**/
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use STD.TEXTIO.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use WORK.INCLUDE.ALL;
entity ID is
Port ( rst: in STD_LOGIC; -- Reset
pc_i: in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input (instruction address) from IF/ID
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input instruction from IF/ID
reg_rd_data_1_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register 1 read data from REGISTERS
reg_rd_data_2_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register 2 read data from REGISTERS
is_in_delayslot_i: in STD_LOGIC; -- input 当前指令是否在延迟槽内 from ID/EX
last_is_load_store_i: in STD_LOGIC; -- input 上一条指令是否为加载/存储指令 from EX
last_funct_i: in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input the funct_o of the last instruction from EX
op_o: out STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- output custom op type to ID/EX
funct_o: out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output custom funct type to ID/EX
inst_o: out STD_LOGIC_VECTOR(INST_LEN - 1 downto 0); -- output 当前指令 to ID/EX for 异常处理
reg_rd_en_1_o: out STD_LOGIC; -- output register 1 read enable to REGISTERS
reg_rd_en_2_o: out STD_LOGIC; -- output register 2 read enable to REGISTERS
reg_rd_addr_1_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register 1 read address to REGISTERS
reg_rd_addr_2_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register 2 read address to REGISTERS
operand_1_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output operand 1 to ID/EX
operand_2_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output operand 2 to ID/EX
extended_offset_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output extended offset to ID/EX
reg_wt_en_o: out STD_LOGIC; -- output register write enable to ID/EX
reg_wt_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to ID/EX
pause_o: out STD_LOGIC; -- output pause information to PAUSE_CTRL
branch_o: out STD_LOGIC; -- output 当前指令是否需要分支跳转 to PC
branch_target_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output 指令跳转目的地址 to PC
is_in_delayslot_o: out STD_LOGIC; -- output the current instruction in delay slot to ID/EX
next_inst_in_delayslot_o: out STD_LOGIC; -- output the next instruction in delay slot to ID/EX
link_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output the return address to save to ID/EX
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0); -- output CP0异常类型 to ID/EX
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0)); -- output 指令地址 to ID/EX
end ID;
architecture Behavioral of ID is
-- [31, 26] (6) 指令操作码
alias op : STD_LOGIC_VECTOR(OP_LEN-1 downto 0) is inst_i(INST_LEN-1 downto INST_LEN-OP_LEN);
-- [25, 21] (5) 源寄存器1
alias reg_s : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) is inst_i(INST_LEN-OP_LEN-1 downto INST_LEN-OP_LEN-REG_ADDR_LEN);
-- [20, 16] (5) 源寄存器2
alias reg_t : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) is inst_i(INST_LEN-OP_LEN-REG_ADDR_LEN-1 downto INST_LEN-OP_LEN-2*REG_ADDR_LEN);
-- [15, 11] (5) 目的寄存器
alias reg_d : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) is inst_i(INST_LEN-OP_LEN-2*REG_ADDR_LEN-1 downto INST_LEN-OP_LEN-3*REG_ADDR_LEN);
-- [10, 6] (5)
alias shamt : STD_LOGIC_VECTOR(SHAMT_LEN-1 downto 0) is inst_i(SHAMT_LEN+FUNCT_LEN-1 downto FUNCT_LEN);
-- [5, 0] (6) 功能码
alias funct : STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0) is inst_i(FUNCT_LEN-1 downto 0);
-- [15, 0] (16) 立即数
alias imm : STD_LOGIC_VECTOR(IMM_LEN-1 downto 0) is inst_i(IMM_LEN-1 downto 0);
-- [25, 0] (26) 跳转地址
alias jump_addr : STD_LOGIC_VECTOR(JUMP_ADDR_LEN-1 downto 0) is inst_i(JUMP_ADDR_LEN-1 downto 0);
-- [25, 21] (5)
alias base : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) is inst_i(INST_LEN-OP_LEN-1 downto INST_LEN-OP_LEN-REG_ADDR_LEN);
-- [15, 0] (16)
alias offset : STD_LOGIC_VECTOR(IMM_LEN-1 downto 0) is inst_i(IMM_LEN-1 downto 0);
-- [25, 25] (1) CP0指令的特殊位
alias c0 : STD_LOGIC is inst_i(INST_LEN-OP_LEN-1);
signal extended_imm : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
alias extended_offset : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0) is extended_imm;
begin
pause_process: process(rst, last_is_load_store_i, last_funct_i, reg_rd_en_1_o, reg_rd_en_2_o,
reg_rd_addr_1_o, reg_rd_addr_2_o, ex_reg_wt_addr_i)
variable pause: STD_LOGIC;
variable output: LINE;
variable last_inst_is_load : STD_LOGIC;
begin
if rst = RST_ENABLE then
reg_1_load_relate := PAUSE_NOT;
reg_2_load_relate := PAUSE_NOT;
pause := PAUSE_NOT;
else
-- 检查上一条指令是否为加载指令
if (last_is_load_store_i = IS_LOAD_STORE) and ((last_funct_i = FUNCT_TYPE_LB) or (last_funct_i = FUNCT_TYPE_LBU) or (last_funct_i = FUNCT_TYPE_LH)
or (last_funct_i = FUNCT_TYPE_LHU) or (last_funct_i = FUNCT_TYPE_LW) or (last_funct_i = FUNCT_TYPE_LWL)
or (last_funct_i = FUNCT_TYPE_LWR)) then
last_inst_is_load := IS_LOAD_STORE;
else
last_inst_is_load := NOT_LOAD_STORE;
end if;
end if;
pause_o <= pause;
end process pause_process;
main_process: process (all)
variable next_pc : STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
variable branch_addr_offset : STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
variable except_type_is_syscall: STD_LOGIC; -- 异常类型是否为系统调用?
variable except_type_is_eret: STD_LOGIC; -- 异常类型是否为ERET?
variable inst_valid : STD_LOGIC; -- 指令是否合法?
begin
if rst = RST_ENABLE then
op_o <= OP_TYPE_NOP;
funct_o <= FUNCT_TYPE_NOP;
reg_rd_en_1_o <= REG_RD_DISABLE;
reg_rd_en_2_o <= REG_RD_DISABLE;
reg_rd_addr_1_o <= REG_ZERO_ADDR;
reg_rd_addr_2_o <= REG_ZERO_ADDR;
reg_wt_en_o <= REG_WT_DISABLE;
reg_wt_addr_o <= REG_ZERO_ADDR;
branch_o <= BRANCH_NOT;
branch_target_addr_o <= INST_ZERO_ADDR;
is_in_delayslot_o <= DELAYSLOT_NOT;
next_inst_in_delayslot_o <= DELAYSLOT_NOT;
link_addr_o <= INST_ZERO_ADDR;
-- CP0
inst_o <= ZERO_DATA;
inst_valid := INST_VALID;
pc_o <= ZERO_ADDR;
else
op_o <= OP_TYPE_NOP; -- 默认指令操作码为NOP
funct_o <= FUNCT_TYPE_NOP; -- 默认指令功能为NOP
reg_rd_en_1_o <= REG_RD_DISABLE; -- 默认不读寄存器1
reg_rd_en_2_o <= REG_RD_DISABLE; -- 默认不读寄存器2
reg_rd_addr_1_o <= reg_s; -- 默认读寄存器地址1
reg_rd_addr_2_o <= reg_t; -- 默认读寄存器地址2
reg_wt_en_o <= REG_WT_DISABLE; -- 默认不写寄存器
reg_wt_addr_o <= reg_d; -- 默认写寄存器地址
branch_o <= BRANCH_NOT; -- 默认当前指令不是分支跳转指令
is_in_delayslot_o <= DELAYSLOT_NOT; -- 默认当前指令不在延迟槽内
next_inst_in_delayslot_o <= DELAYSLOT_NOT; -- 默认下一条指令不在延迟槽内
next_pc := pc_i + b"100"; -- 下一条指令地址为当前指令地址+4
branch_addr_offset(IMM_LEN+1 downto 0) := imm & b"00"; -- branch指令所需的+"00"
branch_addr_offset := sign_extend(branch_addr_offset, DATA_LEN); -- 将branch_addr_offset进行符号扩展
-- 以下为CP0相关赋值
inst_o <= inst_i;
inst_valid := INST_INVALID;
except_type_is_syscall := TRAP_FALSE;
except_type_is_eret := TRAP_FALSE;
pc_o <= pc_i;
-- Decide OP type
op_code: case op is
-- SPECIAL type instructions
when OP_SPECIAL =>
special_funct: case funct is
-- Unknown type of instruction
when FUNCT_MOVCI =>
inst_valid := INST_VALID;
-- SLL rd, rt, sa rd <- rt << sa
when FUNCT_SLL =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_LEFT_LOGIC;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
extended_imm <= x"000000" & b"000" & shamt; -- imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SRL rd, rt, sa rd <- rt >> sa (logical)
when FUNCT_SRL =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_RIGHT_LOGIC;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
extended_imm <= x"000000" & b"000" & shamt;
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SRA rd, rt, sa rd <- rt >> sa (arithmatic)
when FUNCT_SRA =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_RIGHT_ARITH;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
extended_imm <= x"000000" & b"000" & shamt; -- imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SLLV rd, rt, rs rd <- rt << rs
when FUNCT_SLLV =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_LEFT_LOGIC;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SRLV rd, rt, rs rd <- rt >> rs (logical)
when FUNCT_SRLV =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_RIGHT_LOGIC;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SRAV rd, rt, rs rd <- rt >> rs (arithmetic)
when FUNCT_SRAV =>
op_o <= OP_TYPE_SHIFT;
funct_o <= FUNCT_TYPE_SHIFT_RIGHT_ARITH;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- JR rs PC <- rs
when FUNCT_JR =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_JR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
branch_o <= BRANCH;
branch_target_addr_o <= operand_1_o;
next_inst_in_delayslot_o <= DELAYSLOT;
inst_valid := INST_VALID;
-- JALR (rd, = 31) rs rd <- return_addr, PC <- rs
when FUNCT_JALR =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_JALR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
branch_o <= BRANCH;
branch_target_addr_o <= operand_1_o;
next_inst_in_delayslot_o <= DELAYSLOT;
link_addr_o <= pc_i + b"1000";
inst_valid := INST_VALID;
-- MOVZ rd, rs, rt if rt = 0 then rd <- rs
-- Note data problem
when FUNCT_MOVZ =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_ZERO;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- write rd? (EX module solves it)
inst_valid := INST_VALID;
-- MOVN rd, rs, rt if rt != 0 then rd <- rs
when FUNCT_MOVN =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_NOT_ZERO;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- write rd? (EX module solves it)
inst_valid := INST_VALID;
-- MFHI rd rd <- HI
when FUNCT_MFHI =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_FROM_HI;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- MTHI rs HI <- rs
when FUNCT_MTHI =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_TO_HI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MFLO rd rd <- LO
when FUNCT_MFLO =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_FROM_LO;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- MTLO rs LO <- rs
when FUNCT_MTLO =>
op_o <= OP_TYPE_MOVE;
funct_o <= FUNCT_TYPE_MOVE_TO_LO;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- SYSCALL A system call exception occurs
-- CP0 Instruction
when FUNCT_SYSCALL =>
op_o <= OP_TYPE_SYSCALL;
funct_o <= FUNCT_TYPE_SYSCALL;
reg_rd_en_1_o <= REG_RD_DISABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
except_type_is_syscall := TRAP_TRUE;
-- BREAK A breakpoint exception occurs
-- not inplemented
when FUNCT_BREAK =>
inst_valid := INST_VALID;
-- SYNC (stype = 0 implied) To order loads and stores.
-- not inplemented
when FUNCT_SYNC =>
op_o <= OP_TYPE_NOP;
funct_o <= FUNCT_TYPE_NOP;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- do not write
inst_valid := INST_VALID;
-- MULT rs, rt (LO, HI) <- rs × rt
-- Signed
when FUNCT_MULT =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MULT;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MULTU rs, rt (LO, HI) <- rs × rt
-- Unsigned
when FUNCT_MULTU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MULTU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- DIV rs, rt (LO, HI) <- rs / rt
when FUNCT_DIV =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_DIV;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- DIVU rs, rt (LO, HI) <- rs / rt
when FUNCT_DIVU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_DIVU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- ADD rd, rs, rt rd <- rs + rt
-- Generate exception when overflow
when FUNCT_ADD =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_ADD;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- ADDU rd, rs, rt rd <- rs + rt
-- Do not generate exception
when FUNCT_ADDU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_ADDU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SUB rd, rs, rt rd <- rs - rt
-- Generate exception when overflow
when FUNCT_SUB =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SUB;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SUBU rd, rs, rt rd <- rs - rt
-- Do not generate exception
when FUNCT_SUBU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SUB;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- AND rd, rs, rt rd <- rs AND rt
when FUNCT_AND =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_AND;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- OR rd, rs, rt rd <- rs or rt
when FUNCT_OR =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_OR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- XOR rd, rs, rt rd <- rs XOR rt
when FUNCT_XOR =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_XOR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- NOR rd, rs, rt rd <- rs NOR rt
when FUNCT_NOR =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_NOR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SLT rd, rs, rt rd <- (rs < rt)
-- Signed
when FUNCT_SLT =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SLT;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SLTU rd, rs, rt rd <- (rs < rt)
-- Unsigned
when FUNCT_SLTU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SLTU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- TGE rs, rt if rs >= rt then Trap
when FUNCT_TGE =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TGE;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
-- TGEU rs, rt if rs >= rt then Trap
when FUNCT_TGEU =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TGEU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
-- TLT rs, rt if rs < rt then Trap
when FUNCT_TLT =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TLT;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
-- TLTU rs, rt if rs < rt then Trap
when FUNCT_TLTU =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TLTU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
-- TEQ rs, rt if rs = rt then Trap
when FUNCT_TEQ =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TEQ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
-- TNE rs, rt if rs != rt then Trap
when FUNCT_TNE =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TNE;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
when others =>
end case special_funct;
-- REGIMM type instructions
when OP_REGIMM =>
regimm_rt: case reg_t is
-- BLTZ rs, offset if rs < 0 then branch
when RT_BLTZ =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BLTZ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if SIGNED(operand_1_o) < 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BGEZ rs, offset if rs >= 0 then branch
when RT_BGEZ =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BGEZ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if SIGNED(operand_1_o) >= 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BLTZL rs, offset if rs < 0 then branch_likely
-- removed
when RT_BLTZL =>
inst_valid := INST_VALID;
-- BGEZL rs, offset if rs >= 0 then branch_likely
-- removed
when RT_BGEZL =>
inst_valid := INST_VALID;
-- TGEI rs, immediate if rs >= immediate then Trap
when RT_TGEI =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TGEI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- TGEIU rs, immediate if rs >= immediate then Trap
when RT_TGEIU =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TGEIU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- TLTI rs, immediate if rs < immediate then Trap
when RT_TLTI =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TLTI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- TLTIU rs, immediate if rs < immediate then Trap
when RT_TLTIU =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TLTIU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- TEQI rs, immediate if rs = immediate then Trap
when RT_TEQI =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TEQI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- TNEI rs, immediate if rs != immediate then Trap
when RT_TNEI =>
op_o <= OP_TYPE_TRAP;
funct_o <= FUNCT_TYPE_TNEI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; --do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rd
inst_valid := INST_VALID;
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
-- BLTZAL rs, offset if rs < 0 then procedure_call
when RT_BLTZAL =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BLTZAL;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write $31
reg_wt_addr_o <= REG_31_ADDR;
if SIGNED(operand_1_o) < 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
link_addr_o <= pc_i + b"1000";
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BGEZAL rs, offset if rs >= 0 then procedure_call
when RT_BGEZAL =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BGEZAL;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write $31
reg_wt_addr_o <= REG_31_ADDR;
if SIGNED(operand_1_o) >= 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
link_addr_o <= pc_i + b"1000";
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BLTZALL rs, offset if rs < 0 then procedure_call_likely
-- removed
when RT_BLTZALL =>
inst_valid := INST_VALID;
-- BGEZALL rs, offset if rs >= 0 then procedure_call_likely
-- removed
when RT_BGEZALL =>
inst_valid := INST_VALID;
when others =>
end case regimm_rt;
-- SPECIAL2 type instructions
when OP_SPECIAL2 =>
special2_funct: case funct is
-- MADD rs, rt (LO,HI) <- (rs x rt) + (LO,HI)
when FUNCT_MADD =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MADD;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MADDU rs, rt (LO,HI) <- (rs x rt) + (LO,HI)
when FUNCT_MADDU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MADDU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MSUB rs, rt (LO,HI) <- (rs x rt) - (LO,HI)
when FUNCT_MSUB =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MSUB;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MSUBU rs, rt (LO,HI) <- (rs x rt) - (LO,HI)
when FUNCT_MSUBU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MSUBU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
inst_valid := INST_VALID;
-- MUL rd, rs, rt rd <- rs × rt
when FUNCT_MUL =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_MUL;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- CLZ rd, rs rd <- count_leading_zeros rs
when FUNCT_CLZ =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_CLZ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- CLO rd, rs rd <- count_leading_ones rs
when FUNCT_CLO =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_CLO;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rd
inst_valid := INST_VALID;
-- SDBBP code
-- not inplemented
when FUNCT_SDBBP =>
inst_valid := INST_VALID;
when others =>
end case special2_funct;
-- COP0 type instructions
when OP_COP0 =>
cop0_reg_s: case reg_s is
-- mtc0 rt td CPR[0,rd] <- rt
when RS_MTC0 =>
op_o <= OP_TYPE_CP0;
funct_o <= FUNCT_TYPE_MTC0;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rd
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rt
inst_valid := INST_VALID;
-- mfc0 rt td CPR[rt] -> CPR[0,rd]
when RS_MFC0 =>
op_o <= OP_TYPE_CP0;
funct_o <= FUNCT_TYPE_MFC0;
reg_rd_en_1_o <= REG_RD_DISABLE; -- read rd
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
when others =>
if (co = 1) then
cop0_func: case funct is
when FUNCT_ERET =>
op_o <= OP_TYPE_CP0;
funct_o <= FUNCT_TYPE_ERET;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rd
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write rt
inst_valid := INST_VALID;
except_type_is_eret := TRAP_TRUE;
end case cop0_func;
end if;
end case cop0_reg_s;
-- COP1 type instructions
when OP_COP1 =>
-- COP2 type instructions
when OP_COP2 =>
-- COP3 type instructions
when OP_COP3 =>
-- ADDI rt, rs, immediate rt <- rs + immediate
-- Exception
when OP_ADDI =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_ADDI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- ADDIU rt, rs, immediate rt <- rs + immediate
-- No Exception
when OP_ADDIU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_ADDIU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- ANDI rt, rs, immediate rt <- rs AND immediate
when OP_ANDI =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_AND;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= zero_extend(imm, DATA_LEN); -- zero extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- ORI rt, rs, immediate rt <- rs or immediate
when OP_ORI =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_OR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= zero_extend(imm, DATA_LEN); -- zero extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- XORI rt, rs, immediate rt <- rs XOR immediate
when OP_XORI =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_XOR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= zero_extend(imm, DATA_LEN); -- zero extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- LUI rt, immediate rt <- immediate || 0^16
when OP_LUI =>
op_o <= OP_TYPE_LOGIC;
funct_o <= FUNCT_TYPE_OR; -- LUI rt, immediate = ORI rt, $0, (immediate || 0^16)
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
extended_imm <= imm & x"0000"; -- zero extend imm
-- write rt
reg_wt_en_o <= REG_WT_ENABLE;
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- J target To branch within the current 256 MB-aligned region
when OP_J =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_J;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
branch_o <= BRANCH;
branch_target_addr_o <= next_pc(31 downto 28) & jump_addr & b"00";
next_inst_in_delayslot_o <= DELAYSLOT;
inst_valid := INST_VALID;
-- JAL target To execute a procedure call within the current 256 MB-aligned region
when OP_JAL =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_JAL;
reg_rd_en_1_o <= REG_RD_DISABLE; -- do not read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write $31
reg_wt_addr_o <= REG_31_ADDR;
branch_o <= BRANCH;
branch_target_addr_o <= next_pc(31 downto 28) & jump_addr & b"00";
link_addr_o <= pc_i + b"1000";
next_inst_in_delayslot_o <= DELAYSLOT;
inst_valid := INST_VALID;
-- BEQ rs, rt, offset if rs = rt then branch
when OP_BEQ =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BEQ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if operand_1_o = operand_2_o then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BNE rs, rt, offset if rs != rt then branch
when OP_BNE =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BNE;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if not(operand_1_o = operand_2_o) then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BLEZ rs, offset if rs <= 0 then branch
when OP_BLEZ =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BEQ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if SIGNED(operand_1_o) <= 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BGTZ rs, offset if rs > 0 then branch
when OP_BGTZ =>
op_o <= OP_TYPE_BRANCH;
funct_o <= FUNCT_TYPE_BEQ;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
if SIGNED(operand_1_o) > 0 then
branch_o <= BRANCH;
branch_target_addr_o <= branch_addr_offset + next_pc;
next_inst_in_delayslot_o <= DELAYSLOT;
end if;
inst_valid := INST_VALID;
-- BEQL rs, rt, offset if rs = rt then branch_likely
when OP_BEQL =>
-- BNEL rs, rt, offset if rs != rt then branch_likely
when OP_BNEL =>
-- BLEZL rs, rt, offset if rs <= 0 then branch_likely
when OP_BLEZL =>
-- BGTZL rs, rt, offset if rs > 0 then branch_likely
when OP_BGTZL =>
-- SLTI rt, rs, immediate rt <- (rs < immediate)
when OP_SLTI =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SLTI;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- SLTIU rt, rs, immediate rt <- (rs < immediate)
when OP_SLTIU =>
op_o <= OP_TYPE_ARITH;
funct_o <= FUNCT_TYPE_SLTIU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read rs
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
extended_imm <= sign_extend(imm, DATA_LEN); -- sign extend imm
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
inst_valid := INST_VALID;
-- LB rt, offset(base) rt <- memory[base+offset]
when OP_LB =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LB;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LBU rt, offset(base) rt <- memory[base+offset]
when OP_LBU =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LBU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LH rt, offset(base) rt <- memory[base+offset]
when OP_LH =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LH;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LHU rt, offset(base) rt <- memory[base+offset]
when OP_LHU =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LHU;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LW rt, offset(base) rt <- memory[base+offset]
when OP_LW =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LW;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_DISABLE; -- do not read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LWL rt, offset(base) rt <- rt MERGE memory[base+offset]
when OP_LWL =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LWL;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- LWR rt, offset(base) rt <- rt MERGE memory[base+offset]
when OP_LWR =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_LWR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_ENABLE; -- write rt
reg_wt_addr_o <= reg_t;
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- SB rt, offset(base) memory[base+offset] <- rt
when OP_SB =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_SB;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- SH rt, offset(base) memory[base+offset] <- rt
when OP_SH =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_SH;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- SW rt, offset(base) memory[base+offset] <- rt
when OP_SW =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_SW;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- SWL rt, offset(base) memory[base+offset] <- rt
when OP_SWL =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_SWL;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
-- SWR rt, offset(base) memory[base+offset] <- rt
when OP_SWR =>
op_o <= OP_TYPE_LOAD_STORE;
funct_o <= FUNCT_TYPE_SWR;
reg_rd_en_1_o <= REG_RD_ENABLE; -- read base (rs)
reg_rd_en_2_o <= REG_RD_ENABLE; -- read rt
reg_wt_en_o <= REG_WT_DISABLE; -- do not write
extended_offset <= sign_extend(offset, DATA_LEN); -- sign extend offset
inst_valid := INST_VALID;
when others =>
end case op_code;
-- 赋值异常种类
except_type_o <= x"0000" & b"000" & except_type_is_eret & b"00" & inst_valid & except_type_is_syscall & x"00" ;
end if;
end process main_process;
assign_offset_process: process(extended_offset)
begin
extended_offset_o <= extended_offset;
end process assign_offset_process;
end Behavioral;
/* ID/EX Module */
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.INCLUDE.ALL;
entity ID_to_EX is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
op_i : in STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- input custom op type from ID
funct_i : in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input custom funct type from ID
operand_1_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input operand 1 data from ID
operand_2_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input operand 2 read data from ID
extended_offset_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input extended offset from ID
reg_wt_en_i : in STD_LOGIC; -- input register write enable from ID
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from ID
pause_i : in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input pause info from PAUSE_CTRL
is_in_delayslot_i : in STD_LOGIC; -- input the current instruction in delay slot from ID
next_inst_in_delayslot_i : in STD_LOGIC; -- input the next instruction in delay slot from ID
link_addr_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input (the return address to save) from ID
inst_i : in STD_LOGIC_VECTOR(INST_LEN-1 downto 0);
pc_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i : in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
op_o : out STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- output custom op type to EX
funct_o : out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output custom funct type to EX
operand_1_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output operand 1 read data to EX
operand_2_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output operand 2 read data to EX
extended_offset_o : out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output extended offset to EX
reg_wt_en_o : out STD_LOGIC; -- output register write enable to EX
reg_wt_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to EX
is_in_delayslot_o : out STD_LOGIC; -- output the current instruction in delay slot to EX
next_inst_in_delayslot_o : out STD_LOGIC; -- output the next instruction in delay slot to ID
link_addr_o : out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- output the register address to save return address to EX
inst_o : out STD_LOGIC_VECTOR(INST_LEN-1 downto 0);
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0));
end ID_to_EX;
architecture Behavioral of ID_to_EX is
begin
process (clk'event)
begin
if rising_edge(clk) then
if (rst = RST_ENABLE) OR ((pause_i(ID_PAUSE_INDEX) = PAUSE) AND (pause_i(EX_PAUSE_INDEX) = PAUSE_NOT)) then
op_o <= OP_TYPE_NOP;
funct_o <= FUNCT_TYPE_NOP;
operand_1_o <= REG_ZERO_DATA;
operand_2_o <= REG_ZERO_DATA;
extended_offset_o <= REG_ZERO_DATA;
reg_wt_en_o <= REG_WT_DISABLE;
reg_wt_addr_o <= REG_ZERO_ADDR;
is_in_delayslot_o <= DELAYSLOT_NOT;
next_inst_in_delayslot_o <= DELAYSLOT_NOT;
link_addr_o <= INST_ZERO_ADDR;
inst_o <= ZERO_INST;
current_inst_address_o <= ZERO_INST;
except_type_o <= ZERO_DATA;
elsif pause_i(ID_PAUSE_INDEX) = PAUSE_NOT then -- D不暂停,直接输出
op_o <= op_i;
funct_o <= funct_i;
operand_1_o <= operand_1_i;
operand_2_o <= operand_2_i;
extended_offset_o <= extended_offset_i;
reg_wt_en_o <= reg_wt_en_i;
reg_wt_addr_o <= reg_wt_addr_i;
is_in_delayslot_o <= is_in_delayslot_i;
next_inst_in_delayslot_o <= next_inst_in_delayslot_i;
link_addr_o <= link_addr_i;
inst_o <= inst_i;
current_inst_address_o <= current_inst_address_i;
except_type_o <= except_type_i;
end if;
end if;
end process;
end Behavioral;
/**
IF/ID模块
Encoding: UTF-8
**/
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.INCLUDE.ALL;
entity IF_to_ID is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
pc_i: in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input 指令地址 from PC
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input 指令 from RAM
pause_i: in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input 暂停信息 from PAUSE_CTRL
pc_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output 指令地址 to ID
inst_o: out STD_LOGIC_VECTOR(INST_LEN-1 downto 0)); -- output 指令 to ID
end IF_to_ID;
architecture Behavioral of IF_to_ID is
begin
process (clk'event)
begin
if rising_edge(clk) then
if (rst = RST_ENABLE ) OR ((pause_i(IF_PAUSE_INDEX) = PAUSE) and (pause_i(ID_PAUSE_INDEX) = PAUSE_NOT)) then
-- 复位或暂停时输出0
pc_o <= x"00000000";
inst_o <= x"00000000";
else
pc_o <= pc_i;
inst_o <= inst_i;
end if;
end if;
end process;
end Behavioral;
/**
常数头文件
Encoding: UTF-8
**/
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Constants Declaration Package
-- Usage: use WORK.INCLUDE.ALL;
-- WORK is the current working directory
package INCLUDE is
-- Aliases (MIPS32)
constant INST_LEN: integer := 32;
constant REG_DATA_LEN: integer := 32;
constant DATA_LEN: integer := 32;
constant ADDR_LEN: integer := 32;
constant PC_START_ADDR: STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0) := x"80000000";
constant REG_ADDR_LEN : integer := 5;
constant DOUBLE_DATA_LEN : integer := 64;
constant EXCEPT_TYPE_LEN : integer := 32;
-- Pause
constant CTRL_PAUSE_LEN : integer := 6;
constant PAUSE : STD_LOGIC := '1';
constant PAUSE_NOT : STD_LOGIC := '0';
constant P_FLUSH : STD_LOGIC := '1';
constant P_FLUSH_NOT : STD_LOGIC := '0';
constant PC_PAUSE_INDEX : integer := 0;
constant IF_PAUSE_INDEX : integer := 1;
constant ID_PAUSE_INDEX : integer := 2;
constant EX_PAUSE_INDEX : integer := 3;
constant MEM_PAUSE_INDEX : integer := 4;
constant WB_PAUSE_INDEX : integer := 5;
-- Accumulation instruction (MADDU, MSUBU) constants
constant ACCU_CNT_LEN : integer := 2;
-- Load/Store
constant BYTE_IN_DATA : integer := 4;
constant IS_READ : STD_LOGIC := '1';
constant IS_WRITE : STD_LOGIC := '0';
constant BYTE_LEN : integer := 8;
constant HALF_LEN : integer := 16;
constant WORD_LEN : integer := 32;
-- Branch/Jump
constant BRANCH : STD_LOGIC := '1';
constant BRANCH_NOT : STD_LOGIC := '0';
constant DELAYSLOT : STD_LOGIC := '1';
constant DELAYSLOT_NOT : STD_LOGIC := '0';
-- 除法
constant DIV_CNT_LEN : integer := 6;
constant DIV_STATE_FREE : STD_LOGIC_VECTOR(1 downto 0) := "00";
constant DIV_STATE_BY0 : STD_LOGIC_VECTOR(1 downto 0) := "01";
constant DIV_STATE_ON : STD_LOGIC_VECTOR(1 downto 0) := "10";
constant DIV_STATE_STOP : STD_LOGIC_VECTOR(1 downto 0) := "11";
constant DIV_RESULT_READY : STD_LOGIC := '1';
constant DIV_RESULT_READY_NOT : STD_LOGIC := '0';
constant DIV_START : STD_LOGIC := '1';
constant DIV_STOP : STD_LOGIC := '0';
constant OP_LEN : integer := 6;
constant FUNCT_LEN : integer := 6;
constant IMM_LEN : integer := 16;
constant SHAMT_LEN : integer := 5;
constant JUMP_ADDR_LEN : integer := 26;
constant CP0_SEL_LEN : integer := 3;
constant REG_NUM : integer := 32;
constant ROM_SIZE : integer := 131072;
constant ROM_SIZE_LOG2 : integer := 17;
constant RAM_SIZE : integer := 131072;
constant RAM_SIZE_LOG2 : integer := 17;
constant RST_ENABLE : STD_LOGIC := '1';
constant RST_DISABLE : STD_LOGIC := '0';
constant CHIP_ENABLE : STD_LOGIC := '1';
constant CHIP_DISABLE : STD_LOGIC := '0';
constant REG_RD_ENABLE : STD_LOGIC := '1';
constant REG_RD_DISABLE : STD_LOGIC := '0';
constant INST_VALID : STD_LOGIC := '1';
constant INST_INVALID : STD_LOGIC := '0';
constant TRAP_TRUE : STD_LOGIC := '1';
constant TRAP_FALSE : STD_LOGIC := '0';
constant REG_WT_ENABLE : STD_LOGIC := '1';
constant REG_WT_DISABLE : STD_LOGIC := '0';
constant IS_LOAD_STORE : STD_LOGIC := '1';
constant NOT_LOAD_STORE : STD_LOGIC := '0';
-- RAM simulation source
constant IS_READ_RAM : STD_LOGIC := '1';
constant IS_WRITE_RAM : STD_LOGIC := '0';
constant IS_SELECTED : STD_LOGIC := '1';
constant REG_ZERO_ADDR : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00000";
constant REG_31_ADDR : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"11111";
constant REG_ZERO_DATA : STD_LOGIC_VECTOR(REG_DATA_LEN - 1 downto 0) := x"00000000";
constant ZERO_DATA : STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0) := x"00000000";
constant ZERO_ADDR : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"00000000";
constant INST_ZERO_ADDR : STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0) := x"00000000";
constant ZERO_INST : STD_LOGIC_VECTOR(INST_LEN - 1 downto 0) := x"00000000";
constant DOUBLE_ZERO_DATA : STD_LOGIC_VECTOR(DOUBLE_DATA_LEN - 1 downto 0) := x"0000000000000000";
-- Instruction type for EX Module
constant OP_TYPE_NOP : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000000";
constant OP_TYPE_ARITH : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000001";
constant OP_TYPE_LOGIC : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000010";
constant OP_TYPE_SHIFT : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000011";
constant OP_TYPE_MOVE : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000100";
constant OP_TYPE_BRANCH : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000101";
constant OP_TYPE_LOAD_STORE : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000110";
-- Instruction subtype for EX
-- No Operation
constant FUNCT_TYPE_NOP : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000000";
-- Arithmetic
constant FUNCT_TYPE_ADD : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TYPE_ADDI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_ADDIU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TYPE_ADDU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TYPE_SUB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101";
constant FUNCT_TYPE_SUBU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110";
constant FUNCT_TYPE_CLO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000111";
constant FUNCT_TYPE_CLZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001000";
constant FUNCT_TYPE_SLT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001001";
constant FUNCT_TYPE_SLTI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001010";
constant FUNCT_TYPE_SLTIU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001011";
constant FUNCT_TYPE_SLTU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001100";
constant FUNCT_TYPE_MUL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001101";
constant FUNCT_TYPE_MULT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001110";
constant FUNCT_TYPE_MULTU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001111";
constant FUNCT_TYPE_MADD : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010000";
constant FUNCT_TYPE_MADDU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010001";
constant FUNCT_TYPE_MSUB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010010";
constant FUNCT_TYPE_MSUBU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010011";
constant FUNCT_TYPE_DIV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010100";
constant FUNCT_TYPE_DIVU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010101";
-- Logic
constant FUNCT_TYPE_AND : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_OR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TYPE_XOR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TYPE_NOR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101";
-- Shift
constant FUNCT_TYPE_SHIFT_LEFT_LOGIC : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TYPE_SHIFT_RIGHT_LOGIC : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_SHIFT_RIGHT_ARITH : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
-- Move
constant FUNCT_TYPE_MOVE_ZERO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TYPE_MOVE_NOT_ZERO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_MOVE_FROM_HI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TYPE_MOVE_TO_HI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TYPE_MOVE_FROM_LO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101";
constant FUNCT_TYPE_MOVE_TO_LO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110";
-- Branch
constant FUNCT_TYPE_JR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TYPE_JALR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_J : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TYPE_JAL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TYPE_B : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101";
constant FUNCT_TYPE_BAL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110";
constant FUNCT_TYPE_BEQ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000111";
constant FUNCT_TYPE_BGEZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001000";
constant FUNCT_TYPE_BGEZAL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001001";
constant FUNCT_TYPE_BGTZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001010";
constant FUNCT_TYPE_BLEZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001011";
constant FUNCT_TYPE_BLTZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001100";
constant FUNCT_TYPE_BLTZAL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001101";
constant FUNCT_TYPE_BNE : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001110";
-- Load/Store
constant FUNCT_TYPE_LB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TYPE_LBU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TYPE_LH : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TYPE_LHU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TYPE_LW : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101";
constant FUNCT_TYPE_LWL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110";
constant FUNCT_TYPE_LWR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000111";
constant FUNCT_TYPE_SB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001000";
constant FUNCT_TYPE_SH : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001001";
constant FUNCT_TYPE_SW : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001010";
constant FUNCT_TYPE_SWL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001011";
constant FUNCT_TYPE_SWR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001100";
-- Introduction to the MIPS32 Architecture
-- Table A-2 MIPS32 Encoding of the Opcode Field (bits 31..26)
constant OP_SPECIAL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000000";
constant OP_REGIMM : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000001";
constant OP_J : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000010"; -- J target To branch within the current 256 MB-aligned region
constant OP_JAL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000011"; -- JAL target To execute a procedure call within the current 256 MB-aligned region
constant OP_BEQ : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000100"; -- BEQ rs, rt, offset if rs = rt then branch
constant OP_BNE : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000101"; -- BNE rs, rt, offset if rs ��??? rt then branch
constant OP_BLEZ : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000110"; -- BLEZ rs, offset if rs ��??? 0 then branch
constant OP_BGTZ : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"000111"; -- BGTZ rs, offset if rs > 0 then branch
constant OP_ADDI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001000"; -- ADDI rt, rs, immediate rt ��??? rs + immediate
constant OP_ADDIU : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001001"; -- ADDIU rt, rs, immediate rt ��??? rs + immediate
constant OP_SLTI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001010"; -- SLTI rt, rs, immediate rt ��??? (rs < immediate)
constant OP_SLTIU : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001011"; -- SLTIU rt, rs, immediate rt ��??? (rs < immediate)
constant OP_ANDI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001100"; -- ANDI rt, rs, immediate rt ��??? rs AND immediate
constant OP_ORI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001101"; -- ORI rt, rs, immediate rt ��??? rs or immediate
constant OP_XORI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001110"; -- XORI rt, rs, immediate rt ��??? rs XOR immediate
constant OP_LUI : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"001111"; -- LUI rt, immediate rt ��??? immediate || 0^16
constant OP_COP0 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010000";
constant OP_COP1 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010001";
constant OP_COP2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010010";
constant OP_COP3 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010011";
constant OP_BEQL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010100"; -- BEQL rs, rt, offset if rs = rt then branch_likely
constant OP_BNEL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010101"; -- BNEL rs, rt, offset if rs ��??? rt then branch_likely
constant OP_BLEZL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010110"; -- BLEZL rs, rt, offset if rs ��??? 0 then branch_likely
constant OP_BGTZL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"010111"; -- BGTZL rs, rt, offset if rs > 0 then branch_likely
constant OP_SPECIAL2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"011100";
constant OP_JALX : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"011101";
constant OP_LB : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100000"; -- LB rt, offset(base) rt ��??? memory[base+offset]
constant OP_LH : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100001"; -- LH rt, offset(base) rt ��??? memory[base+offset]
constant OP_LWL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100010"; -- LWL rt, offset(base) rt ��??? rt MERGE memory[base+offset]
constant OP_LW : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100011"; -- LW rt, offset(base) rt ��??? memory[base+offset]
constant OP_LBU : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100100"; -- LBU rt, offset(base) rt ��??? memory[base+offset]
constant OP_LHU : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100101"; -- LHU rt, offset(base) rt ��??? memory[base+offset]
constant OP_LWR : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"100110"; -- LWR rt, offset(base) rt ��??? rt MERGE memory[base+offset]
constant OP_SB : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101000"; -- SB rt, offset(base) memory[base+offset] ��??? rt
constant OP_SH : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101001"; -- SH rt, offset(base) memory[base+offset] ��??? rt
constant OP_SWL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101010"; -- SWL rt, offset(base) memory[base+offset] ��??? rt
constant OP_SW : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101011"; -- SW rt, offset(base) memory[base+offset] ��??? rt
constant OP_SWR : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101110"; -- SWR rt, offset(base) memory[base+offset] ��??? rt
constant OP_CACHE : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"101111";
constant OP_LL : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110000";
constant OP_LWC1 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110001";
constant OP_LWC2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110010";
constant OP_PREF : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110011";
constant OP_LDC1 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110101";
constant OP_LDC2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"110110";
constant OP_SC : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"111000";
constant OP_SWC1 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"111001";
constant OP_SWC2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"111010";
constant OP_SDC1 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"111101";
constant OP_SDC2 : STD_LOGIC_VECTOR(OP_LEN - 1 downto 0) := b"111110";
-- Introduction to the MIPS32 Architecture
-- Table A-3 MIPS32 SPECIAL Opcode Encoding of Function Field (bits 5..0)
constant FUNCT_SLL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000000"; -- SLL $rd, $rt, imm rd ��???? rt << sa
constant FUNCT_MOVCI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_SRL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010"; -- SRL rd, rt, sa rd ��???? rt >> sa (logical)
constant FUNCT_SRA : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011"; -- SRA rd, rt, sa rd ��???? rt >> sa (arithmatic)
constant FUNCT_SLLV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100"; -- SLLV rd, rt, rs rd ��???? rt << rs
constant FUNCT_SRLV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110"; -- SRLV rd, rt, rs rd ��???? rt >> rs (logical)
constant FUNCT_SRAV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000111"; -- SRAV rd, rt, rs rd ��???? rt >> rs (arithmetic)
constant FUNCT_JR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001000"; -- JR rs PC ��???? rs
constant FUNCT_JALR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001001"; -- JALR (rd, = 31) rs rd ��???? return_addr, PC ��???? rs
constant FUNCT_MOVZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001010"; -- MOVZ rd, rs, rt if rt = 0 then rd ��???? rs
constant FUNCT_MOVN : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001011"; -- MOVN rd, rs, rt if rt ��???? 0 then rd ��???? rs
constant FUNCT_SYSCALL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001100"; -- SYSCALL A system call exception occurs
constant FUNCT_BREAK : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001101"; -- BREAK A breakpoint exception occurs
constant FUNCT_SYNC : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001111"; -- SYNC (stype = 0 implied) To order loads and stores.
constant FUNCT_MFHI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010000"; -- MFHI rd rd ��???? HI
constant FUNCT_MTHI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010001"; -- MTHI rs HI ��???? rs
constant FUNCT_MFLO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010010"; -- MFLO rd rd ��???? LO
constant FUNCT_MTLO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"010011"; -- MTLO rs LO ��???? rs
constant FUNCT_MULT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"011000"; -- MULT rs, rt (LO, HI) ��???? rs ��??? rt
constant FUNCT_MULTU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"011001"; -- MULTU rs, rt (LO, HI) ��???? rs ��??? rt
constant FUNCT_DIV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"011010"; -- DIV rs, rt (LO, HI) ��???? rs / rt
constant FUNCT_DIVU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"011011"; -- DIVU rs, rt (LO, HI) ��???? rs / rt
constant FUNCT_ADD : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100000"; -- ADD rd, rs, rt rd ��???? rs + rt
constant FUNCT_ADDU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100001"; -- ADDU rd, rs, rt rd ��???? rs + rt
constant FUNCT_SUB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100010"; -- SUB rd, rs, rt rd ��???? rs - rt
constant FUNCT_SUBU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100011"; -- SUBU rd, rs, rt rd ��???? rs - rt
constant FUNCT_AND : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100100"; -- AND rd, rs, rt rd ��???? rs AND rt
constant FUNCT_OR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100101"; -- OR rd, rs, rt rd ��???? rs or rt
constant FUNCT_XOR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100110"; -- XOR rd, rs, rt rd ��???? rs XOR rt
constant FUNCT_NOR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100111"; -- NOR rd, rs, rt rd ��???? rs NOR rt
constant FUNCT_SLT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"101010"; -- SLT rd, rs, rt rd ��???? (rs < rt)
constant FUNCT_SLTU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"101011"; -- SLTU rd, rs, rt rd ��???? (rs < rt)
constant FUNCT_TGE : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110000"; -- TGE rs, rt if rs ��???? rt then Trap
constant FUNCT_TGEU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110001"; -- TGEU rs, rt if rs ��???? rt then Trap
constant FUNCT_TLT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110010"; -- TLT rs, rt if rs < rt then Trap
constant FUNCT_TLTU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110011"; -- TLTU rs, rt if rs < rt then Trap
constant FUNCT_TEQ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110100"; -- TEQ rs, rt if rs = rt then Trap
constant FUNCT_TNE : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"110110"; -- TNE rs, rt if rs ��???? rt then Trap
constant FUNCT_ERET : STD_Logic_vector(FUNCT_LEN - 1 downto 0) := b"011000";
-- Introduction to the MIPS32 Architecture
-- Table A-4 MIPS32 REGIMM Encoding of rt Field (bits 20..16)
constant RT_BLTZ : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00000";
constant RT_BGEZ : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00001";
constant RT_BLTZL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00010";
constant RT_BGEZL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00011";
constant RT_TGEI : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01000";
constant RT_TGEIU : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01001";
constant RT_TLTI : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01010";
constant RT_TLTIU : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01011";
constant RT_TEQI : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01100";
constant RT_TNEI : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"01110";
constant RT_BLTZAL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"10000";
constant RT_BGEZAL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"10001";
constant RT_BLTZALL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"10010";
constant RT_BGEZALL : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"10011";
-- Introduction to the MIPS32 Architecture
-- Table A-5 MIPS32 SPECIAL2 Encoding of Function Field (bits 5..0)
constant FUNCT_MADD : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000000"; -- MADD rs, rt (LO,HI) ��??? (rs x rt) + (LO,HI)
constant FUNCT_MADDU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001"; -- MADDU rs, rt (LO,HI) ��??? (rs x rt) + (LO,HI)
constant FUNCT_MUL : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010"; -- MUL rd, rs, rt rd ��??? rs × rt
constant FUNCT_MSUB : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100"; -- MSUB rs, rt (LO,HI) ��??? (rs x rt) - (LO,HI)
constant FUNCT_MSUBU : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000101"; -- MSUBU rs, rt (LO,HI) ��??? (rs x rt) - (LO,HI)
constant FUNCT_CLZ : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100000"; -- CLZ rd, rs rd ��??? count_leading_zeros rs
constant FUNCT_CLO : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100001"; -- CLO rd, rs rd ��??? count_leading_ones rs
constant FUNCT_SDBBP : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"111111";
-- Introduction to the MIPS32 Architecture
-- Table A-6 MIPS32 MOVCI Encoding of tf Bit (bit 16)
constant TF_MOVF : STD_LOGIC := '0';
constant TF_MOVT : STD_LOGIC := '1';
-- Table A.11 MIPS32 COP0 Encoding of rs Field (bits 25..21)
constant RS_MTC0 : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00100";
constant RS_MFC0 : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00000";
constant RS_MFH : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00010";
constant RS_MTH : STD_LOGIC_VECTOR(REG_ADDR_LEN - 1 downto 0) := b"00110";
-- Table A.12 MIPS32 COP0 Encoding of Function Field When rs=CO
constant FUNCT_TLBR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000001";
constant FUNCT_TLBWI : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000010";
constant FUNCT_TLBINV : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000011";
constant FUNCT_TLBINVF : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000100";
constant FUNCT_TLBWR : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"000110";
constant FUNCT_TLBP : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"001000";
constant FUNCT_WAIT : STD_LOGIC_VECTOR(FUNCT_LEN - 1 downto 0) := b"100000";
constant STATE_LEN : integer := 2;
constant STATE_IDLE : STD_LOGIC_VECTOR(STATE_LEN - 1 downto 0) := b"00";
constant STATE_DATA : STD_LOGIC_VECTOR(STATE_LEN - 1 downto 0) := b"01";
constant STATE_INST : STD_LOGIC_VECTOR(STATE_LEN - 1 downto 0) := b"10";
constant STATE_DEBUG : STD_LOGIC_VECTOR(STATE_LEN - 1 downto 0) := b"11";
constant CE_ENABLE : STD_LOGIC := '1';
constant CE_DISABLE : STD_LOGIC := '0';
constant ACK : STD_LOGIC := '1';
constant ACK_NOT : STD_LOGIC := '0';
constant HIGH_Z : STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0) := x"ZZZZZZZZ";
constant RAM_ADDR_LEN : integer := 20;
constant SRAM_STATE_LEN : integer := 2;
constant SRAM_IDLE : STD_LOGIC_VECTOR(SRAM_STATE_LEN - 1 downto 0) := b"00";
constant SRAM_WRITE : STD_LOGIC_VECTOR(SRAM_STATE_LEN - 1 downto 0) := b"01";
constant SRAM_READ : STD_LOGIC_VECTOR(SRAM_STATE_LEN - 1 downto 0) := b"10";
constant SRAM_BYTE_CHOOSE_NOT : STD_LOGIC_VECTOR(BYTE_LEN - 1 downto 0) := b"11111111";
constant SRAM_BYTE_CHOOSE : STD_LOGIC_VECTOR(BYTE_LEN - 1 downto 0) := b"00000000";
constant SRAM_BYTE_HIGH_Z : STD_LOGIC_VECTOR(BYTE_LEN - 1 downto 0) := b"ZZZZZZZZ";
constant SRAM_WORD_HIGH_Z : STD_LOGIC_VECTOR(WORD_LEN - 1 downto 0) := b"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
constant BYTE_SEL : STD_LOGIC := '1';
constant BYTE_SEL_NOT : STD_LOGIC := '0';
constant WORD_SEL : STD_LOGIC_VECTOR(1 downto 0) := b"11";
constant WORD_SEL_NOT : STD_LOGIC_VECTOR(1 downto 0) := b"00";
constant SERIAL_STATE_LEN : integer := 2;
constant SERIAL_IDLE : STD_LOGIC_VECTOR(SERIAL_STATE_LEN - 1 downto 0) := b"00";
constant SERIAL_READ : STD_LOGIC_VECTOR(SERIAL_STATE_LEN - 1 downto 0) := b"01";
constant SERIAL_WRITE : STD_LOGIC_VECTOR(SERIAL_STATE_LEN - 1 downto 0) := b"10";
constant TYPE_LEN : integer := 3;
--s constant TYPE_NULL : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"000";
constant TYPE_BASE_RAM : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"001";
-- constant TYPE_EXTEND_RAM : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"010";
constant TYPE_LED : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"011";
constant TYPE_NUM : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"100";
constant TYPE_SERIAL : STD_LOGIC_VECTOR(TYPE_LEN - 1 downto 0) := b"101";
constant BASE_RAM_ADDR_MIN : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"80000000";
constant BASE_RAM_ADDR_MAX : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"803FFFFF";
constant EXTEND_RAM_ADDR_MIN : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"80400000";
constant EXTEND_RAM_ADDR_MAX : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"807FFFFF";
constant LED_ADDR : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"bfd0f000"; -- For test
constant NUM_ADDR : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"bfd0f010"; -- For test
constant SERIAL_ADDR : STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0) := x"BFD003F8";
-- constant for cp0
constant INTERRUPT_ASSERT : STD_LOGIC := '1';
constant INTERRUPT_NOT_ASSERT : STD_LOGIC := '1';
--reg status
constant STATUS_CU_CP0 : STD_LOGIC_VECTOR(3 downto 0) := b"0001";
--reg
constant CP0_REG_COUNT : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"01001"; --静靝?
constant CP0_REG_COMPARE : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0 ) := b"01011"; --静靝?
constant CP0_REG_STATUS : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"01100"; --静靝?
constant CP0_REG_CAUSE : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"01101"; --静��??
constant CP0_REG_EPC : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"01110" ; --静靝?
constant CP0_REG_PrId : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"01111" ; --静��??
constant CP0_REG_CONFIG : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0) := b"10000" ; --静��??
constant STATUS_EXL_INDEX : integer := 1;
constant STATUS_IE_INDEX : integer := 0;
constant CAUSE_BD_INDEX : integer := 31;
constant EXCEPT_TYPE_INTERRUPT : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"00000001";
constant EXCEPT_TYPE_SYSCALL : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"00000008";
constant EXCEPT_TYPE_INST_INVALID : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"0000000a";
constant EXCEPT_TYPE_TRAP : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"0000000d";
constant EXCEPT_TYPE_OVERFLOW : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"0000000c";
constant EXCEPT_TYPE_ERET : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0) := x"0000000e";
--cause
constant EXCCODE_INTERRUPT : STD_LOGIC_VECTOR(4 downto 0) := b"00000";
constant EXCCODE_SYSCALL : STD_LOGIC_VECTOR(4 downto 0) := b"01000";
constant EXCCODE_INST_INVALID : STD_LOGIC_VECTOR(4 downto 0) := b"01010";
constant EXCCODE_TRAP : STD_LOGIC_VECTOR(4 downto 0) := b"01101";
constant EXCCODE_OVERFLOW : STD_LOGIC_VECTOR(4 downto 0) := b"01100";
constant EXCEPT_HANDLE_ADDRESS: STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0) := x"80001180";
function count_leading(vector : STD_LOGIC_VECTOR; b : STD_LOGIC) return natural;
function count_leading_ones(vector : STD_LOGIC_VECTOR) return natural;
function count_leading_zeros(vector : STD_LOGIC_VECTOR) return natural;
function sign_extend(vector: STD_LOGIC_VECTOR; newLen: integer) return STD_LOGIC_VECTOR;
function zero_extend(vector: STD_LOGIC_VECTOR; newLen: integer) return STD_LOGIC_VECTOR;
function reverse_vector(vector: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR;
end INCLUDE;
package body INCLUDE is
-- Count leading
function count_leading(vector : STD_LOGIC_VECTOR; b : STD_LOGIC) return natural is
variable x : natural;
variable y : natural;
variable upper : STD_LOGIC_VECTOR(vector'length / 2 - 1 downto 0);
variable lower : STD_LOGIC_VECTOR(vector'length / 2 - 1 downto 0);
begin
if vector'length = 1 then
if vector(0) = b then
return 1;
else
return 0;
end if;
end if;
-- report("Bit width of vector is " & integer'image(vector'length));
upper := vector(vector'length - 1 downto vector'length / 2);
lower := vector(vector'length / 2 - 1 downto 0);
x := count_leading(upper, b);
if x = vector'length / 2 then
y := count_leading(lower, b);
return x + y;
else
return x;
end if;
end function count_leading;
function count_leading_ones(vector : STD_LOGIC_VECTOR) return natural is
begin
return count_leading(vector, '1');
end function count_leading_ones;
function count_leading_zeros(vector : STD_LOGIC_VECTOR) return natural is
begin
return count_leading(vector, '0');
end function count_leading_zeros;
function sign_extend(vector: STD_LOGIC_VECTOR; newLen: integer) return STD_LOGIC_VECTOR is
variable extended: STD_LOGIC_VECTOR(newLen-1 downto 0);
variable bit: STD_LOGIC;
begin
if newLen <= vector'length then
return vector(newLen-1 downto 0);
end if;
bit := vector(vector'high); -- 注意这里的语法,如果直接写vector(vector'length-1)会挂掉�?��??
extended(newLen-1 downto vector'length) := (others => bit);
extended(vector'length-1 downto 0) := vector; -- sign extend vector
return extended;
end function sign_extend;
function zero_extend(vector: STD_LOGIC_VECTOR; newLen: integer) return STD_LOGIC_VECTOR is
variable extended: STD_LOGIC_VECTOR(newLen-1 downto 0);
begin
if newLen <= vector'length then
return vector(newLen-1 downto 0);
end if;
extended(newLen-1 downto vector'length) := (others => '0');
extended(vector'length-1 downto 0) := vector; -- sign extend vector
return extended;
end function zero_extend;
function reverse_vector(vector: in STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
variable result: STD_LOGIC_VECTOR(vector'RANGE);
variable block_size: integer := vector'length / 4;
begin
result(block_size * 4 - 1 downto block_size * 3) := vector(block_size - 1 downto 0);
result(block_size * 3 - 1 downto block_size * 2) := vector(block_size * 2 - 1 downto block_size);
result(block_size * 2 - 1 downto block_size) := vector(block_size * 3 - 1 downto block_size * 2);
result(block_size - 1 downto 0) := vector(block_size * 4 - 1 downto block_size * 3);
return result;
end function reverse_vector;
end INCLUDE;
/**
MIPS_CPU顶层模块
Encoding: UTF-8
**/
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use WORK.INCLUDE.ALL;
entity MIPS_CPU is
Port ( clk: in STD_LOGIC; -- Clock
rst: in STD_LOGIC);
end MIPS_CPU;
architecture Behavioral of MIPS_CPU is
component PC
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
branch_i: in STD_LOGIC; -- input 是否跳转 from ID
branch_target_addr_i: in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input 跳转目的地址 from ID
en_o: out STD_LOGIC; -- output RAM读指令使能 to MMU
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0)); -- output RAM读指令地址 to MMU
end component;
component IF_to_ID is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
pc_i: in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input 指令地址 from PC
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input 指令 from RAM
pause_i: in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input 暂停信息 from PAUSE_CTRL
pc_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output 指令地址 to ID
inst_o: out STD_LOGIC_VECTOR(INST_LEN-1 downto 0));
end component;
component ID is
Port ( rst: in STD_LOGIC; -- Reset
pc_i: in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input (instruction address) from IF/ID
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input instruction from IF/ID
reg_rd_data_1_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register 1 read data from REGISTERS
reg_rd_data_2_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register 2 read data from REGISTERS
is_in_delayslot_i: in STD_LOGIC; -- input 当前指令是否在延迟槽内 from ID/EX
last_is_load_store_i: in STD_LOGIC; -- input 上一条指令是否为加载/存储指令 from EX
last_funct_i: in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input the funct_o of the last instruction from EX
op_o: out STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- output custom op type to ID/EX
funct_o: out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output custom funct type to ID/EX
inst_o: out STD_LOGIC_VECTOR(INST_LEN - 1 downto 0); -- output 当前指令 to ID/EX for 异常处理
reg_rd_en_1_o: out STD_LOGIC; -- output register 1 read enable to REGISTERS
reg_rd_en_2_o: out STD_LOGIC; -- output register 2 read enable to REGISTERS
reg_rd_addr_1_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register 1 read address to REGISTERS
reg_rd_addr_2_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register 2 read address to REGISTERS
operand_1_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output operand 1 to ID/EX
operand_2_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output operand 2 to ID/EX
extended_offset_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output extended offset to ID/EX
reg_wt_en_o: out STD_LOGIC; -- output register write enable to ID_to_EX
reg_wt_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to ID_to_EX
pause_o: out STD_LOGIC; -- output pause information to PAUSE_CTRL
branch_o: out STD_LOGIC; -- output if the current instruction needs to branch
branch_target_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output the branch target address to PC
is_in_delayslot_o: out STD_LOGIC; -- output the current instruction in delay slot to ID/EX
next_inst_in_delayslot_o: out STD_LOGIC; -- output the next instruction in delay slot to ID/EX
link_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output the return address to save to ID/EX
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0); -- output CP0异常类型 to ID/EX
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0)); -- output 指令地址 to ID/EX
end component;
component ID_to_EX is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
op_i : in STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- input custom op type from ID
funct_i : in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input custom funct type from ID
operand_1_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input operand 1 data from ID
operand_2_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input operand 2 read data from ID
extended_offset_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input extended offset from ID
reg_wt_en_i : in STD_LOGIC; -- input register write enable from ID
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from ID
pause_i : in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input pause info from PAUSE_CTRL
is_in_delayslot_i : in STD_LOGIC; -- input the current instruction in delay slot from ID
next_inst_in_delayslot_i : in STD_LOGIC; -- input the next instruction in delay slot from ID
link_addr_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input (the return address to save) from ID
inst_i : in STD_LOGIC_VECTOR(INST_LEN-1 downto 0);
pc_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i : in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
op_o : out STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- output custom op type to EX
funct_o : out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output custom funct type to EX
operand_1_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output operand 1 read data to EX
operand_2_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output operand 2 read data to EX
extended_offset_o : out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output extended offset to EX
reg_wt_en_o : out STD_LOGIC; -- output register write enable to EX
reg_wt_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to EX
is_in_delayslot_o : out STD_LOGIC; -- output the current instruction in delay slot to EX
next_inst_in_delayslot_o : out STD_LOGIC; -- output the next instruction in delay slot to ID
link_addr_o : out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- output the register address to save return address to EX
inst_o : out STD_LOGIC_VECTOR(INST_LEN-1 downto 0);
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0));
end component;
component EX is
Port ( rst: in STD_LOGIC; -- Reset
inst_i: in STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- input 当前指令 from ID/EX for 异常处理
op_i: in STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- input 自定义操作码 from ID/EX
funct_i: in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input 自定义指令功能 from ID/EX
operand_1_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input 操作数1 from ID/EX
operand_2_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input 操作数2 from ID/EX
extended_offset_i: in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input 扩展后的偏移 from ID/EX
reg_wt_en_i: in STD_LOGIC; -- input 寄存器写使能 from ID/EX for 在WB阶段写入
reg_wt_addr_i: in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input 寄存器写地址 from ID/EX for 在WB阶段写入
hi_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input HI寄存器内容 from HI_LO for 在本阶段读HILO寄存器
lo_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input LO寄存器内容 from HI_LO for 在本阶段读HILO寄存器
clock_cycle_cnt_i: in STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- input 累加指令时钟周期计数 from EX/MEM
mul_cur_result_i: in STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- input 累加指令当前结果 from EX/MEM
is_in_delayslot_i: in STD_LOGIC; -- input 当前指令是否在延迟槽中 from ID/EX
link_addr_i: in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- input the 保存返回地址的寄存器的地址 from ID/EX
cp0_reg_data_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input CP0寄存器 from CP0
pc_i: in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i: in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
reg_wt_en_o: out STD_LOGIC; -- output register write enable to EX/MEM
reg_wt_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to EX/MEM
reg_wt_data_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output register write data to EX/MEM
is_load_store_o: out STD_LOGIC; -- output load/store to EX/MEM, ID
funct_o: out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output load/store type to EX/MEM, ID
load_store_addr_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output load/store memory address to EX/MEM
store_data_o: out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output store data to EX/MEM
hilo_en_o: out STD_LOGIC; -- output HI_LO write enable to EX/MEM
hi_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output HI data to EX/MEM
lo_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output LO data to EX/MEM
pause_o: out STD_LOGIC; -- output pause information to PAUSE_CTRL
clock_cycle_cnt_o: out STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- output (clock cycle count) to EX/MEM
mul_cur_result_o: out STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- output (accumulation result) to EX/MEM
is_in_delayslot_o: out std_logic; -- output (is in delay slot) to EX/MEM for exception handling
cp0_reg_read_addr_o: out std_logic_vector(REG_ADDR_LEN-1 downto 0); -- output (which CP0 register to read) to CP0
cp0_reg_we_o: out std_logic; -- output (CP0 write register enable) to EX/MEM
cp0_reg_write_addr_o: out std_logic_vector(REG_ADDR_LEN-1 downto 0); -- output (CP0 write register address) to EX/MEM
cp0_reg_data_o: out std_logic_vector(REG_DATA_LEN-1 downto 0); -- output (CP0 write register data) to EX/MEM
pc_o: out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o: out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0));
end component;
component EX_to_MEM is
Port ( rst : in STD_LOGIC; -- Reset
clk : in STD_LOGIC; -- Clock
reg_wt_en_i : in STD_LOGIC; -- input register write enable from EX
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from EX
reg_wt_data_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register write data from EX
is_load_store_i : in STD_LOGIC; -- input load/store from EX
funct_i : in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input load/store type from EX
load_store_addr_i : in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input load/store memory address from EX
store_data_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input store data from EX
hilo_en_i : in STD_LOGIC; -- input HILO write enable from EX
hi_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input HI data from EX
lo_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input LO data from EX
pause_i : in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input pause info from PAUSE_CTRL
clock_cycle_cnt_i : in STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- input clock cycle count from EX
mul_cur_result_i : in STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- input accumulation result from EX
reg_wt_en_o : out STD_LOGIC; -- output register write enable to MEM
reg_wt_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to MEM
reg_wt_data_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output register write data to MEM
is_load_store_o : out STD_LOGIC; -- output load/store to MEM
funct_o : out STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- output load/store type to MEM
load_store_addr_o : out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output load/store memory address to MEM
store_data_o : out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output store data to MEM
hilo_en_o : out STD_LOGIC; -- output HILO write enable to MEM
hi_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output HI data to MEM
lo_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output LO data to MEM
clock_cycle_cnt_o : out STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0); -- output clock cycle count to EX
mul_cur_result_o : out STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0); -- output accumulation result to EX
ex_cp0_reg_we_i : in std_logic;
ex_cp0_reg_write_addr_i: in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
ex_cp0_reg_data_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
mem_cp0_reg_we_o : out std_logic;
mem_cp0_reg_write_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
mem_cp0_reg_data_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
--寮傚父澶勭悊
flush_i : in std_logic;
current_inst_address_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i : in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
is_in_delayslot_i : in std_logic;
current_inst_address_o : out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o : out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
is_in_delayslot_o : out std_logic
);
end component;
component MEM is
Port ( rst : in STD_LOGIC; -- Reset
reg_wt_en_i : in STD_LOGIC; -- input register write enable from EX/MEM
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from EX/MEM
reg_wt_data_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register write data from EX/MEM
ram_rd_data_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input data read from RAM
is_load_store_i : in STD_LOGIC; -- input load/store from EX/MEM
funct_i : in STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- input load/store type from EX/MEM
load_store_addr_i : in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input load/store memory address from EX/MEM
store_data_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- input store data from EX/MEM
hilo_en_i : in STD_LOGIC; -- input HILO enable from EX/MEM
hi_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input HI data from EX/MEM
lo_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input LO data from EX/MEM
reg_wt_en_o : out STD_LOGIC; -- output register write enable to MEM/WB
reg_wt_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to MEM/WB
reg_wt_data_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output register write data to MEM/WB
ram_en_o : out STD_LOGIC; -- output RAM enable to RAM
ram_is_read_o : out STD_LOGIC; -- output RAM read to RAM
ram_addr_o : out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- output RAM address to RAM
ram_data_o : out STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- output RAM data to RAM
ram_data_sel_o : out STD_LOGIC_VECTOR(BYTE_IN_DATA-1 downto 0); -- output RAM data selection to RAM
hilo_en_o : out STD_LOGIC; -- output HILO write enable to MEM/WB
hi_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output HI data to MEM/WB
lo_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output lo data to MEM/WB
cp0_reg_we_i : in std_logic;
cp0_reg_write_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
cp0_reg_data_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
cp0_reg_we_o : out std_logic;
cp0_reg_write_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
cp0_reg_data_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
current_inst_address_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i : in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
is_in_delayslot_i : in std_logic;
status_i : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
cause_i : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
epc_i : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
wb_cp0_reg_we_i : in STD_LOGIC;
wb_cp0_reg_write_addr_i: in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
wb_cp0_reg_data_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
cp0_epc_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
current_inst_address_o : out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_o : out STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
is_in_delayslot_o : out std_logic
);
end component;
component MEM_to_WB is
Port ( rst : in STD_LOGIC; -- Reset
clk : in STD_LOGIC; -- Clock
reg_wt_en_i : in STD_LOGIC; -- input register write enable from MEM
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from MEM
reg_wt_data_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input register write data from MEM
hilo_en_i : in STD_LOGIC; -- input HILO enable from MEM
hi_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input HI data from MEM
lo_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- input LO data from MEM
pause_i : in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input pause info from PAUSE_CTRL
flush_i : in std_logic;
reg_wt_en_o : out STD_LOGIC; -- output register write enable to REGISTERS
reg_wt_addr_o : out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- output register write address to REGISTERS
reg_wt_data_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output register write data to REGISTERS
hilo_en_o : out STD_LOGIC; -- output HILO write enable to HILO and EX
hi_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output HI data to HILO and EX
lo_o : out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- output lo data to HILO and EX
mem_cp0_reg_we_i : in STD_LOGIC;
mem_cp0_reg_write_addr_i: in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
mem_cp0_reg_data_i: in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
wb_cp0_reg_we_o : out STD_LOGIC;
wb_cp0_reg_write_addr_o: out STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
wb_cp0_reg_data_o: out STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0));
end component;
component CP0_REG is
Port ( rst : in STD_LOGIC; -- Reset
clk : in STD_LOGIC;
raddr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
waddr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
data_i : in STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
we_i : in STD_LOGIC;
int_i : in STD_LOGIC_VECTOR(5 downto 0);
data_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
count_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
compare_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
status_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
cause_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
epc_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
config_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
prid_o : inout STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
timer_int_o : out STD_LOGIC;
current_inst_address_i : in STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
except_type_i : in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
is_in_delayslot_i : in std_logic);
end component;
component REGISTERS is
Port ( rst : in STD_LOGIC; -- Reset
clk : in STD_LOGIC; -- Clock
reg_rd_en_1_i : in STD_LOGIC; -- input register 1 read enable from ID
reg_rd_en_2_i : in STD_LOGIC; -- input register 2 read enable from ID
reg_rd_addr_1_i : in STD_LOGIC_VECTOR (REG_ADDR_LEN-1 downto 0); -- input register 1 read address from ID
reg_rd_addr_2_i : in STD_LOGIC_VECTOR (REG_ADDR_LEN-1 downto 0); -- input register 2 read address from ID
reg_wt_en_i : in STD_LOGIC; -- input register write enable from MEM_to_WEB
reg_wt_addr_i : in STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- input register write address from MEM_to_WEB
reg_wt_data_i : in STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0); -- input register write address from MEM_to_WEB
reg_rd_data_1_o : out STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0); -- output register 1 read data to ID
reg_rd_data_2_o : out STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0)); -- output register 2 read data to ID
end component;
component HI_LO is
Port ( clk : in STD_LOGIC; -- Clock
rst : in STD_LOGIC; -- Reset
en : in STD_LOGIC; -- input enable from MEM/WB
hi_i : in STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0); -- input HI data from MEM/WB
lo_i : in STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0); -- input LO data from MEM/WB
hi_o : out STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0); -- output HI data to EX
lo_o : out STD_LOGIC_VECTOR (REG_DATA_LEN-1 downto 0)); -- output LO data to EX
end component;
component PAUSE_CTRL is
Port ( rst : in STD_LOGIC; -- Reset
id_pause_i : in STD_LOGIC; -- Input pause information from ID
ex_pause_i : in STD_LOGIC; -- Input pause information from EX
if_pause_i : in STD_LOGIC;
mem_pause_i:in STD_LOGIC;
pause_o : out STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- Output pause information to PC, IF/ID, ID/EX, EX/MEM, MEM_WB
except_type_i :in STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
cp0_epc_i : in STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
new_pc_o : out STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
new_pc_en_o: out std_logic;
flush_o : out STD_LOGIC);
end component;
component MMU is
Port (
rst : in STD_LOGIC;
ce_i : in STD_LOGIC;
we_i : in STD_LOGIC;
sel_i : in STD_LOGIC_VECTOR(BYTE_IN_DATA - 1 downto 0);
addr_i : in STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0);
data_i : in STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ram1_data_i : in STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ram1_ack_i : in STD_LOGIC;
ram1_ce_o : out STD_LOGIC;
ram1_we_o : out STD_LOGIC;
ram1_data_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ram1_addr_o : out STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0);
ram1_sel_o : out STD_LOGIC_VECTOR(BYTE_IN_DATA - 1 downto 0);
ram2_data_i : in STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ram2_ack_i : in STD_LOGIC;
ram2_ce_o : out STD_LOGIC;
ram2_we_o : out STD_LOGIC;
ram2_data_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ram2_addr_o : out STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0);
ram2_sel_o : out STD_LOGIC_VECTOR(BYTE_IN_DATA - 1 downto 0);
serial_ce_o : out STD_LOGIC;
serial_we_o : out STD_LOGIC;
serial_data_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
serial_data_i : in STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
serial_ack_i : in STD_LOGIC;
leds_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
num_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
ack_o : out STD_LOGIC;
data_o : out STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0));
end component;
-- PC模块的输出信号
signal pc_from_pc: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- PC -> IF/ID, 指令地址
signal read_inst_en_from_pc: STD_LOGIC; -- PC -> IF/ID, 读指令使能
-- IF/ID模块的输出信号
signal pc_from_ifid: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- IF/ID -> ID, 指令地址
signal inst_from_ifid: STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- IF/ID -> ID, 指令
-- ID模块的输出信号
signal op_from_id: STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- ID -> ID/EX, 自定义指令操作码
signal funct_from_id: STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- ID -> ID/EX, 自定义指令功能码
signal inst_from_id: STD_LOGIC_VECTOR(INST_LEN - 1 downto 0); -- ID -> ID/EX, 指令
signal reg_rd_en_1_from_id: STD_LOGIC; -- ID -> REGISTER, 寄存器1写使能
signal reg_rd_en_2_from_id: STD_LOGIC; -- ID -> REGISTER, 寄存器2写使能
signal reg_rd_addr_1_from_id: STD_LOGIC_VECTOR (REG_ADDR_LEN-1 downto 0); -- ID -> REGISTER, 寄存器1写地址
signal reg_rd_addr_2_from_id: STD_LOGIC_VECTOR (REG_ADDR_LEN-1 downto 0); -- ID -> REGISTER, 寄存器2写地址
signal oprand_1_from_id: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- ID -> ID/EX, 操作数1
signal oprand_2_from_id: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- ID -> ID/EX, 操作数2
signal extended_offset_from_id: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- ID -> ID/EX, 扩展后的偏移量
signal reg_wt_en_from_id: STD_LOGIC; -- ID -> ID/EX, 寄存器写使能
signal reg_wt_addr_from_id: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- ID -> ID/EX, 寄存器写地址
signal pause_from_id: STD_LOGIC; -- ID -> PAUSE_CTRL, 本阶段是否暂停
signal branch_from_id: STD_LOGIC; -- ID -> ID/EX, 当前是否为分支跳转指令
signal is_in_delayslot_from_id: STD_LOGIC; -- ID -> ID/EX, 当前指令是否在延迟槽内
signal next_inst_in_delayslot_from_id: STD_LOGIC; -- ID -> ID/EX, 下一条指令是否在延迟槽内
signal link_addr_from_id: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- ID -> ID/EX, 要保存的返回地址
signal inst_from_id: STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- ID -> ID/EX, 指令
signal except_type_from_id: STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0); -- ID -> ID/EX, CP0异常类型
signal pc_from_id: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- ID -> ID/EX, 指令地址
-- ID/EX模块的输出信号
signal op_from_idex: STD_LOGIC_VECTOR(OP_LEN-1 downto 0); -- ID/EX -> EX, 自定义指令操作码
signal funct_from_idex: STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0); -- ID/EX -> EX, 自定义指令功能码
signal oprand_1_from_idex: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- ID/EX -> EX, 操作数1
signal oprand_2_from_idex: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0); -- ID/EX -> EX, 操作数2
signal extended_offset_from_idex: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0); -- ID/EX -> EX, 扩展后的偏移
signal reg_wt_en_from_idex: STD_LOGIC; -- ID/EX -> EX, 写寄存器使能
signal reg_wt_addr_from_idex: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0); -- ID/EX -> EX, 写寄存器地址
signal is_in_delayslot_from_idex: STD_LOGIC; -- ID/EX -> EX, 当前指令是否在延迟槽内
signal next_inst_in_delayslot_from_idex: STD_LOGIC; -- ID/EX -> ID, 下一条指令是否在延迟槽内
signal link_addr_from_idex: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- ID/EX -> EX, 要保存的返回地址
signal inst_from_idex: STD_LOGIC_VECTOR(INST_LEN-1 downto 0); -- ID/EX -> EX, 指令
signal except_type_to_ex: STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0); -- ID/EX -> EX, 异常类型
signal pc_from_idex: STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0); -- ID/EX -> EX, 指令地址
-- EX to EX/MEM signals
signal reg_wt_en_from_ex: STD_LOGIC;
signal reg_wt_addr_from_ex: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal reg_wt_data_from_ex: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal hilo_en_from_ex: STD_LOGIC;
signal hi_from_ex: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal lo_from_ex: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal clock_cycle_cnt_from_ex: STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0);
signal mul_cur_result_from_ex: STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0);
signal is_load_store_from_ex: STD_LOGIC;
signal funct_from_ex: STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0);
signal load_store_addr_from_ex: STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0);
signal store_data_from_ex: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
signal cp0_reg_we_from_ex : std_logic;
signal cp0_reg_write_addr_from_ex : std_logic_vector(REG_ADDR_LEN-1 downto 0);
signal cp0_reg_data_from_ex : std_logic_vector(REG_DATA_LEN-1 downto 0);
signal except_type_from_ex :std_logic_vector(EXCEPT_TYPE_LEN-1 downto 0);
signal current_inst_address_from_ex :std_logic_vector(INST_ADDR_LEN-1 downto 0);
signal is_in_delayslot_from_ex :std_logic;
-- EX to PAUSE_CTRL signals
signal ex_pause_from_ex: STD_LOGIC;
-- EX to CP0_REG signals
signal cp0_reg_read_addr_from_ex :std_logic_vector(REG_ADDR_LEN-1 downto 0);
-- EX/MEM to MEM signals
signal reg_wt_en_to_mem: STD_LOGIC;
signal reg_wt_addr_to_mem: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal reg_wt_data_to_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal is_load_store_to_mem: STD_LOGIC;
signal funct_to_mem: STD_LOGIC_VECTOR(FUNCT_LEN-1 downto 0);
signal load_store_addr_to_mem: STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0);
signal store_data_to_mem: STD_LOGIC_VECTOR(DATA_LEN-1 downto 0);
signal hilo_en_to_mem: STD_LOGIC;
signal hi_to_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal lo_to_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal mem_cp0_reg_we_to_mem : std_logic;
signal mem_cp0_reg_write_addr_to_mem: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal mem_cp0_reg_data_to_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal except_type_to_mem : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
signal current_inst_address_to_mem : STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
signal is_in_delayslot_to_mem : STD_LOGIC;
-- EX/MEM to EX signals
signal clock_cycle_cnt_to_ex: STD_LOGIC_VECTOR(ACCU_CNT_LEN-1 downto 0);
signal mul_cur_result_to_ex: STD_LOGIC_VECTOR(DOUBLE_DATA_LEN-1 downto 0);
-- MEM to MEM/WB signals
signal reg_wt_en_from_mem: STD_LOGIC;
signal reg_wt_addr_from_mem: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal reg_wt_data_from_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
-- MEM to MEM/WB and EX signals
signal hilo_en_from_mem: STD_LOGIC;
signal hi_from_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal lo_from_mem: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal cp0_reg_we_from_mem : STD_LOGIC;
signal cp0_reg_write_addr_from_mem : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal cp0_reg_data_from_mem : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
-- MEM to CP0_REG signals
signal except_type_from_mem : STD_LOGIC_VECTOR(EXCEPT_TYPE_LEN-1 downto 0);
signal current_inst_address_from_mem : STD_LOGIC_VECTOR(INST_ADDR_LEN-1 downto 0);
signal is_in_delayslot_from_mem : STD_LOGIC;
signal cp0_epc_from_mem : std_logic_vector(REG_DATA_LEN-1 downto 0);
signal flush_from_pause : std_logic;
signal new_pc_from_pause : std_logic_vector(INST_LEN-1 downto 0);
-- MEM/WB to REGISTER signals
signal reg_wt_en_to_register: STD_LOGIC;
signal reg_wt_addr_to_register: STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal reg_wt_data_to_register: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
-- MEM/WB to HILO and EX signals
signal hilo_en_to_hilo: STD_LOGIC;
signal hi_to_hilo: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal lo_to_hilo: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal wb_cp0_reg_we_from_wb : STD_LOGIC;
signal wb_cp0_reg_write_addr_from_wb : STD_LOGIC_VECTOR(REG_ADDR_LEN-1 downto 0);
signal wb_cp0_reg_data_from_wb: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
--cp0 to ex
signal data_from_cp0: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
--cp0 to ?
signal count_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal compare_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal status_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal cause_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal epc_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal config_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal prid_from_cp0 : STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal timer_int_from_cp0 : STD_LOGIC;
-- for cp0
signal int_for_cp0 : STD_LOGIC_VECTOR(5 downto 0);
-- REGISTER to ID signals
signal reg_rd_data_1_from_register: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal reg_rd_data_2_from_register: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
-- HILO to EX signals
signal hi_from_hilo: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
signal lo_from_hilo: STD_LOGIC_VECTOR(REG_DATA_LEN-1 downto 0);
-- PAUSE_CTRL to PC, IF/ID, ID/EX, EX/MEM, MEM/WB signal
signal pause: STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0);
signal new_pc_en_from_pause: std_logic;
signal data_from_ram: STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
signal en_from_mem: STD_LOGIC;
signal is_read_from_mem: STD_LOGIC;
signal addr_from_mem: STD_LOGIC_VECTOR(ADDR_LEN - 1 downto 0);
signal data_from_mem: STD_LOGIC_VECTOR(DATA_LEN - 1 downto 0);
signal sel_from_mem: STD_LOGIC_VECTOR(BYTE_IN_DATA - 1 downto 0);
begin
PC_0 : PC port map(
-- 输入信号
rst => rst, -- => MIPS_CPU.rst
clk => clk, -- => MIPS_CPU.clk
pause_i => pause_from_pausectrl, -- => PAUSE_CTRL.pause_o
branch_i => branch_from_id, -- => ID.branch_o
branch_target_addr_i => branch_target_addr_from_id, -- => ID.branch_target_addr_o
-- 输出信号
en_o => read_inst_en_from_pc, -- => MMU.read_inst_en_i
pc_o => pc_from_pc -- => MMU.pc_i, IF/ID.pc_i
);
IF_to_ID_0 : IF_to_ID port map(
-- 输入信号
rst => rst, -- => MIPS_CPU.rst
clk => clk, -- => MIPS_CPU.clk
pc_i => pc_from_pc, -- => PC.pc_o
inst_i => inst_from_mmu, -- => MMU.inst_o
pause_i => pause, -- => PAUSE_CTRL.pause_o
-- 输出信号
pc_o => pc_from_ifid, -- => ID.pc_i
inst_o => inst_from_ifid -- => ID.inst_i
);
ID_0 : ID port map(
-- 输入信号
rst => rst, -- => MIPS_CPU.rst
pc_i => pc_from_ifid, -- => IF/ID.pc_o
inst_i => inst_from_ifid, -- => IF/ID.inst_o
reg_rd_data_1_i => reg_rd_data_1_from_register, -- => REGISTER.reg_rd_addr_1_o
reg_rd_data_2_i => reg_rd_data_2_from_register, -- => REGISTER.reg_rd_addr_2_o
is_in_delayslot_i => next_inst_in_delayslot_from_idex, -- => ID/EX.next_inst_in_delayslot_o
last_is_load_store_i => is_load_store_from_ex, -- => EX.is_load_store_o
last_funct_i => funct_from_ex, -- => EX.funct_o
-- 输出信号
op_o => op_from_id, -- => ID/EX.op_i
funct_o => funct_from_id, -- => ID/EX.funct_i
inst_o => inst_from_id, -- => ID/EX.inst_i
reg_rd_en_1_o => reg_rd_en_1_from_id, -- => REGISTER.reg_rd_en_1_i
reg_rd_en_2_o => reg_rd_en_2_from_id, -- => REGISTER.reg_rd_en_2_i
reg_rd_addr_1_o => reg_rd_addr_1_from_id, -- => REGISTER.reg_rd_addr_1_i
reg_rd_addr_2_o => reg_rd_addr_2_from_id, -- => REGISTER.reg_rd_addr_2_i
operand_1_o => oprand_1_from_id, -- => ID/EX.operand_1_i
operand_2_o => oprand_2_from_id, -- => ID/EX.operand_2_i
extended_offset_o => extended_offset_from_id, -- => ID/EX.extended_offset_i
reg_wt_en_o => reg_wt_en_from_id, -- => ID/EX.reg_wt_en_i
reg_wt_addr_o => reg_wt_addr_from_id, -- => ID/EX.reg_wt_addr_i
pause_o => id_pause_from_id, -- => PAUSE_CTRL.id_pause_i
branch_o => branch_from_id, -- => PC.branch_i
branch_target_addr_o => branch_target_addr_from_id, -- => PC.branch_target_addr_i
is_in_delayslot_o => is_in_delayslot_from_id, -- => ID/EX.is_in_delayslot_i
next_inst_in_delayslot_o => next_inst_in_delayslot_from_id, -- => ID/EX.next_inst_in_delayslot_i
link_addr_o => link_addr_from_id, -- => ID/EX.link_addr_i
except_type_o => except_type_from_id, -- => ID/EX.except_type_i
pc_o => pc_from_id -- => ID/EX.pc_i
);
ID_to_EX_0 : ID_to_EX port map(
rst => input_rst, clk => clk_out,
op_i => op_from_id, funct_i => funct_from_id,
operand_1_i => oprand_1_from_id, operand_2_i => oprand_2_from_id,
extended_offset_i => extended_offset_from_id,
reg_wt_en_i => reg_wt_en_from_id, reg_wt_addr_i => reg_wt_addr_from_id,
pause_i => pause,
is_in_delayslot_i => is_in_delayslot_from_id, next_inst_in_delayslot_i => next_inst_in_delayslot_from_id,
link_addr_i => link_addr_from_id,
inst_i => inst_from_id,
op_o => op_to_ex, funct_o => funct_to_ex,
operand_1_o => oprand_1_to_ex, operand_2_o => oprand_2_to_ex,
extended_offset_o => extended_offset_to_ex,
reg_wt_en_o => reg_wt_en_to_ex, reg_wt_addr_o => reg_wt_addr_to_ex,
is_in_delayslot_o => is_in_delayslot_to_ex, next_inst_in_delayslot_o => next_inst_in_delayslot_to_id, link_addr_o => link_addr_to_ex,
inst_o => inst_to_ex,
except_type_i => except_type_from_id,
current_inst_address_i => current_inst_address_from_id,
except_type_o => except_type_to_ex,
current_inst_address_o => current_inst_address_to_ex,
flush_i => flush_from_pause
);
EX_0 : EX port map(
rst => input_rst,
op_i => op_to_ex, funct_i => funct_to_ex,
operand_1_i => oprand_1_to_ex, operand_2_i => oprand_2_to_ex,
extended_offset_i => extended_offset_to_ex,
reg_wt_en_i => reg_wt_en_to_ex, reg_wt_addr_i => reg_wt_addr_to_ex,
hi_i => hi_from_hilo, lo_i => lo_from_hilo,
mem_hilo_en_i => hilo_en_from_mem, mem_hi_i => hi_from_mem, mem_lo_i => lo_from_mem,
wb_hilo_en_i => hilo_en_to_hilo, wb_hi_i => hi_to_hilo, wb_lo_i => lo_to_hilo,
clock_cycle_cnt_i => clock_cycle_cnt_to_ex, mul_cur_result_i => mul_cur_result_to_ex,
is_in_delayslot_i => is_in_delayslot_to_ex, link_addr_i => link_addr_to_ex,
reg_wt_en_o => reg_wt_en_from_ex, reg_wt_addr_o => reg_wt_addr_from_ex, reg_wt_data_o => reg_wt_data_from_ex,
is_load_store_o => is_load_store_from_ex, funct_o => funct_from_ex,
load_store_addr_o => load_store_addr_from_ex, store_data_o => store_data_from_ex,
hilo_en_o => hilo_en_from_ex, hi_o => hi_from_ex, lo_o => lo_from_ex,
pause_o => ex_pause_from_ex,
clock_cycle_cnt_o => clock_cycle_cnt_from_ex, mul_cur_result_o => mul_cur_result_from_ex,
inst_i => inst_to_ex,
cp0_reg_data_i => data_from_cp0,
--璁垮瓨闃舵鎸囦护鏄惁瑕佸啓cp0涓殑�?�勫瓨鍣紝鐢ㄤ簬锟��?????娴嬫暟鎹浉锟�???
mem_cp0_reg_we_i => cp0_reg_we_from_mem,
mem_cp0_reg_write_addr_i => cp0_reg_write_addr_from_mem,
mem_cp0_reg_data_i => cp0_reg_data_from_mem,
--鍥炲啓闃舵鎸囦护鏄惁瑕佸啓cp0涓殑�?�勫瓨鍣紝鐢ㄤ簬锟��?????娴嬫暟鎹浉锟�???
wb_cp0_reg_we_i => wb_cp0_reg_we_from_wb,
wb_cp0_reg_write_addr_i => wb_cp0_reg_write_addr_from_wb,
wb_cp0_reg_data_i => wb_cp0_reg_data_from_wb,
cp0_reg_read_addr_o => cp0_reg_read_addr_from_ex,
cp0_reg_we_o => cp0_reg_we_from_ex,
cp0_reg_data_o => cp0_reg_data_from_ex,
cp0_reg_write_addr_o => cp0_reg_write_addr_from_ex,
except_type_i => except_type_to_ex,
current_inst_address_i => current_inst_address_to_ex,
except_type_o => except_type_from_ex,
current_inst_address_o => current_inst_address_from_ex,
is_in_delayslot_o => is_in_delayslot_from_ex
);
EX_to_MEM_0 : EX_to_MEM port map(
rst => input_rst, clk => clk_out,
reg_wt_en_i => reg_wt_en_from_ex, reg_wt_addr_i => reg_wt_addr_from_ex, reg_wt_data_i => reg_wt_data_from_ex,
is_load_store_i => is_load_store_from_ex, funct_i => funct_from_ex,
load_store_addr_i => load_store_addr_from_ex, store_data_i => store_data_from_ex,
hilo_en_i => hilo_en_from_ex, hi_i => hi_from_ex, lo_i => lo_from_ex,
pause_i => pause,
clock_cycle_cnt_i => clock_cycle_cnt_from_ex, mul_cur_result_i => mul_cur_result_from_ex,
reg_wt_en_o => reg_wt_en_to_mem, reg_wt_addr_o => reg_wt_addr_to_mem, reg_wt_data_o => reg_wt_data_to_mem,
is_load_store_o => is_load_store_to_mem, funct_o => funct_to_mem,
load_store_addr_o => load_store_addr_to_mem, store_data_o => store_data_to_mem,
hilo_en_o => hilo_en_to_mem, hi_o => hi_to_mem, lo_o => lo_to_mem,
ex_cp0_reg_we_i => cp0_reg_we_from_ex,
ex_cp0_reg_write_addr_i => cp0_reg_write_addr_from_ex,
ex_cp0_reg_data_i => cp0_reg_data_from_ex,
mem_cp0_reg_we_o => mem_cp0_reg_we_to_mem,
mem_cp0_reg_write_addr_o => mem_cp0_reg_write_addr_to_mem,
mem_cp0_reg_data_o => mem_cp0_reg_data_to_mem,
except_type_i => except_type_from_ex,
current_inst_address_i => current_inst_address_from_ex,
is_in_delayslot_i => is_in_delayslot_from_ex,
except_type_o => except_type_to_mem,
current_inst_address_o => current_inst_address_to_mem,
is_in_delayslot_o => is_in_delayslot_to_mem,
flush_i => flush_from_pause
);
MEM_0 : MEM port map(
rst => input_rst,
reg_wt_en_i => reg_wt_en_to_mem, reg_wt_addr_i => reg_wt_addr_to_mem, reg_wt_data_i => reg_wt_data_to_mem,
ram_rd_data_i => mem_data_from_mem_controll,
is_load_store_i => is_load_store_to_mem, funct_i => funct_to_mem,
load_store_addr_i => load_store_addr_to_mem, store_data_i => store_data_to_mem,
hilo_en_i => hilo_en_to_mem, hi_i => hi_to_mem, lo_i => lo_to_mem,
reg_wt_en_o => reg_wt_en_from_mem, reg_wt_addr_o => reg_wt_addr_from_mem, reg_wt_data_o => reg_wt_data_from_mem,
hilo_en_o => hilo_en_from_mem, hi_o => hi_from_mem, lo_o => lo_from_mem,
ram_en_o => en_from_mem,
ram_is_read_o => is_read_from_mem,
ram_addr_o => addr_from_mem,
ram_data_o => data_from_mem,
ram_data_sel_o => sel_from_mem,
cp0_reg_we_i => mem_cp0_reg_we_to_mem,
cp0_reg_write_addr_i => mem_cp0_reg_write_addr_to_mem,
cp0_reg_data_i => mem_cp0_reg_data_to_mem,
cp0_reg_we_o => cp0_reg_we_from_mem,
cp0_reg_write_addr_o => cp0_reg_write_addr_from_mem,
cp0_reg_data_o => cp0_reg_data_from_mem,
except_type_i => except_type_to_mem,
current_inst_address_i => current_inst_address_to_mem,
is_in_delayslot_i => is_in_delayslot_to_mem,
status_i => status_from_cp0,
epc_i => epc_from_cp0,
cause_i => cause_from_cp0,
wb_cp0_reg_we_i => wb_cp0_reg_we_from_wb,
wb_cp0_reg_write_addr_i => wb_cp0_reg_write_addr_from_wb,
wb_cp0_reg_data_i => wb_cp0_reg_data_from_wb,
except_type_o => except_type_from_mem,
current_inst_address_o => current_inst_address_from_mem,
is_in_delayslot_o => is_in_delayslot_from_mem,
cp0_epc_o => cp0_epc_from_mem
);
MEM_to_WB_0 : MEM_to_WB port map(
rst => input_rst, clk => clk_out,
reg_wt_en_i => reg_wt_en_from_mem, reg_wt_addr_i => reg_wt_addr_from_mem, reg_wt_data_i => reg_wt_data_from_mem,
hilo_en_i => hilo_en_from_mem, hi_i => hi_from_mem, lo_i => lo_from_mem,
pause_i => pause,
reg_wt_en_o => reg_wt_en_to_register, reg_wt_addr_o => reg_wt_addr_to_register, reg_wt_data_o => reg_wt_data_to_register,
hilo_en_o => hilo_en_to_hilo, hi_o => hi_to_hilo, lo_o => lo_to_hilo,
mem_cp0_reg_we_i => cp0_reg_we_from_mem,
mem_cp0_reg_write_addr_i => cp0_reg_write_addr_from_mem,
mem_cp0_reg_data_i => cp0_reg_data_from_mem,
wb_cp0_reg_we_o => wb_cp0_reg_we_from_wb,
wb_cp0_reg_write_addr_o => wb_cp0_reg_write_addr_from_wb,
wb_cp0_reg_data_o => wb_cp0_reg_data_from_wb, flush_i => flush_from_pause);
-- No serial
int_for_cp0(5 downto 1) <= b"00000";
int_for_cp0(0) <= timer_int_from_cp0;
CP0_REG_0 : CP0_REG port map(
rst => input_rst, clk => clk_out,
raddr_i => cp0_reg_read_addr_from_ex,
waddr_i => wb_cp0_reg_write_addr_from_wb,
data_i => wb_cp0_reg_data_from_wb,
we_i => wb_cp0_reg_we_from_wb,
int_i => int_for_cp0,
data_o => data_from_cp0,
count_o => count_from_cp0,
compare_o => compare_from_cp0,
status_o => status_from_cp0,
cause_o => cause_from_cp0,
epc_o => epc_from_cp0,
config_o => config_from_cp0,
prid_o => prid_from_cp0,
timer_int_o => timer_int_from_cp0,
except_type_i => except_type_from_mem,
current_inst_address_i => current_inst_address_from_mem,
is_in_delayslot_i => is_in_delayslot_from_mem
);
REGISTERS_0 : REGISTERS port map(
rst => input_rst, clk => clk_out,
reg_rd_en_1_i => reg_rd_en_1_to_register, reg_rd_en_2_i => reg_rd_en_2_to_register,
reg_rd_addr_1_i => reg_rd_addr_1_to_register, reg_rd_addr_2_i => reg_rd_addr_2_to_register,
reg_wt_en_i => reg_wt_en_to_register, reg_wt_addr_i => reg_wt_addr_to_register, reg_wt_data_i => reg_wt_data_to_register,
reg_rd_data_1_o => reg_rd_data_1_from_register, reg_rd_data_2_o => reg_rd_data_2_from_register);
HI_LO_0 : HI_LO port map (
rst => input_rst, clk => clk_out,
en => hilo_en_to_hilo, hi_i => hi_to_hilo, lo_i => lo_to_hilo,
hi_o => hi_from_hilo, lo_o => lo_from_hilo);
PAUSE_CTRL_0 : PAUSE_CTRL port map (
rst => input_rst,
id_pause_i => id_pause_from_id, ex_pause_i => ex_pause_from_ex,
if_pause_i => inst_pause_from_mem_controll,
mem_pause_i => mem_pause_from_mem_controll,
pause_o => pause,
cp0_epc_i => cp0_epc_from_mem,
except_type_i => except_type_from_mem,
new_pc_o => new_pc_from_pause,
flush_o => flush_from_pause,
new_pc_en_o => new_pc_en_from_pause);
MEM_CONTROLL_0 : MEM_CONTROLL port map (
rst => input_rst,
clk => clk_out,
inst_ce_i => read_inst_en_from_pc,
inst_addr_i => pc_from_pc,
mem_ce_i => en_from_mem,
mem_is_read_i => is_read_from_mem,
mem_sel_i => sel_from_mem,
mem_addr_i => addr_from_mem,
mem_data_i => data_from_mem,
ack_i => ack_from_mmu,
data_i => data_from_mmu,
inst_data_o => inst_from_mem_controll,
mem_data_o => mem_data_from_mem_controll,
inst_pause_o => inst_pause_from_mem_controll,
mem_pause_o => mem_pause_from_mem_controll,
ce_o => ce_from_mem_controll,
we_o => we_from_mem_controll,
sel_o => sel_from_mem_controll,
addr_o => addr_from_mem_controll,
data_o => data_from_mem_controll);
MMU_0 : MMU port map(
rst => input_rst,
ce_i => ce_from_mem_controll,
we_i => we_from_mem_controll,
sel_i => sel_from_mem_controll,
addr_i => addr_from_mem_controll,
data_i => data_from_mem_controll,
ram1_data_i => data_from_ram1,
ram1_ack_i => ack_from_ram1,
ram1_ce_o => ce_to_ram1,
ram1_we_o => we_to_ram1,
ram1_data_o => data_to_ram1,
ram1_addr_o => addr_to_ram1,
ram1_sel_o => sel_to_ram1,
ram2_data_i => data_from_ram2,
ram2_ack_i => ack_from_ram2,
ram2_ce_o => ce_to_ram2,
ram2_we_o => we_to_ram2,
ram2_data_o => data_to_ram2,
ram2_addr_o => addr_to_ram2,
ram2_sel_o => sel_to_ram2,
serial_data_i => data_from_serial,
serial_ack_i => ack_from_serial,
serial_ce_o => ce_to_serial,
serial_we_o => we_to_serial,
serial_data_o => data_to_serial,
leds_o => leds_to_leds,
num_o => num_to_leds,
ack_o => ack_from_mmu,
data_o => data_from_mmu);
BASE_SRAM_CONTROLL : SRAM_CONTROLL port map(
clk => clk_out, rst => input_rst,
ce_i => ce_to_ram1,
we_i => we_to_ram1,
addr_i => addr_to_ram1,
data_i => data_to_ram1,
sel_i => sel_to_ram1,
data_o => data_from_ram1,
ack_o => ack_from_ram1,
ram_ce_n_o => ram1_ce_n_o,
ram_oe_n_o => ram1_oe_n_o,
ram_we_n_o => ram1_we_n_o,
ram_be_n_o => ram1_be_n_o,
ram_addr_o => ram1_addr_o,
ram_data => ram1_data);
EXTEND_RAM_CONTROLL : SRAM_CONTROLL port map(
clk => clk_out, rst => input_rst,
ce_i => ce_to_ram2,
we_i => we_to_ram2,
addr_i => addr_to_ram2,
data_i => data_to_ram2,
sel_i => sel_to_ram2,
data_o => data_from_ram2,
ack_o => ack_from_ram2,
ram_ce_n_o => ram2_ce_n_o,
ram_oe_n_o => ram2_oe_n_o,
ram_we_n_o => ram2_we_n_o,
ram_be_n_o => ram2_be_n_o,
ram_addr_o => ram2_addr_o,
ram_data => ram2_data);
SERIAL_CONTROLL_0 : SERIAL_CONTROLL port map (
clk => clk_out,
clk_uart => clk_uart,
rst => input_rst,
ce_i => ce_to_serial,
we_i => we_to_serial,
data_from_mmu_i => data_to_serial,
RxD_data_ready => RxD_data_ready,
RxD_data => RxD_data,
RxD_idle => RxD_idle,
TxD_start => TxD_start,
TxD_data => TxD_data,
data_from_serial_o => data_from_serial,
ack_o => ack_from_serial);
SERIAL_RECEIVER : ASYNC_RECEIVER
generic map (
ClkFrequency => 11059200,
Baud => 115200)
port map (
clk => clk_uart,
RxD => rxd,
RxD_data_ready => RxD_data_ready,
RxD_data => RxD_data,
RxD_idle => RxD_idle);
SERIAL_TRANSMITTER : ASYNC_TRANSMITTER
generic map (
ClkFrequency => 11059200,
Baud => 115200)
port map (
clk => clk_uart,
TxD => txd,
TxD_start => TxD_start,
TxD_data => TxD_data);
-- leds(7 downto 0) <= addr_from_mem_controll(7 downto 0);
-- leds(15) <= ce_from_mem_controll;
--leds(14 downto 11) <= sel_from_mem_controll;
-- leds(10 downto 9) <= state_from_mem_controll;
-- leds(7 downto 0) <= reg_wt_data_from_ex(7 downto 0);
-- leds(15 downto 8) <= reg_rd_data_1_from_register(7 downto 0);
-- leds(7 downto 4) <= reg_wt_addr_from_ex(3 downto 0);
-- leds(3 downto 0) <= reg_rd_addr_1_to_register(3 downto 0);
-- leds(31) <= branch_from_id;
--leds(7 downto 0) <= reg_wt_data_to_register(7 downto 0);
--leds(31) <= en_from_mem;
number(7 downto 0) <= num_to_leds(7 downto 0);
leds(7 downto 0) <= num_to_leds(31 downto 24);
segL : SEG7_LUT port map(
oSEG1 => osegl,
iDIG => number(3 downto 0));
segH : SEG7_LUT port map(
oSEG1 => osegh,
iDIG => number(7 downto 4));
leds(23 downto 22) <= osegl(7 downto 6);
leds(19 downto 17) <= osegl(5 downto 3);
leds(20) <= osegl(2);
leds(21) <= osegl(1);
leds(16) <= osegl(0);
leds(31 downto 30) <= osegh(7 downto 6);
leds(27 downto 25) <= osegh(5 downto 3);
leds(28) <= osegh(2);
leds(29) <= osegh(1);
leds(24) <= osegh(0);
end Behavioral;
/**
IF模块
Encoding: UTF-8
**/
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use WORK.INCLUDE.ALL;
entity PC is
Port ( rst: in STD_LOGIC; -- Reset
clk: in STD_LOGIC; -- Clock
pause_i : in STD_LOGIC_VECTOR(CTRL_PAUSE_LEN-1 downto 0); -- input pause info from PAUSE_CTRL
branch_i: in STD_LOGIC; -- input 是否跳转 from ID
branch_target_addr_i: in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0); -- input 跳转目的地址 from ID
new_pc_i : in STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0);
new_pc_en_i: in STD_LOGIC;
en_o: out STD_LOGIC; -- output RAM读指令使能 to MMU
pc_o: out STD_LOGIC_VECTOR(ADDR_LEN-1 downto 0)); -- output RAM读指令地址 to MMU
end PC;
architecture Behavioral of PC is
begin
process (clk)
variable is_start: STD_LOGIC;
begin
if rising_edge(clk) then
if rst = RST_ENABLE then
en_o <= CHIP_DISABLE;
pc_o <= x"00000000";
is_start := '1';
else
en_o <= CHIP_ENABLE;
if pause_i(PC_PAUSE_INDEX) = PAUSE_NOT then
if branch_i = BRANCH then
pc_o <= branch_target_addr_i;
elsif new_pc_en_i = '1' then
pc_o <= new_pc_i;
else
if is_start = '0' then
pc_o <= pc_o + x"00000004"; -- IEEE.STD_LOGIC_SIGNED library
else
pc_o <= x"80000000";
is_start := '0';
end if;
end if;
end if;
-- 暂停时输出不变
end if;
end if;
end process;
end Behavioral;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment