Name     QBus11 ;
PartNo   00 ;
Date     10/11/2001 ;
Revision 11 ;
Designer CHD ;
Company  ;
Assembly None ;
Location ;
Device   f1508ispplcc84 ; 

/* PIO Mode Only Adapter */

$define NO_DMA		/* PIO mode logic */
/* $define DMA */ 	/* DMA mode logic */
/* $define JUMPERS */	/* include logic for address switches */
				/*   if not defined, address is hardwired */

/* editor font: Courier New, Regular, 10 */

/*
               
                               BB
                             +--------------------------------+
                             |                                | 
                  +-----+    |        +----------+         +-----+
              QB  |     |<---+-+------|          |   CTL   |     |
              ----|TRANS|      |      |  CPLD    |---------| ATA | 
                  |     |    TSBUF    |          |         |     |
                  +-----+      ^      |          |         +-----+
                     |         |      +----------+   
                     +---------+           |   
                         BA                |
                                           |
                  +-----+                  |
              QB  |     |                  |
              ----|TRANS|------------------+    
                  |     |   
                  +-----+      


*/

/* Device Selection */

/* Q22 addressing */

/* 1   7   7   6   0   0   0   0 */
/* 1 111 111 11A AAA AAA BBR RR0 */
/*   where A is the variable base CSR address */
/*         B is the register bank */
/*         R is the register select */

/* 1 111 111 11A AAA AAA A00 000 CSR - base control register (including DMA address extension) */
/* 1 111 111 11A AAA AAA A00 010 CNT - DMA count register - NOT IMPLEMENTED (reserved) */
/* 1 111 111 11A AAA AAA A00 100 DMA - DMA address register - NOT IMPLEMENTED (reserved) */
/* 1 111 111 11A AAA AAA A00 110 VECT - interupt vector number */
/* 1 111 111 11A AAA AAA A01 000 (reserved) */
/* 1 111 111 11A AAA AAA A01 010 (reserved) */
/* 1 111 111 11A AAA AAA A01 100 CS1 disk controller register */
/* 1 111 111 11A AAA AAA A01 110 (reserved) */
/* 1 111 111 11A AAA AAA A1X XX0 CS0 disk controller registers */

/* clock rate: 32MHz *
/*                state1 state2 state3 state4 state5   */
/* minimum delay     1      2      3      4      5     */
/*                  31ns   63ns   94ns  125ns  156ns   */
/* maximum delay     2      3      4      5      6     */
/*                  63ns   94ns  125ns  156ns  188ns   */

$define TRUE  'b'1
$define FALSE 'b'0

/* DECLARATION */

/* Adapter Tri-State Bus */
pin [8, 9, 6, 5, 4, 37, 36, 35, 31, 30, 28, 29, 27, 11, 24, 10]
               = [DAB0..15];	

field DAB      = [DAB0..15];		/* Full word width bus */
field DAB_HIGH = [DAB8..DAB15];	/*   Upper byte */
field DAB_LOW  = [DAB0..DAB7];	/*   Lower byte */

/* disk control signals */
pin [49, 48, 61]
       = [DA0..2];	/* disk register address */
pin 17 = !DCS1;		/* disk chip select 0 - pin */
node      CS1;		/* disk chip select 0 latch */
pin 34 = !DCS0;		/* disk chip select 1 - pin */
node      CS0;		/* disk chip select 1 latch */						
pin 16 = !DIOR;		/* disk controller read operation */
pin 15 = !DIOW;		/* disk controller write operation */
pin 39 =  DIORDY;		/* disk controller ready for word transfer  */
pin 40 =  DINTRQ;		/* disk controller interrupt request */
pin 50 = !DIOCS16;	/* disk controller 16-bit transfer operation */
pin 60 = !DRESET;		/* disk controller hardware reset */

/* QBUS control signals */
pin  1 = INIT;		/* bus reset */
pin 58 = S7;		/* device page select */
pin 81 = SYNC;		/* bus address sync */
pin  2 = DIN;		/* data read cycle */
pin 45 = DOUT;		/* data write cycle */
pin 25 = RPLY;		/* bus cycle handshake */
pin 18 = IRQ4O;		/* interrupt request - level 4 - QBus out*/
pin 44 = IRQ5;		/* interrupt request - level 5 */
pin 46 = IRQ6;		/* interrupt request - level 6 */
pin 41 = IAKI;		/* interrupt acknowledge daisy chain in */
pin 12 = IAKO;		/* interrupt acknowledge daisy chain out */
$ifdef DMA
pin    = [BDAL16..21];	/* extended address bus */
$endif

pin 83 =  CLOCK32;	/* clock for delays */
pin 20 = !QB_DREN;	/* Qbus read - enable OC bus drivers */
pin 21 = !QB_TSEN;	/* Qbus write - enable TS buffers between bus A and bus B */
pin    =  SEL;		/* address match */
node      [RPLYD0..3];	/* state vector for RPLY delay */
node      [IOWD0..3];	/* state vector for IOW delay */
node      INT_ARB_WON;	/* internal signal indicating that adapter gets interrupt */
node      ATA_IRQ;	/* internal F/F to capture drive interrupt request */

$ifdef JUMPERS
/* Option Configuration */
pin    = [CSR_BASE0..7];	/* CSR base address jumpers */
field    CSR_BASE = [CSR_BASE0..7];
field    DAB_CSR = [DAB5..12];
$endif

/* TEST and misc signals */
pin 22 = SYNC_LITE;		/* light driver showing bus activity */
pin = ieck;

/* CSR - Control and Status Register */
pin    = CS_COM;			/* internal select */				

$ifdef DMA
node     [EXT_DMAADR0..5];	/* 15..10: DMA address extension */
$endif
pin =     INT_ENABLE;		/*      6: interrupt enable from disk controller to QBus */
node     IORDY_ENABLE;		/*      5: use IORDY signal from disk controller */

$ifdef DMA
/* DMACNT - DMA Word Tranfer Count Register */
pin    = CS_DMACNT;		/* internal select */

node     [DMACNT0..7];		/* DMA word transfer count */
field DMACNT = [DMACNT0..7];

/* DMAADR - DMA Address Register */
pin    = CS_DMAADR;		/* internal select */

node     [DMAADR0..15];		/* DMA buffer address */
field DMAADR = [DMAADR0..15];
$endif

/* VECTOR - Interrupt Vector Number Register */
pin    = CS_VECT;			/* internal select */

node     [VECTOR0..6];		/* Interrupt vector number */
field VECTOR = [VECTOR0..6];
field DAB_VECT = [DAB2..8];

/* reserved space */
node RSRVD;

field REG_ADDR = [DAB0..4];

/* LOGIC */

/* QBUS Reset */
DRESET = INIT;

/* QBUS Addressing */

/* 1 111 111 11A AAA AAA BBR RR0 */
/*                1  7  7  7  1  0  0  0 */
$ifndef JUMPERS
SEL = S7 & DAB:'b'xxxxxxxxx10010000xxxxx;
$endif

$ifdef JUMPERS
field MATCH = [MATCH0..7];
MATCH = !(CSR_BASE $ DAB_CSR);
SEL = S7 & MATCH:&;
$endif

CS_COM.L     = SEL & REG_ADDR:'b'00000;	/* BASE + 0 */
CS_COM.LE    = !SYNC;

$ifdef DMA
CS_DMACNT.L  = SEL & REG_ADDR:'b'00010;	/* BASE + 2 */
CS_DMACNT.LE = !SYNC;

CS_DMAADR.L  = SEL & REG_ADDR:'b'00100;	/* BASE + 4 */
CS_DMAADR.LE = !SYNC;
$endif

CS_VECT.L    = SEL & REG_ADDR:'b'00110;	/* BASE + 6 */
CS_VECT.LE   = !SYNC;

RSRVD.L      = SEL & REG_ADDR:'b'01000	/* BASE + 8 */ 
             # SEL & REG_ADDR:'b'01010	/* BASE + 10 */
		 # SEL & REG_ADDR:'b'01110;	/* BASE + 14 */
RSRVD.LE     = !SYNC;

$ifndef DMA
append RSRVD.L = SEL & REG_ADDR:'b'00010	/* BASE + 2 */ 
		   # SEL & REG_ADDR:'b'00100;	/* BASE + 4 */
$endif

CS1.L        = SEL & REG_ADDR:'b'01100;	/* BASE + 12 */
CS1.LE       = !SYNC;
DCS1 = CS1 & SYNC;

CS0.L        = SEL & REG_ADDR:'b'1XXX0;	/* BASE + 16 */
CS0.LE       = !SYNC;
DCS0 = CS0 & SYNC;

[DA0..2].L   = [DAB1..3];       		/* save for disk register select */
[DA0..2].LE  = !SYNC;

DISK_SEL = CS0 # CS1;
$ifdef DMA
ADPTR_SEL = CS_COM # CS_VECT # CS_DMACNT # CS_DMAADR # RSRVD;
$endif
$ifndef DMA
ADPTR_SEL = CS_COM # CS_VECT # RSRVD;
$endif
FAST_CYCLE = CS0 & [DA0..2]:'b'000;		/* data register */
DIOCS16 = FAST_CYCLE;

/* I/O Control - QBUS read */
IOR = DISK_SEL & DIN;				/* disk controller read */
DIOR = IOR;						/*   pin */
QBR = (DISK_SEL # ADPTR_SEL) & DIN;		/* enable QBUS drivers */
QB_DREN = QBR # IAKI & INT_ARB_WON;

/* Reply */
/* Reply from DIN = 91ns for byte transfers */
/*                = 30ns for word transfers */
append RPLY = DIN & ADPTR_SEL
            # DIN & !FAST_CYCLE & RPLYD3 & (IORDY_ENABLE & DIORDY # !IORDY_ENABLE) 
            # DIN &  FAST_CYCLE & RPLYD1 & (IORDY_ENABLE & DIORDY # !IORDY_ENABLE);

/* I/O Control - QBUS write */
IOW = DISK_SEL & DOUT & SYNC & !IOWD3;		/* disk controller write */			
DIOW = IOW;							/*   pin */
QBW = (DISK_SEL # ADPTR_SEL) & DOUT;		/* connect bus A to bus B */
QB_TSEN = QBW # !SYNC & !(IAKI & INT_ARB_WON);	/* let the Qbus address pass thru */

/* Reply */
/* Reply from DOUT = 91ns for byte transfers */
/*                 = 30ns for word transfers */
append RPLY = DOUT & ADPTR_SEL
            # DOUT & IOWD1; 

RPLYD0.D = DISK_SEL & (DIN # DOUT);	/* synchronizer */
RPLYD1.D = RPLYD0;				/* 31ns */
RPLYD2.D = RPLYD0 & RPLYD1;			/* 62ns */
RPLYD3.D = RPLYD0 & RPLYD2;			/* 94ns */
[RPLYD0..3].CK = CLOCK32;

IOWD0.D = DOUT				/* synchonizer */
	 & (!FAST_CYCLE & RPLYD3 # FAST_CYCLE & RPLYD1)
	 & (IORDY_ENABLE & DIORDY # !IORDY_ENABLE);
IOWD1.D = IOWD0;					/* 31ns  63ns 125ns */
IOWD2.D = IOWD0 & IOWD1;			/* 63ns  94ns 156ns */
IOWD3.D = IOWD0 & IOWD2;			/* 94ns 125ns 188ns */
[IOWD0..3].CK = CLOCK32;			/*      word  byte  */

append DAB = 'b'0000000000000000;

append DAB.OE = ADPTR_SEL & DIN & SYNC;

/* QBus Interrupt Cycle */
$ifdef notdefined
ATA_IRQ.D = TRUE;
ATA_IRQ.CK = INT_ENABLE & DINTRQ;		/* interrupt is triggered on leading edge of DINTRQ */
ATA_IRQ.AR = INT_ARB_WON & IAKI;		/* clear interrupt on acknowledge */
$endif

ATA_IRQ = INT_ENABLE & DINTRQ;

IRQ4O.L = ATA_IRQ;				/* QBus signal to processor */
IRQ4O.LE = !DIN;					/* Hold during arbitration period */

INT_ARB_WON.L = IRQ4O & !IRQ5 & !IRQ6;	/* latch arbitration */
INT_ARB_WON.LE = !IAKI;				/* latch on acknowledge */

IAKO = IAKI & !INT_ARB_WON;			/* pass on if not for us */

append DAB_VECT = IAKI & INT_ARB_WON & VECTOR;		/* place vector on TS bus */
append DAB.OE = IAKI & INT_ARB_WON;
append RPLY = IAKI & INT_ARB_WON;			/* reply to acknowledge */

/* CSR - Control and Status Register */
/*   read cycle */
$ifdef DMA
append [DAB10..15] = QBR & CS_COM & [EXT_DMAADR0..5];
$endif
append DAB7 = QBR & CS_COM & DINTRQ;		/* disk interrupt request line */
append DAB6 = QBR & CS_COM & INT_ENABLE;		/* interrupt enable */
append DAB5 = QBR & CS_COM & IORDY_ENABLE;	/* disk IORDY control enable */
append DAB4 = QBR & CS_COM & ATA_IRQ;		/* disk interrupt pending */
append DAB0 = QBR & CS_COM;				/* LSB always reads as 1 */

/*   write cycle */
$ifdef DMA
[EXT_DMAADR0..5].AR = INIT;
$endif
INT_ENABLE.D = DAB6;
/* INT_ENABLE.CK = !(QBW & CS_COM); */
INT_ENABLE.CK = !(CS_COM & DOUT);
ieck = !(CS_COM & DOUT);
INT_ENABLE.AR = INIT;
IORDY_ENABLE.D = DAB5;
/* IORDY_ENABLE.CK = !(QBW & CS_COM); */
IORDY_ENABLE.CK = !(CS_COM & DOUT);
IORDY_ENABLE.AR = INIT;

/* Vector Register */
append DAB_VECT = QBR & CS_VECT & VECTOR;
VECTOR.D = DAB_VECT;
VECTOR.CK = !(QBW & CS_VECT);

$ifdef DMA
/* N-Bit, loadable counter macro that uses the T-type registers */
/*    LD:  jam DIN to Q if true during CLK pulse */
/*    CNT: increment Q by 1 if true during CLK pulse */
/*    DIN: jam input */
/*    Q:   N-bit state register */
/*    N:   bits in counter register */
/*    CLK: jam or increment triggered on trail edge */

$macro counter LD CNT DIN Q N CLK 

$repeat i = [0..{N - 1}]
Q{i}.T = LD & !CNT & !DIN{i} & Q{i}			/* jam logic */
	 # LD & !CNT & DIN{i} & !Q{i};		/*   toggle if DINn != Qn */
$repend

append Q{0}.T = !LD & CNT;				/* LSB toggles on every count */
$repeat i = [{1}..{N - 1}]
append Q{i}.T = !LD & CNT & [Q{0}..{i - 1}]:&;	/* toggle if DINn != Qn */
$repend

[Q{0}..{N - 1}].ck = !((LD # CNT) & CLK);

$mend

/* DMA Address Register */
append DAB = QBR & CS_DMAADR & DMAADR;
counter(CS_DMAADR, RSRVD, DAB, DMAADR, 16, DOUT);

/* DMA Count Register */
append DAB_LOW = QBR & CS_DMACNT & DMACNT;
counter(CS_DMACNT, RSRVD, DAB, DMACNT, 8, DOUT);

/* Extended DMA Address Register */
/*   read register as top of CSR -- see CSR section */
/*   load register as top of CSR */ 
$repeat i = [0..5]
EXT_DMAADR{i}.T = CS_COM & !RSRVD & !DAB{i + 10} &  EXT_DMAADR{i}
	          # CS_COM & !RSRVD &  DAB{i + 10} & !EXT_DMAADR{i};
$repend

append EXT_DMAADR0.T = !CS_COM & RSRVD & DMAADR:&;
$repeat i = [1..5]
append EXT_DMAADR{i}.T = !CS_COM & RSRVD & [EXT_DMAADR{0}..{i - 1}]:& & DMAADR:&;
$repend

[EXT_DMAADR0..5].CK = !((CS_COM # RSRVD) & DOUT);
$endif

/* Miscellaneous logic */
SYNC_LITE = !SYNC;

