• 0
kc5tja

PSRAM chip baked, or am I just high?

Question

Greetings everyone.  I'm Samuel A. Falvo II, creator of the Kestrel-3 home-brew computer project.  I'm currently using the Nexys-2 board as a development platform, since that's a known-working software/hardware configuration for me.  My plan is to migrate to something different/better after I get a working reference model here.

Related to this project, I'm completely ineffectual at getting the PSRAM chip to function.  I was wondering if someone else has created a 16-bit Wishbone(-compatible/-like) interface to the PSRAM chip that I can re-use in my MPLv2-licensed project.  After a month of trying to hack my own, I've come to the conclusion that my PSRAM chip is utterly dead on arrival:

  • When in asynchronous mode, I could never get the chip to respond to memory writes beyond a certain (and seemingly completely unpredictable) point.  But, it could read OK, as evidenced by a stable image of noise on my monitor (video refresh is configured to use external memory).
  • When in synchronous mode, I'm utterly unable to get the PSRAM chip to drive the DQ pins when trying to read from the chip.  As a result, video shows a stable pattern of pixels corresponding to the last 16-bit word written out to memory (since this precharges the DQ lines, the video circuit sees this state and treats it as valid pixel data).  It is completely unknown if it's actually responding to write transactions.

I just don't know, and honestly, I'm getting rather desperate now.  So far as I'm able to tell, I'm well within the timing parameters of asynchronous and (especially) synchronous mode operation.  If there's an existing design I can re-use to sanity-check my design, that would be especially helpful.  Thanks in advance.

Share this post


Link to post
Share on other sites

15 answers to this question

  • 0

There's a board verification design on the Nexys-2 resource page that allows you to test/prove the board, including the cellular RAM, with known code.

Can you tell me if you've tried that test and if it does (or doesn't) work for you?

Dan

Share this post


Link to post
Share on other sites
  • 0

It works with the BIST code, but that's the only place it seems to work.  Under any other circumstances I've attempted to use the PSRAM chip, it has either failed outright to commit writes, OR, has failed to drive the DQ pins on read, as per my bullet list above.  The EPP controller is inscrutible to me, I don't know what it's doing or how it does it.  Moreover, it's bottlenecked with an 8-bit bus; I really need a 16-bit bus.

Per your suggestion on IRC about using an on-chip logic analyzer/scope thing, I attempted to write one that would work for my hardware, but it ends up crashing ISim when I attempt to simulate it.

I'm --><-- this close to just throwing in the towel on the project, after having spent years working on it.  I'm about ready to tell people, "You get 48KB of block RAM, and that's that.  Have fun."  No more 16MB, not even 256KB.  I'm just so very, very, very frustrated right now.

 

Share this post


Link to post
Share on other sites
  • 0

@kc5tja,

Looking over your code this morning, I notice nowhere where you register the outputs into flip-flops before actually sending them to I/O ports, not even in your top level file.  As a result, you may find the I/O pins still switching during the between clock intervals when you believe they are constant.  Further, Xilinx recommends using an ODDR module on any clock output path to avoid having logic glitches in the path, such as you might have if you output the result of a combinatorial process as you have chosen to do.  (Having said that, I can't seem to find where I read that recommendation earlier ...)

Dan

Share this post


Link to post
Share on other sites
  • 0

@kc5tja,

One more note regarding the Epp being an 8-bit interface: I built a converter some time ago to convert from the DEPP 8-bit interface to a 32-bit interface.  You can find that converter here.  I'm not using that code anymore, though, since I later moved to a simpler converter that turns the DEPP words into an 8-bit data channel, that can then be used with an 8-bit to 32-bit wishbone bridge that also handles address and data compression.  That's the wbubus.v module you were looking at the other night, though this link has it without the obfuscation.

Dan

Share this post


Link to post
Share on other sites
  • 0
2 hours ago, D@n said:

@kc5tja,

Looking over your code this morning, I notice nowhere where you register the outputs into flip-flops before actually sending them to I/O ports, not even in your top level file.  As a result, you may find the I/O pins still switching during the between clock intervals when you believe they are constant.  Further, Xilinx recommends using an ODDR module on any clock output path to avoid having logic glitches in the path, such as you might have if you output the result of a combinatorial process as you have chosen to do.  (Having said that, I can't seem to find where I read that recommendation earlier ...)

Dan

Adding registers to the address and/or data output buses (the only signals w/out registers) introduces a clock of latency.  This means now I'd need _seven_ clocks per individual hit to RAM, and it would rule support for 16-color 640x480 displays impossible.  Like I said on IRC: accesses to memory must consume no more than six clocks.  That is a hard limit.

Also, does a Spartan 3 series FPGA even have ODDRs?  I don't recall reading about them in the Spartan 3 family documentation.  Maybe I missed them.

Edited by kc5tja

Share this post


Link to post
Share on other sites
  • 0

@kc5tja,

May I suggest that you get it working first, before trying to get it working better?

Dan

Share this post


Link to post
Share on other sites
  • 0

Two definitions of "it works" are, (1) I can use external RAM for a video frame buffer, and (2) the CPU runs no slower than 2 MIPS.

So far, the lack of this chip's ability to adhere to published documentation on its timing parameters forced me to degrade this project's features twice already, and leaves me to believe that the Nexys-2 is simply inappropriate for what I'm trying to do.  I'm not willing to do it a third time.  I'm evaluating now if my time would be better spent just porting the project to use another FPGA board equipped with real static RAM.

Share this post


Link to post
Share on other sites
  • 0

@kc5tja,

Well ... I suppose you could just try the ODDR buffer with the clock and see if that's enough to get it to work ...

Dan

Share this post


Link to post
Share on other sites
  • 0

Found an old project written by a colleague that should help out:

https://www.dropbox.com/s/rfth9tixtgp5di1/MemCtlForCellularRAM_orig.zip?dl=0

That project contains a very reusable HDL block for reading a framebuffer out of the PSRAM to VGA using synchronous mode and multiplexes in async writes. A rough draft of documentation for it can be found here:

https://www.dropbox.com/s/2xjpq68z5kqcovr/MemCtlForCellularRam.docx?dl=0

The top module example included in the zip above is a Nexys2 project that uses the sub component to stream in a test pattern (whenever SW0 is high) and constantly read out the PSRAM contents to the VGA. I found this project in an old archive on my computer, but unfortunately I am not in the office so I can't test it. I do recall it working though... 

 

 

Share this post


Link to post
Share on other sites
  • 0

@sbobrowiczThanks; looking over the VHDL, what I can make of it at least, it's doing what my own state machines are doing.  Unfortunately, I was unable to synthesize the project for my Nexys-2 due to errors involving collisions on IOBs.

Share this post


Link to post
Share on other sites
  • 0

I built and tested that project using the 500 chip, which probably explains your error. Try replacing the equivalent 4 lines in your pins.ucf file with these:

#NET "LED_O<4>"      LOC = "E16";     # Bank = 1, Pin name = N.C., Type = N.C.,                             Sch name = LD4? other than s3e500
#NET "LED_O<5>"      LOC = "P16";     # Bank = 1, Pin name = N.C., Type = N.C.,                             Sch name = LD5? other than s3e500
#NET "LED_O<6>"      LOC = "E4";      # Bank = 3, Pin name = N.C., Type = N.C.,                             Sch name = LD6? other than s3e500
#NET "LED_O<7>"      LOC = "P4";      # Bank = 3, Pin name = N.C., Type = N.C.,                             Sch name = LD7? other than s3e500

You will also need to retarget the project for the s3e1200, but I'm assuming you already did that  because it threw an error.

Another thing to double check is that the FIFO IP cores are included in the project as .xco coregen files and not prebuilt .ngc netlists (because they would have been built for the wrong part). If you see them in the project explorer pane as .ngc files, remove them from the project and then add the .xco files (the .xco files are all included in the project directory).

Share this post


Link to post
Share on other sites
  • 0

Thanks!  That did the trick.  The circuit seems pretty flaky, but it does generate video.  If I toggle SW0, the video it produces isn't always aligned with the video edges, but it is stable.

Share this post


Link to post
Share on other sites
  • 0

Glad to hear it!

I'm not sure what is causing the instability, but off the top of my head, I'd guess that the 640x480 pixel clock may not be exactly correct. The project uses a 25MHz clock, but I think it is actually supposed to be 25.175 MHz. You could try messing with the clock generator to get closer to this. 

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