Thursday, 17 July 2014

More work on new CPU, and some very skinny raster stripes

It still isn't very exciting to look at right now, but the CPU is getting closer to working properly.

I have found and fixed abut in the TRB (Test Reset Bit) instruction. This is a handy little instruction for clearing bits in byte.  For example, LDA #$01 / TRB $D030 will clear bit 0 in $D030, which on a C65 will bank out the second kilo-byte of colour RAM from $DC00 - $DFFF so that you can see the CIAs again.  The correct calculation for the result is (memory and (not A)), but I had (memory and A), which has the effect of reseting all of the bits except the one(s) you wanted reset.  Needless to say that wasn't working too well.

I also fixed some bugs with IO mapping.  In particular, the SD card controller is visible to the CPU again, and Kickstart even gets as far as loading the master boot record from the SD card.  There does seem to be an out-by-one error with the buffer addresses, such that the whole sector is rotated by one.

Here is Kickstart finding the SD card at 48MHz:


That looked a bit boring, so I wrote a little loop to do some raster effects:

This is the little loop:

loop     LDA $D052   ; VIC-IV physical raster line low bits (range 0 -  1199)
         CMP $D052
         BEQ *-3
         INC $D020
         DEC $D020
         JMP loop

  The loop should increment and decrement $D020 just once at the start of each raster line. However it looks like the compare instructions are using a fixed value, instead of the operand, which is why there are a few rasters on which there are no bars, while the rest fail to properly compare the raster number with itself.

This is due to a bug in the compare instructions, which I have yet to get to the bottom of. My gut feeling is that it is some sort of timing bug, where the wrong value is read from the bus.  I have seen it in simulation once or twice, which suggests that I should be able to analyse it fairly easily to find and fix the cause.

Meanwhile, it is interesting to look at the pattern and how narrow the stripes are.  They are actually almost half the width that they seem at first when you look closer, because of the adjacency of the bars on successive raster. The following image makes this a bit clearer:



The VIC-IV runs at 4x the CPU clock, so every four physical pixels corresponds to once CPU clock tick.  The logical pixels of the character generator are five logical pixels wide here, so one and a quarter CPU clocks wide.

INC and DEC take seven cycles on my CPU at the moment, due to the need to include wait-states to avoid back-to-back memory accesses at 48MHz.  This should equate to 7x4 = 28 pixels, or about five and a half logical pixels, just over half a character wide, which is pretty much what we are seeing.

On a real C64 the same bars would be almost 10x wider, at six characters or 48 pixels wide.  So even allowing for the massively higher pixel clock on the C65GS (192MHz versus 8MHz on the C64), there is certainly scope to do some pretty interesting tricks.  Vertical raster bars and split screens should both be quite possible, although there are probably easier ways to get the same effects.


Wednesday, 16 July 2014

New CPU is working (sort of)

It's taken much longer than I would have liked, but I have the redesigned CPU mostly working now.

The CPU is running at 48MHz, and should be about 40x C64 speed, although the exact figure is likely to change.

The reason it isn't 48x is that I have had to put some wait-states in a few places to make the timing work.

Reading from anything other than fast RAM incurs one extra cycle, which means reading from IO currently has a two cycle penalty.  Fastram, as the name suggests, has no wait states.  Writing to IO also has no wait states.

Also, anywhere where the CPU makes a memory access for which the address or data is dependent on whatever has just been read from memory, this has had to be split into two cycles.  This mostly affects the Read-Modify-Write (RMW) class of instructions, like INC, DEC, ASL and ROR.  This basically means that we have a dummy cycle similar to what the real 6502 has.

Unfortunately, it isn't very practical to perform the dummy write that the 6502 does, so I will need to add an extra cycle for $D019 so that DEC $D019 and variations work for clearing interrupts.

I have some ideas for caching the top of the stack so that RTS can execute in a single cycle, which will provide a solid boost for many programs, but that's some way down the track, because I need to get the CPU working properly first.

The screen shot from simulation below shows that it can run the kickstart ROM and get as far as trying to find the SD card:


The astute observer will notice that the top line of the display is showing the wrong contents.  This is because the bad-line for that row of characters had already occurred.  If I leave the simulation long enough that it can draw a 2nd frame, then it should show the kickstart banner.  As it happens, the simulation managed to draw another frame while I was writing the this post, so you can see the real version below:


I need to shake down the remaining bugs like this in the VIC-IV that have crept in with the substantial rework that it has suffered while I have been doing the CPU.  Both efforts, CPU and VIC-IV rework, are really targeted at making the whole thing use much less of the FPGA so that I have enough space to implement sprites and the other missing functionality.

In any case, the fact that it can set the video mode, clear the screen, and decide that it is looking for the SD card shows that an awful lot of the CPU is actually working.  There are some bugs, however.

First, I haven't finished implementing BRK or interrupts of any sort.

Second, I haven't finished implementing the PHW (push word, either immediate or absolute) instruction.  It won't be hard, but it just hasn't hit the priority queue yet, and it is a little weird, since in the CPU the two addressing modes will likely have very different implementations.

Third, there are some weird bugs with accessing IO.

The SD card controller and other IO functions provided by that module aren't mapping in the address space properly when run on the FPGA, even though they simulate fine.

Also, running the following little routine to draw a rough vertical raster bar locks up as soon as the accumulator has the value $F0.  Once that happens, the Z flag stays perpetually set, and so nothing more gets drawn.

loop    LDA $D012
        CMP $D012
        BEQ *-3
        INC $D020
        INC $D020
        JMP loop

It works fine, however, if I put a NOP between the CMP and the BEQ.  So there is something timing dependant going on.  What is weird is that without the NOP the bug manifests, even if the CPU is in single-stepping mode.

This reworking of the VIC and CPU at the same time hasn't been the most fun, because it has gone backwards from working to a seething mess.  But it is now finally starting to draw back together, and should hopefully soon catch up with where the old excessively large design got to.  Then comes the fun part of adding sprites and other goodies, but that will still be a little while off.

Wednesday, 9 July 2014

Improving simulation of the C65GS to help with debugging

I am continuing to slog through reimplementing much of the CPU and VIC-IV to reduce the size, and hopefully improve the CPU speed.

One of the great pains with VHDL is the time it takes to synthesise (that's VHDL/FPGA speak for "compile") a design.  In the case of the C65GS it varies between 10 minutes and an hour.

Even then, when you spot something wrong, it can be quite hard to work out what it is so that you can start fixing it.

This is why there are simulation tools that let you run VHDL code, albeit really slowly.

However, it isn't quite that simple in practice, especially if you are using the open-source GHDL VHDL simulation tool.

A lot of the problem comes from the Xilinx core generator that is the recommended way to create large memories and other useful stuff in an FPGA design.  Those cores are specified in a very hardware-specific manner.  They do include simulatable versions, but none of them run in GHDL.

A while back I had already started making my own simple memory modules in VHDL.  The only ones that were too tricky to get right so that the Xilinx tools knew what I meant was true dual-port memory where two different things can read and write at the same time.  This meant that I couldn't simulate chipram, which really scuttled any sensible simulation.

However now I have changed the design so that chipram is only ever written to by the CPU.  Reads from chipram are serviced from a separate shadow ram.  This means that chipram is fastram on the C65GS, but more importantly, it removed the barrier to simulation.

So over the last week or so I have been hacking away at improving the simulability of the C65GS, with the direct intention of tracking down bugs much more quickly.  In particular, I have been wanting to get the character generator working again after recently redesigning it to work off a single 8-bit data bus, in preparation for implementing sprites.

It is easy to get VHDL to output text messages at various points, but that can be extremely tedious to wade through as you try to work out if the character generator is fetching one too many or too few bytes during a bad line, or fetching the data from one byte to the left or the right of where it should be.

To make this part easier I wrote a little program that reads the output of the VHDL for me, and then generates a BMP file with all the rendered pixels.  Then I can just look at the static image, see what is wrong, fix it, and repeat the cycle -- in a process that takes just a minute or two, provided you only need to look at the top few rasters of the frame, which is usually enough.

With this in place, I have been able to make much more rapid progress, and already have the character generator mostly working again, as the partially rendered frame below shows.  Excuse the bizarre colours and choice of data.  The main thing is I can see 40 columns being drawn without any significant glitches, and both colour RAM and screen RAM are being addressed correctly:


The purple is the right border, and the text area is currently placed hard-left in the frame, with the left border turned off.  The funny brown stripe is because the right border is still in its normal place, so the space that should have been taken by the left border instead shows up as background colour ($D021).

Now I am just tracking down some simulation bugs that cause the simulation to die before it can draw a complete frame.  Once that is working, I probably have enough of the character generator working again that I can turn my attention back to finishing the re-implementation of the CPU.

Thursday, 3 July 2014

Stunt Car Racer at 29x Speed

When I still owned my C65 I made a YouTube video of it running Stunt Car Racer to show how much faster the C65 is than a stock C64.  You can see it below:




Since the C65GS is now able to run some software, I thought I would try Stunt Car Racer out on it.

In the still image below we can see that it is working fairly well.  The vertical graphics glitches are a known problem with bitmap mode on the C65GS, and I will fix them in due course.


But the real question was how fast it would run.  I knew it ought to run quite fast, and that it lacks any vertical blank interlock, so it would run as fast as it possibly could.

Here is a few seconds of Stunt Car Racer running at Ludicrous Speed.  It goes without saying that it was entirely unplayable at this speed.



It looks like the CPU redesign I am doing should end up at 48MHz and somewhere between 30x and 50x C64 speed.  I'll have to post an update when I get to that point.

Tuesday, 1 July 2014

A frustrating fortnight of work reimplementing the CPU

I realised recently that I needed to reimplement the CPU so that it wasn't taking 70% - 80% of what is really a very large FPGA, so that I could fit the extra bits and pieces in that I have been planning.

Ideally, I would include a 1541 and a complete C64 in the FPGA for compatibility.  This would help to free me from having to make the C65/C65GS mode too compatible with the C64, instead, I would just transfer control of a running program from one to the other when cycle-exact operation or illegal opcodes were needed.

But in the shorter term, I wanted to be able to put a couple of SIDs in, and perhaps also improve the synthesis time a bit.

So I set about redoing the CPU, and the process has been one frustration after another.

My gut feeling was, and remains that 96MHz should be fairly possible on this FPGA, although the complexity of the memory system of a C65 makes that more difficult than it first seems.

I was keeping a careful eye on the maximum clock speed in the synthesis reports, and realised that for the time being at least, 64MHz would be easier. I could then optimise my way back up.

After bashing my head against a lot of bugs and silly design decisions on my part, I started making some progress and got some instructions running.

But then testing LDA/LDX/LDY/LDZ I found that the value loaded into the register was often wrong, or from the previous instruction.

After a lot of poking around, I finally realised that ISE was not constraining the cpu clock in the design, and the late data was being used because the design had a real maximum clock speed of only about 28MHz, but was being run at 64MHz.

I was a bit cranky with ISE for not realising that a clock created by dividing another clock is in fact a clock.

I eventually a way to constrain the clock, discovered how horrible the timing situation was, and have been trying to fix it since.

At this stage it looks like 64MHz should be possible, although with some the odd drive stage when executing instructions to get values or addresses ready to read or write in the following cycle.  Exactly how much impact this will make is hard to estimate at this stage, but the CPU might be in drive states perhaps 20% - 25% of the time.

That means that the speed up compared with a stock C64 might end up around 64MHz * 0.75 / 1MHz = 48x.  The result will be helped a little by the fact that many of the single byte instructions will execute in a single cycle. But it is really too early to say whether I will be able to make the CPU work at 64MHz, and exactly what the speed comparison will be.  It will all depend on whether I can make actual forwards progress or whether I stay bogged down chasing my tail some more.

Sunday, 22 June 2014

Did I mention that FPGA development is frustrating?

Now that the C65GS is getting to a more usable point, I thought it would be nice to burn the latest working FPGA image into the flash ROM on the Nexys4 board that is supplied for exactly that purpose.

I have tried a variety of things all afternoon to no avail.

It turns out I am not the only one having this problem:

http://www.mikrocontroller.net/topic/327257#3698806

Unfortunately no solution posted there.

Then I stumbled across this little gem of a forum post:

http://forums.xilinx.com/xlnx/board/crawl_message?board.id=NewUser&message.id=6124

Quoting from the poster:

"Here is what I am told in a tech support email from Digilent: 1. Nexys4 cannot be programmed with current version of Vivado. We hope problems will be resolved in the next version. Read more on http://www.xilinx.com/support/answers/57385.htm 2. Adept is not able to program Nexys4. And it won’t be. 3. Use iMPACT for programming. They couldn't be bothered to put this very relevant information into their user manual."

Yay.  This would have been really handy to know.  
To add to the intrigue and frustration, the URL they point to redirects somewhere useless now, so the answer isn't even directly accessible.

Digilent have updated the user guide for the Nexys4 since I got my board, but there is no collated errata section for me to work out what has changed, and reading every word to compare two 28 page documents isn't that thrilling a prospect.

The updated reference guide is here.

Now that I know what I am looking for, I can see that they have updated the relevant text on page 5 - 6 to now read:

"Quad-SPI programming can be done using the iMPACT tool included with ISE or the labtools version of Vivado."

This suggests that the latest version of Vivado should be okay, although I am at a loss to know what "labtools version" means.  I hope this doesn't mean it isn't in the free version.  Downloading Vivado isn't for the light hearted, however, as it is several GB just to download.  I will need to enlarge my Linux VM to even try.  Maybe I will just form my Linux VM off and reinstall.

Anyway, it suggests that I should be able to program the thing using iMPACT in ISE.  This would be great except that I run iMPACT from in a VM on my mac, and so it can't see the USB programming cable.  Some sort of dual-boot would be the other option here.  I do have ISE on an older Windows machine here, but haven't succeeded in getting that to program the thing either.

Anyway, currently frustrated with the process, but will keep prodding my way around to find a solution.

End of necessary venting of frustration.


Saturday, 21 June 2014

Another speed bump. Now close to 30x C64 speed

This evening I had a few minutes to implement the next IPC improvement I had in mind.  This one is just implementing the simple end of instruction pipeline for instructions where it is possible, the same as I have already done for single byte instructions, and the same as what the real 6502 has always done.

The result is a nice little speed up as the pictures show.



This is among the last of the speed ups that I will do before a substantial reimplementation of the CPU to make it table driven.  Using a table reduces the FPGA logic consumption a lot, and also has the potential to allow the CPU speed to be increased quite a bit, hopefully to 64MHz or even 96MHz all going well.  But it is really the logic reduction that matters, so that I have space to implement the missing features in the C65GS.