OpenCores
URL https://opencores.org/ocsvn/arm4u/arm4u/trunk

Subversion Repositories arm4u

[/] [arm4u/] [trunk/] [hdl/] [cache.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 Bregalad
-- This file is part of ARM4U CPU
2
-- 
3
-- This is a creation of the Laboratory of Processor Architecture
4
-- of Ecole Polytechnique Fédérale de Lausanne ( http://lap.epfl.ch )
5
--
6
-- cache.vhd  --  A cache with an Avalon master interface. Only for instruction and direct-mapped for now.
7
--
8
-- Written By -  Jonathan Masur and Xavier Jimenez (2013)
9
--
10
-- This program is free software; you can redistribute it and/or modify it
11
-- under the terms of the GNU General Public License as published by the
12
-- Free Software Foundation; either version 2, or (at your option) any
13
-- later version.
14
--
15
-- This program is distributed in the hope that it will be useful,
16
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
17
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
-- GNU General Public License for more details.
19
--
20
-- In other words, you are welcome to use, share and improve this program.
21
-- You are forbidden to forbid anyone else to use, share and improve
22
-- what you give them.   Help stamp out software-hoarding!
23
 
24
library IEEE;
25
use IEEE.std_logic_1164.all;
26
use IEEE.std_logic_unsigned.all;
27
use IEEE.numeric_std.all;
28
 
29
library altera_mf;
30
use altera_mf.all;
31
 
32
library work;
33
use work.utils.all;
34
 
35
entity cache is
36
        generic(
37
                INSTR_BADDR_BITWDTH : natural := 32;  -- input coe_cpu_address width in bits
38
                BLOCK_BITWIDTH      : natural := 5;   -- byte address range of a block (hence C_BLOCK_SIZE = 2**BLOCK_BITWIDTH)
39
                CACHE_SIZE          : natural := 4096 -- cache size in bytes, must be a factor of C_BLOCK_SIZE * CACHE_WAYS
40
        );
41
        port(
42
                -- Globals
43
                clk   : in std_logic;
44
                reset : in std_logic;
45
 
46
                -- CPU conduit extern
47
                coe_cpu_enabled   : in std_logic; -- fetches a new instruction. If deactivated, the last read is kept on the output.
48
                coe_cpu_flush     : in std_logic := '0'; -- flushes the cache line addressed by "coe_cpu_address" and cancels any pending read
49
                coe_cpu_address   : in  std_logic_vector(INSTR_BADDR_BITWDTH-1 downto 0); -- byte address
50
                coe_cpu_readdata  : out std_logic_vector(31 downto 0);
51
                coe_cpu_miss      : out std_logic;
52
 
53
                --Avalon Master Interface
54
                avm_waitrequest   : in  std_logic;
55
                avm_readdatavalid : in  std_logic;
56
                avm_readdata      : in  std_logic_vector(31 downto 0);
57
                avm_read          : out std_logic;
58
                avm_burstcount    : out std_logic_vector(BLOCK_BITWIDTH-2 downto 0);
59
                avm_address       : out std_logic_vector(31 downto 0)
60
          );
61
end cache;
62
 
63
architecture synth of cache is
64
constant C_BLOCK_SIZE     : natural := 2**BLOCK_BITWIDTH;
65
constant C_SET_COUNT      : natural := CACHE_SIZE / C_BLOCK_SIZE;
66
constant C_INDEX_BITWIDTH : natural := log2(C_SET_COUNT);
67
constant C_TAG_BITWIDTH   : natural := INSTR_BADDR_BITWDTH - BLOCK_BITWIDTH - C_INDEX_BITWIDTH;
68
constant C_DATA_WADDR_BITWIDTH : natural := log2(CACHE_SIZE)-2; -- addressable words in the data sram
69
 
70
-- registerd coe_cpu_address (without the 2 lsb)
71
signal r_address : std_logic_vector(INSTR_BADDR_BITWDTH-3 downto 0);
72
signal r_read    : std_logic;
73
-- register flush command
74
signal r_flush : std_logic;
75
-- the current offset in a burst
76
signal r_burstoffset : std_logic_vector(log2(C_BLOCK_SIZE)-3 downto 0);
77
-- the tag and valid bit
78
signal s_vtag_in    : std_logic_vector(C_TAG_BITWIDTH DOWNTO 0);
79
signal s_vtag_out   : std_logic_vector(C_TAG_BITWIDTH DOWNTO 0);
80
-- signals to the tag and data srams
81
signal s_data_wren : std_logic;
82
signal s_data_rdaddr : std_logic_vector(C_DATA_WADDR_BITWIDTH-1 downto 0);
83
signal s_data_wraddr : std_logic_vector(C_DATA_WADDR_BITWIDTH-1 downto 0);
84
signal s_tag_wren  : std_logic;
85
signal s_tag_rdaddr  : std_logic_vector(C_INDEX_BITWIDTH-1 downto 0);
86
signal s_tag_wraddr  : std_logic_vector(C_INDEX_BITWIDTH-1 downto 0);
87
signal s_addr_stall : std_logic;
88
signal s_miss      : std_logic;
89
 
90
type state_type is (S_READY, S_WAIT, S_READ, S_DELAY);
91
signal state, nextstate : state_type;
92
 
93
-- SRAM component declaration
94
component altsyncram
95
generic (
96
        address_reg_b           : STRING;
97
        clock_enable_input_a            : STRING;
98
        clock_enable_input_b            : STRING;
99
        clock_enable_output_a           : STRING;
100
        clock_enable_output_b           : STRING;
101
        intended_device_family          : STRING;
102
        lpm_type                : STRING;
103
        numwords_a              : NATURAL;
104
        numwords_b              : NATURAL;
105
        operation_mode          : STRING;
106
        outdata_aclr_b          : STRING;
107
        outdata_reg_b           : STRING;
108
        power_up_uninitialized          : STRING;
109
        read_during_write_mode_mixed_ports              : STRING;
110
        widthad_a               : NATURAL;
111
        widthad_b               : NATURAL;
112
        width_a         : NATURAL;
113
        width_b         : NATURAL;
114
        width_byteena_a         : NATURAL
115
);
116
port (
117
        addressstall_b : IN STD_LOGIC ;
118
        wren_a  : IN STD_LOGIC ;
119
        clock0  : IN STD_LOGIC ;
120
        clock1  : IN STD_LOGIC ;
121
        address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
122
        address_b : IN STD_LOGIC_VECTOR (widthad_b-1 DOWNTO 0);
123
        q_b       : OUT STD_LOGIC_VECTOR (width_b-1 DOWNTO 0);
124
        data_a    : IN STD_LOGIC_VECTOR (width_a-1 downto 0)
125
);
126
end component;
127
 
128
begin
129
coe_cpu_miss <= s_miss;
130
-- we do not have a coe_cpu_miss when flushing, or when the tag matches a valid entry
131
s_miss <= '0' when r_read='0' or (coe_cpu_flush or r_flush)='1' or s_vtag_in=s_vtag_out else '1'; -- TODO: to be modified for multiple ways
132
 
133
-- the burstcount is fixed
134
avm_burstcount <= std_logic_vector(to_unsigned(C_BLOCK_SIZE/4, avm_burstcount'length));
135
avm_address <= (31 downto INSTR_BADDR_BITWDTH =>'0') & r_address(INSTR_BADDR_BITWDTH-3 downto BLOCK_BITWIDTH-2) & (BLOCK_BITWIDTH-1 downto 0 => '0');
136
 
137
-- signals to the data and tag srams
138
s_addr_stall  <= s_miss or not coe_cpu_enabled;
139
s_data_rdaddr <= coe_cpu_address(C_DATA_WADDR_BITWIDTH+1 downto 2);
140
s_data_wraddr <= r_address(C_DATA_WADDR_BITWIDTH-1 downto BLOCK_BITWIDTH-2) & r_burstoffset;
141
s_tag_rdaddr  <= coe_cpu_address(C_DATA_WADDR_BITWIDTH+1 downto BLOCK_BITWIDTH);
142
s_tag_wraddr  <= r_address(C_DATA_WADDR_BITWIDTH-1 downto BLOCK_BITWIDTH-2);
143
-- s_tag_wren and s_vtag_in
144
process(r_address, r_flush, r_burstoffset, avm_readdatavalid)
145
begin
146
        s_tag_wren <= '0';
147
        s_vtag_in  <= r_address(INSTR_BADDR_BITWDTH-3 downto INSTR_BADDR_BITWDTH-C_TAG_BITWIDTH-2) & '1';
148
        if (r_flush = '1') then
149
                s_tag_wren <= '1';
150
                s_vtag_in  <= (others => '0');
151
        elsif (r_burstoffset = (r_burstoffset'range => '1') and avm_readdatavalid='1') then
152
                s_tag_wren <= '1';
153
        end if;
154
end process;
155
 
156
process(reset, clk)
157
begin
158
        if (reset = '1') then
159
                r_burstoffset <= (others => '0');
160
                state <= S_READY;
161
                r_flush <= '0';
162
                r_read <= '0';
163
        elsif (rising_edge(clk)) then
164
                r_read <= coe_cpu_enabled or s_miss; -- in case of miss we fix r_read to 1.
165
                case state is
166
                        when S_READY =>
167
                                r_flush <= coe_cpu_flush;
168
                                if (s_miss = '1') then
169
                                        if (avm_waitrequest = '1') then
170
                                                state <= S_WAIT;
171
                                        else
172
                                                state <= S_READ;
173
                                        end if;
174
                                else
175
                                        -- in case of a coe_cpu_miss the coe_cpu_address is unchanged
176
                                        if (coe_cpu_enabled = '1' or coe_cpu_flush='1') then
177
                                                r_address <= coe_cpu_address(INSTR_BADDR_BITWDTH-1 downto 2);
178
                                        end if;
179
                                end if;
180
                                r_burstoffset <= (others => '0');
181
 
182
                        when S_WAIT =>
183
                                if (avm_waitrequest = '0') then
184
                                        state <= S_READ;
185
                                end if;
186
 
187
                        when S_READ =>
188
                                if (r_burstoffset = (r_burstoffset'range => '1') and avm_readdatavalid='1') then
189
                                        state <= S_DELAY;
190
                                end if;
191
 
192
                        when S_DELAY =>
193
                                state <= S_READY;
194
 
195
                end case;
196
 
197
                -- update r_burst_offset
198
                if (avm_readdatavalid='1') then
199
                        r_burstoffset <= r_burstoffset + 1;
200
                end if;
201
        end if;
202
end process;
203
 
204
process(state, s_miss)
205
begin
206
        case state is
207
                when S_READY =>
208
                        avm_read <= s_miss;
209
                when S_WAIT =>
210
                        avm_read <= '1';
211
                when others =>
212
                        avm_read <= '0';
213
        end case;
214
end process;
215
 
216
 
217
-- Data SRAM
218
g_data_sram : altsyncram
219
        GENERIC MAP (
220
                address_reg_b => "CLOCK1",
221
                clock_enable_input_a => "BYPASS",
222
                clock_enable_input_b => "BYPASS",
223
                clock_enable_output_a => "BYPASS",
224
                clock_enable_output_b => "BYPASS",
225
                intended_device_family => "Cyclone IV E",
226
                lpm_type => "altsyncram",
227
                numwords_a => CACHE_SIZE/4,
228
                numwords_b => CACHE_SIZE/4,
229
                operation_mode => "DUAL_PORT",
230
                outdata_aclr_b => "NONE",
231
                outdata_reg_b => "UNREGISTERED",
232
                power_up_uninitialized => "FALSE",
233
                read_during_write_mode_mixed_ports => "DONT_CARE",
234
                widthad_a => C_DATA_WADDR_BITWIDTH,
235
                widthad_b => C_DATA_WADDR_BITWIDTH,
236
                width_a => 32,
237
                width_b => 32,
238
                width_byteena_a => 1
239
        )
240
        PORT MAP (
241
                addressstall_b => s_addr_stall,
242
                wren_a => avm_readdatavalid,
243
                clock0 => clk,
244
                clock1 => clk,
245
                address_a => s_data_wraddr,
246
                address_b => s_data_rdaddr,
247
                data_a => avm_readdata,
248
                q_b => coe_cpu_readdata
249
        );
250
 
251
 
252
g_tag_sram : altsyncram
253
        GENERIC MAP (
254
                address_reg_b => "CLOCK1",
255
                clock_enable_input_a => "BYPASS",
256
                clock_enable_input_b => "BYPASS",
257
                clock_enable_output_a => "BYPASS",
258
                clock_enable_output_b => "BYPASS",
259
                intended_device_family => "Cyclone IV E",
260
                lpm_type => "altsyncram",
261
                numwords_a => C_SET_COUNT,
262
                numwords_b => C_SET_COUNT,
263
                operation_mode => "DUAL_PORT",
264
                outdata_aclr_b => "NONE",
265
                outdata_reg_b => "UNREGISTERED",
266
                power_up_uninitialized => "FALSE",
267
                read_during_write_mode_mixed_ports => "DONT_CARE",
268
                widthad_a => C_INDEX_BITWIDTH,
269
                widthad_b => C_INDEX_BITWIDTH,
270
                width_a => C_TAG_BITWIDTH+1,
271
                width_b => C_TAG_BITWIDTH+1,
272
                width_byteena_a => 1
273
        )
274
        PORT MAP (
275
                addressstall_b => s_addr_stall,
276
                wren_a => s_tag_wren,
277
                clock0 => clk,
278
                clock1 => clk,
279
                address_a => s_tag_wraddr,
280
                address_b => s_tag_rdaddr,
281
                data_a => s_vtag_in,
282
                q_b => s_vtag_out
283
        );
284
 
285
end synth;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.