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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.7/] [rtl/] [w11a/] [pdp11_core_rbus.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_core_rbus.vhd 677 2015-05-09 21:52:32Z mueller $
2 2 wfjm
--
3 30 wfjm
-- Copyright 2007-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 9 wfjm
-- Module Name:    pdp11_core_rbus - syn
16
-- Description:    pdp11: core to rbus interface
17 2 wfjm
--
18
-- Dependencies:   -
19 9 wfjm
-- Test bench:     tb/tb_rlink_tba_pdp11core
20 2 wfjm
--
21
-- Target Devices: generic
22 29 wfjm
-- Tool versions:  ise 8.2-14.7; viv 2014.4; ghdl 0.18-0.31
23 28 wfjm
--
24
-- Synthesized (xst):
25
-- Date         Rev  ise         Target      flop lutl lutm slic t peri
26
-- 2014-12-21   591 14.7  131013 xc6slx16-2    52  118    0   58 s  4.9
27
--
28 2 wfjm
-- Revision History: -
29
-- Date         Rev Version  Comment
30 30 wfjm
-- 2015-05-09   677   1.5    start/stop/suspend overhaul; reset overhaul
31 28 wfjm
-- 2014-12-26   621   1.4    use full size 4k word ibus window
32
-- 2014-12-21   617   1.3.1  use separate RB_STAT bits for cmderr and cmdmerr
33 27 wfjm
-- 2014-09-05   591   1.3    use new rlink v4 iface and 4 bit STAT
34
-- 2014-08-15   583   1.2    rb_mreq addr now 16 bit
35 13 wfjm
-- 2011-11-18   427   1.1.1  now numeric_std clean
36 9 wfjm
-- 2010-12-29   351   1.1    renamed from pdp11_core_rri; ported to rbv3
37 8 wfjm
-- 2010-10-23   335   1.2.3  rename RRI_LAM->RB_LAM;
38 2 wfjm
-- 2010-06-20   308   1.2.2  use c_ibrb_ibf_ def's
39
-- 2010-06-18   306   1.2.1  rename RB_ADDR->RB_ADDR_CORE, add RB_ADDR_IBUS;
40
--                           add ibrb register and ibr window logic
41
-- 2010-06-13   305   1.2    add CP_ADDR in port; mostly rewritten for new
42
--                           rri <-> cp mapping
43
-- 2010-06-03   299   1.1.2  correct rbus init logic (use we, din, RB_ADDR)
44
-- 2010-05-02   287   1.1.1  rename RP_STAT->RB_STAT; remove unneeded unsigned()
45
-- 2010-05-01   285   1.1    port to rri V2 interface, add RB_ADDR generic;
46
--                           rename c_rp_addr_* -> c_rb_addr_*
47
-- 2008-05-03   143   1.0.8  rename _cpursta->_cpurust
48
-- 2008-04-27   140   1.0.7  use cpursta interface, remove cpufail
49
-- 2008-03-02   121   1.0.6  set RP_ERR when cmderr or cmdmerr status seen
50
-- 2008-02-24   119   1.0.5  support lah,rps,wps cp commands
51
-- 2008-01-20   113   1.0.4  use single LAM; change to RRI_LAM interface
52
-- 2007-10-12    88   1.0.3  avoid ieee.std_logic_unsigned, use cast to unsigned
53
-- 2007-08-16    74   1.0.2  add AP_LAM interface to pdp11_core_rri
54
-- 2007-08-12    73   1.0.1  use def's; add stat command; wait for step complete
55
-- 2007-07-08    65   1.0    Initial version 
56
------------------------------------------------------------------------------
57
--
58
-- rbus registers:
59
--
60 28 wfjm
--  Addr   Bits  Name        r/w/f  Function
61 2 wfjm
--
62 28 wfjm
-- 00000         conf        r/w/-  cpu configuration (e.g. cpu type)
63 2 wfjm
--                                   (currently unused, all bits MBZ)
64 28 wfjm
-- 00001         cntl        -/f/-  cpu control
65
--         3:00    func               function code
66 2 wfjm
--                                       0000: noop
67
--                                       0001: start
68
--                                       0010: stop
69 30 wfjm
--                                       0011: step
70
--                                       0100: creset
71
--                                       0101: breset
72
--                                       0110: suspend
73
--                                       0111: resume
74 28 wfjm
-- 00010         stat        r/-/-  cpu status
75 30 wfjm
--            9    suspext   r/-/-    cp_stat: statext
76
--            8    suspint   r/-/-    cp_stat: statint
77 28 wfjm
--         7:04    cpurust   r/-/-    cp_stat: cpurust
78 30 wfjm
--            3    cpususp   r/-/-    cp_stat: cpususp
79 28 wfjm
--            2    cpugo     r/-/-    cp_stat: cpugo
80
--            1    cmdmerr   r/-/-    cp_stat: cmdmerr
81
--            0    cmderr    r/-/-    cp_stat: cmderr
82
-- 00011         psw         r/w/-  processor status word access
83
-- 00100         al          r/w/-  address register, low
84
-- 00101         ah          r/w/-  address register, high
85
--            7    ubm       r/w/-    ubmap access
86
--            6    p22       r/w/-    22bit access
87
--         5:00    addr      r/w/-    addr(21:16)  
88
-- 00110         mem         r/w/-  memory access
89
-- 00111         memi        r/w/-  memory access, inc address
90
-- 01rrr         gpr[]       r/w/-  general purpose regs
91
-- 10000         membe       r/w/-  memory write byte enables
92
--            3    stick     r/w/-    sticky flag
93
--         1:00    be        r/w/-    byte enables
94 2 wfjm
--
95
 
96
library ieee;
97
use ieee.std_logic_1164.all;
98 13 wfjm
use ieee.numeric_std.all;
99 2 wfjm
 
100
use work.slvtypes.all;
101 9 wfjm
use work.rblib.all;
102 2 wfjm
use work.pdp11.all;
103
 
104
-- ----------------------------------------------------------------------------
105
 
106 9 wfjm
entity pdp11_core_rbus is               -- core to rbus interface
107 2 wfjm
  generic (
108 28 wfjm
    RB_ADDR_CORE : slv16 := slv(to_unsigned(16#0000#,16));
109
    RB_ADDR_IBUS : slv16 := slv(to_unsigned(16#4000#,16)));
110 2 wfjm
  port (
111
    CLK : in slbit;                     -- clock
112
    RESET : in slbit;                   -- reset
113
    RB_MREQ : in rb_mreq_type;          -- rbus: request
114
    RB_SRES : out rb_sres_type;         -- rbus: response
115 27 wfjm
    RB_STAT : out slv4;                 -- rbus: status flags
116 8 wfjm
    RB_LAM : out slbit;                 -- remote attention
117 30 wfjm
    GRESET : out slbit;                 -- general reset
118 2 wfjm
    CP_CNTL : out cp_cntl_type;         -- console control port
119
    CP_ADDR : out cp_addr_type;         -- console address port
120
    CP_DIN : out slv16;                 -- console data in
121
    CP_STAT : in cp_stat_type;          -- console status port
122
    CP_DOUT : in slv16                  -- console data out
123
  );
124 9 wfjm
end pdp11_core_rbus;
125 2 wfjm
 
126
 
127 9 wfjm
architecture syn of pdp11_core_rbus is
128 2 wfjm
 
129
  type state_type is (
130
    s_idle,                             -- s_idle: wait for rp access
131
    s_cpwait,                           -- s_cpwait: wait for cp port ack
132
    s_cpstep                            -- s_cpstep: wait for cpustep done
133
  );
134
 
135
  type regs_type is record
136
    state : state_type;                 -- state
137 9 wfjm
    rbselc : slbit;                     -- rbus select for core
138
    rbseli : slbit;                     -- rbus select for ibus
139 30 wfjm
    rbinit : slbit;                     -- rbus init seen (1 cycle pulse)
140 2 wfjm
    cpreq : slbit;                      -- cp request flag
141
    cpfunc : slv5;                      -- cp function
142
    cpugo_1 : slbit;                    -- prev cycle cpugo
143
    addr : slv22_1;                     -- address register
144
    ena_22bit : slbit;                  -- 22bit enable
145
    ena_ubmap : slbit;                  -- ubmap enable
146 28 wfjm
    membe : slv2;                       -- memory write byte enables
147
    membestick : slbit;                 -- memory write byte enables sticky
148 2 wfjm
    doinc : slbit;                      -- at cmdack: do addr reg inc
149
    waitstep : slbit;                   -- at cmdack: wait for cpu step complete
150
  end record regs_type;
151
 
152
  constant regs_init : regs_type := (
153
    s_idle,                             -- state
154 9 wfjm
    '0','0',                            -- rbselc,rbseli
155 30 wfjm
    '0',                                -- rbinit
156 2 wfjm
    '0',                                -- cpreq
157
    (others=>'0'),                      -- cpfunc
158
    '0',                                -- cpugo_1
159
    (others=>'0'),                      -- addr
160
    '0','0',                            -- ena_22bit, ena_ubmap
161 28 wfjm
    "11",'0',                           -- membe,membestick
162 2 wfjm
    '0','0'                             -- doinc, waitstep
163
  );
164
 
165
  signal R_REGS : regs_type := regs_init;  -- state registers
166
  signal N_REGS : regs_type := regs_init;  -- next value state regs
167
 
168
  begin
169
 
170
  proc_regs: process (CLK)
171
  begin
172
 
173 13 wfjm
    if rising_edge(CLK) then
174 2 wfjm
      if RESET = '1' then
175
        R_REGS <= regs_init;
176
      else
177
        R_REGS <= N_REGS;
178
      end if;
179
    end if;
180
 
181
  end process proc_regs;
182
 
183
  proc_next: process (R_REGS, RB_MREQ, CP_STAT, CP_DOUT)
184
 
185
    variable r : regs_type := regs_init;
186
    variable n : regs_type := regs_init;
187
 
188
    variable irb_ack  : slbit := '0';
189
    variable irb_busy : slbit := '0';
190
    variable irb_err  : slbit := '0';
191
    variable irb_dout : slv16 := (others=>'0');
192
    variable irb_lam  : slbit := '0';
193 9 wfjm
    variable irbena   : slbit := '0';
194 2 wfjm
 
195
    variable icpreq    : slbit := '0';
196
    variable icpaddr   : cp_addr_type := cp_addr_init;
197
 
198
  begin
199
 
200
    r := R_REGS;
201
    n := R_REGS;
202
 
203
    irb_ack  := '0';
204
    irb_busy := '0';
205
    irb_err  := '0';
206
    irb_dout := (others=>'0');
207
    irb_lam  := '0';
208 9 wfjm
 
209
    irbena  := RB_MREQ.re or RB_MREQ.we;
210
 
211 2 wfjm
    icpreq    := '0';
212
 
213 30 wfjm
    -- generate single cycle pulse in case init against rbus base address seen
214
    -- is used to generate some state machine resets via GRESET
215
    n.rbinit := '0';
216 27 wfjm
    if RB_MREQ.init='1' and RB_MREQ.addr=RB_ADDR_CORE then
217 30 wfjm
      n.rbinit := RB_MREQ.din(0);
218 9 wfjm
    end if;
219
 
220
    -- rbus address decoder
221
    n.rbseli := '0';
222
    n.rbselc := '0';
223
    if RB_MREQ.aval='1' then
224 27 wfjm
      if RB_MREQ.addr(15 downto 5)=RB_ADDR_CORE(15 downto 5) then
225 9 wfjm
        n.rbselc := '1';
226 2 wfjm
      end if;
227 28 wfjm
      if RB_MREQ.addr(15 downto 12)=RB_ADDR_IBUS(15 downto 12) then
228 9 wfjm
        n.rbseli := '1';
229 2 wfjm
      end if;
230
    end if;
231
 
232 9 wfjm
    if (r.rbselc='1' or r.rbseli='1') and irbena='1' then
233
      irb_ack  := '1';                   -- ack all (maybe rejected later)
234
    end if;
235 2 wfjm
 
236
    case r.state is
237
 
238
      when s_idle =>                    -- s_idle: wait for rbus access ------
239
 
240
        n.doinc    := '0';
241
        n.waitstep := '0';
242
 
243 9 wfjm
        if r.rbseli = '1' then
244
          if irbena = '1' then
245
            n.cpfunc    := c_cpfunc_rmem;
246
            n.cpfunc(0) := RB_MREQ.we;
247
            icpreq := '1';
248
          end if;
249 2 wfjm
 
250 9 wfjm
        elsif r.rbselc = '1' then
251 2 wfjm
 
252
          case RB_MREQ.addr(4 downto 0) is
253
 
254
            when c_rbaddr_conf =>         -- conf -------------------------
255
              null;                         -- currently no action
256
 
257
            when c_rbaddr_cntl =>         -- cntl -------------------------
258 9 wfjm
              if irbena = '1' then
259
                n.cpfunc := RB_MREQ.din(n.cpfunc'range);
260
              end if;
261 2 wfjm
              if RB_MREQ.we = '1' then
262
                icpreq := '1';
263
                if RB_MREQ.din(3 downto 0) = c_cpfunc_step(3 downto 0) then
264
                  n.waitstep := '1';
265
                end if;
266
              end if;
267
 
268 28 wfjm
            when c_rbaddr_stat =>           -- stat ------------------
269 30 wfjm
              irb_dout(c_stat_rbf_suspext) := CP_STAT.suspext;
270
              irb_dout(c_stat_rbf_suspint) := CP_STAT.suspint;
271
              irb_dout(c_stat_rbf_cpurust) := CP_STAT.cpurust;
272
              irb_dout(c_stat_rbf_cpususp) := CP_STAT.cpususp;
273
              irb_dout(c_stat_rbf_cpugo)   := CP_STAT.cpugo;
274
              irb_dout(c_stat_rbf_cmdmerr) := CP_STAT.cmdmerr;
275 2 wfjm
              irb_dout(c_stat_rbf_cmderr)  := CP_STAT.cmderr;
276
 
277 28 wfjm
            when c_rbaddr_psw  =>           -- psw -------------------
278 9 wfjm
              if irbena = '1' then
279
                n.cpfunc    := c_cpfunc_rpsw;
280
                n.cpfunc(0) := RB_MREQ.we;
281
                icpreq := '1';
282
              end if;
283 2 wfjm
 
284 28 wfjm
            when c_rbaddr_al   =>           -- al --------------------
285 2 wfjm
              irb_dout(c_al_rbf_addr) := r.addr(c_al_rbf_addr);
286
              if RB_MREQ.we = '1' then
287
                n.addr      := (others=>'0'); -- write to al clears ah !!
288
                n.ena_22bit := '0';
289
                n.ena_ubmap := '0';
290
                n.addr(c_al_rbf_addr) := RB_MREQ.din(c_al_rbf_addr);
291
              end if;
292
 
293 28 wfjm
            when c_rbaddr_ah   =>           -- ah --------------------
294 2 wfjm
              irb_dout(c_ah_rbf_ena_ubmap) := r.ena_ubmap;
295
              irb_dout(c_ah_rbf_ena_22bit) := r.ena_22bit;
296
              irb_dout(c_ah_rbf_addr)      := r.addr(21 downto 16);
297
              if RB_MREQ.we = '1' then
298
                n.addr(21 downto 16) := RB_MREQ.din(c_ah_rbf_addr);
299
                n.ena_22bit          := RB_MREQ.din(c_ah_rbf_ena_22bit);
300
                n.ena_ubmap          := RB_MREQ.din(c_ah_rbf_ena_ubmap);
301
              end if;
302
 
303 28 wfjm
            when c_rbaddr_mem  =>           -- mem -------------------
304 9 wfjm
              if irbena = '1' then
305
                n.cpfunc    := c_cpfunc_rmem;
306
                n.cpfunc(0) := RB_MREQ.we;
307
                icpreq   := '1';
308
              end if;
309
 
310 28 wfjm
            when c_rbaddr_memi  =>          -- memi ------------------
311 9 wfjm
              if irbena = '1' then
312
                n.cpfunc    := c_cpfunc_rmem;
313
                n.cpfunc(0) := RB_MREQ.we;
314
                n.doinc  := '1';
315
                icpreq   := '1';
316
              end if;
317 2 wfjm
 
318
            when c_rbaddr_r0 | c_rbaddr_r1 |
319
                 c_rbaddr_r2 | c_rbaddr_r3 |
320
                 c_rbaddr_r4 | c_rbaddr_r5 |
321 28 wfjm
                 c_rbaddr_sp | c_rbaddr_pc =>  -- r* -----------------
322 9 wfjm
              if irbena = '1' then
323
                n.cpfunc    := c_cpfunc_rreg;
324
                n.cpfunc(0) := RB_MREQ.we;
325
                icpreq   := '1';
326
              end if;
327
 
328 28 wfjm
            when c_rbaddr_membe  =>         -- membe -----------------
329
              irb_dout(c_membe_rbf_be)    := r.membe;
330
              irb_dout(c_membe_rbf_stick) := r.membestick;
331 2 wfjm
              if RB_MREQ.we = '1' then
332 28 wfjm
                n.membe      := RB_MREQ.din(c_membe_rbf_be);
333
                n.membestick := RB_MREQ.din(c_membe_rbf_stick);
334 2 wfjm
              end if;
335
 
336
            when others =>
337
              irb_ack := '0';
338
 
339
          end case;
340
 
341
        end if;
342
 
343
        if icpreq = '1' then
344
          irb_busy := '1';
345
          n.cpreq  := '1';
346
          n.state  := s_cpwait;
347
        end if;
348
 
349
      when s_cpwait =>                  -- s_cpwait: wait for cp port ack ----
350
        n.cpreq := '0';                   -- cpreq only for 1 cycle
351
 
352 9 wfjm
        if (r.rbselc or r.rbseli)='0' or irbena='0' then -- rbus cycle abort
353 28 wfjm
          if r.cpfunc = c_cpfunc_wmem and   -- if wmem command
354
               r.membestick = '0' then        --   and be's not sticky
355
            n.membe := "11";                  -- re-enable both bytes
356
          end if;
357 2 wfjm
          n.state := s_idle;              -- quit
358
        else
359
          irb_dout := CP_DOUT;
360 9 wfjm
          irb_err  := CP_STAT.cmderr or CP_STAT.cmdmerr;
361 2 wfjm
          if CP_STAT.cmdack = '1' then       -- normal cycle end
362 28 wfjm
            if r.cpfunc = c_cpfunc_wmem and   -- if wmem command
363
                 r.membestick = '0' then        --   and be's not sticky
364
              n.membe := "11";                  -- re-enable both bytes
365
            end if;
366 2 wfjm
            if r.doinc = '1' then
367 13 wfjm
              n.addr := slv(unsigned(r.addr) + 1);
368 2 wfjm
            end if;
369
            if r.waitstep = '1' then
370
              irb_busy := '1';
371
              n.state := s_cpstep;
372
            else
373
              n.state := s_idle;
374
            end if;
375
          else
376
            irb_busy := '1';
377
          end if;
378
        end if;
379
 
380
      when s_cpstep =>                  -- s_cpstep: wait for cpustep done ---
381 9 wfjm
        if r.rbselc='0' or irbena='0' then -- rbus cycle abort
382 2 wfjm
          n.state := s_idle;                -- quit
383
        else
384
          if CP_STAT.cpustep = '0' then      -- cpustep done
385
            n.state := s_idle;
386
          else
387
            irb_busy := '1';
388
          end if;
389
        end if;
390
 
391
      when others => null;
392
    end case;
393
 
394 28 wfjm
    icpaddr    := cp_addr_init;
395
    icpaddr.be := r.membe;
396 2 wfjm
 
397 28 wfjm
    if r.rbseli = '0' then              -- access via cp
398
      icpaddr.addr      := r.addr;
399
      icpaddr.racc      := '0';
400
      icpaddr.ena_22bit := r.ena_22bit;
401
      icpaddr.ena_ubmap := r.ena_ubmap;
402
    else                                -- access via ibus window
403
      icpaddr.addr(15 downto 13) := "111";
404
      icpaddr.addr(12 downto 1)  := RB_MREQ.addr(11 downto 0);
405 2 wfjm
      icpaddr.racc      := '1';
406
      icpaddr.ena_22bit := '0';
407
      icpaddr.ena_ubmap := '0';
408
    end if;
409
 
410
    n.cpugo_1 := CP_STAT.cpugo;         -- delay cpugo 
411
    if CP_STAT.cpugo='0' and r.cpugo_1='1' then  -- cpugo 1 -> 0 transition ?
412
      irb_lam := '1';
413
    end if;
414
 
415
    N_REGS <= n;
416
 
417
    RB_SRES.ack  <= irb_ack;
418
    RB_SRES.err  <= irb_err;
419
    RB_SRES.busy <= irb_busy;
420
    RB_SRES.dout <= irb_dout;
421
 
422 28 wfjm
    RB_STAT(3) <= CP_STAT.cmderr;
423
    RB_STAT(2) <= CP_STAT.cmdmerr;
424 30 wfjm
    RB_STAT(1) <= CP_STAT.cpususp;
425 2 wfjm
    RB_STAT(0) <= CP_STAT.cpugo;
426
 
427 8 wfjm
    RB_LAM     <= irb_lam;
428 2 wfjm
 
429 30 wfjm
    GRESET     <= R_REGS.rbinit;
430 2 wfjm
 
431
    CP_CNTL.req  <= r.cpreq;
432
    CP_CNTL.func <= r.cpfunc;
433
    CP_CNTL.rnum <= RB_MREQ.addr(2 downto 0);
434
 
435
    CP_ADDR <= icpaddr;
436
    CP_DIN  <= RB_MREQ.din;
437
 
438
  end process proc_next;
439
 
440
end syn;

powered by: WebSVN 2.1.0

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