Gau_Veldt

My first Zybo/7010 project

Recommended Posts

Greetings fellow FPGA enthusiasts!

 

I'm looking for eyeballs :P  Specifically digital logic enthusiasts, HDL or otherwise, and maybe even those appreciative of retrocomputing (my first Zybo project is a C64 clone after all).

It is my hope I might find some people interested in this project: https://github.com/gau-veldt/InsideTheBox and perhaps also the associated "Inside the Box" YouTube channel https://www.youtube.com/channel/UCnVbLwPm8Rrd8YP44djBfoQ where I am going to attempt to explain aspects of the project to others attempting to learn.

I'd like to break that feeling that I'm the only one in the world interested in these things (I know I'm not but experience and YT video visitor stats keep trying to tell me otherwise :( ).

 

Edited by Gau_Veldt
added link to YT channel

Share this post


Link to post
Share on other sites
On 12/27/2017 at 11:35 AM, jpeyron said:

Hi @Gau_Veldt,

Interesting project! Welcome to the Forums!

cheers,

Jon

Future projects may include clones of other machines or consoles (Apple II, the infamous NES, TRS-80, Amiga there are lots to choose from) and some other projects such as hardware LSTM (long short term memory, used for AI).  The challenge for some will be memory (meaning I'll have to make a design that speaks AXI and uses the PS's DDR memory) since things like space for the NES game ROM memory or Amiga 500/1000 memory (including OS ROMs).  The really big ones like loading a game ROM also aren't suitable for my python ROM-to-hdl script nor Vivado's RAM initialization file workflows.

Share this post


Link to post
Share on other sites

I used a digilent Spartan 3 Starter Board in my return trip back to college sometime around 2007.  I just got my hands upon a Arty A7-35T and have been thinking about my original Idea for an FPGA, which was a C64 Soft/Hardware System.  Now I see that you and a handful of others (found upon Google) have already done this.  I bought my original C64 system back in 1983 and used it daily till about 1998 when I changed to a PC, influenced by a company sponsored college class In C programming I took in 1995.  Over the years ive collected SPARES some useable and some parts boards.  Several years ago I built a USB to RS232 expansion port cable and Dumped the ROMS to disc files. The KernalROM, CHARROM, and BASICROMs which I have now saved in several locations.  I once had over 200 floppies double sided, tho now all I have is about 250 Cartridge ROMS(also on PC files now).  I was going to do this project in steps. 

LEVEL : Step

1)           Make a Software Emulator - to debug the system and get maximum OP (About 82% completed thou haven't touched it in a while) 

2)           Recreate the system - using VHDL code (like you have done, thou I didn't think the Spartan 3 had enough resources so back burner)

3)           The Final system - the real challenge.. a step I've never seen done before ( Make one cleaver logic system say 90%(logic)                                               10% (sequential code) that encompasses the entire set of 250 cartridges).

Are you up for the final system challenge?  Personally I'm not sure if id ever get to It but Id like to see it done.  Note it could be done many ways and I have a specific Method in mind.  I have in mind a program idea that would do the simplification to Parallel logic modules. 

If you or others are interested respond here, and perhaps we could meet in a chat room to discuss the project in more details.

Regards,

DC

Share this post


Link to post
Share on other sites
2 hours ago, DigitalConfig said:

Hope to hear from you soon!

Just a quick rabble on those three points:

1. Software emulators for C64 are already quite plentiful VICE being among the better ones.

2. I've got majority of the design complete for a running C64.  There are some missing bits I need to still add (the SID volume envelopes, ring and sync mod, VIC sprites and bitmap modes).  I ran into some issues with emulating IEC so there's still no disk/floppy image support.  EOI and ATN overrides were causing me grief.  I took a pause at this point and decided it might be time to get a Raspberry Pi going with a breadboard that speaks SPI over one of the Zybo's PMODs for realtime debugging of signals using the Pi (Vivado fails to compile the debug IP every time I've tried to add it so that's a no go).  It also means the Pi could act as the IEC device and transfer files over to my Z64.  I'll work more with this once I return from my visit with my stepmom in a week or so.

3.Cartridges are pretty basic to get going.  There's a few wrinkles if the cartridges use the EXROM or GAME signals (you need the proper logic present in memory decode signals to honor them) but otherwise cartridges are simple memory images that could be loaded into the BRAM on the 7010 and accessed as ROM.  You can set cartridge data to load when the bitstreams are sent to the FPGA but I find the file format used by Vivado is rather cumbersome for this purpose so I use a python script that instead creates a function with a huge case statement the yield the ROM values (input: A[12:0], output: D[7:0] for an 8K ROM) then it's just a matter of adding these into the source tree as a library and accessing that function from a clocked process block in the main design sources (if rising_edge(someClock) then do_something_with_byte(rom_function(address); end if;) to have it synthesize as a ROM.

On a final note I do have my existing hardware sources up on GitHub so you could investigate those in the meantime.

Share this post


Link to post
Share on other sites

PS: I used that python script to generate compile-in ROM VHDL library includes out of the binary images for the Chargen, Kernal and BASIC ROMs.  I don't put the ROM function sources into the github repo for obvious reasons (cough DMCA takedowns cough) but the Python program to convert a ROM binary dump you already have into a VHDL library source is there.  It would just need to be copied to another pyhton and tweaked slightly to make cartridge ROM sourcefiles.

Share this post


Link to post
Share on other sites
Posted (edited)

PSS: If by software simulator you mean logic simulation for the design sources then that's already available in Vivado at deisgn-level, synth-level or implementation-level simulation contexts.  It's just they are really really slow, especially the synth and implementation sims.  Expect a good few hours just for the second-or-two RAM test the C64 Kernal starts with (that you have to wade through because none of the interesting stuff where you see bugs such as interrupts going wrong in CPU sources will happen until after that test runs and the Kernal turns on interrupts).  Just one VIC video frame is a go-have-a-coffee 2-3 minute sim step.  Oh and I don't duplicate all of the C64's quirks (ie: no badlines in my VIC since the master clock is at 80 MHz  (meaning the RAM/ROM will run at 80 MHz) and my VIC uses 76 out of 80 of those (giving it more than enough cycles to fetch all its needed video data in fact most of it even before the VGA horizontal sync and back porch have passed) and the remaining four give my Z64's 6510 a full unimpeded 1 MHz rate (the four clock cycles given to the CPU allow each of its PH1+,PH1-,PH2+ and PH2- clock stages to happen within a single 1 MHz period).

Edited by Gau_Veldt
elaborated

Share this post


Link to post
Share on other sites

First, Thanks For the speedy reply!

all this talking C64 made me dust off the C64 emulator I was working upon.  Reading the Date Modified saying 2/28/2011!  I guess it was really dusty.  Basically what I had achieved was that it loaded the ROMS and an OP code table (addressing modes and such) and started to execute the ROM Basic Program thru the Kernel.  I segmented the Kernels execution so it bypassed all sound and graphics processing and only did Text IN OUT to a scrollable text box (see attached jpeg below).  It does manage to do text responses like the syntax error message comes completely out of addressed in progress program( just noticed it says 0 bytes Free(thought I had that working))  any way thou if I remember correctly I think the actual bug is in the OP code to BASIC code conversion where I replace op code calls with BASIC Code operations.  some work some do not causing errors to occur.  It been seven years since I even looked at it so I am a bit rusty knowing where I was actually at in the debug process.  What do you think?  Would you want to see the code and give me pointers?  Id like to get the full system working so I can implement it to VHDL, however I want you to know I'm not here to compete with you.  It's only for the self educational purpose and id like to learn from you if possible, and do not intend upon publishing the design unless you contribute and wish it so.

Sincerely,

DC

C64ss.jpg

Share this post


Link to post
Share on other sites

I decided to upload my core file that I wrote which is 99% of the program in case you or others want to take a look.  I know I just said I wouldn't publish the project, but I figured the internet is full of comparable code already and besides there are bugs ( I was slowly eliminating as I went ).  I think the bug was gathered erroneously from data specs I took from manuals, which I either interpreted incorrectly or it was represented in the specs inaccurately.  I had previously put in 2 debugging modes to send output reports to files, thou this method moved ahead very slowly and was like looking for a needle in a haystack.  I just figure if I spend time on it again I might find the bug.  I spent many days on it then got side tracked elsewhere and never came back to it till now.  If you or anybody is familiar with the system could you please take a look and if you see anything that is incorrect in the addressing modes or OP code process, or anything else that looks incorrect would you let me know please.  I'm sure ill eventually find it if I keep looking over it, and I suppose I might correct the error by comparing your contributions to mine, If you don't find it first. 

Thanks In advance!

Sincerely,

DC

6810.txt

Share this post


Link to post
Share on other sites
Posted (edited)

I actually did this project to learn FPGA development. :)  and I have learned a few things that I'll apply to future projects but here's the highlights:

1. Bidirectional buses don't work at all on FPGAs.  Buffers are very limited resources on most FPGA topologies.  This means split the bus and have it separate for input versus output (eg: have dataOut 7:0 and dataIn 7:0 buses for data).  This one's a real pain because pretty much all old school computer logic uses some form of bidirectional bus.  You can interface an external (external here means external hardware only if it's buried in a source file include or IP component somewhere and compiled in it's not external) signal from something like SPI or I2C (by declaring as inout) but not for signals between entities of your own design sources (otherwise you get the synth error about signals with multiple drivers).  I got bit so many times by this gotcha on the C64: the bidirectional CIA I/O's, the 6510 databus and bidirectional I/O port, etc.

2. Asynchronous reset lines are bad news so don't use them.  Synchronous (clocked) resets are fine.  States will be set to design-specified initial values whenever the bitstream is loaded so cold-start reset isn't even really all that necessary (though you do want some way to hold processes back long enough for things like clock tile MMCM's and PLL's to be properly running first).

As for your CPU implementation I already have my suspicions starting with that 0 on the memory free report to a possible search area.  That 0 ties to the floating point logic in the BASIC ROM.  The FP code, in particular, requires BIT, ASL, ROL, ROR and LSR to work properly on all addressing modes (BIT is a frequent flyer for bugged implementations since its actual operation and side effects [from the flag-modifying-only AND] are somewhat exotic [eg: don't forget about bit 7->N and bit 6->V]).  I used a few very useful documents when I did my 6510 design: the instruction explanations available on 6502.org and another site which has a grid of all the opcodes and their addressing modes with the grid rows and columns representing the hex nybbles of the instruction opcode.  I can't give you the links since I'm away visiting my stepmom until near the end of the month and as such don't have the computer with those bookmarks in front of me.  Oh and you'll get a working C64 even if you ignore decimal mode (nothing on the KERNAL or BASIC ROMs use decimal mode whatsoever and the only decimal mode related instruction present in the ROMs is CLD which just ensures it's shut off).  Oh and there's also a complete C64 ROM disassembly kicking around on the web as well.  It's also very useful.

Edited by Gau_Veldt

Share this post


Link to post
Share on other sites
Posted (edited)
On 3/21/2018 at 10:37 AM, Gau_Veldt said:

1. Bidirectional buses don't work at all on FPGAs.

I beg to differ and have a lot of completed projects that prove otherwise. I do suggest that all tri-state capable bus driver logic be kept to the toplevel of your HDL code. For logic down the hierarchy use uni-directional buses.

 

On 3/21/2018 at 10:37 AM, Gau_Veldt said:

Asynchronous reset lines are bad news so don't use them

Again, I beg to differ. Resets are not at all as straight-forward as one might imagine. Regardless as to how complex or simple you believe that your reset logic is the designer has the burden of understanding possible failure conditions and designing to mitigate them. Even very seasoned digital engineers get the analysis wrong.

Though I don't have any C64 experience this appears to be a nifty little project that might grow into something not so little. I know that it isn't the only one.

Edited by zygot

Share this post


Link to post
Share on other sites
5 hours ago, DigitalConfig said:

I cant seem to find the C64 information on boot address when a cartridge is inserted, would you happen to know it?

This is where it helps to have the disassembly of the KERNAL ROMs.  Anyways: from c64-wiki.com: the cartridge ROM will use the GAME or EXROM lines (by pulling low) and the ROM will appear in the C64 address space from $8000.  The start address of code to boot in the cartridge ROM gets stored at $8000,1 and the address of code to run on NMI has its address placed at $8002,3.  Finally the CBM80 magic signature must appear at $8004,8 "CBM80" in PETSCII.  I should point also that the ROM address lines will be relative to the ROM offset, not the C64's bus address (so address at the cartridge ROM's address pins will be $0000 but on C64's address bus it will be $8000) GAME and EXROM tell the C64's banking logic when to activate the cartridge ROM's chip select (CS) input.

Share this post


Link to post
Share on other sites
Posted (edited)

As an aside when I went looking for C64 FPGA snippets or significant parts (VIC, SID, etc) of it I hit a lot of nasty paywalls (and/or licensewalls) hence why I did it myself AND made the sources freely available on GitHub.  Edit: Oh yeah, and lots of abandoned stuff or out of date (and/or whose latest version is behind a paywall/licensewall).

Edited by Gau_Veldt

Share this post


Link to post
Share on other sites
3 hours ago, zygot said:

I beg to differ and have a lot of completed projects that prove otherwise. I do suggest that all tri-state capable bus driver logic be kept to the toplevel of your HDL code. For logic down the hierarchy use uni-directional buses.

Hmm ... perhaps there's a misunderstanding here.  FPGA's cannot handle internal tri-state busses, but have no problems with them on the exterior pins.

3 hours ago, zygot said:

Again, I beg to differ. Resets are not at all as straight-forward as one might imagine. Regardless as to how complex or simple you believe that your reset logic is the designer has the burden of understanding possible failure conditions and designing to mitigate them. Even very seasoned digital engineers get the analysis wrong.

As for asynchronous resets, there is a time and a place for them.  Xilinx's official comment on them is to avoid them if possible.  They explain this with the example of an external pin that due to RF interference or other might accidentally trip the pin, but not hold the asynchronous reset line down long enough to be ... useful and reliable.  As a result of this vulnerability, some of the design might reset, but not other parts.  That said, I have been successful using such resets within a design when crossing clock domains--as long as the reset is asynchronously set and synchronously released.  If you can guarantee the reset will be asserted long enough to be relevant across the design, then you shouldn't have a problem.

I do like your quote, though: "Resets are not at all as straight-forward as one might imagine."  The devil's in the details--one of the reasons why I dislike designs that remove the designer from the details ...

Dan

 

Share this post


Link to post
Share on other sites
On 3/22/2018 at 3:26 AM, DigitalConfig said:

I cant seem to find the C64 information on boot address when a cartridge is inserted, would you happen to know it?

From the C64 kernal disassembly ( https://github.com/mist64/c64rom/blob/master/c64rom_en.txt ):

.,FCE7 20 02 FD JSR $FD02       scan for autostart ROM at $8000
.,FCEA D0 03    BNE $FCEF       if not there continue startup
.,FCEC 6C 00 80 JMP ($8000)     else call ROM start code

.,FD02 A2 05    LDX #$05        five characters to test
.,FD04 BD 0F FD LDA $FD0F,X     get test character
.,FD07 DD 03 80 CMP $8003,X     compare wiith byte in ROM space
.,FD0A D0 03    BNE $FD0F       exit if no match
.,FD0C CA       DEX             decrement index
.,FD0D D0 F5    BNE $FD04       loop if not all done
.,FD0F 60       RTS             
                                *** autostart ROM signature
.:FD10 C3 C2 CD 38 30           'CBM80’

.,FE47 48       PHA             save A
.,FE48 8A       TXA             copy X
.,FE49 48       PHA             save X
.,FE4A 98       TYA             copy Y
.,FE4B 48       PHA             save Y
.,FE4C A9 7F    LDA #$7F        disable all interrupts
.,FE4E 8D 0D DD STA $DD0D       save VIA 2 ICR
.,FE51 AC 0D DD LDY $DD0D       save VIA 2 ICR
.,FE54 30 1C    BMI $FE72       
.,FE56 20 02 FD JSR $FD02       scan for autostart ROM at $8000
.,FE59 D0 03    BNE $FE5E       branch if no autostart ROM
.,FE5B 6C 02 80 JMP ($8002)     else do autostart ROM break entry

So again we have the cartridge ROM being physically mapped into the bus at $8000.  The Kernal then looks for the magic word 'CBM80' (high bit set on C,B,M) at the start of the ROM at $8004-$8008.  At $8000 is the pointer into where to start in the cartridge ROM at reset.  At $8002 is the pointer for where to run in the cartridge upon NMI (RUN/STOP+RESTORE).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now