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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [rtl/] [w11a/] [pdp11_cache.vhd] - Blame information for rev 40

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

Line No. Rev Author Line
1 37 wfjm
-- $Id: pdp11_cache.vhd 784 2016-07-09 22:17:01Z mueller $
2 2 wfjm
--
3 36 wfjm
-- Copyright 2008-2016 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 2 wfjm
--
5
-- This program is free software; you may redistribute and/or modify it under
6
-- the terms of the GNU General Public License as published by the Free
7
-- Software Foundation, either version 2, or at your option any later version.
8
--
9
-- This program is distributed in the hope that it will be useful, but
10
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
-- for complete details.
13
-- 
14
------------------------------------------------------------------------------
15
-- Module Name:    pdp11_cache - syn
16
-- Description:    pdp11: cache
17
--
18
-- Dependencies:   memlib/ram_2swsr_rfirst_gen
19
-- Test bench:     -
20
-- Target Devices: generic
21 36 wfjm
-- Tool versions:  ise 8.2-14.7; viv 2014.4-2016.1; ghdl 0.18-0.33
22
--
23
-- Synthesis results
24
--   clw = cache line width (tag+data)
25
--   eff = efficiency (fraction of used BRAM colums)
26
-- - 2016-03-22 (r750) with viv 2015.4 for xc7a100t-1
27
--   TWIDTH   flop  lutl  lutm  RAMB36 RAMB18   bram   clw   eff
28
--        9     43   106     0       0      5    2.5    45  100%
29
--        8     43   109     0       5      0    5.0    44   97%
30
--        7     43   107     0      10      4   12.0    43   89%
31
--        6     43   106     0      19      4   21.0    42  100%
32
--        5     58!  106     0      41      0   41.0    41  100%
33
--
34 2 wfjm
-- Revision History: 
35
-- Date         Rev Version  Comment
36 37 wfjm
-- 2016-05-22   767   1.1.1  don't init N_REGS (vivado fix for fsm inference)
37 36 wfjm
-- 2016-03-22   751   1.1    now configurable size (8,16,32,64,128 kB)
38 13 wfjm
-- 2011-11-18   427   1.0.3  now numeric_std clean
39 2 wfjm
-- 2008-02-23   118   1.0.2  ce cache in s_idle to avoid U's in sim
40
--                           factor invariants out of if's; fix tag rmiss logic
41
-- 2008-02-17   117   1.0.1  use em_(mreq|sres) interface; use req,we for mem
42
--                           recode, ghdl doesn't like partial vector port maps
43
-- 2008-02-16   116   1.0    Initial version 
44
------------------------------------------------------------------------------
45
 
46
library ieee;
47
use ieee.std_logic_1164.all;
48 13 wfjm
use ieee.numeric_std.all;
49 2 wfjm
 
50
use work.slvtypes.all;
51
use work.memlib.all;
52
use work.pdp11.all;
53
 
54
entity pdp11_cache is                   -- cache
55 36 wfjm
  generic (
56
    TWIDTH : positive := 9);            -- tag width (5 to 9)
57 2 wfjm
  port (
58
    CLK : in slbit;                     -- clock
59 30 wfjm
    GRESET : in slbit;                  -- general reset
60 2 wfjm
    EM_MREQ : in em_mreq_type;          -- em request
61
    EM_SRES : out em_sres_type;         -- em response
62
    FMISS : in slbit;                   -- force miss
63
    CHIT : out slbit;                   -- cache hit flag
64
    MEM_REQ : out slbit;                -- memory: request
65
    MEM_WE : out slbit;                 -- memory: write enable
66
    MEM_BUSY : in slbit;                -- memory: controller busy
67
    MEM_ACK_R : in slbit;               -- memory: acknowledge read
68
    MEM_ADDR : out slv20;               -- memory: address
69
    MEM_BE : out slv4;                  -- memory: byte enable
70
    MEM_DI : out slv32;                 -- memory: data in  (memory view)
71
    MEM_DO : in slv32                   -- memory: data out (memory view)
72
  );
73
end pdp11_cache;
74
 
75
 
76
architecture syn of pdp11_cache is
77
 
78 36 wfjm
  constant lwidth: positive := 22-2-TWIDTH; -- line address width
79
 
80
  subtype t_range   is integer range TWIDTH-1 downto  0;      -- tag value regs
81
  subtype l_range   is integer range lwidth-1 downto  0;      -- line addr regs
82
 
83
  subtype af_tag    is integer range 22-1 downto 22-TWIDTH;   -- tag  address
84
  subtype af_line   is integer range 22-TWIDTH-1 downto 2;    -- line address
85
 
86
  subtype df_byte3  is integer range 31 downto 24;
87
  subtype df_byte2  is integer range 23 downto 16;
88
  subtype df_byte1  is integer range 15 downto  8;
89
  subtype df_byte0  is integer range  7 downto  0;
90
 
91
  subtype df_word1  is integer range 31 downto 16;
92
  subtype df_word0  is integer range 15 downto  0;
93
 
94 2 wfjm
  type state_type is (
95
    s_idle,                             -- s_idle: wait for req
96
    s_read,                             -- s_read: read cycle
97
    s_rmiss,                            -- s_rmiss: read miss
98
    s_write                             -- s_write: write cycle
99
  );
100
 
101
  type regs_type is record
102
    state : state_type;                 -- state
103
    addr_w : slbit;                     -- address - word select
104 36 wfjm
    addr_l : slv(l_range);              -- address - cache line address
105
    addr_t : slv(t_range);              -- address - cache tag part
106 2 wfjm
    be : slv4;                          -- byte enables (at 4 byte level)
107
    di : slv16;                         -- data
108
  end record regs_type;
109
 
110
  constant regs_init : regs_type := (
111
    s_idle,                             -- state
112
    '0',                                -- addr_w
113 36 wfjm
    slv(to_unsigned(0,lwidth)),         -- addr_l
114
    slv(to_unsigned(0,TWIDTH)),         -- addr_t
115 2 wfjm
    (others=>'0'),                      -- be
116
    (others=>'0')                       -- di
117
  );
118
 
119 36 wfjm
  signal R_REGS : regs_type := regs_init;
120
  signal N_REGS : regs_type;            -- don't init (vivado fix for fsm infer)
121 2 wfjm
 
122
  signal CMEM_TAG_CEA  : slbit := '0';
123
  signal CMEM_TAG_CEB  : slbit := '0';
124
  signal CMEM_TAG_WEA  : slbit := '0';
125
  signal CMEM_TAG_WEB  : slbit := '0';
126 36 wfjm
  signal CMEM_TAG_DIB  : slv(t_range)  := (others=>'0');
127
  signal CMEM_TAG_DOA  : slv(t_range)  := (others=>'0');
128 2 wfjm
  signal CMEM_DAT_CEA  : slbit := '0';
129
  signal CMEM_DAT_CEB  : slbit := '0';
130
  signal CMEM_DAT_WEA  : slv4 := "0000";
131
  signal CMEM_DAT_WEB  : slv4 := "0000";
132
  signal CMEM_DIA_0    : slv9 := (others=>'0');
133
  signal CMEM_DIA_1    : slv9 := (others=>'0');
134
  signal CMEM_DIA_2    : slv9 := (others=>'0');
135
  signal CMEM_DIA_3    : slv9 := (others=>'0');
136
  signal CMEM_DIB_0    : slv9 := (others=>'0');
137
  signal CMEM_DIB_1    : slv9 := (others=>'0');
138
  signal CMEM_DIB_2    : slv9 := (others=>'0');
139
  signal CMEM_DIB_3    : slv9 := (others=>'0');
140
  signal CMEM_DOA_0    : slv9 := (others=>'0');
141
  signal CMEM_DOA_1    : slv9 := (others=>'0');
142
  signal CMEM_DOA_2    : slv9 := (others=>'0');
143
  signal CMEM_DOA_3    : slv9 := (others=>'0');
144
 
145
begin
146
 
147 36 wfjm
  assert TWIDTH>=5 and TWIDTH<=9
148
  report "assert(TWIDTH>=5 and TWIDTH<=9): unsupported TWIDTH"
149
  severity failure;
150
 
151 2 wfjm
  CMEM_TAG : ram_2swsr_rfirst_gen
152
    generic map (
153 36 wfjm
      AWIDTH => lwidth,
154
      DWIDTH => twidth)
155 2 wfjm
    port map (
156
      CLKA  => CLK,
157
      CLKB  => CLK,
158
      ENA   => CMEM_TAG_CEA,
159
      ENB   => CMEM_TAG_CEB,
160
      WEA   => CMEM_TAG_WEA,
161
      WEB   => CMEM_TAG_WEB,
162 36 wfjm
      ADDRA => EM_MREQ.addr(af_line),
163 2 wfjm
      ADDRB => R_REGS.addr_l,
164 36 wfjm
      DIA   => EM_MREQ.addr(af_tag),
165 2 wfjm
      DIB   => CMEM_TAG_DIB,
166
      DOA   => CMEM_TAG_DOA,
167
      DOB   => open
168
      );
169
 
170
  CMEM_DAT0 : ram_2swsr_rfirst_gen
171
    generic map (
172 36 wfjm
      AWIDTH => lwidth,
173 2 wfjm
      DWIDTH =>  9)
174
    port map (
175
      CLKA  => CLK,
176
      CLKB  => CLK,
177
      ENA   => CMEM_DAT_CEA,
178
      ENB   => CMEM_DAT_CEB,
179
      WEA   => CMEM_DAT_WEA(0),
180
      WEB   => CMEM_DAT_WEB(0),
181 36 wfjm
      ADDRA => EM_MREQ.addr(af_line),
182 2 wfjm
      ADDRB => R_REGS.addr_l,
183
      DIA   => CMEM_DIA_0,
184
      DIB   => CMEM_DIB_0,
185
      DOA   => CMEM_DOA_0,
186
      DOB   => open
187
      );
188
 
189
  CMEM_DAT1 : ram_2swsr_rfirst_gen
190
    generic map (
191 36 wfjm
      AWIDTH => lwidth,
192 2 wfjm
      DWIDTH =>  9)
193
    port map (
194
      CLKA  => CLK,
195
      CLKB  => CLK,
196
      ENA   => CMEM_DAT_CEA,
197
      ENB   => CMEM_DAT_CEB,
198
      WEA   => CMEM_DAT_WEA(1),
199
      WEB   => CMEM_DAT_WEB(1),
200 36 wfjm
      ADDRA => EM_MREQ.addr(af_line),
201 2 wfjm
      ADDRB => R_REGS.addr_l,
202
      DIA   => CMEM_DIA_1,
203
      DIB   => CMEM_DIB_1,
204
      DOA   => CMEM_DOA_1,
205
      DOB   => open
206
      );
207
 
208
  CMEM_DAT2 : ram_2swsr_rfirst_gen
209
    generic map (
210 36 wfjm
      AWIDTH => lwidth,
211 2 wfjm
      DWIDTH =>  9)
212
    port map (
213
      CLKA  => CLK,
214
      CLKB  => CLK,
215
      ENA   => CMEM_DAT_CEA,
216
      ENB   => CMEM_DAT_CEB,
217
      WEA   => CMEM_DAT_WEA(2),
218
      WEB   => CMEM_DAT_WEB(2),
219 36 wfjm
      ADDRA => EM_MREQ.addr(af_line),
220 2 wfjm
      ADDRB => R_REGS.addr_l,
221
      DIA   => CMEM_DIA_2,
222
      DIB   => CMEM_DIB_2,
223
      DOA   => CMEM_DOA_2,
224
      DOB   => open
225
      );
226
 
227
  CMEM_DAT3 : ram_2swsr_rfirst_gen
228
    generic map (
229 36 wfjm
      AWIDTH => lwidth,
230 2 wfjm
      DWIDTH =>  9)
231
    port map (
232
      CLKA  => CLK,
233
      CLKB  => CLK,
234
      ENA   => CMEM_DAT_CEA,
235
      ENB   => CMEM_DAT_CEB,
236
      WEA   => CMEM_DAT_WEA(3),
237
      WEB   => CMEM_DAT_WEB(3),
238 36 wfjm
      ADDRA => EM_MREQ.addr(af_line),
239 2 wfjm
      ADDRB => R_REGS.addr_l,
240
      DIA   => CMEM_DIA_3,
241
      DIB   => CMEM_DIB_3,
242
      DOA   => CMEM_DOA_3,
243
      DOB   => open
244
      );
245
 
246
  proc_regs: process (CLK)
247
  begin
248
 
249 13 wfjm
    if rising_edge(CLK) then
250 2 wfjm
      if GRESET = '1' then
251
        R_REGS <= regs_init;
252
      else
253
        R_REGS <= N_REGS;
254
      end if;
255
    end if;
256
 
257
  end process proc_regs;
258
 
259
  proc_next: process (R_REGS, EM_MREQ, FMISS,
260
                      CMEM_TAG_DOA,
261
                      CMEM_DOA_0, CMEM_DOA_1, CMEM_DOA_2, CMEM_DOA_3,
262
                      MEM_BUSY, MEM_ACK_R, MEM_DO)
263
 
264
    variable r : regs_type := regs_init;
265
    variable n : regs_type := regs_init;
266
 
267
    variable iaddr_w : slbit := '0';
268 36 wfjm
    variable iaddr_l : slv(l_range) := (others=>'0');
269
    variable iaddr_t : slv(t_range)  := (others=>'0');
270 2 wfjm
 
271
    variable itagok : slbit := '0';
272
    variable ivalok : slbit := '0';
273
 
274
    variable icmem_tag_cea : slbit := '0';
275
    variable icmem_tag_ceb : slbit := '0';
276
    variable icmem_tag_wea : slbit := '0';
277
    variable icmem_tag_web : slbit := '0';
278 36 wfjm
    variable icmem_tag_dib : slv(t_range)  := (others=>'0');
279 2 wfjm
    variable icmem_dat_cea : slbit := '0';
280
    variable icmem_dat_ceb : slbit := '0';
281
    variable icmem_dat_wea : slv4  := "0000";
282
    variable icmem_dat_web : slv4  := "0000";
283
    variable icmem_val_doa : slv4  := "0000";
284
    variable icmem_dat_doa : slv32 := (others=>'0');
285
    variable icmem_val_dib : slv4  := "0000";
286
    variable icmem_dat_dib : slv32 := (others=>'0');
287
 
288
    variable iackr : slbit := '0';
289
    variable iackw : slbit := '0';
290
    variable ichit : slbit := '0';
291
    variable iosel : slv2  := "11";
292
 
293
    variable imem_reqr : slbit := '0';
294
    variable imem_reqw : slbit := '0';
295
    variable imem_be   : slv4  := "0000";
296
 
297
  begin
298
 
299
    r := R_REGS;
300
    n := R_REGS;
301
 
302
    iaddr_w := EM_MREQ.addr(1);                -- get word select
303 36 wfjm
    iaddr_l := EM_MREQ.addr(af_line);          -- get cache line addr
304
    iaddr_t := EM_MREQ.addr(af_tag);           -- get cache tag part
305 2 wfjm
 
306
    icmem_tag_cea := '0';
307
    icmem_tag_ceb := '0';
308
    icmem_tag_wea := '0';
309
    icmem_tag_web := '0';
310
    icmem_tag_dib := r.addr_t;          -- default, local define whenver used
311
    icmem_dat_cea := '0';
312
    icmem_dat_ceb := '0';
313
    icmem_dat_wea := "0000";
314
    icmem_dat_web := "0000";
315
    icmem_val_dib := "0000";
316
    icmem_dat_dib := MEM_DO;            -- default, local define whenver used
317
 
318 36 wfjm
    icmem_val_doa(0)        := CMEM_DOA_0(8);
319
    icmem_dat_doa(df_byte0) := CMEM_DOA_0(df_byte0);
320
    icmem_val_doa(1)        := CMEM_DOA_1(8);
321
    icmem_dat_doa(df_byte1) := CMEM_DOA_1(df_byte0);
322
    icmem_val_doa(2)        := CMEM_DOA_2(8);
323
    icmem_dat_doa(df_byte2) := CMEM_DOA_2(df_byte0);
324
    icmem_val_doa(3)        := CMEM_DOA_3(8);
325
    icmem_dat_doa(df_byte3) := CMEM_DOA_3(df_byte0);
326 2 wfjm
 
327
    itagok := '0';
328
    if CMEM_TAG_DOA = r.addr_t then  -- cache tag hit
329
      itagok := '1';
330
    end if;
331
    ivalok := '0';
332
    if (icmem_val_doa and r.be) = r.be then
333
      ivalok := '1';
334
    end if;
335
 
336
    iackr := '0';
337
    iackw := '0';
338
    ichit := '0';
339
    iosel := "11";                      -- default to ext. mem data
340
                                        -- this prevents U's from cache bram's
341
                                        -- to propagate to dout in beginning...
342
 
343
    imem_reqr := '0';
344
    imem_reqw := '0';
345
    imem_be   := r.be;
346
 
347
    case r.state is
348
      when s_idle =>                    -- s_idle: wait for req
349
        n.addr_w := iaddr_w;              -- capture address: word select
350
        n.addr_l := iaddr_l;              -- capture address: cache line addr
351
        n.addr_t := iaddr_t;              -- capture address: cache tag part
352
        n.be     := "0000";
353
        icmem_tag_cea := '1';             -- access cache tag port A
354
        icmem_dat_cea := '1';             -- access cache data port A
355
        if iaddr_w = '0' then             -- capture byte enables at 4 byte lvl
356
          n.be(1 downto 0) := EM_MREQ.be;
357
        else
358
          n.be(3 downto 2) := EM_MREQ.be;
359
        end if;
360
        n.di     := EM_MREQ.din;          -- capture data
361
 
362
        if EM_MREQ.req = '1' then         -- if access requested
363
          if EM_MREQ.we = '0' then          -- if READ requested
364
            n.state := s_read;                -- next: read
365
 
366
          else                              -- if WRITE requested
367
            icmem_tag_wea := '1';             -- write tag
368
            icmem_dat_wea := n.be;            -- write cache data
369
            n.state := s_write;               -- next: write
370
          end if;
371
        end if;
372
 
373
      when s_read =>                    -- s_read: read cycle
374
        iosel := '0' & r.addr_w;          -- output select: cache
375
        imem_be := "1111";                -- mem read: all 4 bytes
376
        if EM_MREQ.cancel = '0' then
377
          if FMISS='0' and itagok='1' and ivalok='1' then -- read tag&val hit
378
            iackr := '1';                   -- signal read acknowledge
379
            ichit := '1';                   -- signal cache hit
380
            n.state := s_idle;              -- next: back to idle 
381
          else                            -- read miss
382
            if MEM_BUSY = '0' then          -- if mem not busy
383
              imem_reqr :='1';                -- request mem read
384
              n.state := s_rmiss;             -- next: rmiss, wait for mem data
385
            end if;
386
          end if;
387
        else
388
          n.state := s_idle;              -- next: back to idle 
389
        end if;
390
 
391
      when s_rmiss =>                   -- s_rmiss: read cycle
392
        iosel := '1' & r.addr_w;          -- output select: memory
393
        icmem_tag_web := '1';             -- cache update: write tag
394
        icmem_tag_dib := r.addr_t;        -- cache update: new tag
395
        icmem_val_dib := "1111";          -- cache update: all valid
396
        icmem_dat_dib := MEM_DO;          -- cache update: data from mem
397
        icmem_dat_web := "1111";          -- cache update: write all 4 bytes
398
        if MEM_ACK_R = '1' then           -- mem data valid
399
          iackr := '1';                     -- signal read acknowledge
400
          icmem_tag_ceb := '1';             -- access cache tag  port B
401
          icmem_dat_ceb := '1';             -- access cache data port B
402
          n.state := s_idle;                -- next: back to idle
403
        end if;
404
 
405
      when s_write =>                   -- s_write: write cycle
406
        icmem_tag_dib := CMEM_TAG_DOA;    -- cache restore: last state 
407
        icmem_dat_dib := icmem_dat_doa;   -- cache restore: last state 
408
        if EM_MREQ.cancel = '0' then      -- request ok
409
          if MEM_BUSY = '0' then            -- if mem not busy
410
            if itagok = '0' then              -- if write tag miss
411
              icmem_dat_ceb := '1';             -- access cache (invalidate)
412
              icmem_dat_web := not r.be;        -- write missed bytes
413
              icmem_val_dib := "0000";          -- invalidate missed bytes
414
            end if;
415
            imem_reqw := '1';                 -- write back to main memory
416
            iackw := '1';                     -- and done
417
            n.state := s_idle;                -- next: back to idle
418
          end if;
419
 
420
        else                              -- request canceled -> restore
421
          icmem_tag_ceb := '1';             -- access cache line
422
          icmem_tag_web := '1';             -- write tag
423
          icmem_dat_ceb := '1';             -- access cache line
424
          icmem_dat_web := "1111";          -- restore cache line
425
          icmem_val_dib := icmem_val_doa;   -- cache restore: last state 
426
          n.state := s_idle;                -- next: back to idle          
427
        end if;
428
 
429
      when others => null;
430
    end case;
431
 
432
    N_REGS <= n;
433
 
434
    CMEM_TAG_CEA <= icmem_tag_cea;
435
    CMEM_TAG_CEB <= icmem_tag_ceb;
436
    CMEM_TAG_WEA <= icmem_tag_wea;
437
    CMEM_TAG_WEB <= icmem_tag_web;
438
    CMEM_TAG_DIB <= icmem_tag_dib;
439
    CMEM_DAT_CEA <= icmem_dat_cea;
440
    CMEM_DAT_CEB <= icmem_dat_ceb;
441
    CMEM_DAT_WEA <= icmem_dat_wea;
442
    CMEM_DAT_WEB <= icmem_dat_web;
443
 
444 36 wfjm
    CMEM_DIA_0(8)        <= '1';
445
    CMEM_DIA_0(df_byte0) <= EM_MREQ.din(df_byte0);
446
    CMEM_DIA_1(8)        <= '1';
447
    CMEM_DIA_1(df_byte0) <= EM_MREQ.din(df_byte1);
448
    CMEM_DIA_2(8)        <= '1';
449
    CMEM_DIA_2(df_byte0) <= EM_MREQ.din(df_byte0);
450
    CMEM_DIA_3(8)        <= '1';
451
    CMEM_DIA_3(df_byte0) <= EM_MREQ.din(df_byte1);
452 2 wfjm
 
453 36 wfjm
    CMEM_DIB_0(8)        <= icmem_val_dib(0);
454
    CMEM_DIB_0(df_byte0) <= icmem_dat_dib(df_byte0);
455
    CMEM_DIB_1(8)        <= icmem_val_dib(1);
456
    CMEM_DIB_1(df_byte0) <= icmem_dat_dib(df_byte1);
457
    CMEM_DIB_2(8)        <= icmem_val_dib(2);
458
    CMEM_DIB_2(df_byte0) <= icmem_dat_dib(df_byte2);
459
    CMEM_DIB_3(8)        <= icmem_val_dib(3);
460
    CMEM_DIB_3(df_byte0) <= icmem_dat_dib(df_byte3);
461 2 wfjm
 
462
    EM_SRES <= em_sres_init;
463
    EM_SRES.ack_r <= iackr;
464
    EM_SRES.ack_w <= iackw;
465
    case iosel is
466 36 wfjm
      when "00" => EM_SRES.dout <= icmem_dat_doa(df_word0);
467
      when "01" => EM_SRES.dout <= icmem_dat_doa(df_word1);
468
      when "10" => EM_SRES.dout <= MEM_DO(df_word0);
469
      when "11" => EM_SRES.dout <= MEM_DO(df_word1);
470 2 wfjm
      when others => null;
471
    end case;
472
 
473
    CHIT  <= ichit;
474
 
475
    MEM_REQ  <= imem_reqr or imem_reqw;
476
    MEM_WE   <= imem_reqw;
477
    MEM_ADDR <= r.addr_t & r.addr_l;
478
    MEM_BE   <= imem_be;
479
    MEM_DI   <= r.di & r.di;
480
 
481
  end process proc_next;
482
 
483
end syn;

powered by: WebSVN 2.1.0

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