First of all you need to determine what you're going to do with the PDF. If you're displaying it, you'll need some memory for the frame buffer, and a way to interface with the display. That should be your primary concern. Then, start thinking about rendering the PDF itself. As PDFs are essentially compressed PostScript of one form or another with embedded fonts, you can divide your tasks into some major elements:
- part of the FPGA to load data from SD card or other media including file system access
- part of the FPGA to decompress chunks of data, or to accelerate this process
- part of the FPGA to decompress image data (JPEG, PNG, etc.) and copy to memory
- part of the FPGA to decode/execute PostScript
- part of the FPGA to figure out what needs to be displayed (such as the current page); this could be simple bounding logic or complex scaling logic handling a variety of different display modes
- a floating point unit for the floating point coordinates in PostScript
- an integer ALU
- several "GPU" engines which render primitives from the PostScript engine (ideally, in parallel) e.g. draw line, draw polygon, ...
- a font engine or two to render fonts (this will likely be very complex as you will need to support complex features like hinting and antialiasing.)
- a display interface and memory interface
- a UI controller of some kind, perhaps implementing copy/paste, selections, menus, etc.
Ideally the engines 1-5 would be pipelined to get maximum throughput. You'll be looking at a big FPGA to do all of this.
You could probably do this on a CPU, but if you realllly want to do it on an FPGA, this is probably the route to take.
I do not own a Nexys II board, but a quick look at the user guide and the schematic from the Digilent website and I can see that all the signals needed for programming the flash ROM device are available at the Spartan 3E pins. This is as I would have expected.
To program this device, you can do one of two thing:
1) The first option is a two step process in iteself. You first create the VHDL code for a Flash Programmer, that erases a block and writes your new data to the ROM. You'll need the datasheet for the Intel Flash ROM to do this. Then assign the ROM pins in the UCF file according to the table in the Digilent user guide and upload this .bit file to the platform flash. When it starts, it will execute the flash programmer code and write the ROM for you. The data you want to program is in the VHDL and thus also in the .bit file so the programmer can access the data to write to flash; or
2) the Flash ROM device does not have a JTAG interface and is thus not part of the JTAG chain. However, with a bit of work, you can use a BSDL file (Boundary Scan Description Language), available from Xilinx for FPGA on your board, and using OpenJTAG you can flip bits on the FPGA to program the device.
This "Boundary Scan Programming" of the flash device is quite common in production, however if you don't have a good Boundary Scan flash programmer it an be tedious to do it by hand using OpenJTAG commands.
I recommed option (1) since it's likely the quickest for you to accomplish. You'll need the Intel Datasheet for the StrataFlash ROM and basically send the commands to the the ROM to do an erase cycle and a write cycle for your data.
For the 20 bytes or so you want to program into ROM I'd consider a simple 20 byte flash programmer in VHDL.
However, for something more complete, there is an app note from Xilinx NOR FLASH Programmer for Spartan-3E Starter Kit. That is for another board but can be easily modified for your own board by changing the pin assignments. That appnote presents a design that programs the FPGA with a UART and a Picoblaze MCU to act as a full featured flash ROM programmer.
Best Answer
Method 1: Create ROMs in your FPGA design
Because you have the same data in every board, one option is to use block RAMs in the FPGA, configured as ROM. To do this you instantiate a block RAM, but don't connect to the write pins. Use a synthesis directive in your HDL code or UCF file to specify the initial contents of the RAM. Read the Spartan-3 Generation User's Guide (Chapter 4) to see how to instantiate the RAM and how to access the data from the RAM. If you use Xilinx ISE, there is probably also a "wizard" to generate the RAM block and set up the initial contents for you.
Unfortunately, the Spartan-3E you are using has only 350 kbits of block RAM, not 8 Mbits like you require. For this to work then, you'll have to work out a scheme to compress your data to fit in 350 kbits. The details of how to do this depend on what kind of data you have. If your data is especially random, it might not be reasonable to get this much compression.
Method 2: Store data in external memory
You say you have a 128 Mbit parallel flash and a 16 Mbit SPI flash. You will need to read the datasheets for these parts and understand how they work. Then write a state machine into your FPGA that can access these devices. But this is your job as the FPGA designer. Some random strangers on the internet are not going to design your FPGA for you.
To store the data onto the flash initially you have two choices. First would be, if you are building these boards in volume, you can have your board assembly shop pre-program the flash devices before assembling them onto the boards. Typically you give them a data file in some format they request, and they charge you some small extra fee to have the data flashed in before assembly.
Second option: Read the datasheet for the flash device. Write an FPGA design that allows you to send data from some other interface available on your board (Ethernet, USB, SPI, I2C, whatever), and load it into the flash. At manufacturing time, you load this design temporarily into your FPGA and program your flash; then you store a different "run-time" FPGA design into the on-board configuration PROM, that doesn't have the ability to modify the FLASH, and your users won't have the ability to mess up the data.