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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [rtl/] [w11a/] [pdp11_vmbox.vhd] - Blame information for rev 36

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

Line No. Rev Author Line
1 30 wfjm
-- $Id: pdp11_vmbox.vhd 677 2015-05-09 21:52:32Z mueller $
2 2 wfjm
--
3 30 wfjm
-- Copyright 2006-2015 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_vmbox - syn
16
-- Description:    pdp11: virtual memory
17
--
18
-- Dependencies:   pdp11_mmu
19
--                 pdp11_ubmap
20
--                 ibus/ib_sres_or_4
21
--                 ibus/ib_sres_or_2
22 8 wfjm
--                 ibus/ib_sel
23 2 wfjm
--
24
-- Test bench:     tb/tb_pdp11_core (implicit)
25
-- Target Devices: generic
26 29 wfjm
-- Tool versions:  ise 8.2-14.7; viv 2014.4; ghdl 0.18-0.31
27 8 wfjm
--
28 2 wfjm
-- Revision History: 
29
-- Date         Rev Version  Comment
30 30 wfjm
-- 2015-04-04   662   1.6.4  atowidth now 6 (was 5) to support ibdr_rprm reset
31 13 wfjm
-- 2011-11-18   427   1.6.3  now numeric_std clean
32 8 wfjm
-- 2010-10-23   335   1.6.2  add r.paddr_iopage, use ib_sel
33
-- 2010-10-22   334   1.6.1  deassert ibus be's at end-cycle; fix rmw logic
34
-- 2010-10-17   333   1.6    implement ibus V2 interface
35 2 wfjm
-- 2010-06-27   310   1.5    redo ibus driver logic, now ibus driven from flops
36
-- 2010-06-20   307   1.4.2  rename cpacc to cacc in vm_cntl_type, mmu_cntl_type
37
-- 2010-06-18   306   1.4.1  for cpacc: set cacc in ib_mreq, forward racc,be
38
--                           from CP_ADDR; now all ibr handling via vmbox
39
-- 2010-06-13   305   1.4    rename CPADDR -> CP_ADDR
40
-- 2009-06-01   221   1.3.8  add dip signal in ib_mreq (set in s_ib)
41
-- 2009-05-30   220   1.3.7  final removal of snoopers (were already commented)
42
-- 2009-05-01   211   1.3.6  BUGFIX: add 177776 stack protect (SCCE)
43
-- 2008-08-22   161   1.3.5  rename pdp11_ibres_ -> ib_sres_, ubf_ -> ibf_
44
-- 2008-04-25   138   1.3.4  add BRESET port, clear stklim with BRESET
45
-- 2008-04-20   137   1.3.3  add DM_STAT_VM port
46
-- 2008-03-19   127   1.3.2  ignore ack state when waiting on a busy IB in s_ib
47
-- 2008-03-02   121   1.3.1  remove snoopers
48
-- 2008-02-24   119   1.3    revamp paddr generation; add _ubmap
49
-- 2008-02-23   118   1.2.1  use sys_conf_mem_losize
50
-- 2008-02-17   117   1.2    use em_(mreq|sres) interface for external memory
51
-- 2008-01-26   114   1.1.4  rename 'ubus' to 'ib' (proper name of intbus now)
52
-- 2008-01-05   110   1.1.3  update snooper.
53
--                           rename IB_MREQ(ena->req) SRES(sel->ack, hold->busy)
54
-- 2008-01-01   109   1.1.2  Use IB_SRES_(CPU|EXT); use r./n. coding style, move
55
--                           all status into regs_type. add intbus HOLD support.
56
-- 2007-12-30   108   1.1.1  use ubf_byte[01]
57
-- 2007-12-30   107   1.1    Use IB_MREQ/IB_SRES interface now; remove DMA port
58
-- 2007-09-16    83   1.0.2  Use ram_1swsr_wfirst_gen, not ram_2swsr_wfirst_gen
59
--                           2nd port was unused, connected ADDR caused slow net
60
-- 2007-06-14    56   1.0.1  Use slvtypes.all
61
-- 2007-05-12    26   1.0    Initial version 
62
------------------------------------------------------------------------------
63
 
64
library ieee;
65
use ieee.std_logic_1164.all;
66 13 wfjm
use ieee.numeric_std.all;
67 2 wfjm
 
68
use work.slvtypes.all;
69
use work.iblib.all;
70
use work.pdp11.all;
71
use work.sys_conf.all;
72
 
73
-- ----------------------------------------------------------------------------
74
 
75
entity pdp11_vmbox is                   -- virtual memory
76
  port (
77
    CLK : in slbit;                     -- clock
78 30 wfjm
    GRESET : in slbit;                  -- general reset
79
    CRESET : in slbit;                  -- cpu reset
80
    BRESET : in slbit;                  -- bus reset
81 2 wfjm
    CP_ADDR : in cp_addr_type;          -- console port address
82
    VM_CNTL : in vm_cntl_type;          -- vm control port
83
    VM_ADDR : in slv16;                 -- vm address
84
    VM_DIN : in slv16;                  -- vm data in
85
    VM_STAT : out vm_stat_type;         -- vm status port
86
    VM_DOUT : out slv16;                -- vm data out
87
    EM_MREQ : out em_mreq_type;         -- external memory: request
88
    EM_SRES : in em_sres_type;          -- external memory: response
89
    MMU_MONI : in mmu_moni_type;        -- mmu monitor port
90
    IB_MREQ_M : out ib_mreq_type;       -- ibus request  (master)
91
    IB_SRES_CPU : in ib_sres_type;      -- ibus response (CPU registers)
92
    IB_SRES_EXT : in ib_sres_type;      -- ibus response (external devices)
93
    DM_STAT_VM : out dm_stat_vm_type    -- debug and monitor status
94
  );
95
end pdp11_vmbox;
96
 
97
architecture syn of pdp11_vmbox is
98
 
99 13 wfjm
  constant ibaddr_slim : slv16 := slv(to_unsigned(8#177774#,16));
100 30 wfjm
  constant atowidth : natural := 6;     -- size of access timeout counter
101 2 wfjm
 
102
  type state_type is (
103
    s_idle,                             -- s_idle: wait for vm_cntl request
104
    s_mem_w,                            -- s_mem_w: check mmu, wait for memory
105
    s_ib_w,                             -- s_ib_w: wait for ibus
106
    s_ib_wend,                          -- s_ib_wend: ibus write completion
107
    s_ib_rend,                          -- s_ib_rend: ibus read completion
108
    s_idle_mw_ib,                       -- s_idle_mw_ib: wait macc write (ibus)
109
    s_idle_mw_mem,                      -- s_idle_mw_mem: wait macc write (mem)
110
    s_mem_mw_w,                         -- s_mem_mw_w: wait for memory (macc)
111
    s_fail,                             -- s_fail: vmbox fatal error catcher
112
    s_errrsv,                           -- s_errrsv: red stack violation
113
    s_errib                             -- s_errib: ibus error handler
114
  );
115
 
116
  type regs_type is record              -- state registers
117
    state : state_type;                 -- state
118
    wacc : slbit;                       -- write access
119
    macc : slbit;                       -- modify access (r-m-w sequence)
120
    cacc : slbit;                       -- console access
121
    bytop : slbit;                      -- byte operation
122
    kstack : slbit;                     -- access through kernel stack
123
    ysv : slbit;                        -- yellow stack violation detected
124
    vaok : slbit;                       -- virtual address valid (from MMU)
125
    trap_mmu : slbit;                   -- mmu trace trap requested
126
    mdin : slv16;                       -- data input (memory order)
127
    paddr : slv22;                      -- physical address register
128 8 wfjm
    paddr_iopage : slv9;                -- iopage base (upper 9 bits of paddr)
129 2 wfjm
    atocnt : slv(atowidth-1 downto 0);  -- access timeout counter
130 8 wfjm
    ibre : slbit;                       -- ibus re signal
131 2 wfjm
    ibwe : slbit;                       -- ibus we signal
132
    ibbe : slv2;                        -- ibus be0,be1 signals
133 8 wfjm
    ibrmw : slbit;                      -- ibus rmw signal
134 2 wfjm
    ibcacc : slbit;                     -- ibus cacc signal
135
    ibracc : slbit;                     -- ibus racc signal
136
    ibdout : slv16;                     -- ibus dout register
137
  end record regs_type;
138
 
139
  constant atocnt_init : slv(atowidth-1 downto 0) := (others=>'1');
140
  constant regs_init : regs_type := (
141
    s_idle,                             -- state
142
    '0','0','0','0',                    -- wacc,macc,cacc,bytop
143
    '0','0','0','0',                    -- kstack,ysv,vaok,trap_mmu
144
    (others=>'0'),                      -- mdin
145
    (others=>'0'),                      -- paddr
146 8 wfjm
    (others=>'0'),                      -- paddr_iopage
147 2 wfjm
    atocnt_init,                        -- atocnt
148 8 wfjm
    '0','0',"00",                       -- ibre,ibwe,ibbe
149
    '0','0','0',                        -- ibrmw,ibcacc,ibracc
150 2 wfjm
    (others=>'0')                       -- ibdout
151
  );
152
 
153
  signal R_REGS : regs_type := regs_init;
154
  signal N_REGS : regs_type := regs_init;
155
 
156
  signal R_SLIM : slv8 := (others=>'0');   -- stack limit register
157
 
158
  signal MMU_CNTL : mmu_cntl_type := mmu_cntl_init;
159
  signal MMU_STAT : mmu_stat_type := mmu_stat_init;
160
  signal PADDRH   : slv16 := (others=>'0');
161
 
162
  signal IBSEL_SLIM :slbit := '0';      -- select stack limit reg
163
  signal IB_SRES_SLIM  : ib_sres_type := ib_sres_init;
164
  signal IB_SRES_MMU   : ib_sres_type := ib_sres_init;
165
  signal IB_SRES_UBMAP : ib_sres_type := ib_sres_init;
166
 
167
  signal UBMAP_MREQ : slbit := '0';
168
  signal UBMAP_ADDR_PM : slv22_1 := (others=>'0');
169
 
170
  signal IB_MREQ : ib_mreq_type := ib_mreq_init; -- ibus request  (local)
171
  signal IB_SRES : ib_sres_type := ib_sres_init; -- ibus response (local)
172
  signal IB_SRES_INT : ib_sres_type := ib_sres_init; -- ibus response (cpu)
173
 
174
begin
175
 
176
  MMU : pdp11_mmu
177
    port map (
178
      CLK     => CLK,
179
      CRESET  => CRESET,
180
      BRESET  => BRESET,
181
      CNTL    => MMU_CNTL,
182
      VADDR   => VM_ADDR,
183
      MONI    => MMU_MONI,
184
      STAT    => MMU_STAT,
185
      PADDRH  => PADDRH,
186
      IB_MREQ => IB_MREQ,
187
      IB_SRES => IB_SRES_MMU
188
    );
189
 
190
  UBMAP : pdp11_ubmap
191
    port map (
192
      CLK     => CLK,
193
      MREQ    => UBMAP_MREQ,
194
      ADDR_UB => CP_ADDR.addr(17 downto 1),
195
      ADDR_PM => UBMAP_ADDR_PM,
196
      IB_MREQ => IB_MREQ,
197
      IB_SRES => IB_SRES_UBMAP
198
    );
199
 
200 8 wfjm
  SRES_OR_INT : ib_sres_or_4
201 2 wfjm
    port map (
202
      IB_SRES_1  => IB_SRES_CPU,
203
      IB_SRES_2  => IB_SRES_SLIM,
204
      IB_SRES_3  => IB_SRES_MMU,
205
      IB_SRES_4  => IB_SRES_UBMAP,
206
      IB_SRES_OR => IB_SRES_INT
207
    );
208
 
209 8 wfjm
  SRES_OR_ALL : ib_sres_or_2
210 2 wfjm
    port map (
211
      IB_SRES_1  => IB_SRES_INT,
212
      IB_SRES_2  => IB_SRES_EXT,
213
      IB_SRES_OR => IB_SRES
214
    );
215
 
216 8 wfjm
  SEL : ib_sel
217
    generic map (
218
      IB_ADDR => ibaddr_slim)
219
    port map (
220
      CLK     => CLK,
221
      IB_MREQ => IB_MREQ,
222
      SEL     => IBSEL_SLIM
223
    );
224 2 wfjm
 
225 8 wfjm
  proc_ibres : process (IBSEL_SLIM, IB_MREQ, R_SLIM)
226
    variable idout : slv16 := (others=>'0');
227 2 wfjm
  begin
228 8 wfjm
    idout := (others=>'0');
229 2 wfjm
    if IBSEL_SLIM = '1' then
230 8 wfjm
      idout(ibf_byte1) := R_SLIM;
231 2 wfjm
    end if;
232 8 wfjm
    IB_SRES_SLIM.dout <= idout;
233
    IB_SRES_SLIM.ack  <= IBSEL_SLIM and (IB_MREQ.re or IB_MREQ.we); -- ack all
234
    IB_SRES_SLIM.busy <= '0';
235
  end process proc_ibres;
236 2 wfjm
 
237
  proc_slim: process (CLK)
238
  begin
239 13 wfjm
    if rising_edge(CLK) then
240 2 wfjm
      if BRESET = '1' then
241
        R_SLIM <= (others=>'0');
242 8 wfjm
      elsif IBSEL_SLIM='1' and IB_MREQ.we='1' then
243 2 wfjm
        if IB_MREQ.be1 = '1' then
244
          R_SLIM <= IB_MREQ.din(ibf_byte1);
245
        end if;
246
      end if;
247
    end if;
248
  end process proc_slim;
249
 
250
  proc_regs: process (CLK)
251
  begin
252 13 wfjm
    if rising_edge(CLK) then
253 2 wfjm
      if GRESET = '1' then
254
        R_REGS <= regs_init;
255
     else
256
        R_REGS <= N_REGS;
257
      end if;
258
    end if;
259
  end process proc_regs;
260
 
261
  proc_next: process (R_REGS, R_SLIM, CP_ADDR, VM_CNTL, VM_DIN, VM_ADDR,
262
                      IB_SRES, UBMAP_ADDR_PM,
263
                      EM_SRES, MMU_STAT, PADDRH)
264
 
265
    variable r : regs_type := regs_init;
266
    variable n : regs_type := regs_init;
267
 
268
    variable ivm_stat : vm_stat_type := vm_stat_init;
269
    variable ivm_dout : slv16 := (others=>'0');
270
    variable iem_mreq : em_mreq_type := em_mreq_init;
271
    variable immu_cntl : mmu_cntl_type := mmu_cntl_init;
272 8 wfjm
 
273
    variable ipaddr        : slv22 := (others=>'0');
274
    variable ipaddr_iopage : slv9 := (others=>'0');
275
 
276
    variable iib_aval : slbit := '0';
277 2 wfjm
 
278
    variable ato_go : slbit := '0';
279
    variable ato_end : slbit := '0';
280
 
281
    variable is_stackyellow : slbit := '1'; -- VM_ADDR in yellow stack zone
282
    variable is_stackred : slbit := '1';    -- VM_ADDR in red stack zone
283
 
284
    variable iubmap_mreq : slbit := '0';
285
    variable paddr_mmu : slbit := '0';
286
    variable paddr_sel : slv2  := "00";
287
    constant c_paddr_sel_vmaddr : slv2 := "00";
288
    constant c_paddr_sel_rpaddr : slv2 := "01";
289
    constant c_paddr_sel_cacc   : slv2 := "10";
290
    constant c_paddr_sel_ubmap  : slv2 := "11";
291
 
292
 
293
  begin
294
 
295
    r := R_REGS;
296
    n := R_REGS;
297
 
298
    n.state := s_fail;
299
 
300
    ivm_stat  := vm_stat_init;
301
    ivm_dout  := EM_SRES.dout;
302
    immu_cntl := mmu_cntl_init;
303
 
304 8 wfjm
    iib_aval  := '0';
305
 
306 2 wfjm
    iem_mreq  := em_mreq_init;
307
    iem_mreq.din  := VM_DIN;
308
 
309
    if VM_CNTL.bytop = '0' then         -- if word access
310
      iem_mreq.be := "11";                -- both be's
311
    else
312
      if VM_ADDR(0) = '0' then            -- if low byte
313
        iem_mreq.be := "01";
314
      else                                -- if high byte
315
        iem_mreq.be := "10";
316
        iem_mreq.din(ibf_byte1) := VM_DIN(ibf_byte0);
317
      end if;
318
    end if;
319
 
320
    iubmap_mreq :='0';
321
 
322
    paddr_mmu := '1';                   -- ipaddr selector, used in s_idle
323
                                        -- and overwritten in s_idle_mw_mem
324
    paddr_sel := "00";
325
    if MMU_STAT.ena_mmu='0' or VM_CNTL.cacc='1' then
326
      paddr_mmu := '0';
327
      paddr_sel := c_paddr_sel_vmaddr;
328
      if VM_CNTL.cacc = '1' then
329
        if CP_ADDR.ena_ubmap='1' and MMU_STAT.ena_ubmap='1' then
330
          paddr_sel := c_paddr_sel_ubmap;
331
        else
332
          paddr_sel := c_paddr_sel_cacc;
333
        end if;
334
      end if;
335
    end if;
336
 
337 8 wfjm
    -- the iopage base is determined based on mmu regs and request type
338
    -- r.paddr_iopage is updated during s_idle. This way the iopage base
339
    -- address is determined in parallel to paddr and latched at end of s_idle.
340
    -- Note: is VM_CNTL.cacc here, the status in s_idle is relevant !
341
 
342
    ipaddr_iopage := "111111111";       -- iopage match pattern (for 22 bit)
343
    if VM_CNTL.cacc = '1' then
344 2 wfjm
      if CP_ADDR.ena_22bit = '0' then
345 8 wfjm
        ipaddr_iopage := "000000111";   -- 16 bit cacc
346 2 wfjm
      end if;
347
    else
348
      if MMU_STAT.ena_mmu = '0' then
349 8 wfjm
        ipaddr_iopage := "000000111";   -- 16 bit mode
350 2 wfjm
      else
351
        if MMU_STAT.ena_22bit = '0' then
352 8 wfjm
          ipaddr_iopage := "000011111"; -- 18 bit mode
353 2 wfjm
        end if;
354
      end if;
355
    end if;
356
 
357
    ato_go := '0';                      -- default: keep access timeout in reset
358
    ato_end := '0';
359
    if unsigned(r.atocnt) = 0 then      -- if access timeout count at zero
360
      ato_end := '1';                   -- signal expiration
361
    end if;
362
 
363
    is_stackyellow := '0';
364
    is_stackred := '0';
365
    if unsigned(VM_ADDR(15 downto 8)) <= unsigned(R_SLIM) then
366
      is_stackyellow := '1';
367
      if unsigned(VM_ADDR(7 downto 5)) /= 7 then  -- below 340
368
        is_stackred := '1';
369
      end if;
370
    end if;
371
 
372
    if VM_ADDR(15 downto 1) = "111111111111111" then  -- vaddr == 177776
373
      is_stackred := '1';
374
    end if;
375
 
376
    immu_cntl.wacc      := VM_CNTL.wacc;
377
    immu_cntl.macc      := VM_CNTL.macc;
378
    immu_cntl.cacc      := VM_CNTL.cacc;
379
    immu_cntl.dspace    := VM_CNTL.dspace;
380
    immu_cntl.mode      := VM_CNTL.mode;
381
    immu_cntl.trap_done := VM_CNTL.trap_done;
382
 
383
    case r.state is
384
      when s_idle =>                    -- s_idle: wait for vm_cntl request --
385
        n.state := s_idle;
386
        iubmap_mreq := '1';             -- activate ubmap always in s_idle
387
 
388
        if VM_CNTL.req = '1' then
389
          n.wacc   := VM_CNTL.wacc;
390
          n.macc   := VM_CNTL.macc;
391
          n.cacc   := VM_CNTL.cacc;
392
          n.bytop  := VM_CNTL.bytop;
393
          n.kstack := VM_CNTL.kstack;
394
          n.ysv    := '0';
395
          n.vaok   := MMU_STAT.vaok;
396
          n.trap_mmu := MMU_STAT.trap;
397
          n.mdin   := iem_mreq.din;
398
          -- n.paddr assignment handled separately in 'if state=s_idle' at the
399
          -- end. 
400
 
401
          immu_cntl.req := '1';
402
 
403
          if VM_CNTL.wacc='1' and VM_CNTL.macc='1' then
404
            n.state := s_fail;
405
 
406
          elsif VM_CNTL.kstack='1' and VM_CNTL.intrsv='0' and
407
                is_stackred='1' then
408
            n.state := s_errrsv;
409
 
410
          else
411
            iem_mreq.req := '1';
412
            iem_mreq.we  := VM_CNTL.wacc;
413
            if VM_CNTL.kstack='1'and VM_CNTL.intrsv='0'  then
414
              n.ysv := is_stackyellow;
415
            end if;
416
            n.state := s_mem_w;
417
          end if;
418
        end if;
419
 
420
      when s_mem_w =>                   -- s_mem_w: check mmu, wait for memory
421
 
422
        if r.bytop='0' and r.paddr(0)='1' then -- odd address ?
423
          ivm_stat.err := '1';
424
          ivm_stat.err_odd := '1';
425
          ivm_stat.err_rsv := r.kstack;      -- escalate to rsv if kstack
426
          iem_mreq.cancel  := '1';           -- cancel pending mem request
427
          n.state := s_idle;
428
 
429
        elsif r.vaok = '0' then          -- MMU abort ?
430
          ivm_stat.err := '1';
431
          ivm_stat.err_mmu := '1';
432
          ivm_stat.err_rsv := r.kstack;      -- escalate to rsv if kstack
433
          iem_mreq.cancel  := '1';           -- cancel pending mem request
434
          n.state := s_idle;
435
 
436
        else
437 8 wfjm
          if r.paddr(21 downto 13) = r.paddr_iopage then
438 2 wfjm
                                             -- I/O page decoded
439
            iem_mreq.cancel  := '1';         -- cancel pending mem request
440 8 wfjm
            iib_aval := '1';                 -- declare ibus addr valid
441
            n.ibre   := not r.wacc;
442 2 wfjm
            n.ibwe   := r.wacc;
443
            n.ibcacc := r.cacc;
444
            n.ibracc := r.cacc and CP_ADDR.racc;
445
            n.ibbe   := "11";
446
            if r.cacc = '1' then               -- console access ?
447
              n.ibbe   := CP_ADDR.be;
448
            else                               -- cpu access ?
449
              if r.bytop = '1' then
450
                if r.paddr(0) = '0' then
451
                  n.ibbe(1) := '0';
452
                else
453
                  n.ibbe(0) := '0';
454
                end if;
455
              end if;
456
            end if;
457 8 wfjm
            n.ibrmw  := r.macc;
458 2 wfjm
            n.state  := s_ib_w;
459
 
460
          else
461
            if unsigned(r.paddr(21 downto 6)) > sys_conf_mem_losize then
462
              ivm_stat.err := '1';
463
              ivm_stat.err_nxm := '1';
464
              ivm_stat.err_rsv := r.kstack;   -- escalate to rsv if kstack
465
              iem_mreq.cancel  := '1';        -- cancel pending mem request
466
              n.state := s_idle;
467
 
468
            else
469
 
470
              if EM_SRES.ack_r='1' or EM_SRES.ack_w='1' then
471
                ivm_stat.ack := '1';
472
                ivm_stat.trap_ysv := r.ysv;
473
                ivm_stat.trap_mmu := r.trap_mmu;
474
                if r.macc='1' and r.wacc='0' then
475
                  n.state := s_idle_mw_mem;
476
                else
477
                  n.state := s_idle;
478
                end if;
479
              else
480
                n.state := s_mem_w;     -- keep waiting
481
              end if;
482
 
483
            end if;
484
          end if;
485
        end if;
486
 
487
      when s_ib_w =>                    -- s_ib_w: wait for ibus -------------
488
        ato_go := '1';                    -- activate timeout counter
489
 
490 8 wfjm
        iib_aval := '1';                  -- declare ibus addr valid
491
 
492
        n.ibre   := '0';                  -- end cycle, unless busy seen
493
        n.ibwe   := '0';
494
        n.ibrmw  := '0';
495
        n.ibbe   := "00";
496
        n.ibcacc := '0';
497
        n.ibracc := '0';
498
 
499 2 wfjm
        if IB_SRES.ack='1' and IB_SRES.busy='0' then -- ibus cycle finished
500
          if r.wacc = '1' then
501
            n.state := s_ib_wend;
502
          else
503 8 wfjm
            if r.macc = '1' then          -- if first part of rmw
504
              n.ibrmw  := r.macc;           -- keep rmw 
505
              n.ibbe   := r.ibbe;           -- keep be's
506
              n.ibcacc := r.ibcacc;
507
              n.ibracc := r.ibracc;
508
            end if;
509 2 wfjm
            n.ibdout := IB_SRES.dout;
510
            n.state  := s_ib_rend;
511
          end if;
512
        elsif IB_SRES.busy='1' and ato_end='0' then
513 8 wfjm
          n.ibre   := r.ibre;             -- continue ibus cycle
514
          n.ibwe   := r.ibwe;
515
          n.ibrmw  := r.ibrmw;
516
          n.ibbe   := r.ibbe;
517
          n.ibcacc := r.ibcacc;
518
          n.ibracc := r.ibracc;
519 2 wfjm
          n.state := s_ib_w;
520
        else
521
          n.state := s_errib;
522
        end if;
523
 
524
      when s_ib_wend =>                 -- s_ib_wend: ibus write completion --
525
        ivm_stat.ack := '1';
526
        n.state := s_idle;
527
 
528
      when s_ib_rend =>                 -- s_ib_rend: ibus read completion ---
529
        ivm_stat.ack := '1';
530
        ivm_dout := r.ibdout;
531 8 wfjm
        if r.macc='1' then                -- first part of read-mod-write
532
          iib_aval := '1';                  -- keep ibus addr valid
533 2 wfjm
          n.state := s_idle_mw_ib;
534
        else
535
          n.state := s_idle;
536
        end if;
537
 
538
      when s_idle_mw_ib =>              -- s_idle_mw_ib: wait macc write (ibus)
539
        n.state := s_idle_mw_ib;
540 8 wfjm
        iib_aval := '1';                  -- keep ibus addr valid
541 2 wfjm
        if r.ibbe = "10" then
542
          iem_mreq.din(ibf_byte1) := VM_DIN(ibf_byte0);
543
        end if;
544
        if VM_CNTL.req = '1' then
545
          n.wacc  := VM_CNTL.wacc;
546
          n.macc  := VM_CNTL.macc;
547
          n.mdin  := iem_mreq.din;
548
          if VM_CNTL.wacc='0' or VM_CNTL.macc='0' then
549
            n.state := s_fail;
550
          else
551
            n.ibwe  := '1';                 -- Note: all other ibus drivers
552
                                            --   already set in 1st part
553
            n.state := s_ib_w;
554
          end if;
555
        end if;
556
 
557
      when s_idle_mw_mem =>             -- s_idle_mw_mem: wait macc write (mem)
558
        n.state := s_idle_mw_mem;
559
 
560
        paddr_mmu := '0';
561
        paddr_sel := c_paddr_sel_rpaddr;
562
 
563
        if VM_CNTL.bytop = '0' then     -- if word access
564
          iem_mreq.be := "11";            -- both be's
565
        else
566
          if r.paddr(0) = '0' then        -- if low byte
567
            iem_mreq.be := "01";
568
          else                            -- if high byte
569
            iem_mreq.be := "10";
570
            iem_mreq.din(ibf_byte1) := VM_DIN(ibf_byte0);
571
          end if;
572
        end if;
573
 
574
        if VM_CNTL.req = '1' then
575
          n.wacc  := VM_CNTL.wacc;
576
          n.macc  := VM_CNTL.macc;
577
          n.bytop := VM_CNTL.bytop;
578
          n.mdin  := iem_mreq.din;
579
 
580
          if VM_CNTL.wacc='0' or VM_CNTL.macc='0' then
581
            n.state := s_fail;
582
          else
583
            iem_mreq.req := '1';
584
            iem_mreq.we  := '1';
585
            n.state := s_mem_mw_w;
586
          end if;
587
        end if;
588
 
589
      when s_mem_mw_w =>                -- s_mem_mw_w: wait for memory (macc)
590
        if EM_SRES.ack_w = '1' then
591
          ivm_stat.ack := '1';
592
          n.state := s_idle;
593
        else
594
          n.state := s_mem_mw_w;        -- keep waiting
595
        end if;
596
 
597
      when s_fail =>                    -- s_fail: vmbox fatal error catcher
598
        ivm_stat.fail := '1';
599
        n.state := s_idle;
600
 
601
      when s_errrsv =>                  -- s_errrsv: red stack violation -----
602
        ivm_stat.err := '1';
603
        ivm_stat.err_rsv := '1';
604
        n.state := s_idle;
605
 
606
      when s_errib =>                   -- s_errib: ibus error handler -------
607
        ivm_stat.err := '1';
608
        ivm_stat.err_iobto := '1';
609
        ivm_stat.err_rsv := r.kstack;    -- escalate to rsv if kstack
610
        n.state := s_idle;
611
 
612
      when others => null;
613
    end case;
614
 
615
    if r.bytop='1' and r.paddr(0)='1' then
616
      ivm_dout(ibf_byte0) := ivm_dout(ibf_byte1);
617
    end if;
618
 
619
    if ato_go = '0' then                -- handle access timeout counter
620
      n.atocnt := atocnt_init;          -- if ato_go=0, keep in reset
621
    else
622 13 wfjm
      n.atocnt := slv(unsigned(r.atocnt) - 1);-- otherwise count down
623 2 wfjm
    end if;
624
 
625
    ipaddr := (others=>'0');
626
    if paddr_mmu = '1' then
627
      ipaddr( 5 downto 0) := VM_ADDR(5 downto 0);
628
      ipaddr(21 downto 6) := PADDRH;
629
      if MMU_STAT.ena_22bit = '0' then
630
        ipaddr(21 downto 18) := (others=>'0');
631
      end if;
632
    else
633
      case paddr_sel is
634
        when c_paddr_sel_vmaddr  =>
635
          ipaddr(15 downto 0) := VM_ADDR(15 downto 0);
636
        when c_paddr_sel_rpaddr =>
637
          ipaddr := r.paddr;
638
        when c_paddr_sel_cacc  =>
639
          ipaddr := CP_ADDR.addr & '0';
640
          if CP_ADDR.ena_22bit = '0' then
641
            ipaddr(21 downto 16) := (others=>'0');
642
          end if;
643
        when c_paddr_sel_ubmap  =>
644
          ipaddr := UBMAP_ADDR_PM & '0';
645
        when others => null;
646
      end case;
647
    end if;
648
 
649
    if r.state = s_idle then
650 8 wfjm
      n.paddr        := ipaddr;
651
      n.paddr_iopage := ipaddr_iopage;
652 2 wfjm
    end if;
653
 
654
    iem_mreq.addr := ipaddr(21 downto 1);
655
 
656
    N_REGS <= n;
657
 
658
    UBMAP_MREQ <= iubmap_mreq;
659
 
660 8 wfjm
    IB_MREQ.aval <= iib_aval;
661
    IB_MREQ.re   <= r.ibre;
662 2 wfjm
    IB_MREQ.we   <= r.ibwe;
663
    IB_MREQ.be0  <= r.ibbe(0);
664
    IB_MREQ.be1  <= r.ibbe(1);
665 8 wfjm
    IB_MREQ.rmw  <= r.ibrmw;
666 2 wfjm
    IB_MREQ.cacc <= r.ibcacc;
667
    IB_MREQ.racc <= r.ibracc;
668 8 wfjm
    IB_MREQ.addr <= r.paddr(12 downto 1);
669 2 wfjm
    IB_MREQ.din  <= r.mdin;
670
 
671
    VM_DOUT  <= ivm_dout;
672
    VM_STAT  <= ivm_stat;
673
    MMU_CNTL <= immu_cntl;
674
 
675
    EM_MREQ  <= iem_mreq;
676
 
677
  end process proc_next;
678
 
679
  IB_MREQ_M <= IB_MREQ;                 -- external drive master port
680
 
681
  DM_STAT_VM.ibmreq <= IB_MREQ;
682
  DM_STAT_VM.ibsres <= IB_SRES;
683
 
684
end syn;

powered by: WebSVN 2.1.0

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