- added instructions 'lwc0' and 'swc0' for testing (which are usually invalid)

- due to cop_reg_we in MEM_Stage, the output register is removed
  (timing is slightly degraded). The reg pointer is delayed instead by one cycle
- test-reg is now writable in user mode regardles of cop0 usability.
Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@406 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2009-03-18 23:30:08 +00:00
parent 2dfce691ce
commit 52e9decf78
+39 -34
View File
@@ -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;