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

Subversion Repositories w11

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

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

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

powered by: WebSVN 2.1.0

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