diff --git a/lib/CPUs/MIPS/src/core/mips_cop.vhd b/lib/CPUs/MIPS/src/core/mips_cop.vhd index 9952ab9..48c3878 100644 --- a/lib/CPUs/MIPS/src/core/mips_cop.vhd +++ b/lib/CPUs/MIPS/src/core/mips_cop.vhd @@ -77,8 +77,11 @@ architecture Behavioral of cop is signal dcache_info : unsigned(7 downto 0); type cop_pipe_t is record + opc : opcode_t; + reg_ptr : reg_ptr_t; rs : reg_ptr_t; rd : reg_ptr_t; + rt : reg_ptr_t; func : func_t; we : std_logic; re : std_logic; @@ -108,17 +111,21 @@ begin icache_info <= "00" & to_unsigned(lg2(icache_line), 3) & to_unsigned(lg2(icache_size)-8, 3); dcache_info <= "00" & to_unsigned(lg2(dcache_line), 3) & to_unsigned(lg2(dcache_size)-8, 3); cop_pipe_ID.cs <= ir_en; + cop_pipe_ID.opc <= extract_opc(ir); cop_pipe_ID.rs <= extract_rs(ir); cop_pipe_ID.rd <= extract_rd(ir); + cop_pipe_ID.rt <= extract_rt(ir); cop_pipe_ID.func <= extract_func(ir); - cop_pipe_ID.re <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00000" else '0'; - cop_pipe_ID.we <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00100" else '0'; + cop_pipe_ID.re <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "111000" or cop_pipe_ID.rs = "00000") else '0'; + cop_pipe_ID.we <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "110000" or cop_pipe_ID.rs = "00100") else '0'; cop_EX_en <= exc_enable and not status_save; ctrl_out.RE <= status(25); ctrl_out.user_mode <= status(1); ctrl_out.int <= eflags.Int; - + + cop_pipe_ID.reg_ptr <= cop_pipe_ID.rd when cop_pipe_ID.opc = "010000" else cop_pipe_ID.rt; + im <= status(15 downto 8); cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00"; @@ -307,44 +314,40 @@ cop_pipe: cop_pipe_EX.cs <= '0'; cop_pipe_EX.we <= '0'; cop_pipe_EX.re <= '0'; - else - if ctrl_in.sdu.stall_all = '0' then - cop_pipe_EX <= cop_pipe_ID; - end if; + elsif ctrl_in.sdu.stall_all = '0' then + cop_pipe_EX <= cop_pipe_ID; end if; end if; end process; cop_register_read: - process(clk) + process(cop_pipe_EX, BadVAddr, status, cause, epc, dcache_info, icache_info, test_reg) variable reg : word_t; begin - if rising_edge(clk) and cop_pipe_ID.re = '1' and ctrl_in.sdu.stall_all = '0' then - case cop_pipe_ID.rd is - when "01000" => -- BadVAddr - reg := BadVAddr; + case cop_pipe_EX.reg_ptr is + when "01000" => -- BadVAddr + reg := BadVAddr; - when "01100" => -- Status - reg := status; + when "01100" => -- Status + reg := status; - when "01101" => -- Cause - reg := cause; + when "01101" => -- Cause + reg := cause; - when "01110" => -- EPC (Exception Program Counter) - reg := epc; + when "01110" => -- EPC (Exception Program Counter) + reg := epc; - when "01111" => -- PRId (Processor Revision Register) - reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8); + when "01111" => -- PRId (Processor Revision Register) + reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8); - when "11111" => -- test_reg - reg := test_reg; + when "11111" => -- test_reg + reg := test_reg; - when others => - reg := (others => '-'); + when others => + reg := (others => '-'); - end case; - dout <= reg after 1 ns; - end if; + end case; + dout <= reg after 2 ns; end process; cop_we_gen: @@ -355,20 +358,20 @@ cop_we_gen: test_reg_we <= '0'; stat_reg_we <= '0'; ip_reg_we <= '0'; - else + elsif ctrl_in.sdu.stall_all = '0' then test_reg_we <= '0'; stat_reg_we <= '0'; ip_reg_we <= '0'; if (cop_EX_en and cop_pipe_EX.we) = '1' then - case cop_pipe_EX.rd is + case cop_pipe_EX.reg_ptr is when "01100" => stat_reg_we <= not status(1) or status(28); when "01101" => ip_reg_we <= not status(1) or status(28); when "11111" => - test_reg_we <= not status(1) or status(28); + test_reg_we <= '1'; -- not status(1) or status(28); when others => null; end case; @@ -384,7 +387,7 @@ cop_test_reg_write: if rising_edge(clk) then if rst = '1' then test_reg <= (others => '0'); - else --if ce = '1' then + elsif ctrl_in.sdu.WB_nop = '0' then if test_reg_we = '1' then test_reg <= din; end if; @@ -406,9 +409,11 @@ cop_status_reg_write: elsif status_rest = '1' then status(1 downto 0) <= status(3 downto 2); status(3 downto 2) <= status(5 downto 4); - elsif stat_reg_we = '1' then - status <= din; - end if; + elsif ctrl_in.sdu.WB_nop = '0' then + if stat_reg_we = '1' then + status <= din; + end if; + end if; end if; end if; end process;