1

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.

Full signal diagram

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;
  • Aren't you supposed to use the clock in the `cache` module? – maximus Feb 25 '21 at 20:22
  • `process (s_addr)` This process sensitivity list isn't complete. The rules for constructing a sensitivity list are found in IEEE Std 1076-2008 10.2 Wait statement, referenced from 11.3 Process statement. Your questions aren't specific and adding information to your waveform troubleshooting would lead you to look at the process. As Rakend alludes there may be other issues with your design description. –  Feb 26 '21 at 01:17

0 Answers0