• 0
PTSmith

PmodSD on CMOD A7

Question

Hello,

I'm looking into storing data from an ADC system read through an FPGA to an SD card at 3.5 Mbps.  I'd prefer not to use a processor.  It looks like I could plug the PmodSD into a CMOD A7 (for example).  I've found some discussions of directly writing to an SD card on the Digilent Forum, and some links to VHDL to do this; I especially like this code:

https://github.com/xesscorp/VHDL_Lib/blob/master/SDCard.vhd?_ga=2.101734593.1593613684.1574706372-1261715882.1574452484

In this discussion:

D@n says he has been able to write to an SD card at 8 Mbps, so that would be fast enough for me.  However, in this discussion:

BenBog says he can't write faster than 1 Mbps.  Is this because he is going through a linux driver from the MicroBlaze?

Once the write gets going, the SPI clock used by the SD card is 25 MHz, so I'm wondering what limits the achievable write speed to much less than 25 Mbps?  Is it because the write is limited to 512 byte blocks and then you have to set up a new write sequence?

If one writes to an SD card directly with vhdl through SPI you obviously don't generate a file system; I presume if you use a formatted SD card the file formatting gets overwritten.  This would be fine, but I'm wondering how/if one can then read this SD card on a computer?  Presumably when you plug in such a card the OS will see that the card isn't formatted and won't know what to do with it.  Is there some way to still get the data off the card?

thanks in advance,

Paul Smith

Indiana University Physics

 

Share this post


Link to post
Share on other sites

12 answers to this question

Recommended Posts

  • 0

@PTSmith,

Can you still get the data off of an SD card that doesn't have a file system on it?  Absolutely!  On a linux system, you would open its respective /dev file, such as /dev/sdh or some such.  You can see what it is when it tries to mount and fails--it'll stuff a message in the logs telling you what device name was assigned to the SD Card.  The "dd" command can then be used directly if you want, or you can use your own program to read from the SD Card.

As for card speed, when I did my SD card work earlier this month, the speed of the SD card wasn't limited by my processor (ZipCPU--so I doubt it would be limited by a MicroBlaze), but rather by the SD card itself not being ready for subsequent writes.  In other words, it's not the protocol that limits the speed, rather it's the card itself that will be the speed limit.

Dan

Share this post


Link to post
Share on other sites
  • 0

Great, thanks for the quick and very informative reply, D@n!  If I can write directly from VHDL without a microBlaze or other processor it will save me a lot of design effort.

I started reading this spec:

http://academy.cba.mit.edu/classes/networking_communications/SD/SD.pdf?_ga=2.9720497.507573557.1574713618-1111739473.1574713618

I wonder if you know of any more recent version of the SD card spec?  I suppose the SPI mode hasn't changed for quite a while.

Anyway, in 7.2.4 there is a description of writing in SPI mode.  So, after you send the block of data, you wait for the card to go NOT BUSY; this is the speed limit I think. I can just buffer my data in block RAM while the card is busy as long as I can get an overall rate of ~3.5 Mbps to the card.

I see you can buy SD cards with different speeds.

Were you using 1-bit or 4-bit communication with the SD card?  Is there any reason the PmodSD can't use a microSD card with an adapter?

One more question; do all SD cards support SPI mode?  It sort of looks like this is required.

Share this post


Link to post
Share on other sites
  • 0

@PTSmith,

Let's see ... I was using this project, and only quite recently I might add.  The most recent/working version is in the dev tree.  I wrote about my recent experiences here.  Your spec is newer than the one I used.  I was using the 1-bit (SPI) mode.  You should be able to use the PmodSD with a microSD card with an adaptor--I've done that myself, although not for this most recent project.  As for whether or not all SD cards support SPI mode, I don't know, but my guess is that it's a high percentage of them.  I was successful using SPI mode with both a Lexar card as well as a SanDisk card.

Dan

Share this post


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

@PTSmith,

 I wrote about my recent experiences here.  Your spec is newer than the one I used.  I was using the 1-bit (SPI) mode. 

Dan

Fun and interesting read; I especially liked your term "jenga design". 😉

Here is an even newer version of the spec:  https://www.sdcard.org/downloads/pls/

Neither include the SPI timing diagram; have you seen it anywhere?  Probably not necessary...

I presume your 8 Mbits/sec write to SD is averaged over some long time...

Share this post


Link to post
Share on other sites
  • 0

@PTSmith,

The "Jenga design" was torn up and rewritten--that's why I was pointing you to the dev branch earliier.

If you'd like to see a timing diagram, feel free to install SymbiYosys together with the boolector engine, and run "make" in the bench/formal directory.  This will generate a series of VCD files under bench/formal/*_cvr/engine_0/trace*.vcd (IIRC) which should illustrate most of what you need to know.  There will be a directory for sending data to the card (bench/formal/spitxdata_cvr/engine*/trace*vcd), another one for receiving data (spirxdata_cvr/...) etc.  It should help you out.

Dan

Share this post


Link to post
Share on other sites
  • 0

@PTSmith,

Almost forgot, a "make" in the main directory (assuming you also have Verilator installed, in addition to symbiyosys and boolector) will generate a file in bench/cpp/trace.vcd showing a trace of 1) how to bring the card up from scratch, 2) read the card specific registers, and then 3) read data from the card, 4) write data to the card, 5) verify the data written to the card, 6) rewrite the original data, 7) verify that the data was rewritten properly.

Dan

Share this post


Link to post
Share on other sites
  • 0

So, I had to work on other stuff for the last few months, but have gotten back to this.

Found a controller I liked even better at:

https://github.com/ibm2030/SimpleSDHC

Was able to write a single block of 512 bytes to an SD card and view it on a Mac with:

dd if=/dev/disk3 | hexdump | more

It took 184 uS to transfer the data, or 2.8 Mbytes/sec.  The card stayed busy for 5.3 mS, so write speed is 96.6 kbytes/sec.  Seems plausible.

However, not fast enough for my application; I'd like to get 1Mbyte/sec write speed if possible which would give me a comfortable margin.

I want to try a multiple block write next which hopefully will be faster.  I suppose the more blocks the faster.

But, it's not at all clear to me what is the maximum number of blocks the card will accept.

Also, it's not obvious what the erase_count input does or whether I need to use it.  I guess I can figure it out, but wouldn't mind a hint.

Share this post


Link to post
Share on other sites
  • 0

So, multiple block write seems inherently faster: two blocks took 3.5 ms (faster than one block!).  Maybe because of the erasing?

4 blocks took 3.9 ms; 525 kBytes per second.

Share this post


Link to post
Share on other sites
  • 0

If I write 16 blocks it takes 6.44 ms, or 1.27 Mbytes/sec.

If I write 32 blocks it takes 9.24 ms, or 1.77 Mbytes/sec.

If I write 256 blocks, it takes ~50 ms, or 2.6 Mbytes/sec.

One surprising thing is the value of erase_count doesn't seem to make any difference; for example changing from 1 to 32 when writing 32 blocks it still takes 9.24 ms; at least thats how long the sd_busy signal stays on.

I haven't been able to write some number of blocks, terminate the write, wait for sd_busy to drop, then initiate another write of the same number of blocks; SimpleSDHC just stays always busy and stops acknowledging write data after the first block in the second group of blocks; sometimes with error 3, but usually no error.

I guess what I have is good enough for what I want to do; I can just start a multi-block write and stream data to the SD card a block at a time.  But I worry that I don't really understand why erase_count doesn't matter, nor why I can't stop and then start up writing again.

Share this post


Link to post
Share on other sites
  • 0

I modified my VHDL so that I can initiate a write of 256 blocks by pushing a button on the CMOD A7; it works as fast as I can push the button, so I guess my loop just tries again too soon; evidently the sd_busy being low doesn't really mean the card is ready for a new multi-block write.  One new discovery; on maybe one out of 50 tries the write of 256 blocks takes longer than 50 ms; I've seen 63 and 76 ms.  Still fast enough, but yet another thing I don't understand about SD cards.

Share this post


Link to post
Share on other sites
  • 0

@PTSmith,

This matches my own experience.  Just don't ask me to explain it to you, 'cause I'm not sure I understand what's really going on either.

Dan

Share this post


Link to post
Share on other sites
  • 0

Modified test vhdl so I can start and stop writing with the two buttons on the CMOD A7.  Wrote over 1 Gbyte with no problems.  Wrote continuously for 100 sec and counted 554,508 blocks or almost 2.84 Mbytes/sec.

So, almost 3X faster than what I need.🤣 Time to move on to design of the PCB.

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