Retro CPC Dongle – Part 29

How time flies – it’s been a month since I posted. I’ve been waiting for the PCBs ordered from OSH Park to arrive. They were tracked all the way from the US to my local post office, and somehow Australia Post managed to lose them 😦 The helpful people at OSH Park didn’t hesitate, they put through another copy of my board on the next production run at no cost to me. They’re on their way already – thank you, OSH Park! I can’t rate these guys highly enough!

So, let’s start with the obligatory graphic:

Simulating the SDRAM controller, connected to a Z80! (Click for large)

This piece of the project is fairly complex, so I had to put together this document noting key aspects of the controller and refined it as I went through the development and testing. While the state diagram is valid, it’s simplified as there are several more sequential steps inside each state ‘bubble’. Take a look at the code in GitHub, the sdram.v file contains the main code.  Line 62, the parameters show the states.

While the SDRAM controller is fairly generic, the general premise of the RAM interface is that each bank of the RAM will service a different function. Bank 1 will be the CPC banked RAM (base 64K will still be FPGA block ram), while bank 2-4 will service the video buffer and ROMs on a rotating basis. Rotating banks 2-4 through video service will allow the video to be triple buffered, providing the frame perfect emulation needed for split mode video effects. Take a look at page 2 of the ‘design’ document for an explanation of how I think this will work.

Following my new code approach the design worked well, with just minimum tweaks. The finite state machine (FSM) that controls the SDRAM turned out to be fairly simple. There’s a great write up of SDRAM operation on the FPGA4Fun site. The only complexity turns out to be the refresh process. This happens regularly, 4096 times every 64mS in accordance with the data sheet for the ram chip. Unfortunately, this can happen at the most inconvenient times, such as when the CPC requests the next CPU instruction. So, I tested what would happen if the refresh was required just before the CPU issued a request for the next instruction. Here’s the simulation waveform.

Simulation Waveform in GTKWave (click for large)

Between the white and red vertical bars is when the refresh and read operations are happening, which is one half of the CPC 4MHz clock. Pay particular attention to row 2, the state. This is the FSM internal state. Here’s what’s happening:

  1. Around the white line, the FSM decides that a refresh is due (hidden in Refresh{}).
  2. All banks are pre-charged(closed), shown as state PREC+
  3. Refresh is issued, shown as state RFSH
  4. The command is given time to operate (60ns), shown as state NOP
  5. Then the row is opened, shown as state OPEN+
  6. A read issued for the correct column, shown as state READ
  7. Then after 2 clock, 8 data words are returned over the next 8 clocks

The first word is returned on the falling edge of the CPC 4MHz clock. So this means that even if the worst possible timing conditions happen, the data will still be returned in the T1 cycle. It’s not required until the end of the T2 cycle, so there is no need for any wait states that would ruin the timing accuracy of the CPC2.


There is one other timing sequence that could cause an issue, that is when the video module requests an 8-word burst just before the CPC request, and a refresh falls due during that process, which would mean the CPC request would have to wait for both the video burst and the refresh to finish before it can open the row and read the CPC program data. However, this would still complete before the end of T1 and so I don’t expect to need to test this.

If the CPU requests data during a refresh the request is queued. If a further request is placed before the first request is completed, then it’s simply ignored.

Now that I have the low-level SDRAM access sorted, the next step is to tidy up the code then write the caching controller. This controller will provide a number of conduits for the CPC RAM, ROM and Video and provide the appropriate byte interface for the CPC.

I hope my OSH Park boards will have arrived by then!Order from OSH Park

 

Previous Post <====> Next Post

p.s. Grimware.org is dead!!!!! For whatever reason, Grimware is offline and has been for a few weeks. This was an amazing source of information for all things CPC. The author of the site Grim, was a CPC demoscener and I’ve reached out to some of his buddies to try and find out where Grim’s gone, but no response so far. Luckily the Internet Archive has crawled the pages so his legacy lives on, but it’s a sad turn of events.

Advertisements

2 thoughts on “Retro CPC Dongle – Part 29

  1. In the old days e.g. in Apple II DRAM was accessed by CPU and video generator on the opposite phases of the main clock, and video generator was opening next DRAM row on each access, effectively doing refresh for free.

    I’m just curious if it could be possible to use video generation to refresh SDRAM? Like conclude each SDRAM access from video generator with precharge and use LSB video generator counter bits as row number? Or would that be too slow? Just thinking out loud, u know… 🙂 I’d need to do lil’ math.

    Like

    • Hi codepainters, you’re right, using the video circuitry to refresh the DRAM would work in the old asynchronous DRAM. Simply closing a row in async DRAM would initiate a refresh of that row, so the video would have the effect of refreshing the DRAM. This would assume the entire DRAM is scanned for the video output, thereby consuming all memory. Assuming the entire memory is consumed for every frame, then full refresh 1sec/60FPS would be about 17mS, which is well within the requirements for most DRAM.

      Synchronous DRAM works differently, using an instruction table, so it requires a special instruction to refresh the row. Also, modern SDRAM tends to be a very large capacity, so it’s unlikely to consume all of the SDRAM for the video frame, leaving parts of the chip without a refresh. It’s also quite inefficient to refresh after each row access, severely limiting the SDRAM usefulness.

      A useful read is the Z80 reference guide that discusses the built-in DRAM refresh for older async chips as this is a good solution to refresh between memory read/write accesses.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s