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;
|