Friday 20 March 2015

Getting closer on the DDR memory front

The DDR2 memory interface continues to amaze me in the fascinating ways that it almost works.

Today, I had the thought to make the CPU wait until the DDR controller can confirm that it has the correct address and data to write, which is tested by reflecting back to the CPU so that it can indeed verify that the DDR controller has the right data.  Only after this round-trip verification does the CPU ask the DDR controller to do the write.

This has confirmed that the DDR controller appears to receive the correct data when asked to write.

This had me a bit perplexed, because when I tried to write a single byte, nothing would show up.

Then I wrote a few consecutive bytes, and noticed that all but the last three writes occurred.  A little more poking around revealed that these last three writes were not actually lost, but each write would appear in the read data after another write was performed.  That is, the DDR RAM appears to always be three memory writes behind where it should.  The following serial monitor shows this, where the various writes appear progressively as more writes are scheduled:

Here I ask for five writes to occur:

m8000000
 :8000000 01 02 03 04 05 06 07 08 09 0A 0B 0C 22 22 B1 FA
.s8000000 11 22 33 44 55

Using the new debug registers I created to verify the last write address and value, I can see that $400000B = $55, the last value I asked to be written, and the LSB-first address in the slowram is $0000004, which is correct:

.m4000000
 :4000000 3F 35 01 00 00 5E 51 00 0D 00 2F 55 04 00 00 00

Now comes the surprise, the last three values written don't appear:

.m8000000
 :8000000 11 22 03 04 05 06 07 08 09 0A 0B 0C 22 22 B1 FA

... so let's write $FF to $800000F and see what happens, and also make sure that it is $FF that gets written:

.s800000f ff
.m4000000
 :4000000 3F 35 01 00 00 60 61 00 0E 00 30 FF 0F 00 00 00

So we see that $33 has appeared in $8000002, but $FF has not (yet) appeared in $800000F!

.m8000000
 :8000000 11 22 33 04 05 06 07 08 09 0A 0B 0C 22 22 B1 FA

So let's continue this pattern, and see that as I write bytes, previous writes progressively appear, but always 3 writes behind:

.s800000e ee
.m4000000
 :4000000 3F 35 01 00 00 62 71 00 0F 00 31 EE 0E 00 00 00
.m8000000
 :8000000 11 22 33 44 05 06 07 08 09 0A 0B 0C 22 22 B1 FA
.s800000d dd
.m8000000
 :8000000 11 22 33 44 55 06 07 08 09 0A 0B 0C 22 22 B1 FA
.s800000c cc
.m8000000
 :8000000 11 22 33 44 55 06 07 08 09 0A 0B 0C 22 22 B1 FF
.s800000b bb
.m8000000
 :8000000 11 22 33 44 55 06 07 08 09 0A 0B 0C 22 22 EE FF

At this point I wondered if it was a cache issue, so I asked to see a line of memory that would cause the cache for $800000x to be invalidated:

.m8010000 
 :8010000 45 00 81 67 30 00 86 94 41 72 C0 00 81 38 62 12
.m8000000
 :8000000 11 22 33 44 55 06 07 08 09 0A 0B 0C 22 22 EE FF

No change, so it seems that the cache probably isn't involved.  But again, if I start writing to memory, I see the previously dispatched writes suddenly show up:

.s800000a aa

.m8000000

 :8000000 11 22 33 44 55 06 07 08 09 0A 0B 0C 22 DD EE FF

So while this is all rather annoying and mysterious, it is nice to see that memory is being written in the right places, and that it does all eventually turn up.  But then as a test I filled the first 1MB of slow ram...

The first time I tried it, it seemed to fill memory with $00, as I asked, and there were no odd values.

But then when I tried again to fill with $FF, I say about half of the bytes still had $00 in them.

Filling a 3rd time with $00 again, some of those $FF's remained.  Then when I tested performing single writes, the DDR memory was only one write behind, instead of three.

So there is still some other strange thing going on apart from delayed writes.

What might work, as detlef suggested I try a few days ago is to just have the CPU read the memory location just written after writing, and if the correct value isn't there, to issue the memory write again.  Really slow and really annoying (because I will have to adjust the CPU state machine), but it might just work.  I'm running out of alternative ideas, however.

No comments:

Post a Comment