Jump to content
Marek Konopka

Project Veronica

Recommended Posts

The cartridge hosts 65C816S CPU clocked at 5 Mhz and 64 KB of RAM. This is a work in progress. I apologise for poor video quality. It's been designed by Zenon/DIAL. I implemented test programs and provided some consultation.

 

 

dscf1984resizedblurred.jpg

dscf1992resizedblurred.jpg

dscf2000resizedblurred.jpg

dscf2008resized.jpg

Edited by Marek Konopka

Share this post


Link to post
Share on other sites

Cool... I've been wanting a slave processor.

 

How is the 5 MHz achieved? Is there a mod to the host machine, or is some sort of host clock multiplier used?

Share this post


Link to post
Share on other sites
How is the 5 MHz achieved? Is there a mod to the host machine, or is some sort of host clock multiplier used?

The CPU is clocked by its own generator. No modding is necessary. All you have to do is attach the module to the cartridge port and run some dedicated programs for it.

Share this post


Link to post
Share on other sites

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...

Share this post


Link to post
Share on other sites

Cool. How does the communication work? I considered using FIFO memory as a low-cost async command/result queue for another project which required two systems with different clock speed. Also... why stop at 5MHz?

Share this post


Link to post
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

Share this post


Link to post
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.

Share this post


Link to post
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

Share this post


Link to post
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 :)

Share this post


Link to post
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 :)

Share this post


Link to post
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?

Share this post


Link to post
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.

Share this post


Link to post
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.

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

So... where are you folks on this? How is it going?

 

Bob

 

 

 

 

 

I've added another video for comparison, showing the same rotator demo running without acceleration.

 

Share this post


Link to post
Share on other sites

So... where are you folks on this? How is it going?

We're working now on the next, integrated version, based on CPLD programmable devices. It will maintain all the features of the previous version but will be much smaller.

Share this post


Link to post
Share on other sites
Interesting. I didn't notice much difference in the video.

 

The videos differ in animation smoothness, not the speed.

 

What price range are you expecting?

 

Something around 200 PLN (~63 USD) is our early estimation for the integrated version being prepared. 

Share this post


Link to post
Share on other sites

Hi-

With this type accelerator, would the PBI/ECI still function to allow existing hard drives? How about current expanded memory (not linear)?

Nice project! Good luck!

-Larry

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

?does Veronica allow a Black Box pbi or could it

 

You gravedigger. ;)

 

Is this project still active?

Was it ever produced?

Share this post


Link to post
Share on other sites

?does Veronica allow a Black Box pbi or could it

 

You gravedigger. ;)

 

Is this project still active?

Was it ever produced?

 

Good grave digging though.. I'd forgotten all about this, and would still love one if it came to fruition..

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

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...