Last active
February 3, 2018 04:04
-
-
Save zhanghuimeng/5e6db5ed9ef1abaf4316ac28476b28ec to your computer and use it in GitHub Desktop.
NewThinpadProject/simulation/srcs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
常数头文件 | |
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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