diff --git a/lib/CPUs/MIPS/src/core/mips_pipeline.vhd b/lib/CPUs/MIPS/src/core/mips_pipeline.vhd index 6b06f11..1138de4 100644 --- a/lib/CPUs/MIPS/src/core/mips_pipeline.vhd +++ b/lib/CPUs/MIPS/src/core/mips_pipeline.vhd @@ -34,7 +34,6 @@ entity pipeline is rst : in STD_LOGIC; clk : in STD_LOGIC; ce : in STD_LOGIC; - int : in unsigned(5 downto 0); imem_err : in STD_LOGIC; imem_rdy : in STD_LOGIC; imem_en : out STD_LOGIC; @@ -171,6 +170,8 @@ architecture Behavioral of pipeline is signal bcu_flags : bcu_flags_t; signal vaddr : word_t; signal dmem_src : word_t; + signal stage_rst : unsigned(3 downto 0); + signal pipe_rst : STD_LOGIC; attribute ram_style : string; @@ -187,13 +188,13 @@ begin cpu_run <= ce; -- Stall Detection Unit --------------------------------------------------- - sdu.ID_nop <= sdu.imem_dep or c0_ctrl_in.exc_pending or EX_stage.exc or MEM_stage.exc; + sdu.ID_nop <= sdu.imem_dep or c0_ctrl_in.exc_pending or ID_stage.exc or EX_stage.exc or MEM_stage.exc; sdu.EX_nop <= sdu.mul_dep or ID_stage.nop or ID_stage.exc; sdu.MEM_nop <= EX_stage.nop or EX_stage.exc; sdu.WB_nop <= sdu.dmem_dep or MEM_stage.nop; sdu.stall_all <= sdu.dmem_dep; - sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or ID_stage.exc; + sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or c0_ctrl_in.exc_exit; sdu.EX_stall <= sdu.stall_all; sdu.MEM_stall <= sdu.stall_all; sdu.WB_stall <= '0'; @@ -210,10 +211,12 @@ begin c0_ctrl_out.bd_wb <= WB_stage.bd; c0_ctrl_out.epc_mem <= MEM_stage.pcn; c0_ctrl_out.epc_wb <= MEM_stage.epc; - c0_ctrl_out.imem_addr <= pc.nxt; + c0_ctrl_out.imem_addr <= EX_stage.epc; c0_ctrl_out.dmem_addr <= MEM_stage.va; c0_ctrl_out.sdu <= sdu; - c0_ctrl_out.events <= MEM_stage.events; + c0_ctrl_out.events <= WB_stage.events; + c0_ctrl_out.exc_req <= MEM_stage.exc; + c0_ctrl_out.exc_ack <= WB_stage.exc; cop_ir <= ID_stage.IR; cop_ir_en <= ID_stage.ctrl.cop_instr_en; cop_dout <= MEM_stage.data; @@ -242,10 +245,24 @@ inst_muldiv: muldiv -------------------------------------------------------------------------- imem_addr <= pc.curr; + pipe_rst <= stage_rst(0); + +proc_stage_reset: + process(clk_1) + begin + if rising_edge(clk_1) then + if rst = '1' then + stage_rst <= (others => '1'); + else + stage_rst <= stage_rst(stage_rst'left-1 downto 0) & '0'; + end if; + end if; + end process; + proc_stage_pc: process(pc, c0_ctrl_in) begin - if pc.is_branch and c0_ctrl_in.exc_pending = '0' then + if pc.is_branch then pc.curr <= pc.pc_branch after 2 ns; else pc.curr <= pc.nxt after 2 ns; @@ -266,17 +283,15 @@ proc_stage_pc_next: process(clk_1) begin if rising_edge(clk_1) then - c0_ctrl_out.exc_left <= '0'; - if rst = '1' then + if pipe_rst = '1' then pc.nxt <= RESET_VECTOR; pc.last <= RESET_VECTOR; branch_ce <= '1'; else - branch_ce <= '0'; - if c0_ctrl_in.exc_commit = '1' then + branch_ce <= c0_ctrl_in.exc_pending; + if c0_ctrl_in.exc_inject = '1' then pc.nxt <= c0_ctrl_in.exc_vec; elsif sdu.ID_stall = '0' then - c0_ctrl_out.exc_left <= c0_ctrl_in.exc_exit; branch_ce <= '1'; pc.last <= pc.curr; if ID_stage.ctrl.jump = '1' then @@ -342,8 +357,8 @@ proc_ID_except: process(ID_stage, c0_ctrl_in, pc) begin ID_stage.events <= events_clr; - ID_stage.events.inst_load_err <= pc.nxt(1) or pc.nxt(0); - ID_stage.events.inst_priv_addr <= pc.nxt(word_t'left) and c0_ctrl_in.user_mode; + ID_stage.events.inst_load_err <= not c0_ctrl_in.exc_pending and (pc.nxt(1) or pc.nxt(0)); + ID_stage.events.inst_priv_addr <= not c0_ctrl_in.exc_pending and (pc.nxt(word_t'left) and c0_ctrl_in.user_mode); end process; proc_stage_hdu: @@ -459,7 +474,7 @@ proc_stage_ID_EX_1: process(clk_1) begin if rising_edge(clk_1) then - if rst = '1' then + if stage_rst(1) = '1' then EX_stage.op <= NOP; EX_stage.IR <= (others => '0'); EX_stage.ctrl <= ctrl_lines_default; @@ -477,13 +492,12 @@ proc_stage_ID_EX_1: EX_stage.nop <= sdu.EX_nop; EX_stage.IR <= ID_stage.IR; EX_stage.pcn <= ID_stage.pcn; + EX_stage.epc <= ID_stage.epc; if sdu.EX_nop = '1' then EX_stage.op <= NOP; EX_stage.IR <= (others => '0'); EX_stage.ctrl <= ctrl_lines_default; EX_stage.reg_write <= '0'; - else - EX_stage.epc <= ID_stage.epc; end if; end if; end if; @@ -518,7 +532,7 @@ proc_stage_EX_mem_except: process(clk_1) begin if rising_edge(clk_1) then - if rst = '1' then + if pipe_rst = '1' then dmem_en <= '0'; elsif sdu.EX_stall = '0' then EX_events_mem <= events_clr; @@ -715,7 +729,7 @@ proc_stage_MEM_n: process(clk_1) begin if rising_edge(clk_1) then - if rst = '1' then + if stage_rst(2) = '1' then MEM_stage.op <= NOP; MEM_stage.wreg_we <= '0'; MEM_stage.ctrl <= ctrl_lines_default; @@ -726,7 +740,9 @@ proc_stage_MEM_n: MEM_stage.op <= EX_stage.op; MEM_stage.wreg_we <= EX_stage.wreg_we; MEM_stage.ctrl <= EX_stage.ctrl; - MEM_stage.va <= EX_stage.va; + if EX_stage.ctrl.dmem_en = '1' then + MEM_stage.va <= EX_stage.va; + end if; MEM_stage.pa_off <= EX_stage.pa_off; MEM_stage.reg_wptr <= EX_stage.reg_wptr; MEM_stage.nop <= sdu.MEM_nop; @@ -760,7 +776,7 @@ proc_stage_MEM_mux: data := MEM_stage.ex_result; be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp); if MEM_stage.ctrl.reg_link = '1' then - data := MEM_stage.pcn + 4; + data := MEM_stage.epc + 8; elsif MEM_stage.ctrl.dmem_en = '1' then temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp); temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en); @@ -782,13 +798,13 @@ proc_stage_MEM_mux: end process; proc_stage_MEM_except: - process(MEM_stage, int) + process(MEM_stage, c0_ctrl_in) begin MEM_stage.events <= MEM_stage.events_in; - MEM_stage.events.Int <= int; + MEM_stage.events.Int <= c0_ctrl_in.int; end process; - MEM_stage.exc <= c0_ctrl_in.int or event_is_active(MEM_stage.events_in); + MEM_stage.exc <= event_is_active(MEM_stage.events); -------------------------------------------------------------------------- -- WB stage @@ -797,22 +813,29 @@ proc_stage_WB_p: process(clk_1) begin if rising_edge(clk_1) then - if rst = '1' then + if stage_rst(3) = '1' then WB_stage.op <= NOP; WB_stage.wreg_we <= '1'; WB_stage.reg_wptr <= (others => '0'); WB_stage.data <= (others => '0'); + WB_stage.events <= events_clr; elsif sdu.WB_stall = '0' then WB_stage.op <= MEM_stage.op; WB_stage.wreg_we <= MEM_stage.wreg_we; WB_stage.reg_wptr <= MEM_stage.reg_wptr; WB_stage.data <= MEM_stage.data; + WB_stage.exc <= '0'; + if sdu.stall_all = '0' then + WB_stage.exc <= MEM_stage.exc; + if MEM_stage.exc = '1' then + WB_stage.events <= MEM_stage.events; + end if; + end if; WB_stage.nop <= sdu.WB_nop; if sdu.WB_nop = '1' then WB_stage.op <= NOP; WB_stage.wreg_we <= '0'; else - WB_stage.epc <= MEM_stage.epc; WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works end if; end if;