I hope you guys are well :)
I am trying to implement a simple cache memory system, however I am finding myself unable to properly do so. When I attempt to test my read miss/ read hit, I am getting the following result: VHDL Signals.
As I understand my design, the Read Miss state should be writing 1011111110101100 however I am either getting 10111111100000000 or 00000010101100. My result seems to fluctuate between both results. s_addr refers to a new instruction from the CPU which starts one process, which in turn starts the state process should there be any changes. I have provided some code. I am unsure of how to proceed. I've walked through my code and I do not understand why it splits the values like that when the output was supposed occur in one go.
Finally, I suspect that this may have something to do with the fact that my signals are initially undefined for some reason.
I am not sure why for the first 6ns, the output of s_readdatta is undefined. My tag values stored in test1 and test2 are also undefined and I am not sure why. I would appreciate any insight you guys can offer. Thank you!
VHDL code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_bit_unsigned.all;
entity cache is
generic(
ram_size : INTEGER := 32768
);
port(
clock : in std_logic;
reset : in std_logic;
-- Avalon interface --
s_addr : in std_logic_vector (31 downto 0);
s_read : in std_logic;
s_readdata : out std_logic_vector (31 downto 0);
s_write : in std_logic;
s_writedata : in std_logic_vector (31 downto 0);
s_waitrequest : out std_logic;
m_addr : out integer range 0 to ram_size-1;
m_read : out std_logic;
m_readdata : in std_logic_vector (7 downto 0);
m_write : out std_logic;
m_writedata : out std_logic_vector (7 downto 0);
m_waitrequest : in std_logic;
test1: out std_logic_vector (5 downto 0);
test2: out std_logic_vector (5 downto 0)
);
end cache;
architecture arch of cache is
-- declare signals here
-- 15 bit signal will be of the following form: VDTTTTBBBBBWWbb
constant number_of_cache_lines: integer := 128;
TYPE t_cache_memory IS ARRAY(number_of_cache_lines-1 downto 0) OF STD_LOGIC_VECTOR(31 downto 0);
-- For data requested by CPU
signal tag_bits: std_logic_vector (5 downto 0);
signal block_index: std_logic_vector (4 downto 0);
signal block_index_int: integer;
signal word_index: std_logic_vector (1 downto 0);
signal word_index_int: integer;
-- For data in the cache
signal in_cache_tag_bits: std_logic_vector (5 downto 0);
signal in_cache_valid_bit: std_logic;
signal in_cache_dirty_bit: std_logic;
signal temp_s_addr: std_logic_vector(14 downto 0);
signal retrieved_address: std_logic_vector (31 downto 0);
type t_State is (readHit, writeHit, writeBack, readMiss, writeMiss, idle);
signal state: t_State;
signal cache_memory: t_cache_memory;
begin
-- For CPU address
temp_s_addr(3 downto 0) <= (others => '0');
temp_s_addr(14 downto 4) <= s_addr (14 downto 4);
tag_bits <= s_addr (14 downto 9);
block_index <= s_addr (8 downto 4);
block_index_int <= 4*to_integer(unsigned(block_index));
word_index <= s_addr (3 downto 2);
word_index_int <= to_integer(unsigned(word_index));
process (s_addr)
begin
if block_index_int /= -2147483648 then
retrieved_address <= cache_memory(block_index_int + word_index_int);
in_cache_valid_bit <= cache_memory(block_index_int)(15);
in_cache_dirty_bit <= cache_memory(block_index_int)(14);
in_cache_tag_bits <= cache_memory(block_index_int)(13 downto 8);
end if;
if s_read = '1' and s_write ='0' then
if in_cache_valid_bit = '1' then
test1 <= s_addr (14 downto 9);
test2 <= in_cache_tag_bits;
if in_cache_tag_bits = s_addr (14 downto 9) then
state <= readHit;
else
if in_cache_dirty_bit = '1' then
state <= writeBack;
else
state <= readMiss;
end if;
end if;
else
state <= readMiss;
end if;
elsif s_write = '1' and s_read = '0' then
if in_cache_valid_bit = '1' then
if tag_bits = in_cache_tag_bits then
state <= writeHit;
else
if in_cache_dirty_bit = '1' then
state <= writeBack;
else
state <= writeMiss;
end if;
end if;
end if;
else
state <= idle;
end if;
end process;
process(state)
begin
s_waitrequest <= '1';
case state is
-- If CPU is not doing anything
when idle =>
report "No Reads or Writes have occured.";
when readHit =>
report "Read Hit Occured:";
s_readdata <= retrieved_address;
-- If write hit
when writeHit =>
report "Write Hit Occured:";
cache_memory(block_index_int + word_index_int)(7 downto 0) <= s_addr(7 downto 0);
cache_memory(block_index_int)(13 downto 8) <= tag_bits;
cache_memory(block_index_int)(14) <= '1';
cache_memory(block_index_int)(15) <= '1';
cache_memory(block_index_int)(31 downto 16) <= (others => '0');
--state <= idle;
-- If cache hit but dirty bit then write-back
when writeBack =>
report "Write Back Occured:";
-- Write back into memory first
m_write <= '1';
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)));
m_writedata <= temp_s_addr(7 downto 0);
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0))) + 4;
m_writedata(3 downto 0) <= "0100";
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0))) + 8;
m_writedata(3 downto 0) <= "1000";
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0))) + 12;
m_writedata(3 downto 0) <= "1100";
m_write <= '0';
-- Write to cache
cache_memory(block_index_int)(13 downto 8) <= tag_bits;
cache_memory(block_index_int)(14) <= '0';
cache_memory(block_index_int)(15) <= '0';
cache_memory(block_index_int)(31 downto 16) <= (others => '0');
--state <= idle;
when readMiss =>
report "Read Miss Occured:";
m_read <= '1';
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)));
cache_memory(block_index_int)(7 downto 0) <= m_readdata;
cache_memory(block_index_int)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+4;
cache_memory(block_index_int+1)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+1)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+8;
cache_memory(block_index_int+2)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+2)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+12;
cache_memory(block_index_int+3)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+3)(31 downto 8) <= (others => '0');
m_read <= '0';
cache_memory(block_index_int)(13 downto 8) <= tag_bits;
cache_memory(block_index_int)(14) <= '0';
cache_memory(block_index_int)(15) <= '1';
cache_memory(block_index_int)(31 downto 16) <= (others => '0');
s_readdata<= cache_memory(block_index_int + word_index_int);
--state <= idle;
-- If write miss
when writeMiss =>
report "Write Miss Occured:";
m_write <= '1';
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0))) + word_index_int;
m_writedata <= s_addr(7 downto 0);
m_write <= '0';
m_read <= '1';
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)));
cache_memory(block_index_int)(7 downto 0) <= m_readdata;
cache_memory(block_index_int)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+4;
cache_memory(block_index_int+1)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+1)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+8;
cache_memory(block_index_int+2)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+2)(31 downto 8) <= (others => '0');
m_addr <= to_integer(unsigned(temp_s_addr(14 downto 0)))+12;
cache_memory(block_index_int+3)(7 downto 0) <= m_readdata;
cache_memory(block_index_int+3)(31 downto 8) <= (others => '0');
m_read <= '0';
cache_memory(block_index_int)(13 downto 8) <= tag_bits;
cache_memory(block_index_int)(14) <= '0';
cache_memory(block_index_int)(15) <= '1';
cache_memory(block_index_int)(31 downto 16) <= (others => '0');
--state <= idle;
end case;
s_waitrequest <= '0';
end process;
end arch;
Testbench Code
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cache_tb is
end cache_tb;
architecture behavior of cache_tb is
component cache is
generic(
ram_size : INTEGER := 32768
);
port(
clock : in std_logic;
reset : in std_logic;
-- Avalon interface --
s_addr : in std_logic_vector (31 downto 0);
s_read : in std_logic;
s_readdata : out std_logic_vector (31 downto 0);
s_write : in std_logic;
s_writedata : in std_logic_vector (31 downto 0);
s_waitrequest : out std_logic;
m_addr : out integer range 0 to ram_size-1;
m_read : out std_logic;
m_readdata : in std_logic_vector (7 downto 0);
m_write : out std_logic;
m_writedata : out std_logic_vector (7 downto 0);
m_waitrequest : in std_logic;
test1: out std_logic_vector (5 downto 0);
test2: out std_logic_vector (5 downto 0)
);
end component;
component memory is
GENERIC(
ram_size : INTEGER := 32768;
mem_delay : time := 10 ns;
clock_period : time := 1 ns
);
PORT (
clock: IN STD_LOGIC;
writedata: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
address: IN INTEGER RANGE 0 TO ram_size-1;
memwrite: IN STD_LOGIC;
memread: IN STD_LOGIC;
readdata: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
waitrequest: OUT STD_LOGIC
);
end component;
-- test signals
signal reset : std_logic := '0';
signal clk : std_logic := '0';
constant clk_period : time := 1 ns;
signal s_addr : std_logic_vector (31 downto 0);
signal s_read : std_logic;
signal s_readdata : std_logic_vector (31 downto 0);
signal s_write : std_logic;
signal s_writedata : std_logic_vector (31 downto 0);
signal s_waitrequest : std_logic;
signal m_addr : integer range 0 to 2147483647;
signal m_read : std_logic;
signal m_readdata : std_logic_vector (7 downto 0);
signal m_write : std_logic;
signal m_writedata : std_logic_vector (7 downto 0);
signal m_waitrequest : std_logic;
signal test1: std_logic_vector (5 downto 0);
signal test2: std_logic_vector (5 downto 0);
begin
-- Connect the components which we instantiated above to their
-- respective signals.
dut: cache
port map(
clock => clk,
reset => reset,
s_addr => s_addr,
s_read => s_read,
s_readdata => s_readdata,
s_write => s_write,
s_writedata => s_writedata,
s_waitrequest => s_waitrequest,
m_addr => m_addr,
m_read => m_read,
m_readdata => m_readdata,
m_write => m_write,
m_writedata => m_writedata,
m_waitrequest => m_waitrequest,
test1 => test1,
test2 => test2
);
MEM : memory
port map (
clock => clk,
writedata => m_writedata,
address => m_addr,
memwrite => m_write,
memread => m_read,
readdata => m_readdata,
waitrequest => m_waitrequest
);
clk_process : process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
test_process : process
begin
REPORT "***Initializing***";
s_read <= '0';
s_write <= '0';
s_addr <= "00000000000000000000000000000000";
wait for clk_period;
report "Initializing Zero complete...";
report "***Start Testing***";
report "Read Miss Test:";
s_read <= '1';
s_write <= '0';
s_addr <= "11111111111111111111111110101111";
wait for clk_period;
assert s_readdata(7 downto 0) = m_readdata report "DATA NOT IN CACHE";
wait for clk_period;
report "Read Hit Test:";
s_read <= '1';
s_write <= '0';
s_addr <= "11111111111111111111111110101111";
wait for clk_period;
assert s_readdata(7 downto 0) = m_readdata report "DATA NOT IN CACHE";
wait for clk_period;
end process;
end;