RLV12 V2.0 CPLD Design
CPLD Functional Description
The following sections describe the functions of the two CPLDs. The two CPLD
design files are named QBUSRLV12V2-A-v2-1.pld
and QBUSRVL12V2-B-v2-1.pld
and are referred to as CPLD A and CPLD B.
CPLD A - ATF1508
This CPLD handles the transmit data path to the Q‐Bus and the Q‐Bus
control functions.
The interface towards the MCU consists of the data bus AD0..7
and the control
signals ALEW
, WR
, INTI
, INTQ
, IRQST
, CRDY
, ABORT
, DMR
and DMG
.
Register Interface
The MCU can only write to registers in the CPLD. The registers are
- Q-Bus Data Register
- DMA Data Register
- DMA Address Register
- Control Register
To access a register the MCU has first to set up the register address. First
the MCU must deassert WR
, then it must place the register address to the
data bus. It then must assert the ALEW
signal to load the register address.
Now it can place the value to be written to the register onto the data bus
and then assert WR
to write the data to the register in the CPLD. To write
another register it must again deassert WR
. Deasserting WR
will change
the register address previously loaded. This happens for every WR
cycle
and depending on the initial register address loaded the register address
will advance as follows
- 0->1->0->1->0->1… This will toggle between the low and high byte of the 16-bit Q-Bus data register
- 2->3->2->3->2->3… This will toggle between the low and high byte of the 16-bit Q-Bus DMA data register
- 4->5->6->4->5->6… This will walk through the low, high and extended byte of the 22-bit Q-Bus DMA address register
This is so we can write either of the Q-Bus registers in a series of bytes
by just using subsequent WR
cycles without having to individually address
each byte of the Q-Bus registers.
Register 7 is used to control the BootROM feature of the RLV12 Emulator. Even so the next register addressed is register 0 this mostly has no advantage.
Register Address | Description |
0 | Q-Bus Write Data Register Low Byte |
1 | Q-Bus Write Data Register High Byte |
2 | Q-Bus DMA Write Data Register Low Byte |
3 | Q-Bus DMA Write Data Register High Byte |
4 | Bit0: DMA direction 0=DMA Write, 1=DMA Read, Bits1...7: Q-Bus DMA Start Address A1..7 |
5 | Q-Bus DMA Start Address A8..15 |
6 | Q-Bus DMA Start Address A16..21 |
7 | Bit0: BootROM Control 0=BootROM disabled, 1=BootROM enabled |
Q-Bus DATI/DATO interface
Whenever the RLV12 Q-Bus registers, default range is 174400..174417
or the
IO-page ROM range 173000..173777
is addressed CPLD B will assert CSRADDR
or
ROMADDR
respectively.
When CSRADDR
is asserted and the controller is ready, i.e. the MCU has asserted
the CRDY
control signal, or when ROMADDR
is asserted and the Bit0 in the BootROM
control register is set to one, the CPLD will deassert INTQ
when the BSYNCL
is
asserted on the Q-Bus.
As INTQ
is connected to the interrupt signal INT0
of the MCU This will rise
an interrupt. Therefore INT0
is configured as a low-level interrupt. The MCU
will then execute the code at the vector associated with this interrupt. First
the MCU will read the status register from CPLD B. The value in this register
will tell the MCU which type of Q-Bus cycle was the reason of the interrupt.
The MCU needs to process the request and create a pulse on IACK
to inform
the CPLD A that the Q-Bus cycle can be finished, i.e. assert BRPLYL and
clear the interrupt.
Q-Bus interrupt interface
The MCU can initiate an interrupt cycle on the Q-Bus by asserting IRQST
. This
will assert BIRQ4L
on the Q-Bus. Eventually the host will start a interrupt
acknowledge cycle. In case the RLV12 Emulator has initiated the interrupt the
CPLD will receive the BIACKI
signal and deassert INTI
to interrupt the MCU.
As with the the DATI/DATO interface the MCU is interrupted, now via the INT1
interrupt input. The MCU will then write the interrupt vector to the Q-Bus
data register and acknowledge the interrupt with a pulse on IACK
. This will
cause the CPLD to assert BRPLYL
, the host will then fetch the vector address
and continue.
In case the CPLD receives the BIACKI
signal without the MCU having initiated
the interrupt, the CPLD will propagate the signal to BIACKO
and the MCU will
not be interrupted.
Q-Bus DMA interface
To perform a DMA the CPLD imlementes a single word DMA interface. The MCU first
has to first set the DMA start address together with the DMA direction in the
Q-Bus DMA address registers 4, 5 and 6. In case of a DMA write it also has
to load the Q-Bus DMA write data register using CPLD registers 2 and 3. When the
MCU asserts DMR
the CPLD will try to perform a single DMA cycle. When the
DMA finished successfully the CPLD will assert DMG
and waits for the MCU
to deassert DMR
.
The MCU should terminated a DMA request by using the ABORT
signal to avoid
bus-timeouts in case DMA accesses non-existing memory when DMG
is not
asserted within a given time, typically 10µsecs.
For DMA reads the result will be available in the Q-Bus DMA read data register implemented in CPLD B.
BINIT interface
To reset the CPLD and to inform the MCU BINITL
is propagated via a receiver
to both devices. The current MCU firmware will use this signal as a pin change
interrupt and resets the units.
CPLD A Design File
As you can see the design file already has some mentions of a new adapter. You can ignore the comments at the beginning as they are not relevant to the RLV12 EMulator V2.0.
Name QBUS RLV12 Version 2 ;
PartNo A ;
Date 15.04.2022 ;
Revision 02 ;
Designer cbscpe ;
Company PRIVAT ;
Assembly None ;
Location ATHOME ;
Device f1508ispplcc84 ;
/*
2022-05-23 Adapter-B was intended to replace the ATmega1284P with a
AVR128DB48. The MVIO was left a 5V so we could use the
same break-out board. However for some reason SPI is not
working correctly. In the meantime the CPLD interface for
the Q-Bus version has changed again. This is now known as
the RVL12Emu-v21. When Adapter-B was developped another
interface was used. To continue to analyze the SPI problem
with Adapter-B we need to switch some pins on the CPLD.
Pin Name ATmega1284P AVR128DB48
CLK 83 2
ALEW 2 83
INTQ 4 80
INTI 6 64
ACK 64 6
ATmega1284P and AVR128DB48 Adapter-C
DEFINE PINCLK 83
DEFINE PINALEW 2
DEFINE PININTQ 4
DEFINE PININTI 6
DEFINE PINACK 64
AVR128DB48 Adapter-B
DEFINE PINCLK 2
DEFINE PINALEW 83
DEFINE PININTQ 80
DEFINE PININTI 64
DEFINE PINACK 6
A new Adapter-C has been designed that keeps the PIN Layout and has a 3V3 LDO for
MVIO Port C
*/
$DEFINE PINCLK 83
$DEFINE PINALEW 2
$DEFINE PININTQ 4
$DEFINE PININTI 6
$DEFINE PINACK 64
PIN 16 = TDAL15; /* Transmit Data/Address */
PIN 15 = TDAL14;
PIN 24 = TDAL13;
PIN 22 = TDAL12;
PIN 18 = TDAL11;
PIN 20 = TDAL10;
PIN 12 = TDAL9;
PIN 17 = TDAL8;
PIN 21 = TDAL7;
PIN 25 = TDAL6;
PIN 27 = TDAL5;
PIN 28 = TDAL4;
PIN 34 = TDAL3;
PIN 35 = TDAL2;
PIN 36 = TDAL1;
PIN 37 = TDAL0;
PIN 58 = TDAL16;
PIN 60 = TDAL17;
PIN 29 = TDAL18;
PIN 30 = TDAL19;
PIN 31 = TDAL20;
PIN 33 = TDAL21;
PIN 61 = RRPLY; /* Receive RPLY */
PIN 57 = RDIN; /* Receive DIN */
PIN 55 = RDOUT; /* Receive DOUT */
PIN 54 = RSYNC; /* Receive SYNC */
PIN 1 = RINIT; /* Receive INIT */
PIN 52 = TRPLY; /* Transmit RPLY */
PIN 46 = TDIN; /* Transmit DIN */
PIN 48 = TDOUT; /* Transmit DOUT */
PIN 50 = TWTBT; /* Transmit WTBT */
PIN 51 = TSYNC; /* Transmit SYNC */
PIN 49 = RIAKI; /* Receive IAKI */
PIN 41 = TIAKO; /* Transmit IAKO */
PIN 44 = TDMR; /* Transmit DMR */
PIN 45 = RDMGI; /* Receive DMGI */
PIN 39 = TDMGO; /* Transmit DMGO */
PIN 40 = TSACK; /* Transmit SACK */
PIN 81 = WR; /* Register WR Clock */
PIN PINCLK = CLK; /* System Clock */
PIN PINALEW = ALEW; /* Address Latch Enable Write */
PIN 74 = AD0; /* MCU Address/Data Bus */
PIN 73 = AD1;
PIN 75 = AD2;
PIN 68 = AD3;
PIN 69 = AD4;
PIN 76 = AD5;
PIN 70 = AD6;
PIN 67 = AD7;
PIN 8 = IRQST; /* Interrupt Request */
PIN 79 = DMR; /* DMA Requst */
PIN 5 = DMG; /* DMA Granted/Finished */
PIN PININTQ = INTQ; /* Q-Bus DATI/DATO Interrupt */
PIN PININTI = INTI; /* Q-Bus IACK Interrupt */
PIN 77 = CRDY; /* Controller Ready */
PIN PINACK = IACK; /* MCU Interrupt Acknowledge */
PIN 63 = ABORT; /* Abort DMA */
PIN 9 = ROMADDR; /* ROM Address Enable */
PIN 10 = CSRADDR; /* CSR Address Enable */
PIN 11 = LD; /* Load Q-Bus DMA Read Data */
/*
CPLD A implements the following functions
- MCU Interface for CSR Access
- DMA Write Data Register
- Q-Bus Data Register
- DMA Address Register
- DMA State Machine
CPLD B implements the following functions
- Device Select
- Device Register Address and Byte Select
- Direct Q-Bus Read for DATO/DATOB cycles
- DMA Read Data Register
2022-04-15
New CPLD Interface for MCU. To access any register in CPLD A or B
you need first to load the register address. The register address
register is part of a state machine. Depending on the address
loaded each register write will advance the state. This is made
because CPLD registers are typically written as 16-bit registers
or as DMA address with 22-bits. Therefore only the first register
address must be loaded. You still can access individual registers.
To set the write register address you use ALEW to set the read
register address you use ALER. Note this CPLD only implements
the writeable registers.
0->1->0->1 Write Q-Bus Data Register
2->3->2->3 Write DMA Data Register
4->5->6->4 Write DMA Address and direction register
7->0 Just to avoid undefined states
CPLD A creates the MCU interrupts and controls the following bus cycles
- DATI/DATO to device registers
- Interrupt Acknowledge
- DMA
CPLD A implements the DMA interface to read or write one 16-bit
word from or to the host memory.
2022-04-26
Boot ROM option using unused CPLD interconnection to signal a ROM
address range
Add a Boot ROM Enable flag using Register 7 to allow enabling or
disabling Boot ROM via software
Enable Q-Bus data for CSR only if CRDY is set. We need this to
still be able to read the ROM during controller busy
2022-05-06
Comment for the four unused signals LED, ALER, SIG, RWTBT, they are
connected on the initial PCB but are not required.
!!!!!!!!! This CPLD requires the interface '22' in the MCU firmware
!!!!!!!!! #define rlv12 22 ; Select Assembler Option
*/
PROPERTY ATMEL {preassign KEEP};
PROPERTY ATMEL {SOFT_BUFFER=I14, I7};
PINNODE = [Q15..0] ; /* Data Output Register */
PINNODE = [D15..0] ; /* DMA Data Register */
PINNODE = [A21..1] ; /* DMA Address */
PINNODE = CSR ; /* */
PINNODE = ROM ; /* */
PINNODE = [DMA5..0] ; /* DMA State Machine */
PINNODE = SYNC ; /* */
PINNODE = DMGI ; /* */
PINNODE = SACK ; /* */
PINNODE = DATA ; /* */
PINNODE = RPLY ; /* */
PINNODE = DMARW ; /* Control bit: DMA read(1) or DMA write(0) */
PINNODE = ROMEN ; /* Enable Bootrom */
PINNODE = DACK ; /* Device Interrupt Acknowledge */
PINNODE = RECI ; /* */
PINNODE = [RS2..0];
PINNODE = EN;
PINNODE = I7;
PINNODE = I14;
/*
Field definitions
*/
FIELD RS = [RS2..0]; /* Register Select Address for Atmega1281 reads/writes */
FIELD DMA = [DMA5..0]; /* DMA State Machine */
/*
Register Select for DMA Address Registers
*/
RS.ar = ALEW & ![AD2..0];
RS.ap = ALEW & [AD2..0];
RS.ck = !WR;
sequence RS {
PRESENT 0 NEXT 1;
PRESENT 1 NEXT 0;
PRESENT 2 NEXT 3;
PRESENT 3 NEXT 2;
PRESENT 4 NEXT 5;
PRESENT 5 NEXT 6;
PRESENT 6 NEXT 4;
PRESENT 7 NEXT 0;
}
/*
CSR is set during every cycle the device is selected
*/
CSR.ck = RSYNC;
CSR.d = CSRADDR;
ROM.ck = RSYNC;
ROM.d = ROMADDR & ROMEN;
/*
Raise an interrupt for every access to any of the device registers
note that an interrupt is only generated in case CRDY is set. In
case of CRDY cleared the MCU will not be interrupted and the cycle
will be acknowledged by the CPLD and the last value written to the
Q-Bus data register will be placed onto the Q-Bus, in other words
you should load the Q-Bus data register with an appropriate value
to indicate the device is busy. Mostly a zero value is appropriate.
The same is true for boot ROM access. Here we have the ROMEN
register to enable or disable the boot ROM via software
*/
INTQ.d = !(CSRADDR & CRDY
# ROMADDR & ROMEN);
INTQ.ck = RSYNC;
INTQ.ap = IACK;
TRPLY = CSR & RSYNC & INTQ & RDIN /* Assert RPLY when MCU is done */
# CSR & RSYNC & INTQ & RDOUT; /* Assert RPLY when MCU is done */
APPEND
TRPLY = ROM & RSYNC & INTQ & RDIN /* Assert RPLY when MCU is done */
# ROM & RSYNC & INTQ & RDOUT; /* Assert RPLY when MCU is done */
/*
Latch the interrupt request with every RDIN
*/
DACK.d = IRQST;
DACK.ck = RDIN;
DACK.ar = RINIT;
TIAKO = RIAKI & !DACK;
INTI.d = !DACK;
INTI.ck = RIAKI;
INTI.ap = IACK;
APPEND
TRPLY = RIAKI & RDIN & DACK & INTI;
/*
Q-Bus Data Register
*/
[Q7..0].d = [AD7..0];
[Q7..0].ce = RS:['d'0];
[Q15..8].d = [AD7..0];
[Q15..8].ce = RS:['d'1];
[Q15..0].ck = WR;
/*
DMA Data Register
*/
[D7..0].d = [AD7..0];
[D7..0].ce = RS:['d'2];
[D15..8].d = [AD7..0];
[D15..8].ce = RS:['d'3];
[D15..0].ck = WR;
/*
DMA Address
*/
DMARW.ar = WR & RS:['d'4] & !AD0;
DMARW.ap = WR & RS:['d'4] & AD0;
DMARW.ck = 'b'0;
DMARW.d = 'b'0;
[A7..1].ar = WR & RS:['d'4] & ![AD7..1];
[A7..1].ap = WR & RS:['d'4] & [AD7..1];
[A15..8].ar = WR & RS:['d'5] & ![AD7..0];
[A15..8].ap = WR & RS:['d'5] & [AD7..0];
[A21..16].ar = WR & RS:['d'6] & ![AD5..0];
[A21..16].ap = WR & RS:['d'6] & [AD5..0];
/*
Enable Boot ROM
*/
ROMEN.ck = 'b'0;
ROMEN.d = 'b'0;
ROMEN.ar = WR & RS:['d'7] & !AD0;
ROMEN.ap = WR & RS:['d'7] & AD0;
/*
Synchronous counter for DMA address which is updated after every DMA
cycle. The address is incremented whenever a DMA cycle has finished.
*/
[A21..1].ck = !DMA5;
A1.t = 'b'1;
A2.t = A1;
A3.t = A1 & A2;
A4.t = A1 & A2 & A3;
A5.t = A1 & A2 & A3 & A4;
A6.t = A1 & A2 & A3 & A4 & A5;
A7.t = A1 & A2 & A3 & A4 & A5 & A6;
I7 = A1 & A2 & A3 & A4 & A5 & A6 & A7;
A8.t = I7;
A9.t = I7 & A8;
A10.t = I7 & A8 & A9;
A11.t = I7 & A8 & A9 & A10;
A12.t = I7 & A8 & A9 & A10 & A11;
A13.t = I7 & A8 & A9 & A10 & A11 & A12;
A14.t = I7 & A8 & A9 & A10 & A11 & A12 & A13;
I14 = I7 & A8 & A9 & A10 & A11 & A12 & A13 & A14;
A15.t = I14;
A16.t = I14 & A15;
A17.t = I14 & A15 & A16;
A18.t = I14 & A15 & A16 & A17;
A19.t = I14 & A15 & A16 & A17 & A18;
A20.t = I14 & A15 & A16 & A17 & A18 & A19;
A21.t = I14 & A15 & A16 & A17 & A18 & A19 & A20;
/*
Q-Bus Output Select and Output Enable
DMA5 DMA is active
DMA4 DMA read
DMA3 DMA data transfer
EN Enable Output during DMA
*/
[TDAL15..0] = !RIAKI & !DMA5 & CSR & RDIN & [Q15..0] & CRDY
# !RIAKI & !DMA5 & ROM & RDIN & [Q15..0]
# !RIAKI & EN & !DMA3 & [A15..1, 'b'0]
# !RIAKI & EN & DMA3 & [D15..0];
APPEND
[TDAL8..2] = RIAKI & DACK & RDIN & [Q8..2];
/*
The upper address bits are just a copy of the DMA address.
*/
[TDAL21..16] = [A21..16] & EN;
/*
The rising edge of DMR from the MCU triggers BDMR of the Q-Bus when
the DMA is granted BDMR is cleared but DMR will be kept asserted by
the MCU until the MCU has finished the DMA. Used to control the state
machine.
*/
TDMR.d = 'b'1;
TDMR.ck = DMR;
TDMR.ar = DMA5 # ABORT;
TSYNC.ck = CLK;
TDOUT.ck = CLK;
TDIN.ck = CLK;
/*
Synchronous Signals
*/
DMGI.ck = CLK;
DMA.ck = CLK;
RPLY.ck = CLK;
DMG.ck = CLK;
LD.ck = CLK;
EN.ck = CLK;
DMA.ar = ABORT;
/*
Latched BDMGI and BRPLY as we need a stable DMGI and RPLY for the state machine
*/
DMGI.d = RDMGI;
RPLY.d = RRPLY;
/*
DMA state machine, the state machine has now 6 bits with certain
bits directly linked to a function.
DMA5 is asserted during an active DMA
DMA4 is asserted for a DMA write cycle and de-asserted for a DMA
read cycle
DMA3 is de-asserted during the address portion of a DMA cycle
and is asserted during the data transfer portion of a DMA
cycle
For DMA writes the MCU must first load the DMA start address register
with the LSB cleared. Then it loads the DMA data register with the
value to be written and then asserts DMR. This will assert TDMG.
When DMR is set and DMA is granted it will execute a DMA write, if
DMR is not set and DMA is granted it will assert TDMGO and grant
DMA to the next device.
When the DMA has been executed the state machine asserts DMG and
waits for the MCU to de-assert DMR to release the bus.
For DMA reads the MCU must first load the DMA start address register
with the LSB set. Then it asserts DMR. This will assert TDMG.
When DMR is set and DMA is granted it will execute a DMA write, if
DMR is not set and DMA is granted it will assert TDMGO and grant
DMA to the next device.
When the DMA has been executed the state machine asserts DMG and
waits for the MCU to de-assert DMR to release the bus. Now the
MCU can read the DMA data latched into CPLD B.
In both cases the DMA address will be incremented by 2 and thus
for further DMA requests of the same type, read or write, the
DMA start address and direction register must no be loaded with
the next address.
*/
sequence DMA {
/*
Wait for DMA grant
*/
PRESENT 'h'00 IF !DMGI NEXT 'h'00;
IF DMGI NEXT 'h'01;
PRESENT 'h'01 IF !DMR NEXT 'h'02;
IF DMR NEXT 'h'03;
PRESENT 'h'02 IF !DMGI NEXT 'h'00;
IF DMGI OUT TDMGO; NEXT 'h'02;
PRESENT 'h'03 IF !DMARW NEXT 'h'20;
IF DMARW NEXT 'h'30;
/*
At the end of the DMA cycle the state machine asserts DMG to let the MCU
know that the DMA has ended. The MCU then must de-assert DMR before it can
start another DMA. This is placed to a state with TSACK de-asserted to
release the bus while we are waiting for the MCU.
*/
PRESENT 'h'04 IF DMR NEXT 'h'04 OUT DMG;
IF !DMR NEXT 'h'00;
/*
DMA Write Cycle
*/
PRESENT 'h'20 NEXT 'h'21 OUT EN;
PRESENT 'h'21 NEXT 'h'22 OUT EN;
PRESENT 'h'22 NEXT 'h'23 OUT EN;
PRESENT 'h'23 NEXT 'h'24 OUT EN OUT TSYNC;
PRESENT 'h'24 NEXT 'h'25 OUT EN OUT TSYNC;
PRESENT 'h'25 NEXT 'h'28 OUT EN OUT TSYNC;
PRESENT 'h'28 IF !RPLY NEXT 'h'28 OUT EN OUT TSYNC OUT TDOUT;
IF RPLY NEXT 'h'29 OUT EN OUT TSYNC OUT TDOUT;
PRESENT 'h'29 NEXT 'h'2A OUT EN OUT TSYNC OUT TDOUT;
PRESENT 'h'2A NEXT 'h'2B OUT EN OUT TSYNC OUT TDOUT;
PRESENT 'h'2B NEXT 'h'2C OUT EN OUT TSYNC OUT TDOUT;
PRESENT 'h'2C IF RPLY NEXT 'h'2C OUT EN OUT TSYNC;
IF !RPLY NEXT 'h'2D;
PRESENT 'h'2D NEXT 'h'04 OUT DMG;
/*
DMA Read Cycle
*/
PRESENT 'h'30 NEXT 'h'31 OUT EN;
PRESENT 'h'31 NEXT 'h'32 OUT EN;
PRESENT 'h'32 NEXT 'h'33 OUT EN;
PRESENT 'h'33 NEXT 'h'34 OUT EN OUT TSYNC;
PRESENT 'h'34 NEXT 'h'35 OUT EN OUT TSYNC;
PRESENT 'h'35 NEXT 'h'38 OUT EN OUT TSYNC;
PRESENT 'h'38 IF !RPLY NEXT 'h'38 OUT TSYNC OUT TDIN OUT LD;
IF RPLY NEXT 'h'39 OUT TSYNC OUT TDIN OUT LD;
PRESENT 'h'39 NEXT 'h'3A OUT TSYNC OUT TDIN OUT LD;
PRESENT 'h'3A NEXT 'h'3B OUT TSYNC OUT TDIN OUT LD;
PRESENT 'h'3B NEXT 'h'3C OUT TSYNC OUT TDIN OUT LD;
PRESENT 'h'3C IF RPLY NEXT 'h'3C OUT TSYNC;
IF !RPLY NEXT 'h'3D;
PRESENT 'h'3D NEXT 'h'04 OUT DMG;
}
TSACK = DMA5;
TWTBT = DMA5 & !DMA4 & !DMA3;
CPLD B ATF1504
Register Interface
Similar to the CPLD A there is a register interface. In this case the
register interface is controller via ALER
and RD
. The first signal
ALER
latches the register address when RD
is deasserted. When RD
is
asserted the CPLD enables the outputs to the data bus and the MCU can then
read the contents of the register. Again the register address proceeds to
the next reasonable register address when RD
is deasserted to be able to
read 16‐bit values without having to load the register address for the
high byte. CPLD B registers can only be read. The sequences are implemented
as follows
- 0->1->2->3->0->1… This will walk throug the status, Q‐bus Data and ROM address register
- 4->5->4->5->4->5… This will walk through the low, high byte of Q-Bus DMA read data register
Register Address | Description |
0 | Status Register |
1 | Q-Bus Read Data Register Low Byte |
2 | Q-Bus Read Data Register High Byte |
3 | Q-Bus ROM Address Bits A1..8 |
4 | Q-Bus DMA Read Data Register Low Byte |
5 | Q-Bus DMA Read Data Register High Byte |
The Status register has the following definitions
Bit | Name | Description |
0 | WTBT | The status of the BWTBTL signal during Q-Bus addressing to identify the cycle, 0=DATI, 1=DATO/DATOB |
1 | C1 | Device Regiser address bit A1 |
2 | C2 | Device Regiser address bit A2 |
3 | C3 | Device Regiser address bit A3 |
4 | C4 | Device Regiser address bit A4 |
5 | ROM | This bit is cleared if a device register is addressed and set if an address of the ROM range is accessed |
6 | LB | This bit is cleared if the lower byte if written during a DATO/DATOB cycle |
7 | UB | This bit is cleared if the higher byte if written during a DATO/DATOB cycle |
CPLD A to CPLD B interconnection
There are three signals running between the two CPLDs.
Signal Name | Description |
CSRADDR | Created by CPLD B signals to CPLD A that a device register is addressed |
ROMADDR | Created by CPLD B signals to CPLD A that a word in the ROM is addressed |
LD | Created by CPLD A signals to CPLD B to load the value of the Q-bus data to the Q-Bus DMA Read data register |
CPLD B Design File
The logic of the CPLD B is very simple as all control functions are handled within the CPLD A.
Name QBUS RLV12 Version 2 ;
PartNo B ;
Date 15.04.2022 ;
Revision 02 ;
Designer cbscpe ;
Company PRIVAT ;
Assembly None ;
Location ATHOME ;
Device f1504ispplcc44 ;
/*
Second CPLD which only performs read of the data bus there are 5 registers
that can be read
Device Address This 8-bit register holds the direction of the
bus cycle in bit 0, address bits A1..5 and whether
the upper or lower byte are updated
Q-Bus Data This register provides the current status of the
16-bits of the multiplexed address/data bus and
are used to read the data in a DATO/DATOB cycle
DMA Data This 16-bit register will store the data of a DMA
read cycle
2022-04-15
New CPLD Interface for MCU. To access any register in CPLD A or B
you need first to load the register address. The register address
register is part of a state machine. Depending on the address
loaded each register write will advance the state. This is made
because CPLD registers are typically read as 16-bit registers
or as a combination of register address and Q-Bus data.
You still can access individual registers.
To set the read register address you first need to de-assert RD
and then use ALER to set the read register start address. Then
you need to assert RD to read the value of the first register
then you can use ALER to advance the state machine and read the
next byte value.
This CPLD implements only the readable registers
0->1->2->3->0 Read Device Register address followed by Q-Bus data
4->5->4->5 Read DMA Data Register
CPLD decodes the address and asserts CSRADDR in case the device is
selected and it loads the 16-bit Q-Bus data to the DMA data register
using the LD input. Both signals connect to CPLD A
2022-04-24
New Register 3 which reads latched bus address A8..1 and modified
register 0 which now reads latched bus address A9 instead of A5.
With this A9 is cleared when a RLV12 register has been accessed and
is set if a 'o'173000 boot ROM address has been accessed. The first
sequence now changes from register 2 to register 3 so we can read
register 3 by simply advancing the counter using ALER without
the need to load register select, just skip address 1 and 2
2022-04-26
Boot ROM option using unused interconnection between the two CPLD
!!!!!!!!! This CPLD requires the interface '22' in the MCU firmware
!!!!!!!!! #define rlv12 22 ; Select Assembler Option
*/
PIN 28 = RDAL0;
PIN 27 = RDAL1;
PIN 26 = RDAL2;
PIN 25 = RDAL3;
PIN 24 = RDAL4;
PIN 21 = RDAL5;
PIN 19 = RDAL6;
PIN 20 = RDAL7;
PIN 18 = RDAL8;
PIN 17 = RDAL9;
PIN 16 = RDAL10;
PIN 14 = RDAL11;
PIN 12 = RDAL12;
PIN 11 = RDAL13;
PIN 9 = RDAL14;
PIN 8 = RDAL15;
PIN 6 = AD0;
PIN 5 = AD1;
PIN 4 = AD2;
PIN 39 = AD3;
PIN 40 = AD4;
PIN 34 = AD5;
PIN 37 = AD6;
PIN 36 = AD7;
PIN 41 = RSYNC;
PIN 33 = RWTBT;
PIN 1 = RBS7;
PIN 29 = CSRADDR; /* Asserted if device is selected */
PIN 31 = ROMADDR; /* Asserted if ROM is selected */
PIN 43 = LD; /* Load Q-Bus data into the DMA data register */
PIN 44 = RD;
PIN 2 = ALER;
PROPERTY ATMEL {preassign=KEEP};
PROPERTY ATMEL {CASCADE_LOGIC=ON};
PROPERTY SOFT_BUFFER {UB, LB};
PINNODE = [Q15..0];
PINNODE = [RS2..0];
PINNODE = [C8..0]; /* CSR Address */
PINNODE = WTBT;
PINNODE = ROM;
FIELD ADDR = [C8..0]; /* Latched address used for register address */
FIELD RS = [RS2..0]; /* Register Select Address for Atmega1281 reads/writes */
FIELD IOADDR = [RDAL12..0]; /* Access to IO Page only requires address lines 0..12 */
/*
Device Address is also generated by this CPLD as only we see the address
*/
ADDR.d = [RDAL8..0];
ADDR.ck = RSYNC;
WTBT.d = RWTBT;
WTBT.ck = RSYNC;
ROM.d = RBS7 & IOADDR:['o'173000..173777];
ROM.ck = RSYNC;
/*
CSR Select must be generated in this CPLD as we are the only CPLD that receives
the DAL status from the BUS
*/
CSRADDR = RBS7 & IOADDR:['o'174400..174417];
ROMADDR = RBS7 & IOADDR:['o'173000..173777];
/*
DMA Data Register for DMA reads
*/
[Q15..0].l = [RDAL15..0];
[Q15..0].le = LD;
/*
Register Select we support two sequences
0->1->2->3->0 to read the Device Address, followed by the Q-Bus
4->5->4->5 to read the DMA data register (6 is not used)
*/
RS.ar = ![AD2..0].io & ALER & !RD;
RS.ap = [AD2..0].io & ALER & !RD;
RS.ce = RD;
RS.ck = ALER;
sequence RS {
present 'd'0 next 'd'1;
present 'd'1 next 'd'2;
present 'd'2 next 'd'3;
present 'd'3 next 'd'0;
present 'd'4 next 'd'5;
present 'd'5 next 'd'4;
present 'd'6 next 'd'4;
present 'd'7 next 'd'4;
}
UB = !RWTBT
# RWTBT & C0;
LB = !RWTBT
# RWTBT & !C0;
[AD7..0] = RS:['d'0] & [!UB, !LB, ROM, C4, C3, C2, C1, WTBT]
# RS:['d'1] & [RDAL7..0].io
# RS:['d'2] & [RDAL15..8].io
# RS:['d'3] & [C8, C7, C6, C5, C4, C3, C2, C1]
# RS:['d'4] & [Q7..0]
# RS:['d'5] & [Q15..8];
[AD7..0].oe = RD;
When placing signals ot the PINs you need to pay special attention to the
RD
and the ALE
signal so they are using one of the global output enable
or clock signals. By using a global output enable input for RD
the output
enable term is not using a macro-cell product-term so a single macro-cell
can be used as a 5-to-1 multiplexor, perfect for the 5 byte registers to read.
The second important point is that ALE
is using one of the global clock inputs
because only then you can use the clock enable input of a macro-cell.