6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 8:08 am

All times are UTC




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Sun Jan 10, 2021 3:43 pm 
Offline
User avatar

Joined: Tue Jul 17, 2018 9:58 am
Posts: 107
Location: Long Island, NY
I'd like to share my implementation of a second 6502 processor on a daughterboard for my main project, initialized through dual ported RAM and controlled through memory-mapped RESET, RDY, and NMI.
My own intended purpose for this system is to serve as a sound generator performing direct digital synthesis, which is why it isn't set up for sending interrupts back to the host system.
Partially I chose to use dual-ported RAM over the inverted clock approach because I'm familiar with its usage in my earlier designs, but it's also convenient to be able to run the smaller and simpler system on a faster clock.

The address space is just the dual-port SRAM and the DAC. A programmable counter simultaneously triggers the IRQ handler to compute each audio sample and transfers the previous sample from the buffer latch to the actual DAC.
The host system controls the IRQ rate with 7 bits of an octal latch, while the eighth bit controls the RDY pin.

Setting up and controlling an audio program is relatively straightforward. The coprocessor is halted by setting the RDY bit low. Then the program is copied from ROM into shared RAM, reset is triggered, and the RDY bit is set high.
The IRQ counter also handles holding RST low for enough cycles by triggering a D flip flop. So far it seems that having IRQ go low at the same time as RES going high isn't causing any problems. (Admittedly I hadn't thought about it until writing this description!)
Development workflow is also not very complicated. Audio programs are written in a separate ASM file and .incbin'ed into the main program since they use different address spaces. Zopfli does a pretty good job at compressing the coprocessor binary, to be loaded with zlib6502.

This design could be pretty easily adapted to other kinds of fire-and-forget output interfaces, or with the addition of an IRQ line going back the other way could be used for parallel computation.
It also is quite stable at 14MHz due to its simplicity. I'd designed the host system to run at 3.5MHz because I'm quite lazy, but it seems the timing on this subsystem was a freebie.

I took a video to demo the soundcard with a little tune: https://youtu.be/O8-H_9GJDMc
The audio program here mimic the capabilities of my old discrete logic soundcard, which I replaced because a critical component was discontinued.
Song is "Bad Apple" which, along with an accompanying animation, is popularly used for demos on low-spec/retro systems. I haven't included the animation yet, but that's the motivation for the 2MB cartridge design I made a thread about earlier this week.


Attachments:
EqoQsB7W8AI2hm1.jpg
EqoQsB7W8AI2hm1.jpg [ 504.2 KiB | Viewed 942 times ]
audio_coprocessor.png
audio_coprocessor.png [ 94.55 KiB | Viewed 942 times ]
Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 10, 2021 10:44 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8514
Location: Midwestern USA
Agumander wrote:
I'd like to share my implementation of a second 6502 processor on a daughterboard for my main project...

Implementation note: the SOB input on the 65C02 should be pulled up to Vcc. CMOS inputs should never be floated and in the case of this one, it could randomly affect program logic.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sun Jan 10, 2021 11:27 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
BigDumbDinosaur wrote:
...the SOB input on the 65C02 should be pulled up to Vcc.

Doesn't the bold arrowhead at the end of the line from SOB indicate that it's connected to Vcc? That's the symbol used for Vcc on the Vdd pin wire, and is also on the other side of what I assume is a BE pullup, since it wouldn't make sense to pull BE down.

Or did you mean that it should have a pull-up resistor, rather than being connected directly to Vcc? Isn't it an input-only pin?

(I'd agree that having different meanings for bold vs. non-bold arrowheads might not be the clearest notation.)

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 11, 2021 12:56 am 
Offline
User avatar

Joined: Tue Jul 17, 2018 9:58 am
Posts: 107
Location: Long Island, NY
BigDumbDinosaur wrote:
Implementation note: the SOB input on the 65C02 should be pulled up to Vcc.

cjs wrote:
Doesn't the bold arrowhead at the end of the line from SOB indicate that it's connected to Vcc?


Yes! Sorry for the confusion, the bold arrowhead is indeed Vcc. I followed the advice of the "Mystery Pins" page of the Primer.

cjs wrote:
(I'd agree that having different meanings for bold vs. non-bold arrowheads might not be the clearest notation.)


...and just like that I noticed that the symbol for the board-to-board connector has a bunch of arrowheads on it that are way too similar to the Vcc symbol. Doh!

All the more reason I should make a custom library symbol for the interface connector.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 11, 2021 1:47 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8514
Location: Midwestern USA
cjs wrote:
BigDumbDinosaur wrote:
...the SOB input on the 65C02 should be pulled up to Vcc.

Doesn't the bold arrowhead at the end of the line from SOB indicate that it's connected to Vcc?

Dunno. I'm not into non-standard electrical symbology.

In any case, I never tie input directly to Vcc, Using pull-up resistors opens the door to being able to later put the input to use without having to butcher the PCB.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 11, 2021 2:59 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Agumander wrote:
Yes! Sorry for the confusion, the bold arrowhead is indeed Vcc. I followed the advice of the "Mystery Pins" page of the Primer.

FWIW, NMI and SOB are edge-triggered inputs. If unused, you can pull them either high or low, whichever happens to be more convenient. The inputs won't activate as long as there's no negative transition.

BigDumbDinosaur wrote:
Using pull-up resistors opens the door to being able to later put the input to use without having to butcher the PCB.
Yup! :)

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Sun May 16, 2021 2:32 pm 
Offline
User avatar

Joined: Tue Aug 11, 2020 3:45 am
Posts: 311
Location: A magnetic field
Don't apologize for using dual port RAM rather than time slicing, especially when both techniques may be used concurrently. While the historical supply of dual port RAM has been intermittent, we may be in an era where hobbyist demand is sufficiently large to ensure stable supply.

Ignoring that, I strongly admire a self consistent design. Many designs are elegant and correct but annoying inconsistent. Your design is elegant (minimum components), correct (solves clock domain crossing problem) and consistent (works in a similar manner in multiple contexts). In particular, I see your design being divided into three cases:-

Compute module, no I/O: A partial solution to zero glue logic. One or two processors are wired to dual port RAM and nothing else. Assuming a global reset and no halting opcodes, you do not require any strobes or latches for the control lines. Instead, it is possible to wipe the memory map with opcode $00 BRK. Eventually, execution of any memory location will invoke IRQ/BRK vector. This will set PC $0000 which will exec BRK and keep cycling in an infinite loop. Meanwhile, it is possible to load the required program and data elsewhere. When this is completed, it is possible to place the execution address at $0001-$0002 and then atomically set $0000 to opcode $4C JMP. Two cores require some differentiation but it otherwise amortizes the cost of dual port RAM.

Write only output stream: I've considered various cases of audio (sine/square/triangle/sawtooth, FM, PCM) without success. The best that I could devise was a superset of Commodore 64 and Amiga sound but it requires a horrendous amount of circuitry - even when it is possible to multiplex. You're wilfully conflating program and data across dual port memory to implement Turing complete sound. Within a finite number of clock cycles, it is possible to construct arbitrary sound. That allows you to do everything I devised, with less circuitry - or discard it and run a completely different mode of operation. For example, decompression of speech codec. Execution speed may exceed 25MHz and runs independently of all other modules. Even if a sound module is monophonic, it is fairly trivial to gang synchronous modules to make a stereo system or beyond. Indeed, you may have enough processing power to run a double binary matrix transpose and drive serial DACs for 7.1 surround sound. Alternatively, you may wish to implement your own one bit audio DAC using a variation of a 6502 clock stretching circuit. Separately, you specifically note that write only I/O is compatible with a doorbell address. That's cunning.

General I/O module: Applications include RAID controller or Turing complete packet router. A homogenous architecture means that unused I/O modules may participate in general computation.

If multiple dual port memory banks are connected on a parallel bus, the common side will run slower and/or consume more energy as the number of devices increase. This is due to physical distance and capacitive load. Therefore, it may or may not be useful to make a fractal tree of co-processors. In this case, there would be one up-stream bank of dual port memory and two or more down-stream banks. In the trivial case, no control lines are required. Likewise, no common clock frequency is required.

To amortize cost of dual port memory, it may be more useful to extend one or more soft cores which run at 50MHz or faster while one hard core runs slower and conducts all activity. This would include boot-strap and self test.

See Also


_________________
Modules | Processors | Boards | Boxes | Beep, Beep! I'm a sheep!


Top
 Profile  
Reply with quote  
PostPosted: Sun May 23, 2021 12:29 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Is audio_reg0 an IO port or a select line?

I would make sure the secondary CPU is kept in RESET until released by the host CPU so it doesn't try to run in uninitialized memory.

I have to look up the algorithms again, how do you synchronize the two programs in both CPUs? There is no hardware memory locking, so you have to take care programmatically.

André

P.S. great work!

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


Top
 Profile  
Reply with quote  
PostPosted: Sun May 23, 2021 7:01 pm 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1120
Location: Albuquerque NM USA
IDT71342 is a 4K dual port RAM with 8 semaphores. The semaphore is implemented in hardware to make sure only one side can set the flag much like a software test-and-set instruction. I also have a dual-port based coprocessor, except the coprocessor is Z80 which is held in reset at power up and boot with program in the dual port RAM when commanded by the master processor. https://www.retrobrewcomputers.org/doku ... asmo:dpram


Top
 Profile  
Reply with quote  
PostPosted: Mon May 24, 2021 4:18 am 
Offline
User avatar

Joined: Tue Jul 17, 2018 9:58 am
Posts: 107
Location: Long Island, NY
So far I've largely ignored the IDT71342's semaphores. Audio_regX are all select lines. Given that it can only interact with the 4K of SRAM and the DAC output, I didn't deem it too critical to make sure it starts out in RESET on power-on, but it does indeed get kept in RESET when loading programs. Typically in audio coprograms I designate a few zero page addresses as only being written by the main CPU, and use those to send parameters to the coprocessor. Besides that I can manipulate the READY bit or send an NMI if I really need to "ring the doorbell", so to speak.
Most of the time though I avoid disturbing the program flow so as not to introduce sample rate jitter.


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

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 63 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: