Close

SATA, DDR3, Verilog Visualizer and Other Stuff

A project log for Nysa: FPGA Development Environment

Hardware and software to simplify FPGA development and interaction.

daveDave 08/02/2015 at 23:241 Comment

SATA Status

After weeks of painful debugging. I have been able to read and write to the hard drive!

I ran into an issue though... the speed at which I can communicate with my FPGA to/from my computer maxes out at about 16MBs and the hard drive reads/writes data at a rate of about 250MBs. There was no way I could stress test the system reading and writing data directly to the hard drive from my host computer!

I needed to verify that the SATA core can absorb and spit out an arbitrary large amount of data without errors...

I started out by creating a temporary pattern generator and validator within the SATA core to write a pattern to the hard drives. Turn around and read that pattern back, verifying that the written data is read back correctly. Some debugging cycles later everything worked!

But the end goal is to create a fast and useful way for users to store/load a large amount data generated or absorbed by their custom cores. It took a while to figure out how to create a test that exemplifies this but I think I got it. I combined the SATA, DDR3 and DMA cores for a test image. The host computer writes a 128MB test pattern (at a snails pace) into the DDR3. The DMA transfer data from the DDR3 to the hard drive and vice versa then the host can read the data out and compare it.

Here is a block diagram of the test

I generated the Nysa image. Here is how the Nysa GUI looks:

SO COOL! I've never had so many slaves on a Nysa image before! Each one of the blue modules above can control an actual core within the FPGA from the host computer. Users can interact with them through a simple Python interface.

Now that I had control of the DDR3 memory, DMA controller and SATA hard drive I devised a test that validates the system, here is what the script does:

  1. Clear the hard drive, the host fills the DDR3 with zeros and writes that data to the SATA hard drive.
  2. Write a test pattern, the host fills the DDR3 with a test pattern, then the DMA writes this pattern into the hard drive.
  3. Clear the DDR3, the host fills the DDR3 with zeros so any data read from hard drive can not be mistaken for old memory data.
  4. Read the contents of the hard drive into DDR3 memory.
  5. Read all the values out of the memory and verify that the values correspond to the original test pattern.

I understand the following is a little cryptic but this is the output. If something went wrong there would have been a lot of unfriendly messages telling me that numbers do not match, or worse the hard drive just hangs:

cospan@loki ~/Projects/nysa/test/hardware $ (master) ./test_dma_sata.py 
Important: Test:setUp: Found a nysa instance: FTYNUFY9
Important: NysaSDBManager:read_sdb: Parsing Top Interconnect Buffer
Info: Test:setUp: Using Platform: artemis_usb2
Info: Test:setUp: Instantiated a SATA Device: /top/peripheral/sata
Info: Test:setUp: Instantiated a DMA Device: /top/peripheral/dma
Info: Test:test_dma_sata: Reseting Hard Drive...
Info: Test:test_dma_sata: Reset Complete
Important: Test:test_dma_sata: Linked up with Hard Drive!
Info: Test:test_dma_sata: 	Initial Status of hard drive (Status): 0x50
Verbose: Test:test_dma_sata: Hard Drive Serial Number: 132481400420        
Verbose: Test:test_dma_sata: Max User Sectors: 33570816
Verbose: Test:test_dma_sata: Max User Size (GB): 17.188258
	SATA Status:                       0x00000050
	SATA Sector Count:                 0x00000001
	SATA Current Address:              0x00000000
Info: Test:test_dma_sata: Setup DMA
Info: Test:test_dma_sata: Transfer Size: 0x00A00000
Verbose: Test:clear_memory: Clearing Memory
Verbose: Test:clear_memory: Memory Size: 0x00000000
Verbose: Test:clear_memory: Memory Size: 0x08000000 is larger than read/write size
Verbose: Test:clear_memory: 	Breaking transaction into 0x00800000 chunks
Verbose: Test:clear_memory: Cleared: 0x00000000 - 0x00800000
Verbose: Test:clear_memory: Cleared: 0x00800000 - 0x01000000
Verbose: Test:clear_memory: Cleared: 0x01000000 - 0x01800000
Verbose: Test:clear_memory: Cleared: 0x01800000 - 0x02000000
Verbose: Test:clear_memory: Cleared: 0x02000000 - 0x02800000
Verbose: Test:clear_memory: Cleared: 0x02800000 - 0x03000000
Verbose: Test:clear_memory: Cleared: 0x03000000 - 0x03800000
Verbose: Test:clear_memory: Cleared: 0x03800000 - 0x04000000
Verbose: Test:clear_memory: Cleared: 0x04000000 - 0x04800000
Verbose: Test:clear_memory: Cleared: 0x04800000 - 0x05000000
Verbose: Test:clear_memory: Cleared: 0x05000000 - 0x05800000
Verbose: Test:clear_memory: Cleared: 0x05800000 - 0x06000000
Verbose: Test:clear_memory: Cleared: 0x06000000 - 0x06800000
Verbose: Test:clear_memory: Cleared: 0x06800000 - 0x07000000
Verbose: Test:clear_memory: Cleared: 0x07000000 - 0x07800000
Verbose: Test:clear_memory: Cleared: 0x07800000 - 0x08000000
Important: Test:test_dma_sata: Fill memory with zeros
Important: Test:test_dma_sata: Configure DMA to transfer 41.943040 MB from DDR3 to Hard Drive
Important: Test:test_dma_sata: Intiate a DMA Transaction
Important: Test:test_dma_sata: DMA Transaction is complete
Info: Test:test_dma_sata: Wait for transaction to finish
Verbose: Test:test_dma_sata: Data from first sector of hard drive (Should be all zeros):
array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Important: Test:test_dma_sata: Fill memory with pattern
Important: Test:test_dma_sata: Configure DMA to transfer 41.943040 MB from DDR3 to Hard Drive
Verbose: Test:fill_memory_with_pattern: Memory Size: 0x08000000 is larger than write size
Verbose: Test:fill_memory_with_pattern: 	Breaking transaction into 0x00800000 chunks
Verbose: Test:fill_memory_with_pattern: Wrote: 0x00000000 - 0x00800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x00800000 - 0x01000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x01000000 - 0x01800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x01800000 - 0x02000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x02000000 - 0x02800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x02800000 - 0x03000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x03000000 - 0x03800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x03800000 - 0x04000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x04000000 - 0x04800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x04800000 - 0x05000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x05000000 - 0x05800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x05800000 - 0x06000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x06000000 - 0x06800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x06800000 - 0x07000000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x07000000 - 0x07800000
Verbose: Test:fill_memory_with_pattern: Wrote: 0x07800000 - 0x08000000
Important: Test:test_dma_sata: Intiate a DMA Transaction
Important: Test:test_dma_sata: DMA Transaction is complete
Info: Test:test_dma_sata: Wait for transaction to finish
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Info: Test:test_dma_sata: Transaction Finished!
	Current SATA DMA Address:          0x00A00000
	SATA Status:                       0x00000050
	SATA Sector Count:                 0x00004000
Verbose: Test:test_dma_sata: Data from first sector of the hard drive (Should be incrementing number patter):
array('B', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127])
Important: Test:test_dma_sata: Clear DDR3 Memory
Verbose: Test:clear_memory: Clearing Memory
Verbose: Test:clear_memory: Memory Size: 0x00000000
Verbose: Test:clear_memory: Memory Size: 0x08000000 is larger than read/write size
Verbose: Test:clear_memory: 	Breaking transaction into 0x00800000 chunks
Verbose: Test:clear_memory: Cleared: 0x00000000 - 0x00800000
Verbose: Test:clear_memory: Cleared: 0x00800000 - 0x01000000
Verbose: Test:clear_memory: Cleared: 0x01000000 - 0x01800000
Verbose: Test:clear_memory: Cleared: 0x01800000 - 0x02000000
Verbose: Test:clear_memory: Cleared: 0x02000000 - 0x02800000
Verbose: Test:clear_memory: Cleared: 0x02800000 - 0x03000000
Verbose: Test:clear_memory: Cleared: 0x03000000 - 0x03800000
Verbose: Test:clear_memory: Cleared: 0x03800000 - 0x04000000
Verbose: Test:clear_memory: Cleared: 0x04000000 - 0x04800000
Verbose: Test:clear_memory: Cleared: 0x04800000 - 0x05000000
Verbose: Test:clear_memory: Cleared: 0x05000000 - 0x05800000
Verbose: Test:clear_memory: Cleared: 0x05800000 - 0x06000000
Verbose: Test:clear_memory: Cleared: 0x06000000 - 0x06800000
Verbose: Test:clear_memory: Cleared: 0x06800000 - 0x07000000
Verbose: Test:clear_memory: Cleared: 0x07000000 - 0x07800000
Verbose: Test:clear_memory: Cleared: 0x07800000 - 0x08000000
Verbose: Test:test_dma_sata: Data read from memory after clear (Should be all zeros):
array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Important: Test:test_dma_sata: Configure DMA to transfer 41.943040 MB from Hard Drive to DDR3
Important: Test:test_dma_sata: Intiate a DMA Transaction
Important: Test:test_dma_sata: DMA Transaction is complete
Info: Test:test_dma_sata: Wait for transaction to finish (Timeout: 1)
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Info: Test:test_dma_sata: Transaction Finished!
	SATA Sector Count:                 0x00004000
Important: Test:test_dma_sata: DMA Transaction is complete
Important: Test:test_dma_sata: Verify values of DDR3 are correct
Verbose: Test:test_dma_sata: Data read from memory after clear (Should be all incrementing number pattern):
array('B', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127])
Verbose: Test:test_dma_sata: Put Hard Drive to Sleep
.
----------------------------------------------------------------------
Ran 1 test in 21.516s

OK

Through the course of this blog entry I ran that test over an over tweaking the outputs to make it more readable (forgive the spelling errors) and I experienced no crashes! I think there are some hidden bugs in there somewhere but as it is right now the system is in pretty good shape.

My goal is that users can take advantage of very fast SATA hard drives to store and load data without spending most of their time developing the infrastructure to do so, the idea is something like this:

If you are interested in working with these cores, with or without Nysa, my github pages has all of these cores available for download, they don't need a Nysa image to work, they can be used with any Wishbone compliant bus:

Verilog Cores

SATA core

I haven't made an entry on this project in a while because I've been working on documentation (SOO BORRING!) if you are interested here is what it looks like so far (still a work in progress)

Nysa Documentation

Verilog Visualizer

I want to dedicate an entire blog post to this but I've also been working on a verilog visualizer that automatically scans your verilog cores you are working on and generates a module level visual flow chart showing the inter-dependency of modules. I hesitate to show this because it is still full of bugs but as they say "release early, release often"

Here is the block diagram of the I2C Wishbone Core, the top core is on the top left, while the dependencies trail off to the bottom right

I mostly did this because I wanted to see what the SATA core looks like:

Awesome! ... errr ... ignore the stuff at the top : /

Hardware Status

I just sent off a new version of Artemis (Rev B) that fixed some bugs in the design. Hopefully the next version will be in a sell-able state and people can use this design setup to interface with high speed sensors that was only available to companies with a lot of money.

Also I'm working on a new board called Nyx that uses the Intel Edison as a host so users can IOT their FPGAs to their hearts content.

When I get closer to sending Nyx out for fabrication I'll post some images.

Discussions

ushadow wrote 08/03/2015 at 00:33 point

Nice post! This is super useful. Thank you for the post! Looking forward to your FPGA platform.

  Are you sure? yes | no