Jump to content
  • 0

Accessing Memory Content on Nexys 4


Wesson

Question

Hi,

I have developed a simple verilog program that reads a matrix from a text file, loads it into BRAM, performs some computation and then store the output back into BRAM. I have simulated the program and it works as expected. Now I want to test it on the FPGA, but I am not sure how to do that.

1- If I continue to use BRAM, how can I view the content of the BRAM after the execution is over to verify the output?

2- If I decided to use USB flash memory to read the matrix and write the result, how do I specify the names of the input/output files? There are a lot of resources that explain AXI USB and SPI using memory addresses, but how can I know the addresses of the input/output text files?

 

Thanks!

Wesson

 

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

Wesson,

Welcome to one of the fundamental problems of using FPGA's.  Sadly, _so_ many solutions exist that it's hard to give you a simple answer.  Perhaps that's not really a sad thing, but ... just a reality. 

Before discussing possibilities, let me start by saying that writing your results to a memory stick is probably well beyond a beginner's task.  To do that, you really want to understand the entire memory stick filesystem, learn about where files are stored, how the directory is laid out and more.  It's difficult enough that I'm not aware of any solution that writes to a memory stick without using some kind of CPU and/or operating system.  (Indeed, I just managed to build a controller for an SD-Card that uses a SPI interface, and I have yet to get gutsy enough to actually do more than write to unused sectors on that card.)

That said, let's look at some possibilities for you:

1. You could send your results from your FPGA out a serial port.  You can find an example serial port here, as part of a CMod-S6 project I did.  (The receiver code can be found there as well.) This would involve converting your results into some ... format that you can then understand in a terminal.  While I often convert things to hexadecimal, with commas or other such between them, other binary conversion possibilities are available--the choices are nearly endless.  The trick here is that you will also need a completely separate piece of logic that will 1) wait until your computation is finished, 2) cycle through all of the block RAM, 3) convert it to your across-the-wire format, and 4) send it away.

2. Another approach I've used is to build a bus controller for the FPGA--something that can turn an internal "bus" (such as a memory bus, or a memory mapped peripheral bus) into something that can be read and written externally.  This is more difficult than #1 above, but also quite useful.  As an example, I built such a bus controller for both the S6-project I mentioned above, as well as for the XuLA2-LX25 SoC project of mine.  To get a feel for how complicated this was, take a look at all of the Verilog files whose names begin with "wbu" in the Verilog portion of the project directory.  These files convert a byte stream to wishbone bus commands, and then the result gets converted back to a byte stream.  To make this worse, that's only half of the problem.  The other half includes software on your host that encodes the characters sent to/from the device into something looking like bus commands.

3. A third approach would be to place a CPU internal to your FPGA, and have that CPU read the memory out and send it to your serial port (or whatever output you are using).  This was the approach I used within my CMod-S6 project, but it was really only used for things the CPU internal to the core calculated--not so much for FPGA calculated values.  For my purposes, I used a ZipCPU for this, but I imagine most of the folk here would recommend using a microBlaze as a beginner's solution--I just have no experience with the microBlaze proecssor myself.

4. While I have sort of focused on a serial port as the ultimate transport mechanism, you can also use a SPI port, a network port, a parallel port (such as the DEPP interface), or ... well, the possibilities are really only limited by what's on your board, and what you have that can interface to your board.  (You didn't list what board you were using ...)  I mean, you could even send your results out via the on-board LED's if you wanted to--although reading those results out by eye might be a minor nightmare.

Put in perspective, it's kind of sad that when you run into a problem that needs an FPGA, you also need to solve the communications problem as well in order to get results into and out of your logic.  It's not an uncommon problem, and I think everyone has dealt with it, but it's just sad that the work you end up doing on what you consider to be your "primary" problem may well be dwarfed by the work you need to do just to get your data into and then your results out of the FPGA.  Indeed, I have been counseling someone recently who wants to use his FPGA for high speed computation, and we have both been frustrated that the FPGA can do the computation in 50ms, but that it will take 900ms just to get the information in and out of his FPGA.

I guess it's all part of putting together a "comprehensive" solution.

Dan

Link to comment
Share on other sites

Don,

Thank you so much for your elaborate response, it is very informative. I will start investigating the first option since it seems to be the easiest. However, I have one question: UART seems to be the most straight-forward option for a serial port, but would it work on a Linux machine? I am running Vivado on Ubuntu, and I'm not sure what would be equivalent of a COM port.

I also wanted to ask about option 4:

My board is Nexys 4 (specs can be found here), it contains an SPI flash memory. If I write the result to this flash memory using SPI, then

1- Is there a way to view the memory content (from Vivado or otherwise)?

2- Correct me if I'm wrong: If I were to write a code that sends the output from the flash memory back to the PC, then I'll be copying the result from BRAM to flash memory through SPI, then from flash memory to PC using serial port (option 1), and therefore using the flash memory as an intermediate step is pointless since I can use option 1 t directly send the result from BRAM to PC using serial port.

Thanks a lot,

Wesson

Link to comment
Share on other sites

Wesson,

1. I am running the UART from a Basys-3 board through a Linux machine.  As I understand, Digilent has used common parts and pieces in their designs so that it should work.  Be careful to set up both sides properly.  My linux machine defaults to 115200 baud, 8 bits, and no parity.  If I do something different, I find myself constantly changing settings.  If you are intending to use the txuart.v code mentioned above, you'll need to set the setup parameter to a 29-bit value equal to your system clock divided by your baud rate (the extra bits, set to zero, will set the 8N part). In a simmilar fashion, you will need to make certain that hardware flow control is turned off.  That was a screwy bug I had to look for the first time I ran UART with my board.

2. Flash programming is quite doable, but you might wish to take a walk through the flash interface guidelines first.  (Here's an example, although you might wish to check that you have the interface guideline for the Nexys-4, this isn't it.) Writing flash is not like writing RAM memory at all.  You will need to first erase the large block you then wish to write (setting all the bits to '1's), and then you will later need to write the block (setting certain '1's to zeros).  Before doing either you will need to set the write enable bit and ... it's a touch complex.  That said, I can get you started.  Here's the Quad-SPI flash controller that I'm using for my Basys-3 board, and that also works with a CMod-S6 board.  Second, here's a software controller that runs on my PC that then talk to the Quad-SPI flash controller in order to command it to write whatever on the board.  Just ... be careful, certain write protect bits in the configuration register once changed cannot be changed back.

3. Writing to the flash memory, though, seems as you describe: pointless, since you still need to build whatever you are going to use to copy it back to the PC.

4. Still, since you mentioned your hardware, it looks like you do have other--though still more complicated--options.  You could write your output to the VGA port, and visualize it on a screen.  This might require a font, a frame buffer, and a display driver, but I imagine it would be a fun project.  You could also create a packet for the network port that you would broadcast from your card (you probably want to broadcast a ping packet first, just to know that you can ...)  This is probably easier than the VGA display port, although I haven't done it (yet--it's on my list).  Another option to consider is that you could write your outputs to a microSD card.  I just finished building a Verilog interface to one of those here that uses SPI mode, not the full 4x SD-Card mode, although OpenCores has an example interface that does use full SD-Card mode.  Still, it shows you how the low-level interface is done. The higher level interface is still complicated, and might make more sense if I documented what I did(!)  If you are interested in chasing this approach, you might wish to ask me for the software I used to demonstrate that I could read and write from the SD card.  At the same time, my software didn't go so far as to understand the file system, just to read/write specific sectors.   This approach of ignoring the file system on the card is, in general, dangerous and will probably lead you to reformatting your SD card many times before you are done--but it's part of the road forward if you take this approach.

But, still, it sounds like you have a lot of options to work with and some fun ahead of you.

If you haven't gathered, though, and for the rest of everyone listening, I've sort of locked on to a way of FPGA programming that is working very well for me: I build a wishbone bus, internal to the FPGA, and then I hang all of the "devices", or realy device controllers, within the FPGA off of that bus.  (Xilinx die-hards will probably want to build an AXI bus and connect it to a microBlaze chip, or perhaps the arm within their Zynq chip--I've chosen Wishbone, so I get to rewrite any coregen IP I might've otherwise used to work with this new bus.)  I then build an interface whereby I can read/write the bus from a PC.  I've done at least three versions of this interface now: one runs off the UART for my Basys-3 board, another runs using the JTAG port for my XuLA2-LX25 board, and the third uses the Digilent's Extended Parallel Port (DEPP) interface for my CMod-S6 board.  This allows me to test and prove all of the "hardware" interfaces within the FPGA.  I'm particularly proud of the fact that I can take my UART interface, bounce it across my home LAN/WiFi to whatever computer I wish to access my FPGA from, and then interact with the FPGA from there.  "Interaction" involves anything on the bus.  I can both read/write flash (as discussed above), as well as instruct the FPGA to reconfigure itself from a special flash load via the ICAPE2 interface.  As a result, ... I've never used the JTAG interface on my Basys-3 board, I only boot-strap it from a USB stick and then read/write configurations to the Quad-SPI flash--regardless of what room in the house I'm working from.

Hope this helps and encourages you,

Dan

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...