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

Subversion Repositories lxp32

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 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
                wclk_i=>clk_i,
115
                we_i=>ram_we,
116
                waddr_i=>ram_waddr,
117
                wdata_i=>wbm_dat_i,
118
 
119
                rclk_i=>clk_i,
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
                else
206
                        if burst_cnt=0 and init='1' then
207
                                if miss='1' and near_miss='0' then
208
                                        wb_stb<='1';
209
                                        wb_cti<="010";
210
                                        current_offset<=read_offset;
211
                                        start_offset<=read_offset;
212
                                        current_base<=read_base;
213
                                        next_base<=read_base+1;
214
                                        burst_cnt<=1;
215
                                        burst1<='1';
216
                                        wrap_cnt<=1;
217
                                elsif prefetch_distance<to_unsigned(PREFETCH_SIZE,8) or near_miss='1' then
218
                                        wb_stb<='1';
219
                                        wb_cti<="010";
220
                                        burst_cnt<=1;
221
                                        burst1<='0';
222
                                end if;
223
                        else
224
                                if wbm_ack_i='1' then
225
                                        current_offset<=current_offset+1;
226
                                        if current_offset=X"FF" then
227
                                                current_base<=next_base;
228
                                                next_base<=next_base+1;
229
                                                prev_base<=current_base;
230
                                                if wrap_cnt<3 then
231
                                                        wrap_cnt<=wrap_cnt+1;
232
                                                end if;
233
                                        end if;
234
                                        if burst_cnt=BURST_SIZE-1 or terminate_burst='1' then
235
                                                burst_cnt<=BURST_SIZE;
236
                                                wb_cti<="111";
237
                                        elsif burst_cnt<BURST_SIZE-1 then
238
                                                burst_cnt<=burst_cnt+1;
239
                                                wb_cti<="010";
240
                                        else
241
                                                if miss='1' and near_miss='0' then
242
                                                        wb_stb<='1';
243
                                                        wb_cti<="010";
244
                                                        current_offset<=read_offset;
245
                                                        start_offset<=read_offset;
246
                                                        current_base<=read_base;
247
                                                        next_base<=read_base+1;
248
                                                        burst_cnt<=1;
249
                                                        burst1<='1';
250
                                                        wrap_cnt<=1;
251
                                                elsif prefetch_distance<to_unsigned(PREFETCH_SIZE,8) or near_miss='1' then
252
                                                        wb_stb<='1';
253
                                                        wb_cti<="010";
254
                                                        burst_cnt<=1;
255
                                                        burst1<='0';
256
                                                else
257
                                                        burst_cnt<=0;
258
                                                        wb_stb<='0';
259
                                                end if;
260
                                        end if;
261
                                end if;
262
                        end if;
263
                end if;
264
        end if;
265
end process;
266
 
267
wbm_cyc_o<=wb_stb;
268
wbm_stb_o<=wb_stb;
269
wbm_cti_o<=wb_cti;
270
wbm_bte_o<="00";
271
wbm_adr_o<=std_logic_vector(current_base&current_offset);
272
 
273
end architecture;

powered by: WebSVN 2.1.0

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