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

Subversion Repositories w11

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

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

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

powered by: WebSVN 2.1.0

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