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

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.5/] [rtl/] [ibus/] [ibdr_rk11.vhd] - Blame information for rev 17

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

Line No. Rev Author Line
1 5 wfjm
-- $Id: ibdr_rk11.vhd 317 2010-07-22 19:36:56Z mueller $
2 2 wfjm
--
3
-- Copyright 2008-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:    ibdr_rk11 - syn
16
-- Description:    ibus dev(rem): RK11-A/B
17
--
18
-- Dependencies:   ram_1swar_gen
19
-- Test bench:     -
20
-- Target Devices: generic
21
-- Tool versions:  xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
22
--
23
-- Synthesized (xst):
24
-- Date         Rev  ise         Target      flop lutl lutm slic t peri
25
-- 2009-06-01   221  10.1.03 K39 xc3s1000-4    46  249   16  148 s  7.1
26
-- 2008-01-06   111   8.2.03 I34 xc3s1000-4    36  189   16  111 s  6.0
27
--
28
-- Revision History: 
29
-- Date         Rev Version  Comment
30
-- 2010-06-11   303   1.1    use IB_MREQ.racc instead of RRI_REQ
31
-- 2009-05-24   219   1.0.9  add CE_MSEC input; inc sector counter every msec
32
--                           BUGFIX: sector counter now counts 000,...,013.
33
-- 2009-05-21   217   1.0.8  cancel pending interrupt requests when IE=0
34
-- 2009-05-16   216   1.0.7  BUGFIX: correct interrupt on IE 0->1 logic
35
--                           BUGFIX: re-work the seek complete handling
36
-- 2008-08-22   161   1.0.6  use iblib
37
-- 2008-05-30   151   1.0.5  BUGFIX: do control reset locally now, add CRDONE
38
-- 2008-03-30   131   1.0.4  issue interrupt when IDE bit set with GO=0
39
-- 2008-02-23   118   1.0.3  remove redundant condition in rkda access code
40
--                           fix bug in control reset logic (we's missing)
41
-- 2008-01-20   113   1.0.2  Fix busy handling when control reset done
42
-- 2008-01-20   112   1.0.1  Fix scp handling; use BRESET
43
-- 2008-01-06   111   1.0    Initial version 
44
------------------------------------------------------------------------------
45
 
46
library ieee;
47
use ieee.std_logic_1164.all;
48
use ieee.std_logic_arith.all;
49
 
50
use work.slvtypes.all;
51
use work.memlib.all;
52
use work.iblib.all;
53
 
54
-- ----------------------------------------------------------------------------
55
entity ibdr_rk11 is                     -- ibus dev(rem): RK11
56
                                        -- fixed address: 177400
57
  port (
58
    CLK : in slbit;                     -- clock
59
    CE_MSEC : in slbit;                 -- msec pulse
60
    BRESET : in slbit;                  -- ibus reset
61
    RRI_LAM : out slbit;                -- remote attention
62
    IB_MREQ : in ib_mreq_type;          -- ibus request
63
    IB_SRES : out ib_sres_type;         -- ibus response
64
    EI_REQ : out slbit;                 -- interrupt request
65
    EI_ACK : in slbit                   -- interrupt acknowledge
66
  );
67
end ibdr_rk11;
68
 
69
architecture syn of ibdr_rk11 is
70
 
71
  constant ibaddr_rk11 : slv16 := conv_std_logic_vector(8#177400#,16);
72
 
73
  constant ibaddr_rkds : slv3 := "000";  -- rkds address offset
74
  constant ibaddr_rker : slv3 := "001";  -- rker address offset
75
  constant ibaddr_rkcs : slv3 := "010";  -- rkcs address offset
76
  constant ibaddr_rkwc : slv3 := "011";  -- rkwc address offset
77
  constant ibaddr_rkba : slv3 := "100";  -- rkba address offset
78 5 wfjm
  constant ibaddr_rkda : slv3 := "101";  -- rkda address offset
79 2 wfjm
  constant ibaddr_rkmr : slv3 := "110";  -- rkmr address offset
80
  constant ibaddr_rkdb : slv3 := "111";  -- rkdb address offset
81
 
82
  subtype  rkds_ibf_id      is integer range 15 downto 13;
83
  constant rkds_ibf_adry  : integer :=  6;
84
  constant rkds_ibf_scsa  : integer :=  4;
85
  subtype  rkds_ibf_sc      is integer range  3 downto  0;
86
 
87
  subtype  rker_ibf_he      is integer range 15 downto  5;
88
  constant rker_ibf_cse   : integer :=  1;
89
  constant rker_ibf_wce   : integer :=  0;
90
 
91
  constant rkcs_ibf_err   : integer := 15;
92
  constant rkcs_ibf_he    : integer := 14;
93
  constant rkcs_ibf_scp   : integer := 13;
94
  constant rkcs_ibf_maint : integer := 12;
95
  constant rkcs_ibf_rdy   : integer :=  7;
96
  constant rkcs_ibf_ide   : integer :=  6;
97
  subtype  rkcs_ibf_mex     is integer range  5 downto  4;
98
  subtype  rkcs_ibf_func    is integer range  3 downto  1;
99
  constant rkcs_ibf_go    : integer :=  0;
100
 
101
  subtype  rkda_ibf_drsel   is integer range 15 downto 13;
102
 
103
  subtype  rkmr_ibf_rid     is integer range 15 downto 13;  -- rem id
104
  constant rkmr_ibf_crdone: integer := 11;                  -- contr. reset done
105
  constant rkmr_ibf_sbclr : integer := 10;                  -- clear sbusy's 
106
  constant rkmr_ibf_creset: integer :=  9;                  -- control reset
107
  constant rkmr_ibf_fdone : integer :=  8;                  -- func done
108
  subtype  rkmr_ibf_sdone   is integer range  7 downto  0;  -- seek done
109
 
110
  type state_type is (
111
    s_idle,
112
    s_init
113
  );
114
 
115
  type regs_type is record              -- state registers
116
    state : state_type;                 -- state
117
    id : slv3;                          -- rkds: drive id of search done
118
    sc : slv4;                          -- rkds: sector counter
119
    cse : slbit;                        -- rker: check sum error
120
    wce : slbit;                        -- rker: write check error
121
    he : slbit;                         -- rkcs: hard error
122
    scp : slbit;                        -- rkcs: seek complete
123
    maint : slbit;                      -- rkcs: maintenance mode
124
    rdy   : slbit;                      -- rkcs: control ready
125
    ide   : slbit;                      -- rkcs: interrupt on done enable
126
    drsel : slv3;                       -- rkda: currently selected drive
127
    fireq : slbit;                      -- func done interrupt request flag
128
    sireq : slv8;                       -- seek done interrupt request flags
129
    sbusy : slv8;                       -- seek busy flags
130
    rid   : slv3;                       -- drive id for rem ds reads
131
    icnt  : slv3;                       -- init state counter
132
    creset : slbit;                     -- control reset flag
133
    crdone : slbit;                     -- control reset done since last fdone
134
  end record regs_type;
135
 
136
  constant regs_init : regs_type := (
137
    s_init,                             --
138
    (others=>'0'),                      -- id
139
    (others=>'0'),                      -- sc
140
    '0','0',                            -- cse, wce
141
    '0','0','0',                        -- he, scp, maint
142
    '1',                                -- rdy (SET TO 1)
143
    '0',                                -- ide
144
    (others=>'0'),                      -- drsel
145
    '0',                                -- fireq
146
    (others=>'0'),                      -- sireq
147
    (others=>'0'),                      -- sbusy
148
    (others=>'0'),                      -- rid
149
    (others=>'0'),                      -- icnt
150
    '0','1'                             -- creset, crdone
151
  );
152
 
153
  signal R_REGS : regs_type := regs_init;
154
  signal N_REGS : regs_type := regs_init;
155
 
156
  signal MEM_1_WE : slbit := '0';
157
  signal MEM_0_WE : slbit := '0';
158
  signal MEM_ADDR : slv4  := (others=>'0');
159
  signal MEM_DIN  : slv16 := (others=>'0');
160
  signal MEM_DOUT : slv16 := (others=>'0');
161
 
162
begin
163
 
164
  MEM_1 : ram_1swar_gen
165
    generic map (
166
      AWIDTH => 4,
167
      DWIDTH => 8)
168
    port map (
169
      CLK  => CLK,
170
      WE   => MEM_1_WE,
171
      ADDR => MEM_ADDR,
172
      DI   => MEM_DIN(ibf_byte1),
173
      DO   => MEM_DOUT(ibf_byte1));
174
 
175
  MEM_0 : ram_1swar_gen
176
    generic map (
177
      AWIDTH => 4,
178
      DWIDTH => 8)
179
    port map (
180
      CLK  => CLK,
181
      WE   => MEM_0_WE,
182
      ADDR => MEM_ADDR,
183
      DI   => MEM_DIN(ibf_byte0),
184
      DO   => MEM_DOUT(ibf_byte0));
185
 
186
  proc_regs: process (CLK)
187
  begin
188
    if CLK'event and CLK='1' then
189
      if BRESET='1' or R_REGS.creset='1' then
190
        R_REGS <= regs_init;
191
        if R_REGS.creset = '1' then
192
          R_REGS.sbusy <= N_REGS.sbusy;
193
        end if;
194
      else
195
        R_REGS <= N_REGS;
196
      end if;
197
    end if;
198
  end process proc_regs;
199
 
200
  proc_next : process (R_REGS, CE_MSEC, IB_MREQ, MEM_DOUT, EI_ACK)
201
    variable r : regs_type := regs_init;
202
    variable n : regs_type := regs_init;
203
    variable ibsel  : slbit := '0';
204
    variable ibbusy : slbit := '0';
205
    variable icrip  : slbit := '0';
206
    variable idout  : slv16 := (others=>'0');
207
    variable ibrd   : slbit := '0';
208
    variable ibrem  : slbit := '0';
209
    variable ibw0   : slbit := '0';
210
    variable ibw1   : slbit := '0';
211
    variable ibwrem : slbit := '0';
212
    variable ilam   : slbit := '0';
213
    variable iscval : slbit := '0';
214
    variable iscid : slv3 := (others=>'0');
215
    variable iei_req : slbit := '0';
216
 
217
    variable imem_we0 : slbit := '0';
218
    variable imem_we1 : slbit := '0';
219
    variable imem_addr : slv4 := (others=>'0');
220
    variable imem_din : slv16 := (others=>'0');
221
  begin
222
 
223
    r := R_REGS;
224
    n := R_REGS;
225
 
226
    ibsel  := '0';
227
    ibbusy := '0';
228
    icrip  := '0';
229
    idout  := (others=>'0');
230
    ibrd   := not IB_MREQ.we;
231
    ibrem  := IB_MREQ.racc or r.maint;
232
    ibw0   := IB_MREQ.we and IB_MREQ.be0;
233
    ibw1   := IB_MREQ.we and IB_MREQ.be1;
234
    ibwrem := IB_MREQ.we and ibrem;
235
    ilam   := '0';
236
    iscval := '0';
237
    iscid  := (others=>'0');
238
    iei_req := '0';
239
 
240
    imem_we0  := '0';
241
    imem_we1  := '0';
242
    imem_addr := '0' & IB_MREQ.addr(3 downto 1);
243
    imem_din  := IB_MREQ.din;
244
 
245
    -- ibus address decoder
246
    if IB_MREQ.req = '1' and
247
       IB_MREQ.addr(12 downto 4)=ibaddr_rk11(12 downto 4) then
248
      ibsel := '1';
249
    end if;
250
 
251
    -- internal state machine (for control reset)
252
    case r.state is
253
      when s_idle =>
254
        null;
255
 
256
      when s_init =>
257
        ibbusy := ibsel;                -- keep req pending if selected
258
        ibsel  := '0';                  -- but don't process selection
259
        icrip  := '1';
260
        n.icnt := unsigned(r.icnt) + 1;
261
        if unsigned(r.icnt) = 7 then
262
          n.state := s_idle;
263
        end if;
264
 
265
      when others => null;
266
    end case;
267
 
268
 
269
    -- ibus transactions
270
    if ibsel = '1' then
271
      idout := MEM_DOUT;
272
      imem_we0 := ibw0;
273
      imem_we1 := ibw1;
274
 
275
      case IB_MREQ.addr(3 downto 1) is
276
 
277
        when ibaddr_rkds =>              -- RKDS -- drive status register ----
278
          if ibrem = '0' then
279
            imem_addr := '1' & r.drsel;  -- loc read ds data: drsel as addr.
280
          else
281
            imem_addr := '1' & r.rid;    -- rem read ds data: rid as addr.
282
          end if;
283
          idout(rkds_ibf_id) := r.id;
284
          if ibrem = '0' then            -- loc ? simulate drive sector monitor
285
            if r.sc = MEM_DOUT(rkds_ibf_sc) then
286
              idout(rkds_ibf_scsa) := '1';
287
            else
288
              idout(rkds_ibf_scsa) := '0';
289
            end if;
290
            idout(rkds_ibf_sc) := r.sc;
291
          end if;
292
 
293
          if r.sbusy(conv_integer(unsigned(imem_addr(2 downto 0))))='1' then
294
            idout(rkds_ibf_adry) := '0';             -- clear drive access rdy
295
          end if;
296
 
297
          if ibwrem = '1' then            -- rem write ? than update ds data
298
            imem_addr := '1' & IB_MREQ.din(rkds_ibf_id); -- use id field as addr
299
          else                          -- loc write ?
300
            imem_we0 := '0';              -- suppress we, is read-only
301
            imem_we1 := '0';
302
          end if;
303
 
304
        when ibaddr_rker =>             -- RKER -- error register ------------
305
          idout(4 downto 2) := (others=>'0');  -- unassigned bits
306
          idout(rker_ibf_cse) := r.cse; -- use state bits (cleared at go !) 
307
          idout(rker_ibf_wce) := r.wce;
308
 
309
          if ibwrem = '1' then          -- rem write ?
310
            if unsigned(IB_MREQ.din(rker_ibf_he)) /= 0 then -- hard errors set ?
311
              n.he := '1';
312
            else
313
              n.he := '0';
314
            end if;
315
            n.cse := IB_MREQ.din(rker_ibf_cse); -- mirror cse bit
316
            n.wce := IB_MREQ.din(rker_ibf_wce); -- mirror wce bit
317
          else                          -- loc write ?
318
            imem_we0 := '0';              -- suppress we, is read-only
319
            imem_we1 := '0';
320
          end if;
321
 
322
        when ibaddr_rkcs =>             -- RKCS -- control status register ---
323
          idout(rkcs_ibf_err) := r.he or r.cse or r.wce;
324
          idout(rkcs_ibf_he)  := r.he;
325
          idout(rkcs_ibf_scp) := r.scp;
326
          idout(rkcs_ibf_rdy) := r.rdy;
327
          idout(rkcs_ibf_go)  := not r.rdy;
328
 
329
          if ibw1 = '1' then
330
            n.maint := IB_MREQ.din(rkcs_ibf_maint); -- mirror maint bit
331
          end if;
332
 
333
          if ibw0 = '1' then
334
            n.ide   := IB_MREQ.din(rkcs_ibf_ide);   -- mirror ide bit
335
            if n.ide = '0' then                     -- if IE 0 or set to 0
336
              n.fireq := '0';                         -- cancel all pending
337
              n.sireq := (others=>'0');               -- interrupt requests
338
            end if;
339
 
340
            if IB_MREQ.din(rkcs_ibf_go) = '1' then    -- GO=1 ?
341
              if r.rdy = '1' then                       -- ready and GO ?
342
                n.scp := '0';                             -- go clears scp !
343
                n.rdy := '0';                             -- mark busy
344
                n.cse := '0';                             -- clear soft errors
345
                n.wce := '0';
346
                n.fireq := '0';                           -- cancel pend. int
347
 
348
                if unsigned(IB_MREQ.din(rkcs_ibf_func))=0 then -- control reset?
349
                  n.creset := '1';                        -- handle locally
350
                else
351
                  ilam  := '1';                           -- issue lam
352
                end if;
353
 
354
                if unsigned(IB_MREQ.din(rkcs_ibf_func))=4 or   -- if seek
355
                   unsigned(IB_MREQ.din(rkcs_ibf_func))=6 then -- or drive reset
356
                  n.sbusy(conv_integer(unsigned(r.drsel))) := '1'; -- set busy
357
                end if;
358
 
359
              end if;
360
            else                                      -- GO=0
361
              if r.ide = '0' and                        -- if ide now 0
362
                 IB_MREQ.din(rkcs_ibf_ide)='1' and      -- and is set to 1
363
                 r.rdy='1' then                         -- and controller ready
364
                n.fireq := '1';                           -- issue interrupt
365
              end if;
366
            end if;
367
          end if;
368
 
369
        when ibaddr_rkda =>             -- RKDA -- disk address register -----
370
          if ibrem = '0' then           -- loc access ?
371
            if r.rdy = '0' then           -- controller busy ?
372
              imem_we0 := '0';              -- suppress write
373
              imem_we1 := '0';
374
            end if;
375
          end if;
376
          if imem_we1 = '1' then
377
            n.drsel := IB_MREQ.din(rkda_ibf_drsel); -- mirror drsel bits
378
          end if;
379
 
380
        when ibaddr_rkmr =>             -- RKMR -- maintenance register ------
381
          idout := (others=>'0');
382
          idout(rkmr_ibf_rid)    := r.rid;
383
          idout(rkmr_ibf_crdone) := r.crdone;
384
          idout(rkmr_ibf_sdone)  := r.sbusy;
385
          if ibwrem = '1' then          -- rem write ?
386
            n.rid := IB_MREQ.din(rkmr_ibf_rid);
387
 
388
            if r.ide='1' and IB_MREQ.din(rkmr_ibf_sbclr)='0' then
389
              n.sireq := r.sireq or (IB_MREQ.din(rkmr_ibf_sdone) and r.sbusy);
390
            end if;
391
            n.sbusy := r.sbusy and not IB_MREQ.din(rkmr_ibf_sdone);
392
 
393
            if IB_MREQ.din(rkmr_ibf_fdone) = '1' then -- func completed
394
              n.rdy    := '1';
395
              n.crdone := '0';
396
              if r.ide = '1' then
397
                n.fireq  := '1';
398
              end if;
399
            end if;
400
            if IB_MREQ.din(rkmr_ibf_creset) = '1' then -- control reset
401
              n.creset := '1';
402
            end if;
403
          end if;
404
 
405
        when others =>                  -- all other regs
406
          null;
407
 
408
      end case;
409
 
410
    end if;
411
 
412
    iscval := '1';
413
       if r.sireq(7) = '1' then  iscid := "111";
414
    elsif r.sireq(6) = '1' then  iscid := "110";
415
    elsif r.sireq(5) = '1' then  iscid := "101";
416
    elsif r.sireq(4) = '1' then  iscid := "100";
417
    elsif r.sireq(3) = '1' then  iscid := "011";
418
    elsif r.sireq(2) = '1' then  iscid := "010";
419
    elsif r.sireq(1) = '1' then  iscid := "001";
420
    elsif r.sireq(0) = '1' then  iscid := "000";
421
    else
422
      iscval := '0';
423
    end if;
424
 
425
    if r.ide = '1' then
426
      if r.fireq='1' or iscval='1' then
427
        iei_req := '1';
428
      end if;
429
    end if;
430
 
431
    if EI_ACK = '1' then                -- interrupt executed
432
      if r.fireq = '1' then
433
        n.scp   := '0';                   -- clear scp flag, is command end
434
        n.fireq := '0';
435
      elsif iscval = '1' then             -- was a seek done
436
        n.scp := '1';                     -- signal seek complete interrupt
437
        n.id := iscid;                        -- load id
438
        n.sireq(conv_integer(unsigned(iscid))) := '0';  -- reset sireq bit
439
      end if;
440
    end if;
441
 
442
    if icrip = '1' then                 -- control reset in progress ?
443
      imem_addr := '0' & r.icnt;          -- use icnt as addr
444
      imem_din  := (others=>'0');         -- force data to zero
445
      imem_we0  := '1';                   -- enable writes
446
      imem_we1  := '1';
447
    end if;
448
 
449
    if CE_MSEC = '1' then               -- advance sector counter every msec
450
      if unsigned(r.sc) = 8#13# then      -- sector counter (count to 8#13#)
451
        n.sc := (others=>'0');
452
      else
453
        n.sc := unsigned(r.sc) + 1;
454
      end if;
455
    end if;
456
 
457
    N_REGS <= n;
458
 
459
    MEM_0_WE <= imem_we0;
460
    MEM_1_WE <= imem_we1;
461
    MEM_ADDR <= imem_addr;
462
    MEM_DIN  <= imem_din;
463
 
464
    IB_SRES.dout <= idout;
465
    IB_SRES.ack  <= ibsel;
466
    IB_SRES.busy <= ibbusy;
467
 
468
    RRI_LAM <= ilam;
469
    EI_REQ  <= iei_req;
470
 
471
  end process proc_next;
472
 
473
 
474
end syn;

powered by: WebSVN 2.1.0

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