Jump to content
IGNORED

Project Veronica


Recommended Posts

cool... i love the monitor and the keyboard click sound... ;) long time not heard from my 800 XL... need to setup it again... ;)

 

so actually the 65816 is taking over or is it running in parallel? and how is the memory interface? at ABBUC we had such turbo boards discussed several years ago but the issue if I remember it correctly was that the 65816 was running not as slave but as main CPU... and shared the memory...

Link to comment
Share on other sites

so actually the 65816 is taking over or is it running in parallel?

It's running in parallel. The rotator effect that is shown in the video is implemented via parallel processing. The Atari gets about 1/4 of the screen and the rest is handled by Veronica's CPU. Screen memory is located under cartridge location - $8000 - $9FFF in this case, but it's also possible to utilize the whole of it, meaning $8000 - $BFFF.

 

and how is the memory interface?ut as main CPU... and shared the memory...

No memory sharing/clashes/dual port memory/sophisticated synchronization scenarios. The communication is done through bank switching. There are two ram banks, let's call them A and B. At the beginning Atari accesses memory A at its standard clock and B is accessed by Veronica at hers individual clock. When it comes to data exchange, the situation is flipped. Atari receives bank B, Veronica bank A, with clock input change as well. And it goes this way on an on. The hardware register located at $d5c0 in Atari's address space has a special bit D7. It is a semaphore flag that is utilized during entire communication phase. Veronica accesses it from her side at $0200.

 

Here is a snippet of code that provides some more detail about bit assignment in hardware register on both sides.

 

/// Enumeration of Atari hardware register bits.

.enum EAtariRegisterBits

SEMAPHORE_READ = 7

SEMAPHORE_WRITE = 7

 

BANK1_ENABLE = 5 // $A000-$BFFF -> $E000-$FFFF or $6000-$7FFF

BANK0_ENABLE = 4 // $8000-$9FFF -> $C000-$DFFF or $4000-$5FFF

 

RAMBANK_CFG = 1

 

VERONICA_CPU_RESET = 0

.ende

 

/// Enumeration of Veronica hardware register bits.

.enum EVeronicaRegisterBits

SEMAPHORE_READ = 7

SEMAPHORE_WRITE = 7

 

WINDOW_LOCATION = 6

.ende

 

/// Enumeration of Atari hardware register bit combinations.

.enum EAtariRegisterStates

UNLOCK_ATARI = (1 << EAtariRegisterBits.SEMAPHORE_WRITE)

VERONICA_UNLOCKED = (1 << EAtariRegisterBits.SEMAPHORE_READ)

SEMAPHORE_MASK = (1 << EAtariRegisterBits.SEMAPHORE_READ)

 

BANK0_ENABLED = (1 << EAtariRegisterBits.BANK0_ENABLE)

BANK0_DISABLED = (0 << EAtariRegisterBits.BANK0_ENABLE)

BANK1_ENABLED = (1 << EAtariRegisterBits.BANK1_ENABLE)

BANK1_DISABLED = (0 << EAtariRegisterBits.BANK1_ENABLE)

BANKS_ENABLED = (BANK0_ENABLED | BANK1_ENABLED)

BANKS_DISABLED = 0

 

BANK0_MASK = (1 << EAtariRegisterBits.BANK0_ENABLE)

BANK1_MASK = (1 << EAtariRegisterBits.BANK1_ENABLE)

BANKS_MASK = (BANK0_MASK | BANK1_MASK)

 

RAMBANK_CFG_MASK = (1 << EAtariRegisterBits.RAMBANK_CFG)

 

VER_CPU_RESET_PULSE_LOW = (0 << EAtariRegisterBits.VERONICA_CPU_RESET)

VER_CPU_RESET_PULSE_HIGH = (1 << EAtariRegisterBits.VERONICA_CPU_RESET)

VER_CPU_RESET_MASK = (1 << EAtariRegisterBits.VERONICA_CPU_RESET)

.ende

 

/// Enumeration of Veronica hardware register bit combinations.

.enum EVeronicaRegisterStates

UNLOCK_VERONICA = (1 << EVeronicaRegisterBits.SEMAPHORE_WRITE)

ATARI_UNLOCKED = (1 << EVeronicaRegisterBits.SEMAPHORE_READ)

SEMAPHORE_MASK = (1 << EVeronicaRegisterBits.SEMAPHORE_WRITE)

 

WINDOW_LOCATION_C000 = (0 << EVeronicaRegisterBits.WINDOW_LOCATION)

WINDOW_LOCATION_4000 = (1 << EVeronicaRegisterBits.WINDOW_LOCATION)

WINDOW_LOCATION_MASK = (1 << EVeronicaRegisterBits.WINDOW_LOCATION)

.ende

 

Also... why stop at 5MHz?

As I already mentioned, it's a work in progress. Our goal is achieving as high frequency as possible, probably 14 MHz of the WDC 65C816S CPU.

Edited by Marek Konopka
Link to comment
Share on other sites

I have considered doing something like this but with the 65816 addressing all of the external memory using 24-bit addressing and the Atari banking in memory in the cartridge space. With a little more memory, say 512KB, rather than 64K, and allowing the 6502 side to HALT the 65816 when it needs external memory access. For a 65816 running at 14 mhz, you only need to give up one storage cycle (70ns) for each 6502-side request. Worst case would then be less than 13% thruput reduction. (way less - the 6502 isn't likely to access memory on every cycle unless you put his code in there) Your $D5xx control register would then select which 8K/16K bank that the 6502 side sees.

 

So, where is Veronica's code located? How does it get there? How do you run a cartridge? Is the 65816 and its memory running at 3v?

 

Nice project - just drop it in... most users can do that!

 

 

Bob

 

 

 

so actually the 65816 is taking over or is it running in parallel?

It's running in parallel. The rotator effect that is shown in the video is implemented via parallel processing. The Atari gets about 1/4 of the screen and the rest is handled by Veronica's CPU. Screen memory is located under cartridge location - $8000 - $9FFF in this case, but it's also possible to utilize the whole of it, meaning $8000 - $BFFF.

 

and how is the memory interface?ut as main CPU... and shared the memory...

No memory sharing/clashes/dual port memory/sophisticated synchronization scenarios. The communication is done through bank switching. There are two ram banks, let's call them A and B. At the beginning Atari accesses memory A at its standard clock and B is accessed by Veronica at hers individual clock. When it comes to data exchange, the situation is flipped. Atari receives bank B, Veronica bank A, with clock input change as well. And it goes this way on an on. The hardware register located at $d5c0 in Atari's address space has a special bit D7. It is a semaphore flag that is utilized during entire communication phase. Veronica accesses it from her side at $0200.

 

Here is a snippet of code that provides some more detail about bit assignment in hardware register on both sides.

 

/// Enumeration of Atari hardware register bits.

.enum EAtariRegisterBits

SEMAPHORE_READ = 7

SEMAPHORE_WRITE = 7

 

BANK1_ENABLE = 5 // $A000-$BFFF -> $E000-$FFFF or $6000-$7FFF

BANK0_ENABLE = 4 // $8000-$9FFF -> $C000-$DFFF or $4000-$5FFF

 

RAMBANK_CFG = 1

 

VERONICA_CPU_RESET = 0

.ende

 

/// Enumeration of Veronica hardware register bits.

.enum EVeronicaRegisterBits

SEMAPHORE_READ = 7

SEMAPHORE_WRITE = 7

 

WINDOW_LOCATION = 6

.ende

 

/// Enumeration of Atari hardware register bit combinations.

.enum EAtariRegisterStates

UNLOCK_ATARI = (1 << EAtariRegisterBits.SEMAPHORE_WRITE)

VERONICA_UNLOCKED = (1 << EAtariRegisterBits.SEMAPHORE_READ)

SEMAPHORE_MASK = (1 << EAtariRegisterBits.SEMAPHORE_READ)

 

BANK0_ENABLED = (1 << EAtariRegisterBits.BANK0_ENABLE)

BANK0_DISABLED = (0 << EAtariRegisterBits.BANK0_ENABLE)

BANK1_ENABLED = (1 << EAtariRegisterBits.BANK1_ENABLE)

BANK1_DISABLED = (0 << EAtariRegisterBits.BANK1_ENABLE)

BANKS_ENABLED = (BANK0_ENABLED | BANK1_ENABLED)

BANKS_DISABLED = 0

 

BANK0_MASK = (1 << EAtariRegisterBits.BANK0_ENABLE)

BANK1_MASK = (1 << EAtariRegisterBits.BANK1_ENABLE)

BANKS_MASK = (BANK0_MASK | BANK1_MASK)

 

RAMBANK_CFG_MASK = (1 << EAtariRegisterBits.RAMBANK_CFG)

 

VER_CPU_RESET_PULSE_LOW = (0 << EAtariRegisterBits.VERONICA_CPU_RESET)

VER_CPU_RESET_PULSE_HIGH = (1 << EAtariRegisterBits.VERONICA_CPU_RESET)

VER_CPU_RESET_MASK = (1 << EAtariRegisterBits.VERONICA_CPU_RESET)

.ende

 

/// Enumeration of Veronica hardware register bit combinations.

.enum EVeronicaRegisterStates

UNLOCK_VERONICA = (1 << EVeronicaRegisterBits.SEMAPHORE_WRITE)

ATARI_UNLOCKED = (1 << EVeronicaRegisterBits.SEMAPHORE_READ)

SEMAPHORE_MASK = (1 << EVeronicaRegisterBits.SEMAPHORE_WRITE)

 

WINDOW_LOCATION_C000 = (0 << EVeronicaRegisterBits.WINDOW_LOCATION)

WINDOW_LOCATION_4000 = (1 << EVeronicaRegisterBits.WINDOW_LOCATION)

WINDOW_LOCATION_MASK = (1 << EVeronicaRegisterBits.WINDOW_LOCATION)

.ende

 

Also... why stop at 5MHz?

As I already mentioned, it's a work in progress. Our goal is achieving as high frequency as possible, probably 14 MHz of the WDC 65C816S CPU.

Link to comment
Share on other sites

I have considered doing something like this but with the 65816 addressing all of the external memory using 24-bit addressing and the Atari banking in memory in the cartridge space.

We're considering linear space addressing as a future upgrade.

 

Worst case would then be less than 13% thruput reduction. (way less - the 6502 isn't likely to access memory on every cycle unless you put his code in there) Your $D5xx control register would then select which 8K/16K bank that the 6502 side sees.

This was exactly my initial idea for implementation, but Zenon came up with a different one - a simpler one.

 

So, where is Veronica's code located?

Wherever you like it to be. Well, almost. There is no ROM memory of any kind. The external CPU is halted just after reset. You enable it by performing some simple routine, placing bootstrap code into one of the ram banks, swapping them and starting the CPU. This way you can place any startup code you like without needing to program and access slow xROM chips.

 

How does it get there?

It gets there though a simple protocol that utilizes the aforementioned hardware register, its semaphore bit 7. The semaphore signals whether transmission can be made, or a party needs to wait till the other one finishes its tasks. The semaphore is signaled back when a party finishes its work.

 

How do you run a cartridge?

You run it by transferring simple BIOS to the Veronica. The BIOS handles simple commands like: identification, data upload, data download, procedure execution. After the start it stays in a message loop, waits for commands and executes them, as soon as they arrive.

 

Is the 65816 and its memory running at 3v?

It is all TTL.

Edited by Marek Konopka
Link to comment
Share on other sites

I have considered doing something like this but with the 65816 addressing all of the external memory using 24-bit addressing and the Atari banking in memory in the cartridge space. With a little more memory, say 512KB, rather than 64K, and allowing the 6502 side to HALT the 65816 when it needs external memory access. For a 65816 running at 14 mhz, you only need to give up one storage cycle (70ns) for each 6502-side request. Worst case would then be less than 13% thruput reduction. (way less - the 6502 isn't likely to access memory on every cycle unless you put his code in there) Your $D5xx control register would then select which 8K/16K bank that the 6502 side sees.

 

Dual-port RAM, while somewhat more expensive, is way, way easier :)

Link to comment
Share on other sites

It's not so bad - the 6502B and the 65816 are designed to be HALTed. Do they even make big, fast DualPort SRAM?

 

Bob

 

 

 

I have considered doing something like this but with the 65816 addressing all of the external memory using 24-bit addressing and the Atari banking in memory in the cartridge space. With a little more memory, say 512KB, rather than 64K, and allowing the 6502 side to HALT the 65816 when it needs external memory access. For a 65816 running at 14 mhz, you only need to give up one storage cycle (70ns) for each 6502-side request. Worst case would then be less than 13% thruput reduction. (way less - the 6502 isn't likely to access memory on every cycle unless you put his code in there) Your $D5xx control register would then select which 8K/16K bank that the 6502 side sees.

 

Dual-port RAM, while somewhat more expensive, is way, way easier :)

Link to comment
Share on other sites

You can load a routine into external memory and then point the 65816 at it to be executed. Very quickly...

 

As an example, consider sorting a large set of data. The 6502 loads the data into the 65816's SRAM and then tells the 65816 to branch to a sort routine (that the 6502 has loaded). The 65816 will then sort the data while the 6502 does something else. (or, just waits) Or, a spelling checker that operates in the background of a WP, using no resources of the 6502. An 80 column driver...

 

The 65816 does not have to deal with interrupts, ANTIC, or REFRESH, which makes it 50% faster in GR.0. At 14mhz, equivalent to a 21mhz system, 12x faster than a stock Atari. If you sync the clocks, you can allocate one cycle to the 6502 in every frame, allowing you to lock the two systems. (think: DLI in the 6502 executed by the 65816, in sync)

 

In the video, the 65816 is calculating screen data. It could replace the FP routines, which would speed up anything that uses them, but, for the most part you would have to program new s/w. That's the advantage of an internal 65816 - it speeds up all existing s/w. No reason why you couldn't have both, actually.

 

Bob

 

 

 

 

What would one do with something like this?

Link to comment
Share on other sites

It's not so bad - the 6502B and the 65816 are designed to be HALTed. Do they even make big, fast DualPort SRAM?

 

Yeah I was digging around on Digi-key and saw that they have up to 128kx8 dual port SRAM in as fast as 6.5ns (!), and even larger sizes if you don't mind more-than-8-bit data width.

Link to comment
Share on other sites

If you sync the clocks, you can allocate one cycle to the 6502 in every frame, allowing you to lock the two systems. (think: DLI in the 6502 executed by the 65816, in sync)

This scenario is not possible in our implementation. Veronica's CPU does not have access to hardware registers in the main processors address space. Veronica is not an "on-board" Turbo accelerator for the main CPU. It can be considered as a slave co-processor, that can be controlled by 6502.

Link to comment
Share on other sites

I was thinking more along the lines of syncing to the 02 clock that is on the cartridge interface. Using a $D5xx control address, you could start the 65816 at the same point in the video frame consistently and do video things in step with ANTIC and the CPU.

 

Bob

 

 

 

 

If you sync the clocks, you can allocate one cycle to the 6502 in every frame, allowing you to lock the two systems. (think: DLI in the 6502 executed by the 65816, in sync)

This scenario is not possible in our implementation. Veronica's CPU does not have access to hardware registers in the main processors address space. Veronica is not an "on-board" Turbo accelerator for the main CPU. It can be considered as a slave co-processor, that can be controlled by 6502.

Link to comment
Share on other sites

  • 3 weeks later...
  • 3 weeks later...
With this type accelerator, would the PBI/ECI still function to allow existing hard drives?

 

Veronica uses single memory location from the $D5xx page for its hardware register ($D5c0). The list of utilized signals is as follows: S4, S5, RD4, RD5, F/2, R/W, CCTL, D0-D7, A0-A12.

 

How about current expanded memory (not linear)?

 

The extension does not interfere with PORTB memory expansions whatsoever.

Link to comment
Share on other sites

  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...