@superbrew:
I know enough about the FPGA blade to get you working with it, but not enough
about VHDL to tell you exactly what is going wrong. I'm going to detail a number
of things you can try and go through the example included in our source so that
you have a few different ways you can go about trying to get your board working.
I'm going to start with getting your hardware and the Eclipse IDE working, then
talk about the example, and finally provide a few comments about your module.
First things first, there's a few things you'll need to know about the FPGA blade.
On the blade itself are several jumpers to determine how the FPGA is instantiated.
The important one if you're using all Netburner software to run things is JP2.
You'll want the cap for this jumper over pins 2 and 3. This sets the pins up so
that the board is brought up over SPI. I can't at this time tell you where in the
documentation it mentions this, but as this is the way my board is configured, I
believe you'll want to have yours set up this way as well. Next you should try
to get the example running. Even if you don't understand what's going on right now
(more on that in a moment), I would still go through the process of compiling the
code and downloading it to the PK70 to see that the serial output indeed matches
what is says it should (ie. "C001BEEF"). If you can't get it all working with the
documentation in \nburn\docs\Platform\PK70, you can import the compiled image from
the example folder and it may says something slightly different, "DEADBEEF" or
"CAFEBABE" if memory serves. If you have problems with these steps, let us know.
Secondly, let's open up that Verilog example and take a look at it to see what's
going on. Essentially, the .v file creates an interface that turns the FPGA into
an external memory port for the PK70. In main.cpp, we instantiate this external
memory device with the following.
Code: Select all
#define BASEADDRESS (0xC0000000)
sim.cs[2].csar = ( BASEADDRESS >> 16 );
sim.cs[2].cscr = 0x2140; /* 0010 0001 0110 0000 */
sim.cs[2].csmr = 0x001F0001;
volatile PBYTE pFpga=(volatile PBYTE) BASEADDRESS;
Now, whenever the Netburner device tries to read from a memory address that is an
offset of pFpga, it asks the FPGA what data is stored at that memory location. How
does it do this? The processor and the FPGA share a number of Address (referred to
as a in the verilog code) and Data lines (DataBus), along with a chip select (nCS2),
and a bit that determines whether the microprocessor is performing a read or a write (Rnw).
Similarly, whenever the processor writes to these locations, it drives this data into
the FPGA according to the addressing scheme. An example of this reading happens in the
following printf statement.
Code: Select all
iprintf("Locations readback %02X%02X%02X%02X %02X%02X\r\n",pFpga[10],pFpga[11],pFpga[12],pFpga[13],pFpga[14],pFpga[15]);
Whatever information is stored in address locations 10, 11, 12, 13, 14, and 15 is driven
onto the datalines and read by the processor. How does this work in the FPGA? Let's look
at the verilog file, XilinxBladGpio.v. The file instantiates one module, module XilinxBladeGpio.
The first few lines are verilog's way of instantiating the module with the given external
wire names. Then each of those wires has a type and size declared, followed by an internal
wiring or buffers used (here i, dir_reg, and drive_reg). Everything that follows is just the
behavioral definition of the module. First the direction and drive registers are set to 0,
then what follows is a description of what comes over the data bus as various memory addresses
are called from the micro-controller. As you can see, in addresses 10-15, the memory is
holding the string "C001BEEF". If you read the lower memory addresses, you could read the
state of the external pins on J2. Writing to the higher memory addresses modifies the direction
and drive registers which determine respectively whether the external pins are inputs or
outputs and if they are outputs what information is driven on those pins. Below that
assignment block, you can see how the direction and data registers drive individual pins
when used as outputs. You might at this point play around with the device, try to read some
of the pins, try to drive some of the pins, change the message and recompile the code, what
have you. If you're still with me so far, great, you should be most of the way there to
making your own application. Being able to make changes to your hdl and reload them onto
the module means you should be able to run whatever else you make on the blade.
Finally, it sounds like you're going to want to be using vhdl instead of verilog. It's not
my native hdl tongue unfortunately, so I can't tell you off hand if there were any problems
with your code. Usually what I end up doing with VHDL is making sure that the RTL image
generated by ISE what you expect it to be. If you see that the logic is being created the
way you expect it to be, and you've been able to confirm the board's hardware works so far,
the last things to check would be the external connections to the board. You've attached
a clock to one of the pins. I believe this is the flexbus clock, but I don't know off hand
what it's speed would be. If you have a scope, it would be a worthwhile activity to look
at the signal and see what speed it's actually coming out. If not, looking at the datasheets
for this is a good place to start. You'll also want to look at your external circuit. You're
driving J2_2 if you weren't aware. Is that the pin you are monitoring? If you're actually
using an LED, is there a current limiting resistor and is the diode arranged in the appropriate
direction? Just little questions to double check always good.
If anything here seems confusing or if you get stuck somewhere on here, tell us about it.
I'm sure there's a few people here that would be interested in hearing about your experience
like myself and rnixon. If you get everything working, great, let me know what kind of cool
stuff you end up building.