breakin

Communication zpuino/fpga

Recommended Posts

Hi!

I've just recently received my DUO board and I have some beginners questions!

First let me say that I'm super happy with it so good work everyone!

 

Falling importance!

 

1)

I've successfully done some zpuino stuff as well as some fpga stuff.

 

I'm looking for a real simple way to communicate between zpuino and fpga. For now I would be happy if the zpuino could set a bit (when all init is ready) and then I could access it in my ISE schematics somehow.

 

If this was running on the AVR I would go via an external pin, but that feels wrong now that I'm completely in fpga land!

 

I've read a little about the wishbone concept but I was hoping I could postpone using it for a little bit. I mostly want simple internal GPIO.

 

Am I missing something simple?

 

2)

I've used malloc to grab a SRAM-memory block in the zpuino. I was wondering if there was a function get a block located at a certain place? I would want to use it to make sure that the zpuino never uses the memory. Something like.

 

unsigned char *a = (unsigned char*)placed_malloc(position, size);

 

That way I can _assume_ where my memory is located at, and the zpuino can malloc as much as it wants without stealing my memory.

 

3)

Is there a way to connect an input directly to an output in an ISE schematics editor?

Are there symbols that represent logic high / logic low?

 

Thanks!

Share this post


Link to post
Share on other sites

Since I haven't worked with these exact tools, I can't give you details or certainties, but I think I can give some general ideas on #1 and #2.

 

Re 1: I believe ZPUino has a GPIO device, providing a bunch of digital input/output lines.  I would expect that in schematic editor, you should be able to connect one or more of these to your other design elements, instead of the external pads of the FPGA.  Then you'd use digitalWrite() on the ZPUino side.

 

For more sophisticated communication, there are a lot of options (serial, I2C, SPI) but I suspect Wishbone would be best at that point.

 

Re 2: What do you want to use that fixed-location memory for?  That might help come up with an alternative.  A cursory look at http://github.com/alvieboy/ZPUino/blob/master/hardware/tools/zpu/zpu-elf/include/malloc.h (assuming that's the right place) and some similar files suggests there isn't such a function.  Since I expect all this software is open-source, you might be able to create one, but that's probably a significant task.

 

Some possibilities that might work:

  • You could, at init time, try malloc()ing blocks of memory until you run out.  Then free all the ones you got which don't contain your desired range.  That requires your desired memory range fall into a single malloc()ed block..
  • Some malloc() implementations have a limit stored somewhere, indicating the location above which they don't allocate.  Maybe you could put your block at the top of that, and move that pointer.
  • malloc() doesn't use space that belongs to the stack, or the program code.  alloca() allocates from the former (it gets freed automatically when you return from the function); the latter is where the global variables you declare in your code are placed.  Neither lets you pick the exact address ahead of time, but they make it a little bit predictable and they protect it from malloc().

Share this post


Link to post
Share on other sites

Hi Jaxartes!

Thanks for the answer!

Re 1: I think you put me on the right track. There is a GPIO-bus coming out from the zpuino with 200 wires. I assumed they were all routed to external pins, but that is not the case.

 

I'm looking at the SD-card project and then the bus was routed out to the Papilio_DUO_Wing_Pinout symbol. The first 54 wires are then re-routed to the physical GPIOs on the DUO headers, but the others could be used for internal purposes. That routing seems to need to be there for some parts of the SD-card project to work (not sure why but let's ignore that for now).

 

I'm currently trying to "splice" the bus into two so I can both route it to the wing AND look at indivual bit. While I'm currently failing I think this is a good approach :)

 

Re 2: I'm currently a beginner and I just wanted to keep down the amount of communication I need to do between zpuino and rest of fpga. I just thought by fixing some memory blocks, I would make it easier for me to get going. Right now I allocate an array an it always ends up at adress 6008 so I can just enter that into the fpga-code by hand until I need to do something more fancy!

 

When someone makes say a small mirocomputer with CPU-RAM, PPU-RAM etc it might be nice for them to just know where it is in SRAM instead of having to get the number from somewhere. But this is just me thinking ahead, perhaps the counter to store the base address is just a small thing compared to everything else going on!

 

Thanks for you tips! I like the limit thing, using the upper 1MB might be safe with some minor change.

 

Re 3.

I guess I could just make VHDL-symbols of my own that route through a wire, and that outputs high/low. Just seems weird that there aren't already any in the standard library of symbols!

Thanks again!

Share this post


Link to post
Share on other sites

Hello Breakin,

 

Welcome to the Papilio community! Sorry for the late response, I had a busy weekend. :)

 

I see that you are thinking about taping into the 200 wire GPIO-bus. Unfortunately that is not going to work as you are thinking... That bus is 200 bits wide, but I only did that for future growth, only 55 of those pins are used on the DUO. The rest get optimized out since they are not connected to anything inside the ZPUino Soft Processor. In order to add more GPIO pins you would need to:

  • Download the ZPUino source code
  • Edit the DUO's DesignLab variant and
  • Update the zpuino_config.vhd file to increase the gpio count.
  • Then run make to generate a new ZPUino_Papilio_DUO_V2_blackbox.ngc file.
  • Replace that file in your version of DesignLab, (or better yet make a new zpuino library from a copy of the existing and update that)

There is a lot to go wrong in all of that and I don't recommend it for someone who is just starting out. It is also not a solution that would be easy to share with others which is another reason for us to look for another way to accomplish the same thing.

 

So how else can we get you easy way to get ZPUino to set a bit inside the schematic editor so you can control FPGA logic? Well, Wishbone really is the way to go here... I think you will find that it is actually easier then you would think... There is actually a tutorial here that shows how to make a Wishbone library to do what you want:

http://gadgetfactory.net/learn/2015/05/14/designlab-libraries-make-a-wishbone-library-2/

 

If you don't want to make a library yet then the key thing you can get from that tutorial is the Wishbone_to_Registers_x10 symbol. You can actually connect that directly to a Wishbone slot in any of your projects and that will give you 10 Wishbone based I/O pins to connect to. The C code to control them is very easy:

To write to a Wishbone register:

REGISTER(IO_SLOT(<wishboneSlot>),<registernumber>) = value;

To read from a Wishbone register:

value = REGISTER(IO_SLOT(<wishboneSlot>),<registernumber>);

This approach should be very easy to do and will allow you to easily make a library to share later.

 

Jack.

Share this post


Link to post
Share on other sites

Jack:

 

Thanks for the welcome! And thanks for the board! It is my first fpga but it helped me get into it step-by-step. I'm not at the last step yet, but at least I'm walking.

 

With regard to the GPIO; that explains why they didn't work! I did learn how to make bus taps in ISE so it was not a total waste of time!

 

I'm going for the wishbone approach as it seem more appropriate in terms of sharing! And it also seems easier.

 

Perhaps you could answer a weird thing. When I disconnected the GPIO_OUT/IN from zpuino to the wings the sd-card example (DumpFile) stopped working. Is that to be expected?

Cheers,

Anders.

Share this post


Link to post
Share on other sites

Hi again Jack,

 

Based on your suggestions I was able to communicate properly using "Wishbone_to_Registers_x10" without having to learn wishbone at all. The only tricky part was getting bus taps to work but that I learned while trying to get the GPIO to work.

 

Openeding the VHDL for the wings I can see that they are referenced. I don't fully understand it at this point but I'm ok with that :)

 

Thanks for the help!

Share this post


Link to post
Share on other sites

Excellent! I'm glad you got communicating over Wishbone worked out and it was easy to use. :) Please don't hesitate to ask any other questions you have.

 

Jack.

Share this post


Link to post
Share on other sites

Excellent! I'm glad you got communicating over Wishbone worked out and it was easy to use. :) Please don't hesitate to ask any other questions you have.

 

Jack.

Thanks for excellent advises. I painted myself into a corner with this approach, but you couldn't have known that.

I'm trying to make a SNES cartridge so I need (sometimes) random 8-bit accesses to SRAM with about 70ns access time.

 

I've seen http://forum.gadgetfactory.net/index.php?/topic/1816-switching-ram-ressources-in-zpuino-on-papilio-pro/?hl=%2Bzpuino+%2Bsram

 

Using DMA over wishbone might make things too slow, or at least make them complicated. It seems more like a SDRAM solution.

I was hoping more of time-multiplexing the SRAM with the zpuino.

So while I want the SD-card stuff and sram initialization from zpunio, I need the random accesses. So might have to move SD-card handling out into VHDL for this to work.

I think I could manage that but I'm open to zpuino-friendly suggestions!

 

An alternative here could be to use the AVR or to use another soft core that uses block ram instead of SRAM (or is more time-multiplexfriendly with regards to SRAM).

 

But thanks anyway, I'm creating these problems myself!

Share this post


Link to post
Share on other sites

Well, what about loading the contents of the SD card into the zpuino memory using the malloc command? Then you don't have the sdcard bottleneck...

 

The other option is to use BRAM in the FPGA, there should be 30-50KB left free for user designs.

 

Jack.

Share this post


Link to post
Share on other sites

Well, what about loading the contents of the SD card into the zpuino memory using the malloc command? Then you don't have the sdcard bottleneck...

 

The other option is to use BRAM in the FPGA, there should be 30-50KB left free for user designs.

 

Jack.

 

Hi,

 

When you say 30-50kb BRAM left, do you mean that I could put my data there? A typical SNES ROM is 512kb-1mb so I would need at least that much memory to pull this off. So that would not fit in BRAM if that was what you suggested...!

 

So my currently approach was to use malloc in the zpuino and load the SD-card content into SRAM. This was easy once I realized that the heap was located in SRAM.

Then my plan was to signal that the SRAM-loading was done to outside-zpuino-land. I would hand of the SRAM-offset so I would know it in outside-zpunio-land.

 

From that point on the FPGA would simply serve as a SRAM, exposing a 24-bit adress and 8-bit data to the real physical SNES using some of the 54 IO-pins.

 

I wouldn't mind if the zpuino was running concurrently in the background with SRAM accesses at all, I just have to be able to squeeze my SRAM requests in-between. Using DMA might be fast enough, but I really only want one byte at the time so it doesn't seem like a DMA-suitable problem.

 

If there is some mean to load my sketch and global variables into BRAM I might get away with that, but if I read http://www.alvie.com/zpuino/releasenotes.htmlcorrectly then sketches must run out of SRAM.

 

I'm currently thinking that an empty loop() function might generate no SRAM-traffic, or that I could disable/pause the zpuino once everything is setup, but I don't know how to progress just yet!

 

Thanks for helping me out! There is absolutely no fault in the board or the setup, I just have to understand my problem properly :)

Share this post


Link to post
Share on other sites

Ah, the BRAM is not enough then.

 

It sounds like you are on the right track, I don't think you need BRAM. I would start out and just see if a sketch running on the ZPUino can serve up the cart our of memory on the GPIO pins fast enough. 70ns is ~15Mhz and the ZPUino runs at 96Mhz so it might be able to keep up...

 

Alvie can shed more light on the best approach here...

 

Jack.

Share this post


Link to post
Share on other sites

Are you trying to make a multicart (like everdrive etc?) for loading games from SD Card or are you trying to do own code with the SNES as a display/interface unit?

Share this post


Link to post
Share on other sites

Are you trying to make a multicart (like everdrive etc?) for loading games from SD Card or are you trying to do own code with the SNES as a display/interface unit?

 

Hi Felix,

 

I like to tinkle with the SNES. Right now I'm trying to make a multicart, much like sd2snes (which is a standalone board with sd-card, fpga and sram). sd2snes is cool with support for some cartridge expansion chips implemented in fpga (but I'm not that ambitious).

 

Mainly it is my first fpga project ever so I'm just trying to learn! Thus I want to make as much as possible outside of the softcore since I don't really want to learn microcontrollers right now. But file system stuff seems more suited to a microcontroller so I'm willing to do a little bit in a softcore and some things in VHDL.

 

For projects that just want the soft core to help a little bit with small tasks it would be better with a soft core that only accessed memory when the outside told it that it was ok! But as I said this is for learning vhdl/fpga so my needs might be a bit unpractical!

Share this post


Link to post
Share on other sites

Ah, the BRAM is not enough then.

 

It sounds like you are on the right track, I don't think you need BRAM. I would start out and just see if a sketch running on the ZPUino can serve up the cart our of memory on the GPIO pins fast enough. 70ns is ~15Mhz and the ZPUino runs at 96Mhz so it might be able to keep up...

 

Alvie can shed more light on the best approach here...

 

Jack.

Hi Jack,

 

While that does make sense, I mostly want to learn VHDL/fpga at this point so I'll try to solve the problem outside of zpuino for now. I know at what offset my ROM resides in SD-card so I'll skip the filesystem interaction for now. Later when I need it I might be able to either find another softcore or make zpuino do what I want!

Thanks for all the suggestions!

Share this post


Link to post
Share on other sites

just remember to be careful. i am not sure how many i/o ports on the papilio duo are 5v tolerant.

you may have to drop down to 3.3v ttl

Share this post


Link to post
Share on other sites

just remember to be careful. i am not sure how many i/o ports on the papilio duo are 5v tolerant.

you may have to drop down to 3.3v ttl

 

Thanks for the tip! Afaik the first 14 GPIO are 5V tolerant, but I've got ICs to handle the rest of them. I know that gadget factory sells 5V-tolerant wings as well but haven't got any of those :)

 

I've already built a breakout cable for a cartridge. It only exposes some of the pins of the cartridge (this game is simple so only needed a few of the pins on the cartridge bus) but should be enough for 1MB games. See here if you are interested http://breakin.github.io/snes-external-maskrom/in the breakout cable.

Share this post


Link to post
Share on other sites

 

I've already built a breakout cable for a cartridge. It only exposes some of the pins of the cartridge (this game is simple so only needed a few of the pins on the cartridge bus) but should be enough for 1MB games. See here if you are interested http://breakin.github.io/snes-external-maskrom/in the breakout cable.

 

As an alternative to your pin headers, you could have used a ribbon cable with dip socket, like this one:

http://www.digikey.com/product-detail/en/C2PXS-4006G/C2PXS-4006G-ND/1122835

 

Since it has 40 pins and your PCB has only room for a 36 pin ROM you would have to cut the four outer pins before solder it in.

 

Magnus

Share this post


Link to post
Share on other sites

As an alternative to your pin headers, you could have used a ribbon cable with dip socket, like this one:

http://www.digikey.com/product-detail/en/C2PXS-4006G/C2PXS-4006G-ND/1122835

 

Since it has 40 pins and your PCB has only room for a 36 pin ROM you would have to cut the four outer pins before solder it in.

 

Magnus

Thanks Magnus!

 

That seems like a very neat solution. The cartridge that I've gutted only has a 32-pin MaskROM which only gives me 1MB ROMs (and unfortunately not access to pins such as RESET, CLOCK etc). While I've looked inside some more cartridges I'm not sure I want to gut them (even though some were cheap) so perhaps I'll instead look at making a custom PCB. That would be fun challenge, one that I'll save for later :)

 

My current solution works (the MaskROM could run from the breadboard) and is very cheap so I still recommend it ;)

 

/Anders

 

ps. Are you also from Sweden?

Share this post


Link to post
Share on other sites

It's too bad there isn't enough BRAM for your design.  I was going to suggest it:  Each BRAM has two independent ports for access, and there are 32 of them, while there's just one SRAM.

 

You mentioned soft processors, so I think I should point out:  You have two hard CPUs in your solution already:  The AVR micro controller on the DUO, and the CPU of the SNES itself.  Each has its own memory, and advantages and disadvantages:

 

AVR: Popular toolchain (Arduino); limited capability (32kB program memory, 2.5kB internal SRAM); accessing external SRAM could take some effort; can run independently while SNES is playing games.

 

5A22 (SNES): Probably harder to program, but you might find it more familiar or interesting since it's SNES.  And although accessing the DUO's SRAM could take some effort here too, it's effort I think you already planned to make.

 

In the latter case, using the SNES CPU, here's what I imagine: the FPGA would provide "glue logic" to access the SRAM, and a variety of custom expansion chips.  These would be mapped into the SNES's memory and might be the following:

  • SD card reader
  • BRAM containing "bootloader" software: this reads the SD card and writes to SRAM
  • memory management unit (MMU), if desired; it might enable/disable writing to SRAM, or hide the boot loader BRAM or SD card reader

I have no idea if this is more or less easy, or useful, than multiplexing access to the SRAM between ZPUino and the SNES.

Share this post


Link to post
Share on other sites

Wow thanks Jaxartes!

 

I'm currently doing SD-card-reading from fixed offset in VHDL just to make sure that the physical side of the project is working (connecetion snes<>fpga is fast/stable enough). Once that is done I might try one of your options!

 

Just my initial thoughts:

* By using the AVR I would probably sacrifice a few of the 5V-tolerant 14-pins (since I need a wishbone bus to talk to the SD-card). This might be ok for now but I like to consider options where I keep as many of the 54-8(SDCARD)=46 pins available. I want to find an approach that would scale to full SNES-cartridge bus. External shift-registers and multiplexers are of course an option but since I'm working on breadboard I want to avoid that until I understand the performance implications.
* Whenever the SNES runs a instruction it fetches data from ROM-memory (at least until it has uploaded code into its own 128kb SRAM and run from there). But by using BRAM for bootloader I'm able to serve the SNES some code directly. Interesting approach! I think that programming menu systems, file system parsing and sd-card reading on the snes-processor would be cumbersome (if possible) but it sure is a good option. Not sure what SD-card reading speed I could get out of it but I can think of workarounds.

 

I'll revisit this once my physical prototype works!

 

Cheers,

Anders.

Share this post


Link to post
Share on other sites

Quick update. I found a micro-usb cable so I managed to put my sketch on the AVR instead. The sketch runs (led blinks and serial is working).

I need to avoid wishbone communication since the wishbone bridge on the fpga uses a zpuino.

Will try to solve it without wishbone.

Then I could write my SRAM using pins somehow.

Seems manageable if I can access the SD-card!

 

I don't see why you couldn't make a wishbone bridge in vhdl, but I might be missing some point on how those works. That would help my scenario a lot.

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