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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [cache/] [icache.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
-----------------------------------------------------------------------------
2
--! @file
3
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
5
--! @brief     Instruction Cache.
6
------------------------------------------------------------------------------
7
 
8
library ieee;
9
use ieee.std_logic_1164.all;
10
library commonlib;
11
use commonlib.types_common.all;
12
--! RIVER CPU specific library.
13
library riverlib;
14
--! RIVER CPU configuration constants.
15
use riverlib.river_cfg.all;
16
 
17
entity ICache is
18
  port (
19
    i_clk : in std_logic;                              -- CPU clock
20
    i_nrst : in std_logic;                             -- Reset. Active LOW.
21
    -- Control path:
22
    i_req_ctrl_valid : in std_logic;
23
    i_req_ctrl_addr : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
24
    o_req_ctrl_ready : out std_logic;
25
    o_resp_ctrl_valid : out std_logic;
26
    o_resp_ctrl_addr : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
27
    o_resp_ctrl_data : out std_logic_vector(31 downto 0);
28
    i_resp_ctrl_ready : in std_logic;
29
    -- Memory interface:
30
    i_req_mem_ready : in std_logic;
31
    o_req_mem_valid : out std_logic;
32
    o_req_mem_write : out std_logic;
33
    o_req_mem_addr : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
34
    o_req_mem_strob : out std_logic_vector(BUS_DATA_BYTES-1 downto 0);
35
    o_req_mem_data : out std_logic_vector(BUS_DATA_WIDTH-1 downto 0);
36
    i_resp_mem_data_valid : in std_logic;
37
    i_resp_mem_data : in std_logic_vector(BUS_DATA_WIDTH-1 downto 0);
38
    -- Debug Signals:
39
    o_istate : out std_logic_vector(1 downto 0)
40
  );
41
end;
42
 
43
architecture arch_ICache of ICache is
44
 
45
  constant State_Idle : std_logic_vector(1 downto 0) := "00";
46
  constant State_WaitGrant : std_logic_vector(1 downto 0) := "01";
47
  constant State_WaitResp : std_logic_vector(1 downto 0) := "10";
48
  constant State_WaitAccept : std_logic_vector(1 downto 0) := "11";
49
 
50
  constant Hit_Line1 : integer := 0;
51
  constant Hit_Line2 : integer := 1;
52
  constant Hit_Response : integer := 2;
53
  constant Hit_Total : integer := 3;
54
 
55
  constant ILINE_TOTAL : integer := 2;
56
 
57
  type line_type is record
58
      addr : std_logic_vector(BUS_ADDR_WIDTH-4 downto 0);
59
      data : std_logic_vector(BUS_DATA_WIDTH-1 downto 0);
60
  end record;
61
 
62
  type iline_vector is array (0 to ILINE_TOTAL-1) of line_type;
63
 
64
  type line_signal_type is record
65
       hit : std_logic_vector(ILINE_TOTAL downto 0);     -- Hit_Total = ILINE_TOTAL + 1
66
       hit_hold : std_logic_vector(ILINE_TOTAL-1 downto 0);
67
       hit_data : std_logic_vector(BUS_DATA_WIDTH-1 downto 0);
68
       hold_data : std_logic_vector(BUS_DATA_WIDTH-1 downto 0);
69
  end record;
70
 
71
  type line_signal_vector is array (0 to ILINE_TOTAL-1) of line_signal_type;
72
 
73
  type RegistersType is record
74
      iline : iline_vector;
75
      iline_addr_req : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
76
      addr_processing : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
77
      state : std_logic_vector(1 downto 0);
78
      double_req : std_logic;
79
      delay_valid : std_logic;
80
      delay_data : std_logic_vector(31 downto 0);
81
  end record;
82
 
83
  type adr_type is array (0 to 1) of std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
84
 
85
  signal r, rin : RegistersType;
86
 
87
begin
88
 
89
  comb : process(i_nrst, i_req_ctrl_valid, i_req_ctrl_addr,
90
                i_resp_ctrl_ready, i_req_mem_ready,
91
                i_resp_mem_data_valid, i_resp_mem_data, r)
92
    variable v : RegistersType;
93
    variable w_need_mem_req : std_logic;
94
    variable wb_hit_word : std_logic_vector(31 downto 0);
95
    variable wb_l : line_signal_vector;
96
    variable w_reuse_lastline : std_logic;
97
    variable w_wait_response : std_logic;
98
 
99
    variable w_o_req_ctrl_ready : std_logic;
100
    variable w_o_req_mem_valid : std_logic;
101
    variable wb_o_req_mem_addr : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
102
    variable w_req_ctrl_valid : std_logic;
103
    variable w_req_fire : std_logic;
104
    variable w_o_resp_valid : std_logic;
105
    variable wb_o_resp_addr : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
106
    variable wb_o_resp_data : std_logic_vector(31 downto 0);
107
    variable wb_req_addr : adr_type;
108
    variable wb_hold_addr : adr_type;
109
  begin
110
 
111
    v := r;
112
 
113
    w_wait_response := '0';
114
    if r.state = State_WaitResp and i_resp_mem_data_valid = '0' then
115
        w_wait_response := '1';
116
    end if;
117
 
118
    w_req_ctrl_valid := not w_wait_response
119
                        and (i_req_ctrl_valid or r.double_req);
120
    wb_req_addr(0) := i_req_ctrl_addr;
121
    wb_req_addr(1) := i_req_ctrl_addr + 2;
122
 
123
    wb_hold_addr(0) := r.addr_processing;
124
    wb_hold_addr(1) := r.addr_processing + 2;
125
 
126
    for i in 0 to ILINE_TOTAL-1 loop
127
        wb_l(i).hit := (others => '0');
128
        wb_l(i).hit_data := (others => '0');
129
        if wb_req_addr(i)(BUS_ADDR_WIDTH-1 downto 3) = r.iline(0).addr then
130
            wb_l(i).hit(Hit_Line1) := w_req_ctrl_valid;
131
            wb_l(i).hit_data := r.iline(0).data;
132
        elsif wb_req_addr(i)(BUS_ADDR_WIDTH-1 downto 3) = r.iline(1).addr then
133
            wb_l(i).hit(Hit_Line2) := w_req_ctrl_valid;
134
            wb_l(i).hit_data := r.iline(1).data;
135
        elsif wb_req_addr(i)(BUS_ADDR_WIDTH-1 downto 3) =
136
            r.iline_addr_req(BUS_ADDR_WIDTH-1 downto 3) then
137
            wb_l(i).hit(Hit_Response) := i_resp_mem_data_valid;
138
            wb_l(i).hit_data := i_resp_mem_data;
139
        end if;
140
 
141
        wb_l(i).hit_hold := (others => '0');
142
        wb_l(i).hold_data := (others => '0');
143
        if wb_hold_addr(i)(BUS_ADDR_WIDTH-1 downto 3) = r.iline(0).addr then
144
            wb_l(i).hit_hold(Hit_Line1) := '1';
145
            wb_l(i).hold_data := r.iline(0).data;
146
        elsif wb_hold_addr(i)(BUS_ADDR_WIDTH-1 downto 3) = r.iline(1).addr then
147
            wb_l(i).hit_hold(Hit_Line2) := '1';
148
            wb_l(i).hold_data := r.iline(1).data;
149
        elsif wb_hold_addr(i)(BUS_ADDR_WIDTH-1 downto 3) =
150
            r.iline_addr_req(BUS_ADDR_WIDTH-1 downto 3) then
151
            wb_l(i).hold_data := i_resp_mem_data;
152
        end if;
153
    end loop;
154
 
155
    wb_hit_word := (others => '0');
156
    w_need_mem_req := '1';
157
    if wb_l(0).hit /= "000" and wb_l(1).hit /= "000" then
158
        w_need_mem_req := '0';
159
    end if;
160
    case r.addr_processing(2 downto 1) is
161
    when "00" =>
162
        wb_hit_word := wb_l(0).hold_data(31 downto 0);
163
    when "01" =>
164
        wb_hit_word := wb_l(0).hold_data(47 downto 16);
165
    when "10" =>
166
        wb_hit_word := wb_l(0).hold_data(63 downto 32);
167
    when others =>
168
        wb_hit_word := wb_l(1).hold_data(15 downto 0) &
169
                       wb_l(0).hold_data(63 downto 48);
170
    end case;
171
 
172
    if w_req_ctrl_valid = '1' and w_need_mem_req = '0' then
173
        v.delay_valid := '1';
174
        case i_req_ctrl_addr(2 downto 1) is
175
        when "00" =>
176
            v.delay_data := wb_l(0).hit_data(31 downto 0);
177
        when "01" =>
178
            v.delay_data := wb_l(0).hit_data(47 downto 16);
179
        when "10" =>
180
            v.delay_data := wb_l(0).hit_data(63 downto 32);
181
        when others =>
182
            v.delay_data := wb_l(1).hit_data(15 downto 0) &
183
                            wb_l(0).hit_data(63 downto 48);
184
        end case;
185
    elsif i_resp_ctrl_ready = '1' then
186
        v.delay_valid := '0';
187
        v.delay_data := (others => '0');
188
    end if;
189
 
190
    w_o_req_mem_valid := w_need_mem_req and w_req_ctrl_valid;
191
    if r.double_req = '1' then
192
        if (r.addr_processing(BUS_ADDR_WIDTH-1 downto 3) =
193
            r.iline_addr_req(BUS_ADDR_WIDTH-1 downto 3))
194
            or (r.addr_processing(BUS_ADDR_WIDTH-1 downto 3) =
195
                wb_hold_addr(0)(BUS_ADDR_WIDTH-1 downto 3)) then
196
            wb_o_req_mem_addr := wb_hold_addr(1)(BUS_ADDR_WIDTH-1 downto 3) & "000";
197
        else
198
            wb_o_req_mem_addr := wb_hold_addr(0)(BUS_ADDR_WIDTH-1 downto 3) & "000";
199
        end if;
200
    elsif wb_l(0).hit = "000" then
201
        wb_o_req_mem_addr := wb_req_addr(0)(BUS_ADDR_WIDTH-1 downto 3)  & "000";
202
    else
203
        wb_o_req_mem_addr := wb_req_addr(1)(BUS_ADDR_WIDTH-1 downto 3)  & "000";
204
    end if;
205
    w_o_req_ctrl_ready := not w_need_mem_req or (i_req_mem_ready and not w_wait_response);
206
    w_req_fire := w_req_ctrl_valid and w_o_req_ctrl_ready;
207
 
208
    if (w_o_req_mem_valid and i_req_mem_ready and not w_wait_response) = '1'
209
       or r.double_req = '1' then
210
        v.iline_addr_req := wb_o_req_mem_addr;
211
    end if;
212
 
213
    case r.state is
214
    when State_Idle =>
215
        if i_req_ctrl_valid = '1' then
216
            if w_need_mem_req = '0' then
217
                v.state := State_WaitAccept;
218
            elsif i_req_mem_ready = '1' then
219
                v.state := State_WaitResp;
220
            else
221
                v.state := State_WaitGrant;
222
            end if;
223
        end if;
224
    when State_WaitGrant =>
225
        if i_req_mem_ready = '1' then
226
            v.state := State_WaitResp;
227
        elsif w_need_mem_req = '0' then
228
            --! Fetcher can change request address while request wasn't
229
            --! accepteed.
230
            v.state := State_WaitAccept;
231
        end if;
232
    when State_WaitResp =>
233
        if i_resp_mem_data_valid = '1' then
234
            if i_resp_ctrl_ready = '0' then
235
                v.state := State_WaitAccept;
236
            elsif w_req_ctrl_valid = '0' then
237
                v.state := State_Idle;
238
            else
239
                -- New request
240
                if w_need_mem_req = '0' then
241
                    v.state := State_WaitAccept;
242
                elsif i_req_mem_ready = '1' then
243
                    v.state := State_WaitResp;
244
                else
245
                    v.state := State_WaitGrant;
246
                end if;
247
            end if;
248
        end if;
249
    when State_WaitAccept =>
250
        if i_resp_ctrl_ready = '1' then
251
            if w_req_ctrl_valid = '0' then
252
                v.state := State_Idle;
253
            else
254
                if w_need_mem_req = '0' then
255
                    v.state := State_WaitAccept;
256
                elsif i_req_mem_ready = '1' then
257
                    v.state := State_WaitResp;
258
                else
259
                    v.state := State_WaitGrant;
260
                end if;
261
            end if;
262
        end if;
263
    when others =>
264
    end case;
265
 
266
 
267
    if w_req_fire = '1' then
268
        v.double_req := '0';
269
        if i_req_ctrl_addr(2 downto 1) = "11"
270
            and wb_l(0).hit = "000" and wb_l(1).hit = "000"
271
            and r.double_req = '0' then
272
            v.double_req := '1';
273
        end if;
274
        if r.double_req = '0' then
275
            v.addr_processing := i_req_ctrl_addr;
276
        end if;
277
    end if;
278
 
279
    w_reuse_lastline := '0';
280
 
281
    if i_resp_mem_data_valid = '1' then
282
        --! Condition to avoid removing the last line:
283
        if i_resp_ctrl_ready = '1' then
284
            if (wb_l(0).hit(Hit_Line2) or wb_l(1).hit(Hit_Line2)) = '1'
285
                and r.iline(1).addr /= i_req_ctrl_addr(BUS_ADDR_WIDTH-1 downto 3) then
286
                w_reuse_lastline := w_need_mem_req;
287
            end if;
288
        else
289
            if (wb_l(0).hit_hold(Hit_Line2) or wb_l(1).hit_hold(Hit_Line2)) = '1'
290
                and (wb_l(0).hit_hold(Hit_Line1) or wb_l(1).hit_hold(Hit_Line1)) = '0'
291
                and r.iline(1).addr /= r.iline_addr_req(BUS_ADDR_WIDTH-1 downto 3) then
292
                w_reuse_lastline := '1';
293
            end if;
294
                  end if;
295
        if w_reuse_lastline = '0' then
296
            v.iline(1).addr := r.iline(0).addr;
297
            v.iline(1).data := r.iline(0).data;
298
        end if;
299
 
300
        v.iline(0).addr := r.iline_addr_req(BUS_ADDR_WIDTH-1 downto 3);
301
        v.iline(0).data := i_resp_mem_data;
302
    end if;
303
 
304
    if r.state = State_WaitAccept then
305
        w_o_resp_valid := not r.double_req;
306
    else
307
        w_o_resp_valid := i_resp_mem_data_valid and not r.double_req;
308
    end if;
309
    if r.delay_valid = '1' then
310
        wb_o_resp_data := r.delay_data;
311
    else
312
        wb_o_resp_data := wb_hit_word;
313
    end if;
314
    wb_o_resp_addr := r.addr_processing;
315
 
316
 
317
    if i_nrst = '0' then
318
        v.iline(0).addr := (others => '1');
319
        v.iline(0).data := (others => '0');
320
        v.iline(1).addr := (others => '1');
321
        v.iline(1).data := (others => '0');
322
        v.iline_addr_req := (others => '0');
323
        v.addr_processing := (others => '0');
324
        v.state := State_Idle;
325
        v.double_req := '0';
326
        v.delay_valid := '0';
327
        v.delay_data := (others => '0');
328
    end if;
329
 
330
    o_req_ctrl_ready <= w_o_req_ctrl_ready;
331
 
332
    o_req_mem_valid <= w_o_req_mem_valid;
333
    o_req_mem_addr <= wb_o_req_mem_addr;
334
    o_req_mem_write <= '0';
335
    o_req_mem_strob <= (others => '0');
336
    o_req_mem_data <= (others => '0');
337
 
338
    o_resp_ctrl_valid <= w_o_resp_valid;
339
    o_resp_ctrl_data <= wb_o_resp_data;
340
    o_resp_ctrl_addr <= wb_o_resp_addr;
341
    o_istate <= r.state;
342
 
343
    rin <= v;
344
  end process;
345
 
346
  -- registers:
347
  regs : process(i_clk)
348
  begin
349
     if rising_edge(i_clk) then
350
        r <= rin;
351
     end if;
352
  end process;
353
 
354
end;

powered by: WebSVN 2.1.0

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