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

Subversion Repositories w11

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

powered by: WebSVN 2.1.0

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