6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Oct 24, 2024 4:32 am

All times are UTC




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: ROMulus the 2nd
PostPosted: Mon Jul 18, 2016 8:02 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
So I finally decided to go the PCB path. After the concepts have been tested with ROMulus the 1st on some breadboards I wanted to build something more durable. ROMulus the 2nd has all the features of the 1st but also has some enhancements. When finished it will (should be) able to emulate an Apple IIe including the double hires mode with 160 x 192 pixels and 16 colors. However due to the design you can convert the system into whatever you want. Everything is "configurable" within limits, that is as long as the CPLD design can be implemented in the CPLD and the given allocation of the PINs fits the design you're save. And as with all the ROMulus there is no ROM, there is only some RAM that emulates ROM, all depends on the CPLD design. It basically features

- A home-brew video controller using a ATmega1284P with 32kbyte dual-port video RAM and VGA output (560x480 pixels, this is due to the fact that I want to use the 7-bit wide original character sets of legacy systems)
- A PS/2 keyboard interface using the ATmega1284P using one of it's USART in synchronous mode
- Initial Machine Load of ROM images through the ATmega (as with the 1st you can have ROM images in flash or download images via XMODEM)
- A ATF1508AS CPLD which holds almost all of the glue logic (a 74HCT14 schmitt-trigger has been added to deglitch the PS/2 signals and a 74HCT573 has been added to support the 32kbyte video RAM via the ATMega1284P, as the CPLD does not provide enough pins)
- 512kbyte RAM

Here is a picture of the PCB
Attachment:
File comment: PCB
IMG_0474.jpg
IMG_0474.jpg [ 2.69 MiB | Viewed 1978 times ]
as ordered with dirtypcbs.

I'm slowly bringing up the system in several stages. The first stage was to check the CPLD Glue logic that emulates the 74HC166 from ROMulus the 1st
Attachment:
File comment: Controller, CPLD and Schmitt Trigger
IMG_0466.jpg
IMG_0466.jpg [ 2.57 MiB | Viewed 1978 times ]

and also the first color mapping logic which is new in this version of the series. In this stage the internal RAM of the AVR was used as video RAM

Currently I have reached the state where the dual-port RAM and the address latch has been added and a stable VGA signal is created using the dual-port RAM as video RAM
Attachment:
File comment: plus Video RAM (DP-RAM) and Address Latch
IMG_0470.jpg
IMG_0470.jpg [ 2.64 MiB | Viewed 1978 times ]

the only missing parts now are the 512kbyte SRAM and the CPU.

Up to now the process was rather successful, although I had to make same smaller "corrections" to the PCB. But nothing what a Proxxon drill and vero-wire couldn't solve.

More to come

Cheers

Peter


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Mon Jul 18, 2016 9:16 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
cbscpe wrote:
... When finished it will (should be) able to emulate an Apple IIe including the double hires mode with 160 x 192 pixels and 16 colors ...

I think you meant to say 560 x 192.

Nice looking kit!

Mike B.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Tue Jul 19, 2016 5:13 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
560x192 is BW, when using 16 colors its only 160x192


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Tue Jul 19, 2016 2:59 pm 
Offline
User avatar

Joined: Wed Aug 17, 2005 12:07 am
Posts: 1230
Location: Soddy-Daisy, TN USA
That's right. Because the Apple II is always generating B/W signals. But, when you run them through a color monitor, you get the classic NTSC artifacts.

The 160 pixels is about as fast as NTSC can change colors per pixel with minimal color clashing.

Anyway, awesome project.

_________________
Cat; the other white meat.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Thu Jul 21, 2016 7:40 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
After some more hardware and PCB checks I decided to populate the rest of the essential parts

Attachment:
File comment: Fully populated PCB
IMG_0516.jpg
IMG_0516.jpg [ 2.28 MiB | Viewed 1905 times ]


The missing MAX232 and the corresponding connector is for the RS-232 of the AVR, but currently I'm using a USB-TTL serial adapter and don't need the level shifter. As always software errors are more common than hardware errors and in this case I have to program the CPLD and the bootcontroller (the ATmega1284P) in parallel that makes it even worse. So I added some decent debugging output (in hardware of course) to the bus interface. Now step by step I eliminate the software errors :roll: Fortunately the AVR and the CPLD support a lot of programming cycles.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Sat Jul 23, 2016 4:39 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
Seems that there weren't too many errors. The software is still not finished but at least I can load a ROM image and the SBC can take over control. At the moment I was able to load the Apple IIplus ROM image and write programs in Applesoft Basic. PS/2 interface works and 40-column Text Output as well. Now the rest is diligence work. Also so far the two errors in the PCB were really stupid. Both are related to the programming connectors. The AVR ISP interface had MOSI and MISO swapped and the JTAG interface had connected VTG (Vcc Target) to Pin 7 instead of Pin 4.

The following schematic already contains the bugfixes to these errors.
Attachment:
ROMulus2ndV2xrev1.pdf [44.62 KiB]
Downloaded 159 times


Cheers Peter


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Thu Jul 28, 2016 7:14 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
So here comes the next piece of documentation, the WinCUPL design file of the CPLD

Code:
Name     ROMULUS2ND ;
PartNo   00 ;
Date     04.06.2016 ;
Revision V2 ;
Designer cbscpe ;
Company  privat ;
Assembly None ;
Location athome ;
Device   f1508ispplcc84;

/*
   2016-06-22   Peter Schranz
      Added some ideas for double hires
      splitted D7 into SSW read and D7
      Renamed SEL to GR
      Still missing is hires
   2016-06-04   Peter Schranz
      Instead of R11, R12 and R13 we map the different regions now
      to Banks 0 to 7, this will leave only very littel contingous
      extended RAM but on the other side it saves pins, product terms
      connections, also there is no reason to have extended RAM when
      using only the Apple IIe side
   2016-04-28   Peter Schranz
   This is a system that is based on the projects
      ROMulus1st
      AppleIIeV8

   It includes the following functions
   -   ROMulus ROM-less boot using blind-load (IML)
   -   All 128kbyte Apple IIe logic, i.e. softswitches RAM
      mapping and extended ROM
   -   IO ROM mapping
   -   Video Glue logic that replaces the 74HCT574, the 74HC166
      and the ANNUNCIATORS GAL22V10 of the AppleIIeV8
   Recode R16 generation. It seems the first version of the 24-bit
   version of the generation of R16 is not correct, so we take the
   version used in AppleIIeV8 that make sure this design fits, how-
   ever the result of the optimizer uses 2 level of foldback signals
   which is not optimal for high clock rates
   2016-05-21   Peter Schranz
   New version of R16 generation with 24-bit address support and
   only 1 level of foldback signals
*/

PROPERTY ATMEL {preassign = KEEP};
/*PROPERTY ATMEL {logic_doubling = ON};
/*PROPERTY ATMEL {cascade_logic = OFF};
/*PROPERTY ATMEL {fold = IOPAGE};*/
PROPERTY ATMEL {SOFT_BUFFER = IOPAGE};

/* $define ROMULUS1ST */

/* *************** CPU Interface **************************************/
PIN    48   = A0      ; /* CPU Address Bus                            */
PIN    49   = A1      ; /*                                            */
PIN    50   = A2      ; /*                                            */
PIN    51   = A3      ; /*                                            */
PIN    46   = A4      ; /*                                            */
PIN    34   = A5      ; /*                                            */
PIN    44   = A6      ; /*                                            */
PIN    45   = A7      ; /*                                            */
PIN    36   = A8      ; /*                                            */
PIN    35   = A9      ; /*                                            */
PIN    55   = A10     ; /*                                            */
PIN    56   = A11     ; /*                                            */
PIN    39   = A12     ; /*                                            */
PIN    58   = A13     ; /*                                            */
PIN    33   = A14     ; /*                                            */
PIN    60   = A15     ; /*                                            */
 
PIN    52   = D0      ; /* CPU Data Bus                               */
PIN    41   = D1      ; /*                                            */
PIN    40   = D2      ; /*                                            */
PIN    37   = D3      ; /*                                            */
PIN    57   = D4      ; /*                                            */
PIN    61   = D5      ; /*                                            */
PIN    63   = D6      ; /*                                            */
PIN    15   = D7      ; /*                                            */
 
PIN    17   = RW      ; /* CPU R/W Signal                             */
PIN     1   =!RES     ; /* System Reset                               */
PIN     2   = PHI2    ; /* System Clock                               */

/* *************** Video / Boot Controller Interface ******************/

/*
   The Video Interface is using a ATmega1248P which is used similarly
   to the AVR in the ROMulus 1st however there are some changes. Here
   is the usage from ROMulus 1st
   
   Port A      Connects to the CPLD Video Port and the lower address
            bits of the dual-port video RAM
   Port B      VPB, INP, KEY, IML, INH, !CE, !RES, SHLD
   Port C      Connects to the data bus of the dual-port video RAM
   Port D      RXD, TXD, DATA, BLANK, CLOCK, HSYNC, PHI2, LE
   Port E      VA7, VA8, VA9, VA10, !WE, !OE, SEL, VSYNC
   Port F      TEXT, MIXED, PAGE2, HIRES, 80COL, ALTCHAR, 80STO, DHIRES
   
   This CPLD makes changes to the following signals

   INP      is now RDV and reads the bits directly from the CPLD (Port F)
   KEY      is now WRK and writes the byte to the CPLD internally
   IML      is now WRC and is used to write controll signals to the CPLD
   
   SEL      is now added to the control signals internal to the CPLD and not
         on the 74HCT573 (Port E) and is renamed to GR (Graphics)
   WE      is now a latch in the CPLD
   OE      is no longer available
   
   SEL, WE and OE on PORT E are now used for VA12, 13, 14 of the 32kbyte
   video RAM.

   RDV      Active Low, Output Enable to read the video control bits
         like TEXT, GR, PAGE2, etc.
   WRK      Write Keyboard/Byte Buffer clock. The content of control bus
         data (V0..7) is written to the keyboard/byte buffer with the
         leading edge of the signal
   WRC      A system control register latch write enable signal. Active
         high.
   BLANK   Active Low, disables the color outputs. When high enables
         the color outputs Rx, Gx and Bx.
   
   The video controller can now read the video control bits of the
   Apple IIe (via RDV). Then it must set the system control signals
   and the internal logic. The video controller does this after he
   has displayed a full screen. The system control bits are
   [IML, VBL, WE, GR, HRES, CA, OA, TAPE].le = WRC;

   IML      Sets the Initial Machine Load mode, normally when set it allows
         the CPU to write the complete memory and reads are always
         directed to the keyboard/byte buffer. The video controller
         controls PHI2 of the CPU manually and presents a boot load
         code to the CPU via the keyboard/byte buffer (blind load).
         The video controller also controls RES of the CPU. So it can
         tell for every PHI2 cycle what the CPU expects and is thus
         able to send the reset vector and the instructions which
         write the ROM image to the RAM. When cleared it normally write
         protects the ROM portion of the RAM
   VBL      is the video blank signal set during the non displayed lines
         can be used by the CPU
   WE      An extension of AVR ports to write enable the video RAM.
         Actually this is not necessary for the system to work it
         only is used during development and debugging
   GR      When set activates the graphics mode
   HRES   High Resolution Graphics
   CA      Closed Apple
   OA      Open Apple
   TAPE   Tape

 */   
PIN     84  =!RDV     ; /* Control Bus Read Enable                    */
PIN     81  = WRC     ; /* System Control Write Enable                */
PIN      6  = WRK     ; /* Keyboardbuffer/Boot Loader Write Clock     */

PIN     67  = V0      ; /* Control Bus Data                           */
PIN     68  = V1      ; /*                                            */
PIN     70  = V2      ; /*                                            */
PIN     69  = V3      ; /*                                            */
PIN     73  = V4      ; /*                                            */
PIN     74  = V5      ; /*                                            */
PIN     76  = V6      ; /*                                            */
PIN     75  = V7      ; /*                                            */

PIN     83  = CLK     ; /*  Video Clock                               */
PIN     16  = INH     ; /*  Video Clock Inhibit                       */
PIN      5  = SHLD    ; /*  Shift=1 / Load=0 Video Shift Register     */
PIN     10  =!BLANK   ; /*  Video Blank input                         */

PIN     25  = BH      ; /* Video DAC Blue High                        */
PIN     27  = BL      ; /* Video DAC Blue Low                         */

PIN     18  = GH      ; /* Video DAC Green High                       */
PIN     20  = GM      ; /* Video DAC Green Medium                     */

PIN     29  = RH      ; /* Video DAC Red High                         */
PIN     28  = RM      ; /* Video DAC Red Medium                       */

/* *************** Memory Interface ***********************************/
PIN      4  =!RAM     ; /* Main RAM Enable                            */
PIN     54  =!VRAM    ; /* Video RAM Enable                           */
PIN     30  =!RAME    ; /* Extended RAM Enable                        */
PIN     77  = WE      ; /* Write Enable Video RAM                     */
 
PIN     80  =!MRD     ; /* Master Read                                */
PIN     79  =!MWR     ; /* Master Write                               */

PIN     31  =!IO65    ; /* 65xx Peripheral Enable                     */
PIN     65  =!IDE     ; /* Disk Enable                                */
PIN     64  =!IOBD    ; /* Another Peripheral Enable                  */
 
PIN     24  = R16     ; /*                                            */
PIN      8  = R17     ; /*                                            */
PIN     11  = R18     ; /*                                            */

/* *************** PINNODES    *********************/
PINNODE     = Q0      ; /* Language Card                              */
PINNODE     = Q1      ; /*                                            */
PINNODE     = Q2      ; /*                                            */
PINNODE     = Q3      ; /*                                            */
 
PINNODE     = BK0     ; /* Bank Address                               */
PINNODE     = BK1     ; /*                                            */
PINNODE     = BK2     ; /*                                            */
PINNODE     = BK3     ; /*                                            */
PINNODE     = BK4     ; /*                                            */
PINNODE     = BK5     ; /*                                            */
PINNODE     = BK6     ; /*                                            */
PINNODE     = BK7     ; /*                                            */
 
PINNODE     = KBD0    ; /* ASCII Keyboard register                    */
PINNODE     = KBD1    ; /*                                            */
PINNODE     = KBD2    ; /*                                            */
PINNODE     = KBD3    ; /*                                            */
PINNODE     = KBD4    ; /*                                            */
PINNODE     = KBD5    ; /*                                            */
PINNODE     = KBD6    ; /*                                            */
PINNODE     = KBD7    ; /*                                            */
 
PINNODE     = VSHFT0  ; /* ASCII Keyboard register                    */
PINNODE     = VSHFT1  ; /*                                            */
PINNODE     = VSHFT2  ; /*                                            */
PINNODE     = VSHFT3  ; /*                                            */
PINNODE     = VSHFT4  ; /*                                            */
PINNODE     = VSHFT5  ; /*                                            */
PINNODE     = VSHFT6  ; /*                                            */
PINNODE     = VSHFT7  ; /*                                            */
 
PINNODE     = TEXT    ; /* Annunciators                               */
PINNODE     = MIXED   ; /*                                            */
PINNODE     = PAGE2   ; /*                                            */
PINNODE     = HIRES   ; /*                                            */
 
PINNODE     = STO80   ; /* Softswitches  Store 80 column              */
PINNODE     = RAMRD   ; /*               RD AUX RAM                   */
PINNODE     = RAMWR   ; /*               WR AUX RAM                   */
PINNODE     = ALTZP   ; /*               ZP, STACK, LC AUX RAM        */
PINNODE     = C3ROM   ; /*               C3-Slot ROM                  */
PINNODE     = CXROM   ; /*               CX ROM                       */
PINNODE     = ALTCH   ; /*               Alternate Character Set      */
PINNODE     = COL80   ; /*               80-column display            */

PINNODE     = L8      ; /* Latched IO Slot Address                    */
PINNODE     = L9      ; /*                                            */
PINNODE     = L10     ; /*                                            */

PINNODE     = TAPE    ; /*  Simulation of TAPE Input                  */
PINNODE     = OA      ; /*  Open Apple Key                            */
PINNODE     = CA      ; /*  Closed Apple Key                          */
PINNODE     = HRES    ; /*  Select between Low-Res and High-Res       */
PINNODE     = GR      ; /*  Select between TEXT and Low-Res           */
PINNODE     = VBL     ; /*  Vertical Blank (VSYNC from Video Ctrl)    */
PINNODE     = IML     ; /*  Initial Machine Load                      */
 
PINNODE     = IOUDIS  ; /*                                            */
PINNODE     = DHIRES  ; /*                                            */

PINNODE     = I16      ; /*                                            */

PINNODE     = SLOTCK   ; /*                                            */

PINNODE     =  RR16;    /* if deasserted use ROMRD and ROMWR          */
PINNODE     =  VR16;    /* if asserted use PAGE2                      */
PINNODE     =  AR16;    /* if asserted ALTZP is used to assert R16    */
PINNODE     =  CR16;    /* if asserted then directly assert R16       */
PINNODE     =  AUX;     /* RAMWR and RAMRD preselected with RW        */

PINNODE        =  CSHFT6;
PINNODE        =  CSHFT5;
PINNODE        =  CSHFT4;
PINNODE        =  CSHFT3;
PINNODE        =  CSHFT2;
PINNODE        =  CSHFT1;
PINNODE        =  CSHFT0;

PINNODE        =  CLATCH0;
PINNODE        =  CLATCH1;
PINNODE        =  CLATCH2;
PINNODE        =  CLATCH3;
PINNODE        =  CLATCH4;
PINNODE        =  CLATCH5;

PINNODE        =  IOPAGE;
PINNODE        =  SSW;

/*
   IO Map
   
   C00x   Keyboard / Softswitches
   C010   KBDCLR
   C01x   Status
   C02x   
   C03x
   C04x   
   C05x   Annunciators
   C06x   Inputs
   C07x   
   C08x   Language Card
   C09x   IO65 65xx Peripheral
   C0Ax   IO65 65xx Peripheral
   C0Bx   IOBD Device
   C0Cx   IO65 65xx Peripheral
   C0Dx   IOBD Device 5
   C0Ex   IDE
   C0Fx   
 */

/*
   Field Definitions
*/
FIELD  ADDRESS   = [A15..0];
FIELD  IOADDR    = [A7..0];
FIELD  BANK      = [BK7..0];
FIELD  DATA      = [D7..0];
FIELD  CTRL      = [C2..0];
FIELD  VIDEO     = [V7..0];
FIELD  KBD       = [KBD7..0];
FIELD  VSHFT     = [VSHFT7..0];

/*
   Soft Buffer Signal
*/
IOPAGE    = !BK7 & !BK6 & !BK5 & !BK4 & !BK3 & !BK2 & !BK1 & !BK0
          &  A15 &  A14 & !A13 & !A12 & !A11 & !A10 & !A9  & !A8;
 
/*
   Bank Address Latch
*/
BANK.l    =  DATA.io;
BANK.le   = !PHI2;
 
/*
   The Keyboard buffer has two functions
   -   During IML it provides the bytes for the boot code
   -   In normal operation it acts as a keybaord input
      where bit7 indicates a key is waiting and can be
      cleared by the CPU by accessing the IO address $C010.
*/
KBD.d     =  VIDEO.io;
KBD.ck    =  WRK;
KBD7.ar   =  IOPAGE & IOADDR:[10] & PHI2;

/*
   Read the video status bits from the CPU
 */
VIDEO     =  [DHIRES, STO80, ALTCH, COL80, HIRES, MIXED, PAGE2, TEXT];
VIDEO.oe  =  RDV;

/*
   Video Shift register
 */
VSHFT.ck  =  CLK;
VSHFT.ce  = !INH;

VSHFT.d   =  VIDEO.io   & !SHLD;

APPEND
VSHFT0.d  =  VSHFT0     &  GR  &  SHLD;

APPEND
VSHFT1.d  =  VSHFT1     &  GR  &  SHLD
          #  VSHFT0     & !GR  &  SHLD;

APPEND
VSHFT2.d  =  VSHFT2     &  GR  &  SHLD
          #  VSHFT1     & !GR  &  SHLD;

APPEND
VSHFT3.d  =  VSHFT3     &  GR  &  SHLD
          #  VSHFT2     & !GR  &  SHLD;

APPEND
VSHFT4.d  =  VSHFT4     &  GR  &  SHLD
          #  VSHFT3     & !GR  &  SHLD;

APPEND
VSHFT5.d  =  VSHFT5     &  GR  &  SHLD
          #  VSHFT4     & !GR  &  SHLD;

APPEND
VSHFT6.d  =  VSHFT6     &  GR  &  SHLD
          #  VSHFT5     & !GR  &  SHLD;

APPEND
VSHFT7.d  =  VSHFT7     &  GR  &  SHLD
          #  VSHFT6     & !GR  &  SHLD;

/*
   Double High Resolution support, together with INH
   every 4-bits the topmost 4 bits are converted to
   a 6-bit colour value as in the icolors table of the
   low-resolution mode.
 */
CSHFT6.ck =  CLK;
CSHFT6.d  =  VSHFT0;
CSHFT5.ck =  CLK;
CSHFT5.d  =  CSHFT6;
CSHFT4.ck =  CLK;
CSHFT4.d  =  CSHFT5;

CSHFT3.ck =  CLK;
CSHFT3.d  =  CSHFT4;
CSHFT2.ck =  CLK;
CSHFT2.d  =  CSHFT3;
CSHFT1.ck =  CLK;
CSHFT1.d  =  CSHFT2;
CSHFT0.ck =  CLK;
CSHFT0.d  =  CSHFT1;

TABLE [CSHFT3..0] => [CLATCH5..0].d {
/*
   Color Mapping Table only produces 6bits. The icolors
   table has RRRGGGBB, we drop the least significant
   bit of R and G.

 */
 'h'0 => 'b'000000;  /* 0x00   Black       */
 'h'1 => 'b'110000;  /* 0xE0   Red         */
 'h'2 => 'b'000010;  /* 0x02               */
 'h'3 => 'b'100010;  /* 0x82               */
 'h'4 => 'b'000100;  /* 0x0C               */
 'h'5 => 'b'010101;  /* 0x49   Grey I      */
 'h'6 => 'b'000011;  /* 0x03   Blue        */
 'h'7 => 'b'001111;  /* 0x1F               */
 'h'8 => 'b'100000;  /* 0x84               */
 'h'9 => 'b'110100;  /* 0xEC               */
 'h'A => 'b'101010;  /* 0x92   Grey II     */
 'h'B => 'b'110110;  /* 0xEE               */
 'h'C => 'b'001100;  /* 0x1C   Green       */
 'h'D => 'b'111100;  /* 0xFC               */
 'h'E => 'b'001110;  /* 0x3E               */
 'h'F => 'b'111111;  /* 0xFF   White       */

}

CLATCH0.ck = CLK;
CLATCH1.ck = CLK;
CLATCH2.ck = CLK;
CLATCH3.ck = CLK;
CLATCH4.ck = CLK;
CLATCH5.ck = CLK;

CLATCH0.ce = INH;
CLATCH1.ce = INH;
CLATCH2.ce = INH;
CLATCH3.ce = INH;
CLATCH4.ce = INH;
CLATCH5.ce = INH;

/*
   The Video output is limit to 6-bit, 2 bits for each colour.
   The use of bits 7,6,4,3,1,0 as the source comes from the
   icolors table used in ROMULUS1st that had actually 8-bits
   (R:3-bit, G:3-bit, B:2-bit), so we can use the same table.
 */
RH        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT7
          # !BLANK &        HRES & CLATCH5;

RM        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT6
          # !BLANK &        HRES & CLATCH4;
         
GH        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT4
          # !BLANK &        HRES & CLATCH3;
         
GM        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT3
          # !BLANK &        HRES & CLATCH2;
         
BH        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT1
          # !BLANK &        HRES & CLATCH1;
         
BL        = !BLANK & !GR & !HRES & VSHFT7
          # !BLANK &  GR & !HRES & VSHFT0
          # !BLANK &        HRES & CLATCH0;
         
/*
   System Control and Inputs. Note that these signals are not
   cleared on power up, it is the task of the video controller
   to initialise these system control bits.
 */
[IML, VBL, WE, GR, HRES, CA, OA, TAPE].l  = VIDEO.io;
[IML, VBL, WE, GR, HRES, CA, OA, TAPE].le = WRC;
 
/*
   CPU data read interface. The CPU can read various
   status bits and the keyboard buffer from the CPLD.
   The status bits can be read via D7 as in the Apple IIe.
   Bits 0..6 are directly connected to the lower 7 bits
   of the keyboard buffer. When IML is asserted the CPU
   just reads the keyboard buffer. This is used to initially
   load the ROM image. In this mode CPU reads always read
   the byte in the keyboard buffer and writes go to the RAM.
   
*/
[D6..0]   = [KBD6..0];

SSW       =  !A3 & !A2 & !A1 &  A0     & !Q3
          #  !A3 & !A2 &  A1 & !A0     &  Q0
          #  !A3 & !A2 &  A1 &  A0     &  RAMRD
          #  !A3 &  A2 & !A1 & !A0     &  RAMWR
          #  !A3 &  A2 & !A1 &  A0     &  CXROM
          #  !A3 &  A2 &  A1 & !A0     &  ALTZP
          #  !A3 &  A2 &  A1 &  A0     &  C3ROM
          #   A3 & !A2 & !A1 & !A0     &  STO80
          #   A3 & !A2 & !A1 &  A0     &  VBL
          #   A3 & !A2 &  A1 & !A0     &  TEXT
          #   A3 & !A2 &  A1 &  A0     &  MIXED
          #   A3 &  A2 & !A1 & !A0     &  PAGE2
          #   A3 &  A2 & !A1 &  A0     &  HIRES
          #   A3 &  A2 &  A1 & !A0     &  ALTCH
          #   A3 &  A2 &  A1 &  A0     &  COL80;


D7        = !IML & IOADDR:[00..0F] &  KBD7
          # !IML & IOADDR:[10..1F] &  SSW
          # !IML & IOADDR:[60]     &  TAPE
          # !IML & IOADDR:[61]     &  OA
          # !IML & IOADDR:[62]     &  CA
          # !IML & IOADDR:[7E]     &  IOUDIS
          # !IML & IOADDR:[7F]     &  DHIRES
          #  IML                   &  KBD7;

[D7..0].oe = !IML & IOPAGE & IOADDR:[00..1F] & RW & PHI2
           # !IML & IOPAGE & IOADDR:[60..7F] & RW & PHI2
           #  IML                            & RW & PHI2;

/*
   Double Hires Support Flags. This is only for accuracy but not of
   any functionality.
*/
IOUDIS.CE = (IOPAGE & IOADDR:[7E..7F] & !RW);
IOUDIS.CK = !PHI2;
IOUDIS.D  =  A0;
IOUDIS.AR =  RES;
 
DHIRES.CE = (IOPAGE & IOADDR:[5E..5F] & !RW & IOUDIS);
DHIRES.CK = !PHI2;
DHIRES.D  =  A0;
DHIRES.AR =  RES;
/*
   Latch to hold the last IO Slot ROM accessed.
*/
SLOTCK    = BANK:[00] & ADDRESS:[C100..C7FF];
 
[L8..10].AR =  RES;
[L8..10].LE =  PHI2 & SLOTCK;
[L8..10].L  =  [A8..10];
 
/*
   Language Card
*/
[Q0..3].CK  = !PHI2;
 
[Q0..3].CE  =  IOPAGE & IOADDR:[80..8F];
 
[Q0..3].AR  =  RES;

Q0.D      =  A0  &  A1
          # !A0  & !A1;

Q1.D      =  A0  &  RW;

!Q2.D     =  A0  &  RW  &  Q1
          #  A0  & !Q2;

Q3.D      =  A3;

/*
   Softswitches
*/
STO80.CE  =  (IOPAGE & IOADDR:[00..01] & !RW);
STO80.CK  = !PHI2;
STO80.D   =  A0;
ST080.AR  =  RES;
 
RAMRD.CE  =  (IOPAGE & IOADDR:[02..03] & !RW);
RAMRD.CK  = !PHI2;
RAMRD.D   =  A0;
RAMRD.AR  =  RES;
 
RAMWR.CE  =  (IOPAGE & IOADDR:[04..05] & !RW);
RAMWR.CK  = !PHI2;
RAMWR.D   =  A0;
RAMWR.AR  =  RES;
 
CXROM.CE  =  (IOPAGE & IOADDR:[06..07] & !RW);
CXROM.CK  = !PHI2;
CXROM.D   =  A0;
CXROM.AR  =  RES;
 
ALTZP.CE  =  (IOPAGE & IOADDR:[08..09] & !RW);
ALTZP.CK  = !PHI2;
ALTZP.D   =  A0;
ALTZP.AR  =  RES;
 
C3ROM.CE  =  (IOPAGE & IOADDR:[0A..0B] & !RW);
C3ROM.CK  = !PHI2;
C3ROM.D   =  A0;
C3ROM.AR  =  RES;
 
COL80.CE  =  (IOPAGE & IOADDR:[0C..0D] & !RW);
COL80.CK  = !PHI2;
COL80.D   =  A0;
COL80.AR  =  RES;
 
ALTCH.CE  =  (IOPAGE & IOADDR:[0E..0F] & !RW);
ALTCH.CK  = !PHI2;
ALTCH.D   =  A0;
ALTCH.AR  =  RES;

/*
   Annunciators.
*/
TEXT.CE   =  (IOPAGE & IOADDR:[50..51]);
TEXT.CK   = !PHI2;
TEXT.D    =  A0;
TEXT.AR   =  RES;
 
MIXED.CE  =  (IOPAGE & IOADDR:[52..53]);
MIXED.CK  = !PHI2;
MIXED.D   =  A0;
MIXED.AR  =  RES;
 
PAGE2.CE  =  (IOPAGE & IOADDR:[54..55]);
PAGE2.CK  = !PHI2;
PAGE2.D   =  A0;
PAGE2.AR  =  RES;
 
HIRES.CE  =  (IOPAGE & IOADDR:[56..57]);
HIRES.CK  = !PHI2;
HIRES.D   =  A0;
HIRES.AR  =  RES;

/*
   Select Signals
 */
MRD       =  PHI2  &  RW;
MWR       =  PHI2  & !RW;

$ifndef ROMULUS1ST
RAM       =  BANK:[00] & ADDRESS:[0000..03FF] & !IML
          #  BANK:[00] & ADDRESS:[0C00..1FFF] & !IML
          #  BANK:[00] & ADDRESS:[4000..BFFF] & !IML
          #  BANK:[00] & ADDRESS:[C100..CFFF] & !IML &  RW         /* normal mode only allows read   */
          #  BANK:[00] & ADDRESS:[CF00..CFFF] & !IML & !CXROM      /* Each Slot has some private RAM */
          #  BANK:[00] & ADDRESS:[D000..FFFF] & !IML & !RW & !Q2   /* Language Card RAM Write        */
          #  BANK:[00] & ADDRESS:[D000..FFFF] & !IML &  RW         /* Language Card RAM/ROM Read     */
          #  BANK:[00] &                         IML & !RW          /* Write enabled during IML       */
          #  BANK:[01..07];                                         /* Can always access upper BANKS  */

VRAM      =  BANK:[00] & ADDRESS:[0400..0BFF] & !IML
          #  BANK:[00] & ADDRESS:[2000..3FFF] & !IML;
 
RAME      =  BANK:[08..0F];

$endif
$ifdef ROMULUS1ST
RAM     =                          IML  & !RW
        #  ADDRESS:[0000..03FF] & !IML
        #  ADDRESS:[0C00..BFFF] & !IML
        #  ADDRESS:[C100..FFFF] & !IML  &  RW;

VRAM   =  ADDRESS:[0400..0BFF] & !IML
       #  ADDRESS:[0000..0FFF] &  IML  & !RW;

$endif
/*
   To emulate an Apple IIe the 512kbyte SRAM, that covers 8 memory banks,
   is mapped as following
   
   0000..BFFF   Using Bank 0 and 1 for MAIN and AUX
   C100..C2FF   Using Bank 0 and 1 for SLOTROM and CXROM controlled by CX
   C300..C3FF   Using Bank 0 and 1 for SLOTROM and CXROM controlled by C3
   C400..C7FF   Using Bank 0 and 1 for SLOTROM and CXROM controlled by CX
   C800..CFFF   Using Banks 0 to 7 for IOROM and CXROM
   D000..DFFF   Using Bank 0, 1, 2 and 3 for MAIN and AUX and BANK
            and Bank 4 for ROM
   E000..FFFF   Using Bank 0 and 1 for MAIN and AUX and Bank 4 for ROM

   To initialse the ROM images the boot loader can either change the memory
   map control signals via CPU code or it can just use absolutelong addresses
   to write directly to the appropriate Banks.

 */

AUX       = !RW &  RAMWR
          #  RW &  RAMRD;

/*   RR16: R16 does not depend on RAMRD or RAMWR                                     */
RR16      =  ADDRESS:[0000..01FF]
          #  ADDRESS:[C000..FFFF];

/*   VR16: R16 depends on PAGE2 and hence not on RAMRD and RAMWR                     */
VR16      =  ADDRESS:[0400..07FF] &  STO80
          #  ADDRESS:[2000..3FFF] &  STO80  &  HIRES;

/*   AR16: R16 depends on ALTZP                                                      */
AR16      =  ADDRESS:[0000..01FF]
          #  ADDRESS:[D000..FFFF] & !RW   & !Q2
          #  ADDRESS:[D000..FFFF] &  RW   &  Q0;

/*  CR16: R16 in Slot ROM Region and in IO ROM Region for Slots 1,3,5,7             */
CR16      =  ADDRESS:[C100..C2FF] &  CXROM
          #  ADDRESS:[C300..C3FF] & !C3ROM
          #  ADDRESS:[C400..CFFF] &  CXROM
          #  ADDRESS:[C800..CFFF] & !CXROM & !L10 & !L9  &  L8    /* Slot 1         */
          #  ADDRESS:[C800..CFFF] &  C3ROM & !L10 &  L9  &  L8    /* Slot 3         */
          #  ADDRESS:[C800..CFFF] & !CXROM &  L10        &  L8;   /* Slot 5,7       */
/*  Combine all conditions to set R16                                               */
$ifndef ROMULUS1ST
R16       =  BANK:[00] & !RR16 & !VR16 &  AUX
          #  BANK:[00] &          VR16 &  PAGE2
          #  BANK:[00] &  AR16         &  ALTZP
          #  BANK:[00] &  CR16
          #  BK0;
/*  R17 is set for LC Card Bank 2 and for IO ROM Banks in C8 region for slots 2,3,6,7*/
R17       =  BANK:[00] &  ADDRESS:[D000..DFFF] & !RW  & !Q2  &  Q3
          #  BANK:[00] &  ADDRESS:[D000..DFFF] &  RW  &  Q0  &  Q3
          #  BANK:[00] &  ADDRESS:[C800..CFFF] & !CXROM & !L10 &  L9  & !L8    /* Slot 2         */
          #  BANK:[00] &  ADDRESS:[C800..CFFF] &  C3ROM & !L10 &  L9  &  L8    /* Slot 3         */
          #  BANK:[00] &  ADDRESS:[C800..CFFF] & !CXROM &  L10 &  L9           /* Slot 6,7       */
          #  BK1;
/*  R18 is set for D0 to F8 ROM and for IO ROM Banks in C8 region for slots 4-7      */
R18       =  BANK:[00] &  ADDRESS:[C800..CFFF] & !CXROM &  L10                 /* Slot 4,5,6,7   */
          #  BANK:[00] &  ADDRESS:[D000..FFFF] &  RW  & !Q0
          #  BK2;

$endif ROMULUS1ST
$ifdef ROMULUS1ST
[R18..16] = 'b'000;
$endif
/*
   IO Select
   
   IO65   is intended for 65xx peripherals, 65xx peripherals normally
         have two chip select a negative and a positive logic. IOB
         is connected to the negative active CS and the positive active
         CS is connected to A4,A5,A6. IOB as asserted only for three
         ranges where only one of these three address bits is high.
   IDE      is a general IO, primary purpose is a CFA mass storage.
 */
IO65      =  IOPAGE & IOADDR:[90..9X]
          #  IOPAGE & IOADDR:[A0..AX]
          #  IOPAGE & IOADDR:[C0..CX];
             
IDE       =  IOPAGE & IOADDR:[E0..EF];

IOBD      =  IOPAGE & IOADDR:[B0..BX]
          #  IOPAGE & IOADDR:[D0..DX];


Certainly a lot of background is required to understand everything, but so far I did not spend enough time to make a decent documentation.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Thu Jul 28, 2016 7:25 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1948
Location: Sacramento, CA, USA
My Apple 2 background was immediately useful in understanding what you are trying to do, even though I know next to nothing about WinCUPL. Nice work!

Mike B.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Mon Aug 01, 2016 1:34 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
Although the CPLD worked for Apple II and Apple II plus ROM images the Apple IIe ROM image only partially worked, e.g. the 80-column mode was not working as the CX ROM mapping was not correct.
Attachment:
File comment: Updated CPLD design file with correct CX ROM mapping
ROMULUS2NDV2.txt [27.66 KiB]
Downloaded 136 times

Now this design file supports the CX ROM Mapping and 80-column text mode works. The 65SC816 system, with no devices attached to the bus except for the debugging hardware, runs at 11MHz and is stable.


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Sat Aug 20, 2016 1:32 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
Here some further information to my ROMulus project. In the past two weeks I was working on the AVR code and on other projects as well. The hardware now runs the Apple IIe system check successfully. At least I get the "SYSTEM OK" page after the systems self test run (that's when you reset the system with the solid apple key pressed). This self-test checks the built-in IO and the memory.

During the setup of the hardware, as I already mentioned, I found two "bugs" in the PCB layout. One was a missing connection to VCC on the JTAG connector in pin 4 and the other was that I swapped pins 1 and 4 on the ISP header for the AVR processor. Here is now the schematic with the 2 errors already fixed.

The first page shows the dual-port RAM and the AVR with the additional glue logic which acts as Video Controller, PS/2 Interface and the boot controller
Attachment:
File comment: Schematic Page 1
ROMulus2ndV2xrev1-p1.pdf [21.89 KiB]
Downloaded 135 times


The second page shows the CPU, RAM and the CPLD
Attachment:
File comment: Schematic Page 2
ROMulus2ndV2xrev1-p2.pdf [18 KiB]
Downloaded 126 times


And the third page shows the MAX232 level shifter and the IO Bus expansion Port
Attachment:
File comment: Schematic Page 3
ROMulus2ndV2xrev1-p3.pdf [19.21 KiB]
Downloaded 128 times


There are two 8-bit paths to the CPLD, one is the SBC data-bus which goes into the CPLD and one is the address/control bus from the AVR to the CPLD. At startup the AVR sets the IML bit in the CPLD which causes the memory map to be slightly different. First all CPU reads go to the so called keyboard buffer and the memory map is flat. So only 512kbyte of RAM which is selected for write cycles. The AVR controls not only the IML bit but also can write to the keyboard buffer and controls CPU RESET and PHI2.

After the AVR has set IML it will assert reset and the manually control PHI2 so the W65C816 gets its required two PHI2 cycles with reset asserted to initiate a reset sequence. Then the AVR de-asserts reset and continues to manually control PHI2. Manually controlling PHI2 means it sets and resets the PHI2 level using set bit and clear bit IO instructions. As the W65C816 is a static CPU toggling of PHI2 must not occur at a given rate. Even though this would be not a big issue. By counting the cycles the AVR generates he exactly nows when the W65C816 reads the vector and the subsequent instructions. The absolute value of the reset vector is not important at all, because once the reset vector has been sent the AVR will then feed the W65C816 with a continuous loop of the following instructions
Code:
     lda   #<data>
     stal  <absolutelongaddress>
     jmp  $300

the AVR will continue to send the above loop until all memory locations that are later ROM locations have been updated with the correct <data>.

Then the AVR will perform a second reset cycle. Only this time IML will be reset and the CPLD will now activate a memory mapping that matches the requirements, in my case a mapping which mimics a Apple IIe. You can of course you can implement whatever you need. Also the AVR now no longer manually controls PHI2 but rather programs the output used for PHI2 (OC2B) to generate a PWM signal of the desired clock speed. The fastest PHI2 clock that the AVR can generate is 1/2 the AVR clock speed, in my case 11MHz. But you can also generate any rate that is compatible with the PWM output signal generator and the best is it does not even have be be symmetric if you need that. Using a 8-bit counter the clock speed can go down to approx 100kHz. Very handy in case you want to test hardware so you can see everything in slow motion.

Once the second reset cycle has been executed the AVR will then start to generate the video signal and activates the PS/2 interface. The keyboard buffer used to boot the SBC is now used to send the PS/2 codes or ASCII keys (whatever you need) to the SBC. With the CPLD implementing the correct hardware you can read the keyboard from the W65C816.

The whole boot process is controlled via the serial interface of the AVR using USART0. At the moment I have to type in the commands that perform all the above steps. But there is also the option to save a initial sequence of commands in the EEPROM of the AVR that is executed whenever the AVR is reset.

The video controller uses a dual-port RAM, that's my lazy solution for video signal generation. The AVR is not the best video controller, but with some tricks (memory mapping as in Apple IIe) you can create everything from a simple text display, a low-res colour display (160 pixels wide with up to 480 lines) up to a 640x480pixel BW signal. As long as you provide enough dual-port RAM.

The system features also a small IO bus. The IO bus only brings out the signal as show in page 3 of the schematic. It has enough signals to address a page (256bytes) to act as IO page and is only intended to be used as IO expansion. Plans exist for a 4-channel USART (using one of those famous chips that BDD always praises) and a 8-bit CF-Card interface. The bus is breadboard friendly so you can test your IO separately.

Of course I have already come up with a list of items I would do different. But for now the system does for what it was initially designed for

Cheers

Peter


Top
 Profile  
Reply with quote  
 Post subject: Re: ROMulus the 2nd
PostPosted: Sun Sep 04, 2016 8:18 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 491
Location: Switzerland
I'm watching the thread about the 3 chip design and the challenges to load an initial image to the 6502 system using a minimal count of a controller with great interest. So I take the time to elaborate a little more on the boot loader as it is implemented in ROMulus the 2nd and in principal in the 1st as well. Although this method will not fit into 3 chips a minimal version will at least fit into a 4 chip design: CPU, RAM, MCU, GLUE and uses a reasonable count of PINs. Depending on the requirements the GLUE will fit into a SPLD (GAL16V8 or GAL22V10) in my case, as GLUE does much more, the logic is part af a CPLD (ATF1508). I recommend that you have a look at the design file already attached to this thread.

There are the following signals that are controlled by the AVR

!RES this pin is constatly set to 0. Instead of de-asserting !RES the AVR switches between input and output so it is rather a open drain output and requires a pull-up, the advantage is that you can have a switch in parallel

PHI2 this pin uses OC2B of the AVR used here. Depending on the mode the AVR controll program either toggles the state manually using sbi and cbi instructions ore it activates Timer 2 to create a steady PHI2 clock

IML this signals to the CPLD (or whatever glue logic you use) which memory decoding scheme shall be active. When all reads from the 65C816 are directed to the internal byte buffer of the CPLD and all writes go to the memory. Memory is then addressed linearly as one 512kbyte RAM covering the first 8 banks. Note that IML is implemented as a bit in the internal control byte of the CPLD. The control byte can be written using WRC clock

WRK this signal latches the value on PORTA into the internal byte buffer of the CPLD

PORTA this is the data port of the AVR, in this design it connects to the CPLD to write internal registers, one of these is the byte register which can be read by the 65xxx

If you use this method for a minimal system, then you typically will just connect PORTA to the databus and of course you need also to add some instructions to control the direction of the PORTA when the CPU performs a write cycle. Using a PIC controller with a parallel port this could also be handled in the GLUE logic as the PORT of the PIC in this mode can be tri-stated. Or you could add a buffer between the MCU and the data bus. In any case this design in a minimal setup would use 11 pins of the MCU to be connected to the system: RES, PHI2, IML and D0..7. Of course much more pins than in the 3 chip design challenge but very few when compared to solutions that connect all bus signals to the MCU. If the pin count is critical the data bus could also be connected via a shift register, buth this will then make the system at least a 5 chip design. But I think 11 pins is quite good and there are no pull-up/downs on the databus and hence the system is capable of higher clock rates, in my case 11MHz.


At the beginning the AVR initialises the ports and starts in a known state with IML set in the CPLD control register

Code:
;--------------------------------------------------------------------------
;
;   PORTA   A0..A7
;
;   Multiple Purpose Output Port, this port is connected to the CPLD to
;   the address lines of the DPRAM and to the upper video RAM address
;   latch.
;
   out      PORTA, ff
   out      DDRA, ff
;--------------------------------------------------------------------------
;
;   SYSCTL: This is a register that holds the current value of the CPLD control register
;
;   These flags are used to control the 65C816 system.
;
;   IML, VBL, WE, GR, SHFT, CA, OA, TAPE
;
.set   TAPE   = 0      ;   Simlulate TAPE input
.set   OA      = 1      ;   Open Apple Key
.set   CA      = 2      ;    Closed Apple Key
.set   SHFT   = 3      ;   Shift Key
.set   GR      = 4      ;   Graphics
.set   WE      = 5      ; 0=Write Enable RAM
.set   VBL      = 6      ;   Vertical Blank
.set   IML      = 7      ; 1=Set Initial Machine Load
;
;
;
   ldi      temp, (1<<IML) | (1<<WE)
   out      PORTA, temp
   nop
   sbi      PORTB, WRC
   cbi      PORTB, WRC      ; Latch Control Bits into CPLD
   in      SYSCTL, PORTA   ; keep a copy

Then it will disable the clock and assert reset
Code:
;--------------------------------------------------------------------------
;
;   PORTB   VPB, RDV, WRK, WRC, CE, RES, SHLD
;
.equ   VPB   = 0         ; Vector Pull from 65xxx
.equ   RDV   = 1         ; Read Video Control bits, active low!
.equ   WRK   = 2         ; Write Byte Buffer/Keyboard Clock normally high
.equ   WRC = 3         ; Write Control Bits Latch Enable normally low
.equ   INH   = 4         ; Inhibit Video Pixel Clock OC0B
.equ   CE   = 5         ; Video RAM Chip Enable
.equ   RES   = 6         ; 65xxx reset
.equ   SHLD= 7         ; SHLD video shift register connected to OC3B
;
;   Reset pin is set low and normally is configured as input. The normal
;   pull-up on the reset line will pull the signal high. To activate
;   reset we just set the pin as output which will pull the line low.
;
#define RESETPIN   DDRB, RES
;
   ldi      temp, (1<<RDV) | (1<<WRK) | (0<<WRC) | (1<<CE)
   out      PORTB, temp
   ldi      temp, (1<<RDV) | (1<<WRK) | (1<<WRC) | (1<<INH) | (1<<CE) | (1<<SHLD)
   out      DDRB, temp   


Now we can initialise the 65xxx system. For this we execute the following code

Code:

imlprepare:
;
;   Stop the clock
;
   cbi      PORTD, PHI2      ; Make sure we and with PHI2=Low
   sts      TCCR2B, zero   ; Stop the timer
   sts      TCCR2A, zero
   sts      OCR2A, zero
;
   sbi      RESETPIN
;
;   After Reset is asserted (pulled low) the 65816 requires two
;   full PHI2 cycles to reset.
;
   sbi      PORTD, PHI2      ; Note that consecutive sbi/cbi
   cbi      PORTD, PHI2      ; create a clock requency of 4 AVR
   sbi      PORTD, PHI2      ; cycles in our case 5.5MHz.
   cbi      PORTD, PHI2
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2
   sbi      PORTD, PHI2
;
;   De-assert Reset when PHI2 is high so the 65816 will detect
;   the rising edge of reset at the next falling edge of PHI2
;
   cbi      RESETPIN
   nop
   nop
   out      PORTA, SYSCTL
   sbi      PORTA, IML
   sbi      PORTB, WRC
   cbi      PORTB, WRC      ; Latch Control Bits into CPLD
   in      SYSCTL, PORTA
   cbi      PORTD, PHI2      ; this for some reason does not
                     ; detect reset being de-asserted
;
;   It seems that the number of cycles after a reset is not well
;   and accurately documented in the W65C816 manual from WDC. How-
;   ever it is in line with the Synertek manual of the 6502
;
;      http://archive.6502.org/datasheets/synertek_hardware_manual.pdf
;
;   which states that after RESET is de-asserted (high) the 6502 will
;   delay 6 cycles and then fetch the program counter, so we wait
;   6 cycles before emitting the start address of IML.
;
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; This detects that reset is de-asserted
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; Cylce 1
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; Cylce 2
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; Cylce 3
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; Cylce 4
   sbi      PORTD, PHI2
   cbi      PORTD, PHI2      ; Cylce 5
   ret
;


Now the 65xxx processor is fully initialsed. The next the CPU expects is the reset vector and instructions. So we provide the necessary data. A small subroutine is used to place a byte into the byte buffer and strobe PHI2

Code:
imlbyte:
   out      PORTA, temp      ; Set value
   cbi      PORTB, WRK      ; Reset WRK
   sbi      PORTB, WRK      ; Load with leading edge
   sbi      PORTD, PHI2      ; PHI2 = high
   nop
   nop
   nop
   cbi      PORTD, PHI2      ; PHI2 = low
   ret


The following routine will take a ROM image in flash and copies it to the RAM address that late is the ROM. It expects the pointer Z to point the the flash image with the 65C816 ROM image. X is expected to be setup with the starting address of the ROM image as seen by the 65C816. In our case the ROM image must be copied into BANK 0 and BANK 4 depending on the value in X. This of course depends on how the CPLD maps the memory addresses. At the moment this routine just copies a ROM image from the starting address up to $FFFF. Different to ROMulus the 1st I now use the store absolute long instruction so I can write to the complete 24-address range of the 65C816. As this works as well in emulation mode I don't need to switch into native mode here. The loop starts with sending an address. When entered first this is the time when the 65C816 expects the address from the reset vector.

Code:
wloop:
;
   ldi      temp, 0x00         ; The first time we need to provide
   rcall   imlbyte
;
   ldi      temp, 0x03         ; a RESET vector, any address will do so
   rcall   imlbyte            ; we use the same address as in the JMP.
;
   ldi      temp, LDA_         ; Load <immediate>
   rcall   imlbyte
;
   lpm      temp, Z+         ; next byte from ROM image
   rcall   imlbyte
;
    ldi      temp, STAL_         ; Store <absolutelong>
;   ldi      temp, STA_         ; Store <absolute>
   rcall   imlbyte
;
   mov      temp, xl         ; to the current pointer
   rcall   imlbyte
;
   mov      temp, xh         ; of the ROM image destination
   rcall   imlbyte
;
   mov      temp, zero         ; CX ROM is in Bank 0
   cpi      xh, 0xD0
   brlo   wbank4
   ldi      temp, 0x04         ; D0..F8 ROM is in Bank 4
wbank4:
   rcall   imlbyte
;
   ldi      temp, 0xff         ; the write cycle, the value is not
   rcall   imlbyte            ; relevant
;
   ldi      temp, JMP_         ; Jump to start of loop
   rcall   imlbyte            ;
                        ;
   adiw   xh:xl, 1         ; Next ROM destination address
   brne   wloop            ; if not overflow to 0 then continue


Now we have loaded the ROM image to the memory section that later will be mapped as ROM and typically will be write protected. To activate the ROM we first stop the clock, clear IML, assert RESET and the start the clock

Code:
;
; Toggle IML in the control byte of the CPLD
;
imliml:
   sbi      GPIOR0, LOCKA
   out      PORTA, SYSCTL
   sbi      PINA, IML
   sbi      PORTB, WRC
   cbi      PORTB, WRC      ; Latch Control Bits into CPLD
   in      SYSCTL, PORTA
   cbi      GPIOR0, LOCKA
   ret
;
; Start the clock, the value in a1l is set to the desired rate
;
imlclock:
   lds      temp, a1l
   tst      temp
   breq   imlstop
   ori      temp, 0x01      ; 1 = 11MHz, 0x14 is ~1MHz, 0xC8 is ~ 100kHz
   sts      OCR2A, temp
   lsr      temp
   sts      OCR2B, temp
   ldi      temp, (1<<WGM22) | (0<<CS22) | (0<<CS21) | (1<<CS20)
   sts      TCCR2B, temp
   ldi      temp, (0<<COM2A1) | (0<<COM2A0) | (1<<COM2B1) | (1<<COM2B0) | (1<<WGM21) | (1<<WGM20)
   sts      TCCR2A, temp
   ret

The AVR must wait at least 2 clock cycles before de-asserting RESET. As IML has been cleared the memory mapping is switched to the normal SBC layout and the ROM image in RAM mapped to the upper addresses (in our case $C100..FFFF). Once RESET has been de-asserted the CPU will restart using the "ROM" image.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: