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

Subversion Repositories pdp8

[/] [pdp8/] [trunk/] [pdp8/] [rk8e/] [rk05.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 trurl
--------------------------------------------------------------------
2
--!
3
--! PDP-8 Processor
4
--!
5
--! \brief
6
--!      RK05 Disk Simulation
7
--!
8
--! \file
9
--!      rk05.vhd
10
--!
11
--! \author
12
--!      Rob Doyle - doyle (at) cox (dot) net
13
--!
14
--! \details
15
--!
16
--!      An RK05 has the following parameters:
17
--!
18
--!      -#    2 heads per disk
19
--!      -#  203 cylinders (or tracks) per head.
20
--!      -#   16 sectors per cylinder (or track).
21
--!      -#  256 words per sector.
22
--!
23
--!      Assuming the 12-bit word is stored in two bytes, an
24
--!      RK05 image requires 3,325,952 bytes of storage.
25
--!
26
--!      It is a matter of good fortune that the RK05 has 256
27
--!      word sectors and a standard Secure Digital chip has
28
--!      512 byte sectors.  As before, the mapping between the
29
--!      12 bit data and the two bytes of the Secure Digital
30
--!      chip is borrowed from SIMH.
31
--!
32
--!      The SD drive requires a 32-bit address that selects 512-
33
--!      byte sectors.  512 byte sectors work nicely because a 512-
34
--!      byte sector maps nicely to a 256 word (12-bit) sector by
35
--!      ignoring the 4- MSB bits out of every 16-bits.
36
--!
37
--!      The mapping between DISK, HEAD, CYL, and SECTOR and Secure
38
--!      Digital (SD) Sectors is as follows:
39
--!
40
--! \verbatim
41
--!
42
--!             +-----+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
43
--!        SD:  |31-15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
44
--!             +-----+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
45
--!       RK8E: |  0  |D0|D1|C0|C1|C2|C3|C4|C5|C6|C7|H0|S0|S1|S2|S3|
46
--!             +-----+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
47
--!
48
--!       where:
49
--!          D(0:1) : RK8E Disk Select
50
--!          C(0:7) : RK8E Cylinder Select
51
--!          H(0:0) : RK8E Head Select
52
--!          S(0:3) : RK8E Sector Select
53
--!
54
--! \endverbatim
55
--!
56
--!      Therefore the total system capacity is 6651904 words.  This
57
--!      occupies 8388608 words (16 MB) of disk space because we
58
--!      round up the 203 cylinders to 256 and convert to bytes.
59
--!
60
--!      The Secure Digital card can read or write a sector in about
61
--!      400 microseconds.  Obviously this is way faster than a real
62
--!      RK05 Disk Drive operated.
63
--!
64
--!      In order to simulate the actual timing, four RK05 "Disk
65
--!      Simulators" are implemented in this code.   The purpose of
66
--!      Disk Simulators is to simulate the head seek timing and to
67
--!      simulate the rotational latency of a real disk.  Note: the
68
--!      Disk Simulators don't actually read or write data - their
69
--!      purpose is strictly to simulate timing.
70
--!
71
--!      When the RK05 simulator finishes, the Secure Digital
72
--!      Interface device reads or writes the data to the physical
73
--!      media.
74
--!
75
--!      This device simulates the timing of an RK05.
76
--!
77
--!      The following table is used for determining seek timing:
78
--!
79
--! \verbatim
80
--!      +-----+----------+
81
--!      |   0 |    0 ms  |
82
--!      +-----+----------+
83
--!      |   1 |   10 ms  |
84
--!      +-----+----------+
85
--!      |   2 |   20 ms  |
86
--!      +-----+----------+
87
--!      |   4 |   30 ms  |
88
--!      +-----+----------+
89
--!      |   7 |   40 ms  |
90
--!      +-----+----------+
91
--!      |  15 |   50 ms  |
92
--!      +-----+----------+
93
--!      |  30 |   60 ms  |
94
--!      +-----+----------+
95
--!      |  55 |   70 ms  |
96
--!      +-----+----------+
97
--!      |  99 |   80 ms  |
98
--!      +-----+----------+
99
--!      | 205 |   90 ms  |
100
--!      +-----+----------+
101
--! \endverbatim
102
--!
103
--! \note
104
--!      The sector mapping described above has matches SIMH.
105
--!      Therefore SIMH disk images may be used for this
106
--!      application without reformatting.
107
--!
108
--! \note
109
--!      This doesn't simulate the read/write actions of the RK05.
110
--!      It merely simulates the latency on the RK05.
111
--!      When the RK8E receives a command to do something, it
112
--!      determines which RK05 the command is intended.  The RK8E
113
--!      passes the command to the RK05 where the disk latencies
114
--!      are simulated.  When the latencies have expired, the RK05
115
--!      passes the command to the single Secure Disk device where
116
--!      the actual read/write operation occurs.
117
--!
118
--------------------------------------------------------------------
119
--
120
--  Copyright (C) 2009, 2010, 2011, 2012 Rob Doyle
121
--
122
-- This source file may be used and distributed without
123
-- restriction provided that this copyright statement is not
124
-- removed from the file and that any derivative work contains
125
-- the original copyright notice and the associated disclaimer.
126
--
127
-- This source file is free software; you can redistribute it
128
-- and/or modify it under the terms of the GNU Lesser General
129
-- Public License as published by the Free Software Foundation;
130
-- version 2.1 of the License.
131
--
132
-- This source is distributed in the hope that it will be
133
-- useful, but WITHOUT ANY WARRANTY; without even the implied
134
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
135
-- PURPOSE. See the GNU Lesser General Public License for more
136
-- details.
137
--
138
-- You should have received a copy of the GNU Lesser General
139
-- Public License along with this source; if not, download it
140
-- from http://www.gnu.org/licenses/lgpl.txt
141
--
142
--------------------------------------------------------------------
143
--
144
-- Comments are formatted for doxygen
145
--
146
 
147
library ieee;                                           --! IEEE Library
148
use ieee.std_logic_1164.all;                            --! IEEE 1164
149
use ieee.numeric_std.all;                               --! IEEE Numeric Standard
150
use work.cpu_types.all;                                 --! CPU types
151
use work.rk05_types.all;                                --! RK05 types
152
use work.sd_types.all;                                  --! SD Types
153
 
154
--
155
--! RK05 Disk Simulation Entity
156
--
157
 
158
entity eRK05 is port (
159
    sys         : in  sys_t;                            --! Clock/Reset
160
    ioclr       : in  std_logic;                        --! IOCLR
161
    simtime     : in  std_logic;                        --! Simulate RK05 Timing
162
    sdWP        : in  std_logic;                        --! WP from SD Card (Asserted when WP)
163
    sdCD        : in  std_logic;                        --! CD from SD Card (Asserted when No Card)
164
    sdFAIL      : in  std_logic;                        --! SD Failure
165
    rk05INH     : in  rk05WRINH_t;                      --! Write Inhibited
166
    rk05MNT     : in  rk05MNT_t;                        --! Drive is Mounted
167
    rk05OP      : in  rk05OP_t;                         --! RK05 OP
168
    rk05CYL     : in  rk05CYL_t;                        --! RK05 Cylinder
169
    rk05HEAD    : in  rk05HEAD_t;                       --! RK05 Head
170
    rk05SECT    : in  rk05SECT_t;                       --! RK05 Sector
171
    rk05DRIVE   : in  rk05DRIVE_t;                      --! RK05 Drive
172
    rk05LEN     : in  rk05LEN_t;                        --! RK05 Read/Write Length
173
    rk05MEMaddr : in  addr_t;                           --! RK05 Memory Address
174
    rk05STAT    : out rk05STAT_t                        --! RK05 Status
175
);
176
end eRK05;
177
 
178
--
179
--! RK05 Disk Simulation RTL
180
--
181
 
182
architecture rtl of eRK05 is
183
 
184
    type     state_t    is (stateIDLE,
185
                            stateSeekONLY,
186
                            stateSeekRDWR,
187
                            stateWaitRDWR,
188
                            stateDONE);                 --! State type definition
189
    signal   state      : state_t;                      --! State
190
    signal   active     : std_logic;                    --! Activity (timed oneshot)
191
    signal   rk05WRLOCK : rk05WRINH_t;                  --! write locked
192
    signal   rk05state  : rk05STATE_t;                  --! Returned State
193
    signal   rk05RECAL  : std_logic;                    --! Recalibrate
194
    signal   curCYL     : rk05CYL_t;                    --! Current Cylinder
195
    signal   diskADDR   : sdDISKaddr_t;                 --! Disk Address
196
    signal   delayCount : integer range 0 to 45000000;  --! time delay counter
197
    signal   sdOP       : sdOP_t;                       --! SD OP
198
    signal   sdLEN      : sdLEN_t;                      --! SD Read/Write Length
199
    signal   sdMEMaddr  : addr_t;                       --! SD Memory Address
200
    signal   sdDISKaddr : sdDISKaddr_t;                 --! SD Disk Address
201
    constant tenMS      : integer := 500000;            --! 10 milliseconds
202
    constant shortDelay : integer := 50;                --!  1 microseconds
203
    constant sdADDRpad  : std_logic_vector(0 to 16) := (others => '0');
204
    constant rk05CYL0   : rk05CYL_t := (others => '0');
205
 
206
    --!
207
    --! This function returns the number of 50 MHz clock cycles to delay
208
    --! for the seek delay simulation.
209
    --!
210
 
211
    function seekDelay(newCYL : rk05CYL_t; oldCYL : rk05CYL_t) return integer is
212
        variable diffCYL : integer range 0 to 255;
213
    begin
214
 
215
        if newCYL > oldCYL then
216
            diffCYL := to_integer(unsigned(newCYL) - unsigned(oldCYL));
217
        else
218
            diffCYL := to_integer(unsigned(oldCYL) - unsigned(newCYL));
219
        end if;
220
 
221
        if diffCYL < 1 then
222
            return 0;                   -- 0 ms
223
        elsif diffCYL < 2 then
224
            return tenMS * 1;           -- 10 ms
225
        elsif diffCYL < 3 then
226
            return tenMS * 2;           -- 20 ms
227
        elsif diffCYL < 5 then
228
            return tenMS * 3;           -- 30 ms
229
        elsif diffCYL < 8 then
230
            return tenMS * 4;           -- 40 ms
231
        elsif diffCYL < 16 then
232
            return tenMS * 5;           -- 50 ms
233
        elsif diffCYL < 31 then
234
            return tenMS * 6;           -- 60 ms
235
        elsif diffCYL < 56 then
236
            return tenMS * 7;           -- 70 ms
237
        elsif diffCYL < 100 then
238
            return tenMS * 8;           -- 80 ms
239
        else
240
            return tenMS * 9;           -- 90 ms
241
        end if;
242
 
243
    end seekDelay;
244
 
245
begin
246
 
247
    --
248
    -- Disk Address
249
    --
250
 
251
    diskADDR <= sdADDRpad & rk05DRIVE & rk05CYL & rk05HEAD & rk05SECT;
252
 
253
    --
254
    --! State machine
255
    --
256
 
257
    RK05_SIM : process(sys, ioclr)
258
    begin
259
 
260
        if sys.rst = '1' or ioclr = '1' then
261
 
262
            delayCount      <= 0;
263
            rk05WRLOCK <= '0';
264
            rk05RECAL  <= '0';
265
            state      <= stateIdle;
266
            sdOP       <= sdopNOP;
267
            sdLEN      <= '0';
268
            curCYL     <= (others => '0');
269
            sdMEMaddr  <= (others => '0');
270
            sdDISKaddr <= (others => '0');
271
 
272
        elsif rising_edge(sys.clk) then
273
 
274
            if ioclr = '1' then
275
 
276
                delayCount      <= 0;
277
                rk05WRLOCK <= '0';
278
                rk05RECAL  <= '0';
279
                state      <= stateIdle;
280
                sdOP       <= sdopNOP;
281
                sdLEN      <= '0';
282
                curCYL     <= (others => '0');
283
                sdMEMaddr  <= (others => '0');
284
                sdDISKaddr <= (others => '0');
285
 
286
            else
287
 
288
                if rk05OP = rk05opCLR then
289
                    rk05WRLOCK <= '0';
290
                    sdOP       <= sdopABORT;
291
                    state      <= stateDONE;
292
 
293
                else
294
 
295
                    case state is
296
 
297
                        --
298
                        -- Nothing happening
299
                        --
300
 
301
                        when stateIDLE =>
302
                            case rk05OP is
303
 
304
                                --
305
                                -- IDLE:
306
                                -- Nothing to do
307
                                --
308
 
309
                                when rk05opNOP =>
310
                                    null;
311
 
312
                                --
313
                                -- Reset:
314
                                -- Handled above
315
                                --
316
 
317
                                when rk05opCLR =>
318
                                    null;
319
 
320
                                --
321
                                -- Wrprot:
322
                                -- Write protect the drive
323
                                --
324
 
325
                                when rk05opWRPROT =>
326
                                    rk05WRLOCK <= '1';
327
                                --
328
                                -- Recalibrate:
329
                                -- Seek to cylinder 0
330
                                --
331
 
332
                                when rk05opRECAL =>
333
                                    sdOP       <= sdopNOP;
334
                                    sdLEN      <= rk05LEN;
335
                                    sdMEMaddr  <= rk05MEMaddr;
336
                                    sdDISKaddr <= diskADDR;
337
                                    rk05RECAL  <= '1';
338
                                    curCYL     <= rk05CYL0;
339
                                    if simtime = '1' then
340
                                        delayCount <= seekDelay(curCYL, rk05CYL0);
341
                                    else
342
                                        delayCount <= shortDelay;
343
                                    end if;
344
                                    state <= stateSeekONLY;
345
 
346
                                --
347
                                -- Seek Operation
348
                                -- Seek to new cyclinder
349
                                --
350
 
351
                                when rk05opSEEK =>
352
                                    sdOP       <= sdopNOP;
353
                                    sdLEN      <= rk05LEN;
354
                                    sdMEMaddr  <= rk05MEMaddr;
355
                                    sdDISKaddr <= diskADDR;
356
                                    curCYL     <= rk05CYL;
357
                                    if simtime = '1' then
358
                                        delayCount <= seekDelay(curCYL, rk05CYL);
359
                                    else
360
                                        delayCount <= shortDelay;
361
                                    end if;
362
                                    state <= stateSeekONLY;
363
 
364
                                --
365
                                -- Read Operation
366
                                --
367
 
368
                                when rk05opREAD =>
369
                                    sdOP       <= sdopRD;
370
                                    sdLEN      <= rk05LEN;
371
                                    sdMEMaddr  <= rk05MEMaddr;
372
                                    sdDISKaddr <= diskADDR;
373
                                    curCyl     <= rk05CYL;
374
                                    if simtime = '1' then
375
                                        delayCount <= seekDelay(curCYL, rk05CYL);
376
                                    else
377
                                        delayCount <= shortDelay;
378
                                    end if;
379
                                    state <= stateSeekRDWR;
380
 
381
                                --
382
                                -- Write Operation
383
                                --
384
 
385
                                when rk05opWRITE =>
386
                                    sdOP       <= sdopWR;
387
                                    sdLEN      <= rk05LEN;
388
                                    sdMEMaddr  <= rk05MEMaddr;
389
                                    sdDISKaddr <= diskADDR;
390
                                    curCyl     <= rk05CYL;
391
                                    if simtime = '1' then
392
                                        delayCount <= seekDelay(curCYL, rk05CYL);
393
                                    else
394
                                        delayCount <= shortDelay;
395
                                    end if;
396
                                    state <= stateSeekRDWR;
397
 
398
                                --
399
                                -- Anything else?
400
                                --
401
 
402
                                when others =>
403
                                    null;
404
 
405
                            end case;
406
 
407
                        --
408
                        -- stateSeekONLY:
409
                        --  Simulate Seek Timing on Seeks
410
                        --
411
 
412
                        when stateSeekONLY =>
413
                            if delayCount = 0 then
414
                                state <= stateDONE;
415
                            else
416
                                delayCount <= delayCount - 1;
417
                            end if;
418
 
419
                        --
420
                        -- stateSeekRDWR:
421
                        --  Simulate Seek Timing on Read/Writes
422
                        --
423
 
424
                        when stateSeekRDWR =>
425
                            if delayCount = 0 then
426
                                if simtime = '1' then
427
                                    delayCount <= tenMS;
428
                                else
429
                                    delayCount <= shortDelay;
430
                                end if;
431
                                state <= stateWaitRDWR;
432
                            else
433
                                delayCount <= delayCount - 1;
434
                            end if;
435
 
436
                        --
437
                        -- stateWaitRDWR:
438
                        --  Simuate rotational latency on Read/Writes
439
                        --
440
 
441
                        when stateWaitRDWR =>
442
                            if delayCount = 0 then
443
                                state <= stateDone;
444
                            else
445
                                delayCount <= delayCount - 1;
446
                            end if;
447
 
448
                        --
449
                        -- stateDone:
450
                        --
451
 
452
                        when stateDONE =>
453
                            rk05RECAL <= '0';
454
                            state     <= stateIDLE;
455
 
456
                        --
457
                        -- Anything else?
458
                        --
459
 
460
                        when others =>
461
                            null;
462
 
463
                    end case;
464
                end if;
465
            end if;
466
        end if;
467
    end process RK05_SIM;
468
 
469
    --
470
    --! Activity Timer for LED
471
    --
472
 
473
    ACTIVITY : process(sys)
474
        variable timer   : integer range 0 to 4999999;  --! Timer
475
        constant maxTIME : integer := 4999999;          --! Time delay
476
    begin
477
        if sys.rst = '1' then
478
            timer  := 0;
479
            active <= '0';
480
        elsif rising_edge(sys.clk) then
481
            if ((rk05OP =  rk05opRECAL) or
482
                (rk05OP =  rk05opSEEK ) or
483
                (rk05OP =  rk05opREAD ) or
484
                (rk05OP =  rk05opWRITE)) then
485
                timer  := maxTIME;
486
                active <= '1';
487
            elsif timer = 0 then
488
                active <= '0';
489
            else
490
                timer := timer - 1;
491
            end if;
492
        end if;
493
    end process ACTIVITY;
494
 
495
    --
496
    -- Combinational logic
497
    --
498
 
499
    with state select
500
        rk05state <= rk05stIDLE when stateIDLE,
501
                     rk05stDONE when stateDONE,
502
                     rk05stBUSY when others;
503
 
504
    rk05STAT.active     <= active;
505
    rk05STAT.state      <= rk05state;
506
    rk05STAT.mounted    <= rk05MNT and not(sdFAIL) and not(sdCD);
507
    rk05STAT.WRINH      <= rk05INH or rk05WRLOCK or sdWP;
508
    rk05STAT.recal      <= rk05RECAL;
509
    rk05STAT.sdOP       <= sdOP;
510
    rk05STAT.sdLEN      <= sdLEN;
511
    rk05STAT.sdMEMaddr  <= sdMEMaddr;
512
    rk05STAT.sdDISKaddr <= sdDISKaddr;
513
 
514
end rtl;

powered by: WebSVN 2.1.0

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