Line 47... |
Line 47... |
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- KNOWN TROUBLE:
|
-- KNOWN TROUBLE:
|
--
|
--
|
-- Apart from the very rough looks of the code, there's a few known problems:
|
-- Apart from the very rough looks of the code, there's a few known problems:
|
--
|
--
|
-- 1.- Access to unmapped areas wil crash the CPU
|
-- 1.- Write address setup and hold wrt. WE\ not guaranteed
|
|
-- WE\ needs to be asserted later and deasserted earlier. The easy way
|
|
-- would be using two extra cycles. Must find some less cosly way.
|
|
-- So far, in my particular test conditions, this is not giving me trouble
|
|
-- so this will have to wait.
|
|
--
|
|
-- 2.- Access to unmapped areas will crash the CPU
|
-- A couple states are missing in the state machine for handling accesses
|
-- A couple states are missing in the state machine for handling accesses
|
-- to unmapped areas. I haven't yet decided how to handle that (return
|
-- to unmapped areas. I haven't yet decided how to handle that (return
|
-- zero, trigger trap, mirror another mapped area...)
|
-- zero, trigger trap, mirror another mapped area...).
|
-- 2.- Code refills from SRAM is unimplemented yet
|
--
|
|
-- 3.- Code refills from SRAM is unimplemented yet
|
-- To be done for sheer lack of time.
|
-- To be done for sheer lack of time.
|
-- 3.- Address decoding is hardcoded in mips_pkg
|
--
|
-- It should be done here using module generics and not package constants.
|
|
-- 4.- Does not work as a real 1-word cache yet
|
-- 4.- Does not work as a real 1-word cache yet
|
-- That functionality is still missing, all accesses 'miss'. It should be
|
-- That functionality is still missing, all accesses 'miss'. It should be
|
-- implemented, as a way to test the real cache logic on a small scale.
|
-- implemented, as a way to test the real cache logic on a small scale.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
Line 121... |
Line 127... |
|
|
|
|
|
|
architecture stub of mips_cache_stub is
|
architecture stub of mips_cache_stub is
|
|
|
|
-- Wait state counter -- we're supporting static memory from 10 to >100 ns
|
|
subtype t_wait_state_counter is std_logic_vector(2 downto 0);
|
|
|
-- state machines: definition of states -----------------------------
|
-- state machines: definition of states -----------------------------
|
|
|
type t_code_cache_state is (
|
type t_code_cache_state is (
|
code_normal, --
|
code_normal, --
|
code_wait_for_dcache, -- wait for D-cache to stop using the buses
|
code_wait_for_dcache, -- wait for D-cache to stop using the buses
|
Line 140... |
Line 149... |
code_bug -- caught an error in the state machine
|
code_bug -- caught an error in the state machine
|
);
|
);
|
|
|
-- I-cache state machine state register & next state
|
-- I-cache state machine state register & next state
|
signal cps, cns : t_code_cache_state;
|
signal cps, cns : t_code_cache_state;
|
|
-- Wait state counter, formally part of the state machine register
|
|
signal code_wait_ctr : t_wait_state_counter;
|
|
|
|
|
type t_data_cache_state is (
|
type t_data_cache_state is (
|
data_normal,
|
data_normal,
|
|
|
Line 156... |
Line 167... |
data_read_io_0, -- rd addr on io_rd_addr, io_vma active
|
data_read_io_0, -- rd addr on io_rd_addr, io_vma active
|
data_read_io_1, -- rd data on io_rd_data
|
data_read_io_1, -- rd data on io_rd_data
|
|
|
data_write_io_0, -- wr addr & data in io_wr_*, io_byte_we active
|
data_write_io_0, -- wr addr & data in io_wr_*, io_byte_we active
|
|
|
data_writethrough_sram_0, -- wr addr & data in SRAM buses (low hword)
|
data_writethrough_sram_0a, -- wr addr & data in SRAM buses (low hword)
|
data_writethrough_sram_1, -- wr addr & data in SRAM buses (high hword)
|
data_writethrough_sram_0b, -- WE asserted
|
|
data_writethrough_sram_0c, -- WE deasserted
|
|
data_writethrough_sram_1a, -- wr addr & data in SRAM buses (high hword)
|
|
data_writethrough_sram_1b, -- WE asserted
|
|
data_writethrough_sram_1c, -- WE deasserted
|
|
|
data_ignore_write, -- hook for raising error flag FIXME untested
|
data_ignore_write, -- hook for raising error flag FIXME untested
|
|
data_ignore_read, -- hook for raising error flag FIXME untested
|
|
|
data_bug -- caught an error in the state machine
|
data_bug -- caught an error in the state machine
|
);
|
);
|
|
|
|
|
-- D-cache state machine state register & next state
|
-- D-cache state machine state register & next state
|
signal dps, dns : t_data_cache_state;
|
signal dps, dns : t_data_cache_state;
|
|
-- Wait state counter, formally part of the state machine register
|
|
signal dws_ctr, dws : t_wait_state_counter;
|
|
signal load_dws_ctr : std_logic;
|
|
signal dws_wait_done : std_logic;
|
|
|
|
|
|
|
-- CPU interface registers ------------------------------------------
|
-- CPU interface registers ------------------------------------------
|
signal data_rd_addr_reg : t_pc;
|
signal data_rd_addr_reg : t_pc;
|
signal data_wr_addr_reg : t_pc;
|
signal data_wr_addr_reg : t_pc;
|
signal code_rd_addr_reg : t_pc;
|
signal code_rd_addr_reg : t_pc;
|
Line 224... |
Line 246... |
signal code_rd_addr_mask : t_addr_decode;
|
signal code_rd_addr_mask : t_addr_decode;
|
signal data_rd_addr_mask : t_addr_decode;
|
signal data_rd_addr_mask : t_addr_decode;
|
signal data_wr_addr_mask : t_addr_decode;
|
signal data_wr_addr_mask : t_addr_decode;
|
|
|
-- Memory map area being accessed for each of the 3 buses:
|
-- Memory map area being accessed for each of the 3 buses:
|
-- 00 -> BRAM (read only)
|
|
-- 01 -> SRAM
|
|
-- 10 -> IO
|
|
-- 11 -> Unmapped
|
|
|
|
signal code_rd_attr : t_range_attr;
|
signal code_rd_attr : t_range_attr;
|
signal data_rd_attr : t_range_attr;
|
signal data_rd_attr : t_range_attr;
|
signal data_wr_attr : t_range_attr;
|
signal data_wr_attr : t_range_attr;
|
signal code_rd_type : t_memory_type;
|
|
signal data_rd_type : t_memory_type;
|
|
signal data_wr_type : t_memory_type;
|
|
|
|
|
|
|
|
begin
|
begin
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- Cache control state machines
|
-- Cache control state machines
|
Line 259... |
Line 271... |
end if;
|
end if;
|
end process cache_state_machine_regs;
|
end process cache_state_machine_regs;
|
|
|
-- (The code state machine occasionally 'waits' for the D-cache)
|
-- (The code state machine occasionally 'waits' for the D-cache)
|
code_state_machine_transitions:
|
code_state_machine_transitions:
|
process(cps, dps, code_rd_vma, code_miss, code_rd_type,
|
process(cps, dps, code_rd_vma, code_miss, code_rd_attr,
|
write_pending, read_pending)
|
write_pending, read_pending)
|
begin
|
begin
|
case cps is
|
case cps is
|
when code_normal =>
|
when code_normal =>
|
-- FIXME wrong logic, these signals are not active in the same cycle
|
-- FIXME wrong logic, these signals are not active in the same cycle
|
Line 310... |
Line 322... |
|
|
|
|
-- This state machine does not overlap IO/BRAM/SRAM accesses for simplicity.
|
-- This state machine does not overlap IO/BRAM/SRAM accesses for simplicity.
|
|
|
data_state_machine_transitions:
|
data_state_machine_transitions:
|
process(dps, write_pending, read_pending, data_rd_type, data_wr_type)
|
process(dps, write_pending, read_pending,
|
|
data_rd_attr, data_wr_attr, dws_wait_done)
|
begin
|
begin
|
case dps is
|
case dps is
|
when data_normal =>
|
when data_normal =>
|
if write_pending='1' then
|
if write_pending='1' then
|
case data_wr_type is
|
case data_wr_attr.mem_type is
|
when MT_BRAM => dns <= data_ignore_write;
|
when MT_BRAM => dns <= data_ignore_write;
|
when MT_SRAM_16B => dns <= data_writethrough_sram_0;
|
when MT_SRAM_16B => dns <= data_writethrough_sram_0a;
|
when MT_IO_SYNC => dns <= data_write_io_0;
|
when MT_IO_SYNC => dns <= data_write_io_0;
|
when others => dns <= dps; -- ignore write to undecoded area
|
-- FIXME ignore write to undecoded area (clear pending flag)
|
|
when others => dns <= dps;
|
end case;
|
end case;
|
|
|
elsif read_pending='1' then
|
elsif read_pending='1' then
|
case data_rd_type is
|
case data_rd_attr.mem_type is
|
when MT_BRAM => dns <= data_refill_bram_0;
|
when MT_BRAM => dns <= data_refill_bram_0;
|
when MT_SRAM_16B => dns <= data_refill_sram_0;
|
when MT_SRAM_16B => dns <= data_refill_sram_0;
|
when MT_IO_SYNC => dns <= data_read_io_0;
|
when MT_IO_SYNC => dns <= data_read_io_0;
|
when others => dns <= dps; -- ignore read from undec. area
|
-- FIXME ignore read from undecoded area (clear pending flag)
|
-- FIXME should raise debug flag
|
when others => dns <= data_ignore_read;
|
end case;
|
end case;
|
else
|
else
|
dns <= dps;
|
dns <= dps;
|
end if;
|
end if;
|
|
|
Line 344... |
Line 358... |
|
|
when data_read_io_1 =>
|
when data_read_io_1 =>
|
dns <= data_normal;
|
dns <= data_normal;
|
|
|
when data_refill_sram_0 =>
|
when data_refill_sram_0 =>
|
|
if dws_wait_done='1' then
|
dns <= data_refill_sram_1;
|
dns <= data_refill_sram_1;
|
|
else
|
|
dns <= dps;
|
|
end if;
|
|
|
when data_refill_sram_1 =>
|
when data_refill_sram_1 =>
|
|
if dws_wait_done='1' then
|
dns <= data_normal;
|
dns <= data_normal;
|
|
else
|
|
dns <= dps;
|
|
end if;
|
|
|
when data_refill_bram_0 =>
|
when data_refill_bram_0 =>
|
dns <= data_refill_bram_1;
|
dns <= data_refill_bram_1;
|
|
|
when data_refill_bram_1 =>
|
when data_refill_bram_1 =>
|
dns <= data_normal;
|
dns <= data_normal;
|
|
|
when data_writethrough_sram_0 =>
|
when data_writethrough_sram_0a =>
|
dns <= data_writethrough_sram_1;
|
dns <= data_writethrough_sram_0b;
|
|
|
when data_writethrough_sram_1 =>
|
when data_writethrough_sram_0b =>
|
|
if dws_wait_done='1' then
|
|
dns <= data_writethrough_sram_0c;
|
|
else
|
|
dns <= dps;
|
|
end if;
|
|
|
|
when data_writethrough_sram_0c =>
|
|
dns <= data_writethrough_sram_1a;
|
|
|
|
when data_writethrough_sram_1a =>
|
|
dns <= data_writethrough_sram_1b;
|
|
|
|
when data_writethrough_sram_1b =>
|
|
if dws_wait_done='1' then
|
|
dns <= data_writethrough_sram_1c;
|
|
else
|
|
dns <= dps;
|
|
end if;
|
|
|
|
when data_writethrough_sram_1c =>
|
dns <= data_normal;
|
dns <= data_normal;
|
|
|
|
|
when data_ignore_write =>
|
when data_ignore_write =>
|
dns <= data_normal;
|
dns <= data_normal;
|
|
|
|
when data_ignore_read =>
|
|
dns <= data_normal;
|
|
|
when data_bug =>
|
when data_bug =>
|
-- Something weird happened, we have 1 cycle to do something like raise
|
-- Something weird happened, we have 1 cycle to do something like raise
|
-- an error flag, etc. After 1 cycle, back to normal.
|
-- an error flag, etc. After 1 cycle, back to normal.
|
dns <= data_normal;
|
dns <= data_normal;
|
|
|
Line 375... |
Line 421... |
-- Should never arrive here. If we do, we handle it in state data_bug.
|
-- Should never arrive here. If we do, we handle it in state data_bug.
|
dns <= data_bug;
|
dns <= data_bug;
|
end case;
|
end case;
|
end process data_state_machine_transitions;
|
end process data_state_machine_transitions;
|
|
|
|
load_dws_ctr <= '1' when
|
|
(dns=data_refill_sram_0 and dps/=data_refill_sram_0) or
|
|
(dns=data_refill_sram_1 and dps/=data_refill_sram_1) or
|
|
(dns=data_writethrough_sram_0a) or
|
|
(dns=data_writethrough_sram_1a)
|
|
else '0';
|
|
|
|
with dns select dws <=
|
|
data_rd_attr.wait_states when data_refill_sram_0,
|
|
data_wr_attr.wait_states when data_writethrough_sram_0a,
|
|
data_wr_attr.wait_states when data_writethrough_sram_1a,
|
|
data_wr_attr.wait_states when others;
|
|
|
|
data_wait_state_counter:
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if reset='1' then
|
|
dws_ctr <= (others => '0');
|
|
else
|
|
if load_dws_ctr='1' then
|
|
dws_ctr <= dws;
|
|
elsif dws_wait_done='0' then
|
|
dws_ctr <= dws_ctr - 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process data_wait_state_counter;
|
|
|
|
dws_wait_done <= '1' when dws_ctr="000" else '0';
|
|
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- CPU interface registers and address decoding --------------------------------
|
-- CPU interface registers and address decoding --------------------------------
|
|
|
|
|
Line 400... |
Line 477... |
if data_rd_vma='1' then
|
if data_rd_vma='1' then
|
read_pending <= '1';
|
read_pending <= '1';
|
data_rd_addr_reg <= data_rd_addr(31 downto 2);
|
data_rd_addr_reg <= data_rd_addr(31 downto 2);
|
elsif dps=data_refill_sram_1 or
|
elsif dps=data_refill_sram_1 or
|
dps=data_refill_bram_1 or
|
dps=data_refill_bram_1 or
|
dps=data_read_io_0 then
|
dps=data_read_io_0 or
|
|
dps=data_ignore_read then
|
read_pending <= '0';
|
read_pending <= '0';
|
end if;
|
end if;
|
|
|
-- Raise 'write_pending' at the 1st cycle of a read, clear it when
|
-- Raise 'write_pending' at the 1st cycle of a read, clear it when
|
-- the write (writethrough actually) operation has been done.
|
-- the write (writethrough actually) operation has been done.
|
Line 412... |
Line 490... |
if byte_we/="0000" and dps=data_normal then
|
if byte_we/="0000" and dps=data_normal then
|
byte_we_reg <= byte_we;
|
byte_we_reg <= byte_we;
|
data_wr_reg <= data_wr;
|
data_wr_reg <= data_wr;
|
data_wr_addr_reg <= data_wr_addr;
|
data_wr_addr_reg <= data_wr_addr;
|
write_pending <= '1';
|
write_pending <= '1';
|
elsif dps=data_writethrough_sram_1 or
|
elsif dps=data_writethrough_sram_1b or
|
dps=data_write_io_0 or
|
dps=data_write_io_0 or
|
dps=data_ignore_write then
|
dps=data_ignore_write then
|
write_pending <= '0';
|
write_pending <= '0';
|
byte_we_reg <= "0000";
|
byte_we_reg <= "0000";
|
end if;
|
end if;
|
Line 449... |
Line 527... |
data_rd_addr_mask <= data_rd_addr_reg(31 downto t_addr_decode'low);
|
data_rd_addr_mask <= data_rd_addr_reg(31 downto t_addr_decode'low);
|
data_wr_addr_mask <= data_wr_addr_reg(31 downto t_addr_decode'low);
|
data_wr_addr_mask <= data_wr_addr_reg(31 downto t_addr_decode'low);
|
|
|
|
|
code_rd_attr <= decode_addr(code_rd_addr_mask);
|
code_rd_attr <= decode_addr(code_rd_addr_mask);
|
code_rd_type <= code_rd_attr(6 downto 4);
|
|
|
|
data_rd_attr <= decode_addr(data_rd_addr_mask);
|
data_rd_attr <= decode_addr(data_rd_addr_mask);
|
data_rd_type <= data_rd_attr(6 downto 4);
|
|
|
|
data_wr_attr <= decode_addr(data_wr_addr_mask);
|
data_wr_attr <= decode_addr(data_wr_addr_mask);
|
data_wr_type <= data_wr_attr(6 downto 4);
|
|
|
|
|
|
--with code_rd_addr_mask select code_rd_type <=
|
|
-- "000" when ADDR_BOOT,
|
|
-- "001" when ADDR_XRAM,
|
|
-- "011" when others;
|
|
--
|
|
--with data_rd_addr_mask select data_rd_type <=
|
|
-- "000" when ADDR_BOOT,
|
|
-- "001" when ADDR_XRAM,
|
|
-- "010" when ADDR_IO,
|
|
-- "011" when others;
|
|
--
|
|
--with data_wr_addr_mask select data_wr_type <=
|
|
-- "001" when ADDR_XRAM,
|
|
-- "010" when ADDR_IO,
|
|
-- "011" when others;
|
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- BRAM interface
|
-- BRAM interface
|
|
|
|
|
-- BRAMm address can come from code or data buses
|
-- BRAMm address can come from code or data buses
|
Line 585... |
Line 642... |
data_wr_addr_reg(sram_address'high downto 2) when others;
|
data_wr_addr_reg(sram_address'high downto 2) when others;
|
|
|
-- SRAM addr bus LSB depends on the D-cache state because we read/write the
|
-- SRAM addr bus LSB depends on the D-cache state because we read/write the
|
-- halfwords sequentially in successive cycles.
|
-- halfwords sequentially in successive cycles.
|
with dps select sram_address(1) <=
|
with dps select sram_address(1) <=
|
'0' when data_writethrough_sram_0,
|
'0' when data_writethrough_sram_0a,
|
'1' when data_writethrough_sram_1,
|
'0' when data_writethrough_sram_0b,
|
|
'0' when data_writethrough_sram_0c,
|
|
'1' when data_writethrough_sram_1a,
|
|
'1' when data_writethrough_sram_1b,
|
|
'1' when data_writethrough_sram_1c,
|
'0' when data_refill_sram_0,
|
'0' when data_refill_sram_0,
|
'1' when data_refill_sram_1,
|
'1' when data_refill_sram_1,
|
'0' when others;
|
'0' when others;
|
|
|
-- SRAM databus i(when used for output) comes from either hword of the data
|
-- SRAM databus i(when used for output) comes from either hword of the data
|
-- write register.
|
-- write register.
|
with dps select sram_databus <=
|
with dps select sram_databus <=
|
data_wr_reg(31 downto 16) when data_writethrough_sram_0,
|
data_wr_reg(31 downto 16) when data_writethrough_sram_0a,
|
data_wr_reg(15 downto 0) when data_writethrough_sram_1,
|
data_wr_reg(31 downto 16) when data_writethrough_sram_0b,
|
|
data_wr_reg(31 downto 16) when data_writethrough_sram_0c,
|
|
data_wr_reg(15 downto 0) when data_writethrough_sram_1a,
|
|
data_wr_reg(15 downto 0) when data_writethrough_sram_1b,
|
|
data_wr_reg(15 downto 0) when data_writethrough_sram_1c,
|
(others => 'Z') when others;
|
(others => 'Z') when others;
|
|
|
-- The byte_we is split in two similarly.
|
-- The byte_we is split in two similarly.
|
with dps select sram_byte_we_n <=
|
with dps select sram_byte_we_n <=
|
not byte_we_reg(3 downto 2) when data_writethrough_sram_0,
|
not byte_we_reg(3 downto 2) when data_writethrough_sram_0b,
|
not byte_we_reg(1 downto 0) when data_writethrough_sram_1,
|
not byte_we_reg(1 downto 0) when data_writethrough_sram_1b,
|
"11" when others;
|
"11" when others;
|
|
|
-- SRAM OE\ is only asserted low for read cycles
|
-- SRAM OE\ is only asserted low for read cycles
|
with dps select sram_oe_n <=
|
with dps select sram_oe_n <=
|
'0' when data_refill_sram_0,
|
'0' when data_refill_sram_0,
|
Line 618... |
Line 683... |
|
|
sram_input_halfword_register:
|
sram_input_halfword_register:
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if clk'event and clk='1' then
|
if clk'event and clk='1' then
|
|
if dps=data_refill_sram_0 then
|
sram_rd_data_reg <= sram_databus;
|
sram_rd_data_reg <= sram_databus;
|
end if;
|
end if;
|
|
end if;
|
end process sram_input_halfword_register;
|
end process sram_input_halfword_register;
|
|
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- I/O interface -- IO is assumed to behave like synchronous memory
|
-- I/O interface -- IO is assumed to behave like synchronous memory
|
Line 651... |
Line 718... |
'0' when others;
|
'0' when others;
|
|
|
-- Assert code_wait until the cycle where the CPU has valid data word on its
|
-- Assert code_wait until the cycle where the CPU has valid data word on its
|
-- code bus AND no other operations are ongoing that may use the external buses.
|
-- code bus AND no other operations are ongoing that may use the external buses.
|
with dps select data_wait <=
|
with dps select data_wait <=
|
'1' when data_writethrough_sram_0,
|
'1' when data_writethrough_sram_0a,
|
'1' when data_writethrough_sram_1,
|
'1' when data_writethrough_sram_0b,
|
|
'1' when data_writethrough_sram_0c,
|
|
'1' when data_writethrough_sram_1a,
|
|
'1' when data_writethrough_sram_1b,
|
|
'1' when data_writethrough_sram_1c,
|
'1' when data_refill_sram_0,
|
'1' when data_refill_sram_0,
|
'1' when data_refill_sram_1,
|
'1' when data_refill_sram_1,
|
'1' when data_refill_bram_0,
|
'1' when data_refill_bram_0,
|
'1' when data_refill_bram_1,
|
'1' when data_refill_bram_1,
|
'1' when data_read_io_0,
|
'1' when data_read_io_0,
|