Concurrently with the redesign of POC V2's PCB, I've been working on the CPLD code needed to make it work. My goals aren't too lofty, mostly just latching of the bank address, generation of appropriate chip selects, generating wait-states on ROM and I/O hardware accesses, etc. I originally was going to make it very simple but after compiling the code and simulating it, decided to get a little more advanced.
The address ranges $00C000-$00CFFF and $00E000-$00FFFF can be made to have either RAM or ROM. Also, the range $00D000-$00DEFF can be made to have I/O or RAM. The "hardware management unit" (HMU) in the CPLD, which is always present at $00DF00, accepts a bit pattern that sets the memory mapping rules. The architecture is as follows:
Code:
+--------------------------+ $07FFFF
| |
| RAM (448 KB) |
| |
+-------+--------------------------+ $010000
| | |
| E-RAM | E-ROM (8 KB) |
| | |
+-------+--------------------------+ $00E000
| Hardware Management Unit |
+-------+--------------------------+ $00DF00
| | |
| D-RAM | I/O (3.75 KB) |
| | |
+-------+--------------------------+ $00D000
| | |
| C-ROM | C-RAM (4 KB) |
| | |
+-------+--------------------------+ $00C000
| |
| RAM (48 KB) |
| |
+--------------------------+ $000000
In order to control all this, the HMU is programmed as follows:
Code:
HMU
Register Address Register Description Bit Function
----------------------------------------------------------
hmumcfg $00DF00 System configuration: 0 0: I/O
1: D-RAM
1 0: C-RAM
1: C-ROM
2 0: E-ROM
1: E-RAM
----------------------------------------------------------
The default memory map following a hard reset is C-RAM, I/O and E-ROM. As the HMU is read/write, instructions such as TRB and TSB may be used to quickly change the map. An STZ instruction on the HMU is all that is required to re-establish the default map.
Logic rules are such that a write to C-ROM or E-ROM will "bleed through" to RAM, making it possible, for example, to copy the E-ROM firmware to RAM with the MVN instruction and then map out E-ROM and continue in RAM. Running the firmware that way will be faster because ROM accesses incur a wait-state. I also wanted to make it possible to write-protect E-RAM, but couldn't fit the design with that feature. Maybe next time...
Here are some logic simulation results. Signals that are in yellow are manipulated by the simulator. Red and green signals represent inputs or outputs from devices other than the CPLD.
Attachment:
File comment: E-ROM & E-RAM Accesses
logic_sim_rom_ram_run.gif [ 33.09 KiB | Viewed 939 times ]
In the above, starting at vector 4 and ending at vector 10, a read access of E-ROM is made. Note the generation of a 1 cycle wait-state when ROM is selected. Note that D0-D2 are %000 during Ø2 low at vector 4, as the address from which data is being fetched is $00E000. It can be seen that the simulator has asserted the /RD signal, qualified by Ø2, and that the MPU's RDY input is negated for a full clock cycle, starting at vector 5. This is the wait-state that occurs on all ROM accesses.
At vector 12, a write to the same address occurs. As the logic causes a write on a ROM address to be directed to RAM, RAM is selected and there is no wait-state. Again, D0-D2 are %000 during Ø2 low at vector 12. Also note that the /WD output is asserted, as this is a write operation. As with /RD, /WD is qualified by Ø2.
Attachment:
File comment: Extended RAM Accesses
logic_sim_ext_ram_run.gif [ 33.23 KiB | Viewed 939 times ]
In the above and starting at vector 4, data is fetched from "extended" RAM at $07FFFF. Starting at vector 12, data is written to extended RAM at $06E500. Note the conditions of the A16-A18 outputs during the operations.
Attachment:
File comment: I/O Device 'A' Access
logic_sim_IO_run.gif [ 51.42 KiB | Viewed 939 times ]
In the above, a write access to I/O device 'A' (the real-time clock) is being made. Note that I/O also incurs a wait-state, again lasting a clock cycle. As I have successfully run POC V1.1 at 12.5 MHz, it follows that a single-cycle wait-state should be sufficient for all I/O devices, even at 20 MHz.
Attachment:
File comment: I/O Device 'C' Access
logic_sim_IO_C_run.gif [ 27.74 KiB | Viewed 939 times ]
In the above, a read access on I/O device 'C' is performed. Behavior is like that of the previous simulation run, except a different chip select output is asserted and, of course, /RD is asserted instead of /WD.
Here is the CUPL code that makes all this work:
Code:
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* W65C816S PROOF OF CONCEPT SINGLE-BOARD COMPUTER *
* *
* =============================================================================== *
* *
* Copyright (c)2015 by BCS Technology Limited. All rights reserved. *
* *
* Permission is hereby granted to use, copy, modify and distribute this software, *
* provided this copyright notice remains unaltered in the source code and proper *
* attribution is given. Redistribution, in any form, must be at no charge to the *
* end user. This code or any part thereof, including any derivation, MAY NOT be *
* incorporated into any package intended for sale unless written permission to do *
* so has been granted by the copyright holder. *
* ------------------------------------------------------------------------------- *
* THERE IS NO WARRANTY OF ANY KIND WITH THIS SOFTWARE. *
* *
* While it is believed that all code will perform as intended, the user assumes *
* all risk in connection with the incorporation of this software into any system. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * *
* VERSION HISTORY *
* * * * * * * * * *
Ver Rev Date Revision
--------------------------------------------------------------------------------
0.1.0 2015/08/21 Original version.
--------------------------------------------------------------------------------
*/
Name glue;
PartNo B402170001;
Date 2015/08/21;
Revision 0.1.0;
Designer BDD;
Company BCS Technology Limited;
Assembly POC V2;
Location U2;
Device f1504ispplcc44; /* ATF1504AS (PLCC44):
R P
R V A E V H G A A
W R O C 1 S P I N 1 1
D D M C 2 B B 2 D 1 0
____________________________________
/ 6 5 4 3 2 1 44 43 42 41 40 \
(JTAG) TDI | 7 39 | A9
D2 | 8 38 | TDO (JTAG)
D1 | 9 37 | A8
GND | 10 36 | N/C
D0 | 11 35 | VCC
IO0 | 12 34 | VDA
(JTAG) TMS | 13 33 | VPA
RAM | 14 32 | TCK (JTAG)
VCC | 15 31 | A18
RDY | 16 30 | GND
IO1 | 17 29 | A16
| 18 19 20 21 22 23 24 25 26 27 28 |
\____________________________________/
I A I I G V A A A R R
O 1 O O N C 1 1 1 W S
3 7 2 4 D C 3 4 5 B T
*/
property atmel {cascade_logic=on};
property atmel {logic_doubling=on};
property atmel {output_fast=on};
property atmel {pin_keep=off};
property atmel {preassign=keep};
property atmel {security=off};
property atmel {xor_synthesis=on};
/*
=====================
INPUT PIN ASSIGNMENTS
=====================
*/
pin 1 = RESB; /* system reset */
pin 2 = A12; /* address line */
pin 24 = A13; /* address line */
pin 25 = A14; /* address line */
pin 26 = A15; /* address line */
pin 27 = RWB; /* read/write */
pin 33 = VPA; /* valid instruction address */
pin 34 = VDA; /* valid data address */
pin 37 = A8; /* address line */
pin 39 = A9; /* address line */
pin 40 = A10; /* address line */
pin 41 = A11; /* address line */
pin 43 = PHI2; /* system clock */
pin 44 = VPB; /* interrupt vector pull */
/*
======================
OUTPUT PIN ASSIGNMENTS
======================
*/
pin 4 = !ROM; /* ROM chip select */
pin 5 = !RD; /* read data */
pin 6 = !WD; /* write data */
pin 12 = !IO0; /* I/O device 'A' select */
pin 14 = !RAM; /* RAM chip select */
pin 17 = !IO1; /* I/O device 'B' select */
pin 18 = !IO3; /* I/O device 'D' select */
pin 19 = A17; /* address line */
pin 20 = !IO2; /* I/O device 'C' select */
pin 21 = !IO4; /* I/O device 'E' select */
pin 28 = !RST; /* inverted reset */
pin 29 = A16; /* address line */
pin 31 = A18; /* address line */
/*
=============================
BIDIRECTIONAL PIN ASSIGNMENTS
=============================
*/
pin 8 = D2; /* data line */
pin 9 = D1; /* data line */
pin 11 = D0; /* data line */
pin 16 = RDY; /* MPU wait */
/*
==========================================================
MACHINE ARCHITECTURE & HARDWARE MANAGEMENT UNIT DEFINTIONS
==========================================================
+--------------------------+ $07FFFF
| |
| RAM (448 KB) |
| |
+-------+--------------------------+ $010000
| | |
| E-RAM | E-ROM (8 KB) |
| | |
+-------+--------------------------+ $00E000
| Hardware Management Unit |
+-------+--------------------------+ $00DF00
| | |
| D-RAM | I/O (3.75 KB) |
| | |
+-------+--------------------------+ $00D000
| | |
| C-ROM | C-RAM (4 KB) |
| | |
+-------+--------------------------+ $00C000
| |
| RAM (48 KB) |
| |
+--------------------------+ $000000
1 KB = 1024 bytes
HMU
Register Address Register Description Bit Function
----------------------------------------------------------
hmumcfg $00DF00 System configuration: 0 0: I/O
1: D-RAM
1 0: C-RAM
1: C-ROM
2 0: E-ROM
1: E-RAM
----------------------------------------------------------
Notes: 1) The default map following hard reset is C-RAM, I/O & E-ROM.
2) An STZ instruction on hmumcfg sets the default map.
3) Writing to C-ROM or E-ROM touches RAM at same address.
4) The HMU is read/write & always present.
*/
$DEFINE dblkmap hmumcfg0 /* $00D0xx-$00DExx */
$DEFINE cblkmap hmumcfg1 /* $00C0xx-$00CFxx */
$DEFINE eblkmap hmumcfg2 /* $00E0xx-$00FFxx */
/*
=========================
BURIED LOGIC DECLARATIONS
=========================
*/
pinnode = bank0; /* 1 = address is $000000-$00FFFF */
pinnode = basram; /* 1 = address is $000000-$00BFFF */
pinnode = cblk; /* 1 = address is $00C000-$00CFFF */
pinnode = dblk; /* 1 = address is $00D000-$00DFFF */
pinnode = eblk; /* 1 = address is $00E000-$00FFFF */
pinnode = extram; /* 1 = address is $010000-$07FFFF */
pinnode = hmusel; /* 1 = HMU being accessed */
pinnode = ioblk; /* 1 = I/O address space being accessed */
pinnode = iosel; /* 1 = I/O device being accessed */
pinnode = mcfgsel; /* 1 = HMU configuration being accessed */
pinnode = ramsel; /* 1 = RAM being accessed */
pinnode = rdflag; /* 1 = data fetch in progress */
pinnode = rdyout; /* 1 = MPU wait-stated */
pinnode = rhflag; /* 1 = data fetch on high clock */
pinnode = romsel; /* 1 = ROM being accessed */
pinnode = vbus; /* 1 = address bus valid */
pinnode = vplatch; /* 1 = hardware vector being accessed */
pinnode = wdflag; /* 1 = data store in progress */
pinnode = wsflag; /* 1 = wait-state in progress */
pinnode = wsff; /* wait-state flip-flop */
pinnode = [blatch0..2]; /* bank address latches */
pinnode = [hmumcfg0..2]; /* HMU hardware configuration register */
/*
=========================
REGISTER RESETS & PRESETS
=========================
*/
$REPEAT i = [0..2]
hmumcfg{i}.AR = !RESB;
/* hmumcfg{i}.AP = 'b'0; */
$REPEND
vplatch.AR = !RESB;
wsff.AR = !RESB;
vplatch.AP = 'b'0;
wsff.AP = 'b'0;
/*
==========================
INTERMEDIATE CONTROL LOGIC
==========================
*/
phi1 = !PHI2; /* inverted system clock */
vbus = (VDA # VPA) & RESB; /* true if valid address */
rdflag = RWB & vbus; /* true if fetch operation */
rhflag = rdflag & PHI2; /* true if fetch on high clock */
wdflag = !RWB & vbus; /* true if store operation */
/* vector pull stuff is experimental; it's not actually in use... */
vplatch.LE = !VPB; /* open vector pull latch */
vplatch.L = VPB; /* indicate vector pull */
/*
=============================
EXTENDED RAM ADDRESSING LOGIC
=============================
Bits 0-2 of the extended address are captured during a valid bus cycle while
the clock is low. In the event a wait-state is in progress when the clock
goes low the bank latches will not be disturbed.
*/
[blatch0..2].LE = vbus & phi1 & !rdyout; /* open latches */
[blatch0..2].L = vbus & phi1 & [D0..2]; /* capture bank */
bank0 = [blatch0..2]:'b'000; /* 1 if bank is $00 */
extram = !bank0; /* 1 if bank is $01-$07 */
/*
====================
MEMORY MAPPING LOGIC
====================
*/
basram = (!A15 # !A14) & bank0; /* true if $000000-$00BFFF */
cblk = A15 & A14 & !(A13 # A12) & bank0; /* true if $00C000-$00CFFF */
dblk = A15 & A14 & !A13 & A12 & bank0; /* true if $00D000-$00DFFF */
eblk = A15 & A14 & A13 & bank0; /* true if $00E000-$00FFFF */
ioblk = dblk & !(A11 & A10 & A9 & A8); /* true if $00D000-$00DEFF */
/* RAM selection rules... */
ramsel = basram # /* base RAM, or... */
cblk & (!RWB # !cblkmap) # /* C-RAM if mapped, or... */
ioblk & dblkmap # /* D-RAM if mapped, or... */
eblk & (!RWB # eblkmap) # /* E-RAM if mapped, or... */
extram; /* extended RAM */
/* ROM selection rules... */
romsel = cblk & RWB & cblkmap # /* C-ROM if mapped, or... */
eblk & RWB & !eblkmap; /* E-ROM if mapped */
/* I/O devices selection rules... */
iosel = ioblk & !dblkmap; /* $00D0xx-$00DExx if mapped */
/* HMU selection rules... */
hmusel = dblk & A11 & A10 & A9 & A8; /* $00DFxx, always present */
mcfgsel = hmusel; /* configuration */
/*
================
WAIT-STATE LOGIC
================
*/
wsflag = (iosel # romsel) & vbus; /* wait-state if I/O or ROM & enabled */
wsff.CK = PHI2 & wsflag;
wsff.D = wsff & wsflag;
rdyout = wsff & wsflag;
/*
=========================
CONTROL OUTPUT STATEMENTS
=========================
*/
[A16..18] = [blatch0..2] & vbus; /* A16-A18 address bits */
IO0 = iosel & !A10 & !A9 & !A8 & vbus; /* I/O device 'A' select */
IO1 = iosel & !A10 & !A9 & A8 & vbus; /* I/O device 'B' select */
IO2 = iosel & !A10 & A9 & !A8 & vbus; /* I/O device 'C' select */
IO3 = iosel & !A10 & A9 & A8 & vbus; /* I/O device 'D' select */
IO4 = iosel & A10 & !A9 & !A8 & vbus; /* I/O device 'E' select */
RAM = ramsel & vbus; /* RAM chip enable */
RD = rdflag & (PHI2 # rdyout) & !hmusel; /* active low read */
RDY = !rdyout; /* MPU wait-state input */
RDY.oe = wsflag; /* active if wait-stating */
ROM = romsel & vbus; /* ROM chip enable */
RST = RESB; /* inverted reset */
WD = wdflag & (PHI2 # rdyout) & !hmusel; /* active low write */
/*
============================
HMU REGISTER READ STATEMENTS
============================
*/
[D0..2].oe = mcfgsel & rhflag; /* enable output on D0-D2 */
[D0..2] = mcfgsel & [hmumcfg0..2] & rhflag; /* HMU bit pattern on D0-D2 */
/*
=============================
HMU REGISTER WRITE STATEMENTS
=============================
*/
[hmumcfg0..2].LE = mcfgsel & wdflag & PHI2; /* open HMU latches */
[hmumcfg0..2].L = mcfgsel & [D0..2] & /* D0-D2 bit pattern on HMU */
wdflag & PHI2;
/* * * * * E N D O F F I L E * * * * */
The simulator says it will fly. Now I have to build it and hope the simulator is right!