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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_icache.vhd] - Blame information for rev 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 ring0_mipt
---------------------------------------------------------------------
2
-- Instruction cache
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8
-- A simple single-page buffer providing both caching and
9
-- prefetching capabilities. Useful for high-latency memory,
10
-- such as external SDRAM.
11
---------------------------------------------------------------------
12
 
13
library ieee;
14
use ieee.std_logic_1164.all;
15
use ieee.numeric_std.all;
16
 
17
entity lxp32_icache is
18
        generic(
19
                BURST_SIZE: integer;
20
                PREFETCH_SIZE: integer
21
        );
22
        port(
23
                clk_i: in std_logic;
24
                rst_i: in std_logic;
25
 
26
                lli_re_i: in std_logic;
27
                lli_adr_i: in std_logic_vector(29 downto 0);
28
                lli_dat_o: out std_logic_vector(31 downto 0);
29
                lli_busy_o: out std_logic;
30
 
31
                wbm_cyc_o: out std_logic;
32
                wbm_stb_o: out std_logic;
33
                wbm_cti_o: out std_logic_vector(2 downto 0);
34
                wbm_bte_o: out std_logic_vector(1 downto 0);
35
                wbm_ack_i: in std_logic;
36
                wbm_adr_o: out std_logic_vector(29 downto 0);
37
                wbm_dat_i: in std_logic_vector(31 downto 0)
38
        );
39
end entity;
40
 
41
architecture rtl of lxp32_icache is
42
 
43
signal lli_adr_reg: std_logic_vector(lli_adr_i'range);
44
signal lli_adr_mux: std_logic_vector(lli_adr_i'range);
45
 
46
signal ram_waddr: std_logic_vector(7 downto 0);
47
signal ram_raddr: std_logic_vector(7 downto 0);
48
signal ram_re: std_logic;
49
signal ram_we: std_logic;
50
 
51
signal read_base: unsigned(21 downto 0);
52
signal read_offset: unsigned(7 downto 0);
53
 
54
signal init: std_logic:='0';
55
signal burst1: std_logic;
56
signal terminate_burst: std_logic;
57
signal near_miss: std_logic:='0';
58
signal prefetch_distance: unsigned(7 downto 0);
59
signal wrap_cnt: integer range 0 to 3:=0;
60
signal burst_cnt: integer range 0 to BURST_SIZE:=0;
61
signal wb_stb: std_logic:='0';
62
signal wb_cti: std_logic_vector(2 downto 0);
63
 
64
-- Note: the following five signals are zero-initialized for
65
-- simulation only, to suppress warnings from numeric_std.
66
-- This initialization is not required for synthesis.
67
 
68
signal current_base: unsigned(21 downto 0):=(others=>'0');
69
signal current_offset: unsigned(7 downto 0):=(others=>'0');
70
signal prev_base: unsigned(21 downto 0):=(others=>'0');
71
signal next_base: unsigned(21 downto 0):=(others=>'0');
72
signal start_offset: unsigned(7 downto 0):=(others=>'0');
73
 
74
signal hitc: std_logic;
75
signal hitp: std_logic;
76
signal miss: std_logic:='0';
77
 
78
begin
79
 
80
assert PREFETCH_SIZE>=4
81
        report "PREFETCH_SIZE cannot be less than 4"
82
        severity failure;
83
assert BURST_SIZE>=4
84
        report "BURST_SIZE cannot be less than 4"
85
        severity failure;
86
assert PREFETCH_SIZE+BURST_SIZE<=128
87
        report "PREFETCH_SIZE and BURST_SIZE combined cannot be greater than 128"
88
        severity failure;
89
 
90
 
91
process (clk_i) is
92
begin
93
        if rising_edge(clk_i) then
94
                if miss='0' then
95
                        lli_adr_reg<=lli_adr_i;
96
                end if;
97
        end if;
98
end process;
99
 
100
lli_adr_mux<=lli_adr_i when miss='0' else lli_adr_reg;
101
 
102
read_base<=unsigned(lli_adr_mux(29 downto 8));
103
read_offset<=unsigned(lli_adr_mux(7 downto 0));
104
 
105
-- Cache RAM
106
 
107
ram_waddr<=std_logic_vector(current_offset);
108
ram_raddr<=std_logic_vector(read_offset);
109
ram_we<=wb_stb and wbm_ack_i;
110
ram_re<=lli_re_i or miss;
111
 
112
ram_inst: entity work.lxp32_ram256x32(rtl)
113
        port map(
114
                clk_i=>clk_i,
115
 
116
                we_i=>ram_we,
117
                waddr_i=>ram_waddr,
118
                wdata_i=>wbm_dat_i,
119
 
120
                re_i=>ram_re,
121
                raddr_i=>ram_raddr,
122
                rdata_o=>lli_dat_o
123
        );
124
 
125
-- Determine hit/miss
126
 
127
-- This cache uses a single ring buffer. Address in buffer corresponds
128
-- to the lower 8 bits of the full address. The part of the buffer that
129
-- is higher than current_offset represents a previous block ("p"), the
130
-- other part represents a current block ("c").
131
 
132
hitc<='1' when read_base=current_base and read_offset<current_offset and
133
        ((wrap_cnt=1 and read_offset>=start_offset) or
134
        wrap_cnt=2 or wrap_cnt=3) else '0';
135
 
136
hitp<='1' when read_base=prev_base and read_offset>current_offset and
137
        ((wrap_cnt=2 and read_offset>=start_offset) or
138
        wrap_cnt=3) else '0';
139
 
140
process (clk_i) is
141
begin
142
        if rising_edge(clk_i) then
143
                if rst_i='1' then
144
                        miss<='0';
145
                else
146
                        if hitc='0' and hitp='0' and ram_re='1' then
147
                                miss<='1';
148
                        else
149
                                miss<='0';
150
                        end if;
151
                end if;
152
        end if;
153
end process;
154
 
155
lli_busy_o<=miss;
156
 
157
-- Set INIT flag when the first lli_re_i signal is detected
158
 
159
process (clk_i) is
160
begin
161
        if rising_edge(clk_i) then
162
                if rst_i='1' then
163
                        init<='0';
164
                elsif lli_re_i='1' then
165
                        init<='1';
166
                end if;
167
        end if;
168
end process;
169
 
170
-- Fill cache
171
 
172
prefetch_distance<=current_offset-read_offset;
173
 
174
-- Note: "near_miss" signal prevents cache invalidation when difference
175
-- between the requested address and the currently fetched address 
176
-- is too small (and, therefore, the requested data will be fetched soon
177
-- without invalidation).
178
 
179
process (clk_i) is
180
begin
181
        if rising_edge(clk_i) then
182
                if rst_i='1' then
183
                        near_miss<='0';
184
                elsif wrap_cnt>0 and read_offset-current_offset<=to_unsigned(BURST_SIZE/2,8) and
185
                        ((read_base=current_base and read_offset>=current_offset) or
186
                        (read_base=next_base and read_offset<current_offset))
187
                then
188
                        near_miss<='1';
189
                else
190
                        near_miss<='0';
191
                end if;
192
        end if;
193
end process;
194
 
195
terminate_burst<='1' when burst_cnt<BURST_SIZE-1 and miss='1' and
196
        (burst_cnt>2 or burst1='0') and near_miss='0' else '0';
197
 
198
process (clk_i) is
199
begin
200
        if rising_edge(clk_i) then
201
                if rst_i='1' then
202
                        burst_cnt<=0;
203
                        wb_stb<='0';
204
                        wrap_cnt<=0;
205
                        wb_cti<=(others=>'-');
206
                        burst1<='-';
207
                        current_offset<=(others=>'-');
208
                        start_offset<=(others=>'-');
209
                        current_base<=(others=>'-');
210
                        next_base<=(others=>'-');
211
                        prev_base<=(others=>'-');
212
 
213
                        -- To suppress numeric_std warnings
214
                        -- synthesis translate_off
215
                        current_offset<=(others=>'0');
216
                        start_offset<=(others=>'0');
217
                        current_base<=(others=>'0');
218
                        next_base<=(others=>'0');
219
                        prev_base<=(others=>'0');
220
                        -- synthesis translate_on
221
                else
222
                        if burst_cnt=0 and init='1' then
223
                                if miss='1' and near_miss='0' then
224
                                        wb_stb<='1';
225
                                        wb_cti<="010";
226
                                        current_offset<=read_offset;
227
                                        start_offset<=read_offset;
228
                                        current_base<=read_base;
229
                                        next_base<=read_base+1;
230
                                        burst_cnt<=1;
231
                                        burst1<='1';
232
                                        wrap_cnt<=1;
233
                                elsif prefetch_distance<to_unsigned(PREFETCH_SIZE,8) or near_miss='1' then
234
                                        wb_stb<='1';
235
                                        wb_cti<="010";
236
                                        burst_cnt<=1;
237
                                        burst1<='0';
238
                                end if;
239
                        else
240
                                if wbm_ack_i='1' then
241
                                        current_offset<=current_offset+1;
242
                                        if current_offset=X"FF" then
243
                                                current_base<=next_base;
244
                                                next_base<=next_base+1;
245
                                                prev_base<=current_base;
246
                                                if wrap_cnt<3 then
247
                                                        wrap_cnt<=wrap_cnt+1;
248
                                                end if;
249
                                        end if;
250
                                        if burst_cnt=BURST_SIZE-1 or terminate_burst='1' then
251
                                                burst_cnt<=BURST_SIZE;
252
                                                wb_cti<="111";
253
                                        elsif burst_cnt<BURST_SIZE-1 then
254
                                                burst_cnt<=burst_cnt+1;
255
                                                wb_cti<="010";
256
                                        else
257
                                                if miss='1' and near_miss='0' then
258
                                                        wb_stb<='1';
259
                                                        wb_cti<="010";
260
                                                        current_offset<=read_offset;
261
                                                        start_offset<=read_offset;
262
                                                        current_base<=read_base;
263
                                                        next_base<=read_base+1;
264
                                                        burst_cnt<=1;
265
                                                        burst1<='1';
266
                                                        wrap_cnt<=1;
267
                                                elsif prefetch_distance<to_unsigned(PREFETCH_SIZE,8) or near_miss='1' then
268
                                                        wb_stb<='1';
269
                                                        wb_cti<="010";
270
                                                        burst_cnt<=1;
271
                                                        burst1<='0';
272
                                                else
273
                                                        burst_cnt<=0;
274
                                                        wb_stb<='0';
275
                                                end if;
276
                                        end if;
277
                                end if;
278
                        end if;
279
                end if;
280
        end if;
281
end process;
282
 
283
wbm_cyc_o<=wb_stb;
284
wbm_stb_o<=wb_stb;
285
wbm_cti_o<=wb_cti;
286
wbm_bte_o<="00";
287
wbm_adr_o<=std_logic_vector(current_base&current_offset);
288
 
289
end architecture;

powered by: WebSVN 2.1.0

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