- 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); signal dcache_info : unsigned(7 downto 0);
type cop_pipe_t is record type cop_pipe_t is record
opc : opcode_t;
reg_ptr : reg_ptr_t;
rs : reg_ptr_t; rs : reg_ptr_t;
rd : reg_ptr_t; rd : reg_ptr_t;
rt : reg_ptr_t;
func : func_t; func : func_t;
we : std_logic; we : std_logic;
re : 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); 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); 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.cs <= ir_en;
cop_pipe_ID.opc <= extract_opc(ir);
cop_pipe_ID.rs <= extract_rs(ir); cop_pipe_ID.rs <= extract_rs(ir);
cop_pipe_ID.rd <= extract_rd(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.func <= extract_func(ir);
cop_pipe_ID.re <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00000" 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.rs = "00100" 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; cop_EX_en <= exc_enable and not status_save;
ctrl_out.RE <= status(25); ctrl_out.RE <= status(25);
ctrl_out.user_mode <= status(1); ctrl_out.user_mode <= status(1);
ctrl_out.int <= eflags.Int; 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); im <= status(15 downto 8);
cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00"; 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.cs <= '0';
cop_pipe_EX.we <= '0'; cop_pipe_EX.we <= '0';
cop_pipe_EX.re <= '0'; cop_pipe_EX.re <= '0';
else elsif ctrl_in.sdu.stall_all = '0' then
if ctrl_in.sdu.stall_all = '0' then cop_pipe_EX <= cop_pipe_ID;
cop_pipe_EX <= cop_pipe_ID;
end if;
end if; end if;
end if; end if;
end process; end process;
cop_register_read: cop_register_read:
process(clk) process(cop_pipe_EX, BadVAddr, status, cause, epc, dcache_info, icache_info, test_reg)
variable reg : word_t; variable reg : word_t;
begin begin
if rising_edge(clk) and cop_pipe_ID.re = '1' and ctrl_in.sdu.stall_all = '0' then case cop_pipe_EX.reg_ptr is
case cop_pipe_ID.rd is when "01000" => -- BadVAddr
when "01000" => -- BadVAddr reg := BadVAddr;
reg := BadVAddr;
when "01100" => -- Status when "01100" => -- Status
reg := status; reg := status;
when "01101" => -- Cause when "01101" => -- Cause
reg := cause; reg := cause;
when "01110" => -- EPC (Exception Program Counter) when "01110" => -- EPC (Exception Program Counter)
reg := epc; reg := epc;
when "01111" => -- PRId (Processor Revision Register) when "01111" => -- PRId (Processor Revision Register)
reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8); reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8);
when "11111" => -- test_reg when "11111" => -- test_reg
reg := test_reg; reg := test_reg;
when others => when others =>
reg := (others => '-'); reg := (others => '-');
end case; end case;
dout <= reg after 1 ns; dout <= reg after 2 ns;
end if;
end process; end process;
cop_we_gen: cop_we_gen:
@@ -355,20 +358,20 @@ cop_we_gen:
test_reg_we <= '0'; test_reg_we <= '0';
stat_reg_we <= '0'; stat_reg_we <= '0';
ip_reg_we <= '0'; ip_reg_we <= '0';
else elsif ctrl_in.sdu.stall_all = '0' then
test_reg_we <= '0'; test_reg_we <= '0';
stat_reg_we <= '0'; stat_reg_we <= '0';
ip_reg_we <= '0'; ip_reg_we <= '0';
if (cop_EX_en and cop_pipe_EX.we) = '1' then 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" => when "01100" =>
stat_reg_we <= not status(1) or status(28); stat_reg_we <= not status(1) or status(28);
when "01101" => when "01101" =>
ip_reg_we <= not status(1) or status(28); ip_reg_we <= not status(1) or status(28);
when "11111" => when "11111" =>
test_reg_we <= not status(1) or status(28); test_reg_we <= '1'; -- not status(1) or status(28);
when others => null; when others => null;
end case; end case;
@@ -384,7 +387,7 @@ cop_test_reg_write:
if rising_edge(clk) then if rising_edge(clk) then
if rst = '1' then if rst = '1' then
test_reg <= (others => '0'); test_reg <= (others => '0');
else --if ce = '1' then elsif ctrl_in.sdu.WB_nop = '0' then
if test_reg_we = '1' then if test_reg_we = '1' then
test_reg <= din; test_reg <= din;
end if; end if;
@@ -406,9 +409,11 @@ cop_status_reg_write:
elsif status_rest = '1' then elsif status_rest = '1' then
status(1 downto 0) <= status(3 downto 2); status(1 downto 0) <= status(3 downto 2);
status(3 downto 2) <= status(5 downto 4); status(3 downto 2) <= status(5 downto 4);
elsif stat_reg_we = '1' then elsif ctrl_in.sdu.WB_nop = '0' then
status <= din; if stat_reg_we = '1' then
end if; status <= din;
end if;
end if;
end if; end if;
end if; end if;
end process; end process;