Line 1... |
Line 1... |
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
-- mips_cache_stub.vhdl -- cache module with no actual cache memory.
|
-- mips_cache_stub.vhdl -- 1-word cache module
|
--
|
--
|
-- FOR SIMULATION ONLY! does not resemble structure of final cache
|
-- This module has the same interface and logic as a real cache but the cache
|
|
-- memory is just 1 word for each of code and data.
|
--
|
--
|
-- This module has the same interface as a real cache but has no cache memory.
|
-- It interfaces the CPU to the following:
|
-- It just interfaces the CPU to the following:
|
|
--
|
--
|
-- 1.- Internal 32-bit-wide BRAM for read and write
|
-- 1.- Internal 32-bit-wide BRAM for read only
|
-- 2.- Internal 32-bit I/O bus
|
-- 2.- Internal 32-bit I/O bus
|
-- 3.- External 16-bit wide SRAM
|
-- 3.- External 16-bit wide SRAM
|
--
|
--
|
-- The purpose of this module is just to test the SRAM interface in simulation.
|
-- The SRAM memory interface signals are meant to connect directly to FPGA pins
|
-- It will evolve to a real cache as the project goes on.
|
-- and all outputs are registered (tco should be minimal).
|
|
-- SRAM data inputs are NOT registered, though. They go through a couple muxes
|
|
-- before reaching the first register so watch out for tsetup.
|
|
-- The SRAM is assumed to be fast enough to read or write in a clock cycle.
|
|
--
|
|
-- Obviously this module provides no performance gain; on the contrary, by
|
|
-- coupling the CPU to slow external memory (16 bit bus) it actually slows it
|
|
-- down. The purpose of this module is just to test the SRAM interface and the
|
|
-- cache logic and timing.
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
-- KNOWN TROUBLE:
|
|
--
|
|
-- Apart from the very rough looks of the code, there's a few known faults with
|
|
-- it:
|
|
--
|
|
-- 1.- Access to unmapped areas wil crash the CPU
|
|
-- 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
|
|
-- zero, trigger trap, mirror another mapped area...)
|
|
-- 2.- Address decoding is hardcoded in mips_pkg
|
|
-- It should be done here using module generics and not package constants.
|
|
-- 3.- Does not work as a real 1-word cache yet
|
|
-- 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.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
Line 42... |
Line 66... |
data_wr_addr : in std_logic_vector(31 downto 2);
|
data_wr_addr : in std_logic_vector(31 downto 2);
|
byte_we : in std_logic_vector(3 downto 0);
|
byte_we : in std_logic_vector(3 downto 0);
|
data_wr : in std_logic_vector(31 downto 0);
|
data_wr : in std_logic_vector(31 downto 0);
|
|
|
mem_wait : out std_logic;
|
mem_wait : out std_logic;
|
|
cache_enable : in std_logic;
|
|
|
-- interface to FPGA i/o devices
|
-- interface to FPGA i/o devices
|
io_rd_data : in std_logic_vector(31 downto 0);
|
io_rd_data : in std_logic_vector(31 downto 0);
|
io_rd_addr : out std_logic_vector(31 downto 2);
|
io_rd_addr : out std_logic_vector(31 downto 2);
|
io_wr_addr : out std_logic_vector(31 downto 2);
|
io_wr_addr : out std_logic_vector(31 downto 2);
|
Line 57... |
Line 82... |
bram_rd_data : in std_logic_vector(31 downto 0);
|
bram_rd_data : in std_logic_vector(31 downto 0);
|
bram_wr_data : out std_logic_vector(31 downto 0);
|
bram_wr_data : out std_logic_vector(31 downto 0);
|
bram_rd_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
|
bram_rd_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
|
bram_wr_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
|
bram_wr_addr : out std_logic_vector(BRAM_ADDR_SIZE+1 downto 2);
|
bram_byte_we : out std_logic_vector(3 downto 0);
|
bram_byte_we : out std_logic_vector(3 downto 0);
|
|
bram_data_rd_vma: out std_logic;
|
|
|
-- interface to asynchronous 16-bit-wide EXTERNAL SRAM
|
-- interface to asynchronous 16-bit-wide EXTERNAL SRAM
|
sram_address : out std_logic_vector(SRAM_ADDR_SIZE-1 downto 1);
|
sram_address : out std_logic_vector(SRAM_ADDR_SIZE downto 1);
|
sram_databus : inout std_logic_vector(15 downto 0);
|
sram_databus : inout std_logic_vector(15 downto 0);
|
sram_byte_we_n : out std_logic_vector(1 downto 0);
|
sram_byte_we_n : out std_logic_vector(1 downto 0);
|
sram_oe_n : out std_logic
|
sram_oe_n : out std_logic
|
);
|
);
|
end entity mips_cache_stub;
|
end entity mips_cache_stub;
|
|
|
|
|
|
|
architecture stub of mips_cache_stub is
|
architecture stub of mips_cache_stub is
|
|
|
type t_cache_state is (
|
type t_code_cache_state is (
|
idle,
|
code_normal,
|
|
code_wait_for_dcache,
|
|
|
|
code_refill_bram_0, -- pc in bram_rd_addr
|
|
code_refill_bram_1, -- op in bram_rd
|
|
code_refill_bram_2, -- op in code_rd
|
|
code_refill_bram_3,
|
|
|
|
code_refill_sram_0,
|
|
code_refill_sram_1,
|
|
code_refill_sram_2,
|
|
|
|
code_bug
|
|
);
|
|
|
|
signal cps, cns : t_code_cache_state;
|
|
|
|
|
|
type t_data_cache_state is (
|
|
data_normal,
|
|
|
|
data_refill_sram_0,
|
|
data_refill_sram_1,
|
|
|
read_bram_data_0,
|
data_refill_bram_0, -- rd addr in bram_rd_addr
|
read_bram_data_1,
|
data_refill_bram_1, -- rd data in bram_rd_data
|
|
|
read_data_0,
|
data_read_io_0, -- rd addr on io_rd_addr, io_vma active
|
read_data_1,
|
data_read_io_1, -- rd data on io_rd_data
|
|
data_write_io_0,
|
|
data_write_io_1,
|
|
|
read_code_0,
|
data_writethrough_sram_0,
|
read_code_1,
|
data_writethrough_sram_1,
|
|
|
write_0,
|
data_ignore_write,
|
write_1
|
|
|
data_bug
|
);
|
);
|
|
|
signal ps, ns : t_cache_state;
|
|
|
signal dps, dns : t_data_cache_state;
|
|
|
|
|
signal use_sram_wr : std_logic;
|
signal use_sram_wr : std_logic;
|
signal use_sram_rd : std_logic;
|
signal use_sram_rd : std_logic;
|
signal use_io_wr : std_logic;
|
signal use_io_wr : std_logic;
|
signal use_io_rd : std_logic;
|
signal use_io_rd : std_logic;
|
signal data_addr_reg : std_logic_vector(SRAM_ADDR_SIZE-1 downto 2);
|
signal data_addr_reg : std_logic_vector(SRAM_ADDR_SIZE downto 2);
|
signal data_wr_reg : std_logic_vector(31 downto 0);
|
signal data_wr_reg : std_logic_vector(31 downto 0);
|
signal data_input_reg : std_logic_vector(15 downto 0);
|
signal data_input_reg : std_logic_vector(15 downto 0);
|
signal bram_rd_data_reg : std_logic_vector(31 downto 0);
|
signal bram_rd_data_reg : std_logic_vector(31 downto 0);
|
|
signal io_rd_data_reg : std_logic_vector(31 downto 0);
|
signal byte_we_reg : std_logic_vector(3 downto 0);
|
signal byte_we_reg : std_logic_vector(3 downto 0);
|
|
|
|
|
|
signal code_rd_addr_reg : t_pc;
|
|
|
|
subtype t_code_tag is std_logic_vector(23 downto 2);
|
|
signal code_cache_tag : t_code_tag;
|
|
signal code_cache_tag_store : t_code_tag;
|
|
signal code_cache_store : t_word;
|
|
|
|
signal code_cache_rd : t_word;
|
|
signal code_miss : std_logic;
|
|
|
|
|
|
signal data_rd_addr_reg : t_pc;
|
|
signal data_wr_addr_reg : t_pc;
|
|
|
|
subtype t_data_tag is std_logic_vector(23 downto 2);
|
|
signal data_cache_tag : t_data_tag;
|
|
signal data_cache_tag_store : t_data_tag;
|
|
signal data_cache_store : t_word;
|
|
-- Stores first (high) HW read from SRAM
|
|
signal sram_rd_data_reg : std_logic_vector(31 downto 16);
|
|
-- Data read from SRAM, valid in refill_1
|
|
signal sram_rd_data : t_word;
|
|
|
|
signal write_pending : std_logic;
|
|
signal read_pending : std_logic;
|
|
|
|
signal data_cache_rd : t_word;
|
|
signal data_miss : std_logic;
|
|
|
|
signal code_wait : std_logic;
|
|
signal data_wait : std_logic;
|
|
|
|
|
|
signal code_rd_addr_mask : t_addr_decode;
|
|
signal data_rd_addr_mask : t_addr_decode;
|
|
signal data_wr_addr_mask : t_addr_decode;
|
|
|
|
signal code_rd_area : std_logic_vector(1 downto 0);
|
|
signal data_rd_area : std_logic_vector(1 downto 0);
|
|
signal data_wr_area : std_logic_vector(1 downto 0);
|
|
|
begin
|
begin
|
|
|
|
|
cache_state_machine_reg:
|
cache_state_machine_regs:
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if clk'event and clk='1' then
|
if clk'event and clk='1' then
|
if reset='1' then
|
if reset='1' then
|
ps <= idle; --wait_idle;
|
cps <= code_normal;
|
|
dps <= data_normal;
|
else
|
else
|
ps <= ns;
|
cps <= cns;
|
|
dps <= dns;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process cache_state_machine_reg;
|
end process cache_state_machine_regs;
|
|
|
|
|
|
|
cache_state_machine_transitions:
|
code_state_machine_transitions:
|
process(clk,ps)
|
process(cps, dps, code_rd_vma, code_miss, code_rd_area, write_pending, read_pending)
|
begin
|
begin
|
case ps is
|
case cps is
|
when idle =>
|
when code_normal =>
|
ns <= ps;
|
if code_rd_vma='1' and code_miss='1' and read_pending='0' and write_pending='0' then
|
|
cns <= code_refill_bram_0; -- FIXME check memory area
|
if code_rd_vma='1' and use_sram_rd='1' then
|
|
ns <= read_code_0;
|
|
elsif data_rd_vma='1' and use_sram_rd='1' then
|
|
ns <= read_data_0;
|
|
elsif data_rd_vma='1' and use_sram_rd='0' then
|
|
ns <= read_bram_data_0;
|
|
elsif byte_we/="0000" and use_sram_wr='1' then
|
|
ns <= write_0;
|
|
else
|
else
|
ns <= ps;
|
cns <= cps;
|
end if;
|
end if;
|
|
|
when read_bram_data_0 =>
|
when code_refill_bram_0 =>
|
ns <= read_bram_data_1;
|
cns <= code_refill_bram_1;
|
|
|
|
when code_refill_bram_1 =>
|
|
cns <= code_refill_bram_2;
|
|
|
when read_bram_data_1 =>
|
when code_refill_bram_2 =>
|
ns <= idle;
|
if dps/=data_normal and read_pending='0' and write_pending='0' then
|
|
cns <= code_wait_for_dcache;
|
|
else
|
|
cns <= code_normal;
|
|
end if;
|
|
|
when read_code_0 =>
|
when code_refill_bram_3 =>
|
ns <= read_code_1;
|
cns <= code_normal;
|
|
|
when read_code_1 =>
|
when code_wait_for_dcache =>
|
if data_rd_vma='1' and use_sram_rd='1' then
|
-- if D-cache is busy, wait for it to become idle
|
ns <= read_data_0;
|
if dps/=data_normal then
|
elsif byte_we/="0000" and use_sram_wr='1' then
|
cns <= cps;
|
ns <= write_0;
|
elsif code_miss='1' then
|
|
cns <= code_refill_bram_1; -- FIXME check memory area
|
else
|
else
|
ns <= idle;
|
cns <= code_normal;
|
end if;
|
end if;
|
|
|
when read_data_0 =>
|
when code_bug =>
|
ns <= read_data_1;
|
cns <= code_normal;
|
|
|
|
when others =>
|
|
cns <= code_bug;
|
|
end case;
|
|
end process code_state_machine_transitions;
|
|
|
|
|
|
data_state_machine_transitions:
|
|
process(dps, write_pending, read_pending, data_rd_area, data_wr_area)
|
|
begin
|
|
case dps is
|
|
when data_normal =>
|
|
if write_pending='1' then
|
|
case data_wr_area is
|
|
when "00" => dns <= data_ignore_write; -- Write to BRAM ignored
|
|
when "01" => dns <= data_writethrough_sram_0;
|
|
when "10" => dns <= data_write_io_0;
|
|
when others => dns <= dps; -- Write to undecoded area ignored
|
|
end case;
|
|
|
when read_data_1 =>
|
elsif read_pending='1' then
|
if byte_we/="0000" and use_sram_wr='1' then
|
case data_rd_area is
|
ns <= write_0;
|
when "00" => dns <= data_refill_bram_0;
|
|
when "01" => dns <= data_refill_sram_0;
|
|
when "10" => dns <= data_read_io_0;
|
|
when others => dns <= dps; -- ignore read from undecoded area
|
|
-- FIXME should raise debug flag
|
|
end case;
|
else
|
else
|
ns <= idle;
|
dns <= dps;
|
end if;
|
end if;
|
|
|
when write_0 =>
|
when data_write_io_0 =>
|
ns <= write_1;
|
dns <= data_normal;
|
|
|
|
when data_read_io_0 =>
|
|
dns <= data_read_io_1;
|
|
|
|
when data_read_io_1 =>
|
|
dns <= data_normal;
|
|
|
|
when data_refill_sram_0 =>
|
|
dns <= data_refill_sram_1;
|
|
|
|
when data_refill_sram_1 =>
|
|
dns <= data_normal;
|
|
|
when write_1 =>
|
when data_refill_bram_0 =>
|
ns <= idle;
|
dns <= data_refill_bram_1;
|
|
|
|
when data_refill_bram_1 =>
|
|
dns <= data_normal;
|
|
|
|
when data_writethrough_sram_0 =>
|
|
dns <= data_writethrough_sram_1;
|
|
|
|
when data_writethrough_sram_1 =>
|
|
dns <= data_normal;
|
|
|
|
when data_ignore_write =>
|
|
dns <= data_normal;
|
|
|
|
when data_bug =>
|
|
dns <= data_normal;
|
|
|
when others =>
|
when others =>
|
-- BUG: should raise some debug signal
|
dns <= data_bug;
|
ns <= idle;
|
|
end case;
|
end case;
|
end process cache_state_machine_transitions;
|
end process data_state_machine_transitions;
|
|
|
sram_address(sram_address'high downto 2) <=
|
|
data_addr_reg(sram_address'high downto 2);
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- CPU interface registers and address decoding --------------------------------
|
|
|
with ps select sram_address(1) <=
|
|
'0' when read_data_0,
|
|
'1' when read_data_1,
|
|
'0' when read_code_0,
|
|
'1' when read_code_1,
|
|
'0' when write_0,
|
|
'1' when write_1,
|
|
'0' when others;
|
|
|
|
with ps select sram_oe_n <=
|
-- Everything coming and going to the CPU is registered, so that the CPU has
|
'0' when read_data_0,
|
-- some timing marging.
|
'0' when read_data_1,
|
|
'0' when read_code_0,
|
|
'0' when read_code_1,
|
|
'1' when others;
|
|
|
|
with ps select sram_byte_we_n <=
|
cpu_interface_registers:
|
not byte_we_reg(3 downto 2) when write_0,
|
process(clk)
|
not byte_we_reg(1 downto 0) when write_1,
|
begin
|
|
if clk'event and clk='1' then
|
|
if reset='1' then
|
|
write_pending <= '0';
|
|
read_pending <= '0';
|
|
byte_we_reg <= "0000";
|
|
else
|
|
-- Raise 'read_pending' at the 1st cycle of a read, clear it when
|
|
-- the read (and/or refill) operation has been done.
|
|
-- data_rd_addr_reg always has the addr of any pending read
|
|
if data_rd_vma='1' then
|
|
read_pending <= '1';
|
|
data_rd_addr_reg <= data_rd_addr(31 downto 2);
|
|
elsif dps=data_refill_sram_1 or
|
|
dps=data_refill_bram_1 or
|
|
dps=data_read_io_0 then
|
|
read_pending <= '0';
|
|
end if;
|
|
|
|
-- Raise 'write_pending' at the 1st cycle of a read, clear it when
|
|
-- the write (writethrough actually) operation has been done.
|
|
-- data_wr_addr_reg always has the addr of any pending write
|
|
if byte_we/="0000" and dps=data_normal then
|
|
byte_we_reg <= byte_we;
|
|
data_wr_reg <= data_wr;
|
|
data_wr_addr_reg <= data_wr_addr;
|
|
write_pending <= '1';
|
|
elsif dps=data_writethrough_sram_1 or
|
|
dps=data_write_io_0 or
|
|
dps=data_ignore_write then
|
|
write_pending <= '0';
|
|
byte_we_reg <= "0000";
|
|
end if;
|
|
|
|
-- Register code fetch addresses only when they are valid; so that
|
|
-- code_rd_addr_reg always holds the last fetch address.
|
|
if (cps=code_normal and code_rd_vma='1') or cps=code_refill_bram_2 then
|
|
code_rd_addr_reg <= code_rd_addr;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process cpu_interface_registers;
|
|
|
|
-- Address decoding ------------------------------------------------------------
|
|
|
|
-- Decoding is done on the high bits of the address only, there'll be mirroring.
|
|
-- Write to areas not explicitly decoded will be silently ignored. Reads will
|
|
-- get undefined data.
|
|
|
|
code_rd_addr_mask <= code_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);
|
|
|
|
|
|
with code_rd_addr_mask select code_rd_area <=
|
|
"00" when ADDR_BOOT,
|
|
"01" when ADDR_XRAM,
|
"11" when others;
|
"11" when others;
|
|
|
with ps select sram_databus <=
|
with data_rd_addr_mask select data_rd_area <=
|
data_wr_reg(31 downto 16) when write_0,
|
"00" when ADDR_BOOT,
|
data_wr_reg(15 downto 0) when write_1,
|
"01" when ADDR_XRAM,
|
(others => 'Z') when others;
|
"10" when ADDR_IO,
|
|
"11" when others;
|
|
|
|
with data_wr_addr_mask select data_wr_area <=
|
|
"01" when ADDR_XRAM,
|
|
"10" when ADDR_IO,
|
|
"11" when others;
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Code cache
|
|
|
sdram_address_register:
|
bram_rd_addr <= data_rd_addr_reg(bram_rd_addr'high downto 2)
|
|
when dps=data_refill_bram_0
|
|
else code_rd_addr_reg(bram_rd_addr'high downto 2) ;
|
|
|
|
code_rd <= code_cache_rd;
|
|
|
|
-- FIXME Actual 1-word cache functionality is unimplemented yet
|
|
code_miss <= '1'; --code_rd_vma;
|
|
|
|
|
|
-- Read cache code and tag from code store
|
|
code_cache_rd <= code_cache_store;
|
|
code_cache_tag <= code_cache_tag_store;
|
|
|
|
code_cache_memory:
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if clk'event and clk='1' then
|
if clk'event and clk='1' then
|
|
|
|
|
if reset='1' then
|
if reset='1' then
|
data_addr_reg <= (others => '0');
|
-- in the real hardware the tag store can't be reset and it's up
|
|
-- to the SW to initialize the cache.
|
|
code_cache_tag_store <= (others => '0');
|
|
code_cache_store <= (others => '0');
|
else
|
else
|
if data_rd_vma='1' then
|
-- Refill cache if necessary
|
data_addr_reg <= data_rd_addr(sram_address'high downto 2);
|
if cps=code_refill_bram_1 then
|
elsif byte_we/="0000" then
|
code_cache_tag_store <=
|
data_addr_reg <= data_wr_addr(sram_address'high downto 2);
|
"01" & code_rd_addr_reg(t_code_tag'high-2 downto t_code_tag'low);
|
|
code_cache_store <= bram_rd_data;
|
|
--elsif cps=code_refill_sram_2 then
|
|
-- code_cache_tag_store <=
|
|
-- "01" & code_rd_addr_reg(t_code_tag'high-2 downto t_code_tag'low);
|
|
-- code_cache_store <= sram_rd_data;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process sdram_address_register;
|
end process code_cache_memory;
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- Data cache
|
|
|
|
with dps select data_rd <=
|
|
io_rd_data when data_read_io_1,
|
|
data_cache_rd when others;
|
|
|
data_input_register:
|
|
|
data_cache_rd <= data_cache_store;
|
|
data_cache_tag <= data_cache_tag_store;
|
|
|
|
data_cache_memory:
|
process(clk)
|
process(clk)
|
begin
|
begin
|
if clk'event and clk='1' then
|
if clk'event and clk='1' then
|
|
|
|
|
if reset='1' then
|
if reset='1' then
|
data_input_reg <= (others => '0');
|
-- in the real hardware the tag store can't be reset and it's up
|
|
-- to the SW to initialize the cache.
|
|
data_cache_tag_store <= (others => '0');
|
|
data_cache_store <= (others => '0');
|
else
|
else
|
if ps=read_data_0 then
|
-- Refill data cache if necessary
|
data_input_reg <= sram_databus;
|
if dps=data_refill_sram_1 then
|
|
data_cache_tag_store <=
|
|
"01" & data_rd_addr_reg(t_data_tag'high-2 downto t_data_tag'low);
|
|
data_cache_store <= sram_rd_data;
|
|
elsif dps=data_refill_bram_1 then
|
|
data_cache_tag_store <=
|
|
"01" & data_rd_addr_reg(t_data_tag'high-2 downto t_data_tag'low);
|
|
data_cache_store <= bram_rd_data;
|
end if;
|
end if;
|
bram_rd_data_reg <= bram_rd_data;
|
|
if byte_we/="0000" then
|
|
byte_we_reg <= byte_we;
|
|
data_wr_reg <= data_wr;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end process data_cache_memory;
|
|
|
|
with dps select sram_address(sram_address'high downto 2) <=
|
|
data_rd_addr_reg(sram_address'high downto 2) when data_refill_sram_0,
|
|
data_rd_addr_reg(sram_address'high downto 2) when data_refill_sram_1,
|
|
data_wr_addr_reg(sram_address'high downto 2) when others;
|
|
|
|
with dps select sram_address(1) <=
|
|
'0' when data_writethrough_sram_0,
|
|
'1' when data_writethrough_sram_1,
|
|
'0' when data_refill_sram_0,
|
|
'1' when data_refill_sram_1,
|
|
'0' when others;
|
|
|
|
with dps select sram_databus <=
|
|
data_wr_reg(31 downto 16) when data_writethrough_sram_0,
|
|
data_wr_reg(15 downto 0) when data_writethrough_sram_1,
|
|
(others => 'Z') when others;
|
|
|
|
with dps select sram_byte_we_n <=
|
|
not byte_we_reg(3 downto 2) when data_writethrough_sram_0,
|
|
not byte_we_reg(1 downto 0) when data_writethrough_sram_1,
|
|
"11" when others;
|
|
|
|
with dps select sram_oe_n <=
|
|
'0' when data_refill_sram_0,
|
|
'0' when data_refill_sram_1,
|
|
'1' when others;
|
|
|
|
sram_rd_data <= sram_rd_data_reg & sram_databus;
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
--if ps=xxx then
|
|
sram_rd_data_reg <= sram_databus;
|
|
--end if;
|
end if;
|
end if;
|
end process data_input_register;
|
end process;
|
|
|
|
bram_data_rd_vma <= '1' when dps=data_refill_bram_1 else '0';
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
with ps select code_rd <=
|
io_byte_we <= byte_we_reg when dps=data_write_io_0 else "0000";
|
data_input_reg & sram_databus when read_code_1,
|
io_rd_addr <= data_rd_addr_reg;
|
bram_rd_data when others;
|
io_wr_addr <= data_wr_addr_reg;
|
|
io_wr_data <= data_wr_reg;
|
|
io_rd_vma <= '1' when dps=data_read_io_0 else '0';
|
data_rd <=
|
|
data_input_reg & sram_databus when ps=read_data_1 else
|
|
bram_rd_data_reg;
|
|
-- FIXME IO RD data missing
|
|
--io_rd_data when (ps=idle and use_io_rd='1') else
|
|
|
|
mem_wait <= '1' when
|
|
ps=read_bram_data_0 or
|
|
ps=read_data_0 or
|
|
ps=write_0 or
|
|
(ps=idle and use_sram_wr='1' and byte_we/="0000")
|
|
else '0';
|
|
|
|
use_sram_rd <= '1'
|
|
when (addr_decode(data_rd_addr,ADDR_XRAM)='1' and data_rd_vma='1') or
|
|
(addr_decode(code_rd_addr,ADDR_XRAM)='1' and code_rd_vma='1')
|
|
else '0';
|
|
|
|
use_sram_wr <= '1'
|
|
when addr_decode(data_wr_addr,ADDR_XRAM)='1'
|
|
else '0';
|
|
|
|
use_io_rd <= '1'
|
|
when addr_decode(data_rd_addr,ADDR_IO)='1' and data_rd_vma='1'
|
|
else '0';
|
|
|
|
use_io_wr <= '1'
|
|
when addr_decode(data_wr_addr,ADDR_IO)='1' and byte_we/="0000"
|
|
else '0';
|
|
|
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
|
|
bram_rd_addr <= data_rd_addr(bram_rd_addr'high downto 2) when
|
mem_wait <= (code_wait or data_wait) and not reset;
|
(ps=idle and use_sram_rd='0' and data_rd_vma='1')
|
|
else code_rd_addr(bram_rd_addr'high downto 2);
|
|
|
|
bram_wr_addr <= data_wr_addr(bram_wr_addr'high downto 2);
|
|
bram_byte_we <= byte_we when addr_decode(data_wr_addr,ADDR_BOOT)='1' else "0000";
|
|
|
|
|
with cps select code_wait <=
|
|
'1' when code_refill_bram_0,
|
|
'1' when code_refill_bram_1,
|
|
'1' when code_refill_bram_2,
|
|
'1' when code_wait_for_dcache,
|
|
'0' when others;
|
|
|
io_wr_addr <= data_wr_addr;
|
with dps select data_wait <=
|
io_rd_addr <= data_rd_addr(31 downto 2);
|
'1' when data_writethrough_sram_0,
|
io_wr_data <= data_wr;
|
'1' when data_writethrough_sram_1,
|
io_byte_we <= byte_we when addr_decode(data_wr_addr,ADDR_IO)='1' else "0000";
|
'1' when data_refill_sram_0,
|
|
'1' when data_refill_sram_1,
|
|
'1' when data_refill_bram_0,
|
|
'1' when data_refill_bram_1,
|
|
'1' when data_read_io_0,
|
|
'0' when others;
|
|
|
|
|
end architecture stub;
|
end architecture stub;
|
|
|
No newline at end of file
|
No newline at end of file
|