• 0
Paul_kimelman

How to add own logic to Arty board flow?

Question

The Arty board examples and tutorials use the Vidado drag and drop editor. But, there is no example how one would add their own custom logic. I have hacked this so far by dropping a peripheral and then replacing the stub verilog file, but it would help to show how this should be done. The natural would be to drop in a custom bus i/f file (e.g. using the AXI to AHB or AXI to APB bridge to a stub) and also how you add pins to the port list. Hacking away at it seems just wrong - if there is some intended flow, it is not apparent. The old way of editing the .ucf file and adding the ports to the top file does not seem like a fit for this SDK/Microblaze environment. 

Thanks, Paul

Share this post


Link to post
Share on other sites

61 answers to this question

  • 0

Hi @Paul_kimelman,

In Vivado 2016.x there is a new feature called add a block. you right click on empty part of block design and click and add a block. you can add your vhdl or verilog file to that and then use an axi gpio block to connect it. You will also need touse the xdc to constrain the pins from the add a block. I have attached a project that does that for some vhdl code working with the PmodAD1(not our IP core).  If you are wanting to make your own IP then here and here are some tutorials that deal with that. 

GPIO_add_a_block.zip

Share this post


Link to post
Share on other sites
  • 0

Hi Jpeyron, thanks. I saw add a block but I did not realize it would allow me to add my own. I will look at your example for the pins since that was unclear. I have plenty of my own IP so it was more about moving it from a Spartan6 and ISE to this Artix env while also using Microbiaze for some SW.

Share this post


Link to post
Share on other sites
  • 0

Hi D@n. Thanks. I normally do, but I need to use MB for the SW since I need to provide someone a standalone firmware based setup on the Artix. So, it was about mixing the flows.

Share this post


Link to post
Share on other sites
  • 0

Don, I should have been more clear about this. The ZipCPU or whatever it is called is a GPL license. if you mix your own IP with that you have contaminated it. I would have been really happy if it was a BSD licensed core. But, I will never mix my "commercial" IP with GPL IP as that is forbidden in most companies.
That said, I wish there was a normal flow project with a core. The Vivado MBlaze thing is a disaster. It horrible. They make everything hard and they do not seem to even release the sources to their GPIO driver, not even the top level stub, so it makes it impossible to use it as a launching off point. I do not know what Xilinx is doing here, but this makes normal use of an FPGA to trial out some ASIC logic pre-tapeout much harder and that is a shame.

I am also saddened that Diligent has not pushed back on this mess. If you want to use MBlaze, there should be a "core" block you can just instantiate into your normal Verilog (or VHDL) flow, instead of this mess. If there is, I would love to see how; in ISE it would have just been a core generator and done. So, what would have taken me a couple hours in ISE is taking hours in Vivado because I have to package up things and I have to guess at the interface ports since it does not even expose the templates or anything. Crazy and Sad.

Share this post


Link to post
Share on other sites
  • 0

Hi Paul,

Let me try to relive your frustration. I had myself similar feelings when I started my project on Zybo board. My past experience was limited to small VHDL projects on Xilinx and Actel FPGAs. For a while I had a hard time understanding interactions between PL and PS. Learning curve was steep but in the end I came to realization that introduction of block design can simplify integration of various IP modules.

You don't need to know all Xilinx code to implement interfaces. You can get sufficient info from the HDL wrapper. In case of GPIO if you don't use AXI you don't need it at all.

Take a look at
https://forum.digilentinc.com/topic/3822-what-is-the-fastest-way-to-save-pl-data/?do=findComment&comment=14413

Following this approach I was able to integrate several custom VHDL modules into the system. PL receives control signals from the processor, sends interrupts to the processor and share data. There several benefits of this :

1. No effort is needed on SDK side for obtaining addresses because they are supplied by Vivado automatically with the bitstream.

2. No effort is needed for instantiation of Xilnx modules because when you connect blocks it is done by Vivado behind the scene. You only need to have the necessary interface signals and can call them anyway you want.

3. SDK programming is a piece of cake because you can reuse a plenty of examples available in Xilinx documentation.

4. It is easier to debug HDL because if you expose a signal (wire) on a block diagram you can use JTAG logic analyzer which is now included for free with Vivado. I used it for checking interrupts and for GPIO and was happy with how much time it saved me.

It is clear to me that without the new Xilinx programming paradigm I would never accomplished my goals and that short time. Also I developed very high opinion about the Zynq processor. Adding two ARM cores increased productivity manifold. It is easier to document and most important to review the project by peers. 

Hope you find it useful, good luck to you!

 

Share this post


Link to post
Share on other sites
  • 0

Hi Notarobot. Thanks, I will check this out. I agree the designer is fine for throwing together pre-built IP blocks into the equivalent of a hard-macro. It was the next steps that I find very irritating. I tried the AXI to APB bridge and they give you no help and it does not even expose the nets and so you cannot just hook them up (you have to figure out the interface and then replicate it by exact name and then hope they recognize it). I am glad if there is a better way, although it still looks like this create a package thing and I will need to see what the block-RAM interface looks like. This is what is so unnatural about this. I tried to pump the AXI 2 APB as external, but I do not see where it does - it does not seem to come out of the system.v file which is what I would expect (so I could just dump my custom instantiation into the system_wrapper.v). I do not understand why this has to be this hard, most systems with these builders at least allow you to "externalize" nets like the output of the AXI APB bridge and then you can just connect them the normal way in the top.v type file. They seem way too enamored of this flow - quite painful for development.

I will compare the page you sent me and my completion of the AXI to APB bridge since I have it connected. I will need to change my package since I had not considered that I cannot tie off ports easily with the designer (no 0 or 1 to attach to). So, I will layer one more level and only expose what I have to.

Also, I got burned by a parameter defined in a wrapper as: "parameter name = other_name[1] & other_name2[0]" which their tool freaked out with since it removes the [ and ] and then blows up with errors that other_name1 does not exist and so on. If you tell it to skip that param, it then fails when building the package with no explanation. 

Share this post


Link to post
Share on other sites
  • 0

Hi Paul,

Unfortunately, I can't advice you on AXI-APB since know nothing about it. But I've learned that Digilent forum is the most helpful/useful/friendly. You will find help here. Unlike Xilinx forum which I find arrogant and just a waste of time in 90% of cases.

BTW, BRAM on my Zybo dev board works well and serves the purpose. I like that very little code is required for its implementaion.

You might know already but when you click on a "+' sign on the IP module, it will list all interface wires and you can connect to each one without declaration or any other extra code. They should be of the same type and proper direction only.

For the AXI interface you can check Youtube examples made by Mohammad Sadri. He also showed utilization of HDL wrapper for embedding a custom code.

 

Share this post


Link to post
Share on other sites
  • 0

As one follow up, does anyone know how to simply get the block designer to port out nets of interest? This makes no sense. See below (not in system or system_wrapper). The system wrapper does not export the APB signals it says are there, nor the LED and other GPIO pins. So, where do they go? I am assuming this means some non-standard "magic" to get them to the FPGA pins, but it makes things much harder.

Further, if I try to locally connect, I get the below garbage error. You can see every pin of the APB bridge is connected, yet I get this error. This whole designer things very fragile and very buggy. The only things that work are to follow very narrow rules. So how did you get past this with your idea of a block RAM connector? Does it export the nets?

 

 

Screen Shot 2017-04-16 at 12.20.51 PM.png

Screen Shot 2017-04-16 at 12.31.34 PM.png

Share this post


Link to post
Share on other sites
  • 0

@Paul_kimelman,

I'm not sure I can thank you enough for your honest feedback regarding the ZipCPU and its related cores.  Thank you, and thank you again.  :)

Unlike many other open source products, the ZipCPU and its related cores are not the result of a community of effort.  Instead, they have been the result of two years of hard and at times painstaking work on my part--work that has not been paid for, and hence the GPLv3 license with all of its "viral" problems. 

I guess what I'm trying to say is that, with the exception of the tool chain (GCC, binutils, and newlib), the license for the rest of the ZipCPU and any other products I have put together is subject to negotiation.  While I have tried to place a notice to this effect on the various project pages, I may not have been clear enough.  Please feel free to name your terms, and I will be glad to name a price.  Indeed, I'd be glad to release all of this work under a BSD type of license, but I would want to be paid for my work first. 

If you think this solution would be of value to you under a different license, then lets talk off of the forum.  Tell me what value it would have to you, and what license you would need me to offer it to you under, and I'm sure we could come to an arrangement.  :)

Either way, thank you for your honest, open, willing, and frank feedback.  It is much appreciated.

Dan

Share this post


Link to post
Share on other sites
  • 0

You might want to check out this Youtube playlist: 

It talks mostly about Zynq, but all of concepts described are equally applicable for Microblaze-based systems.

 

Share this post


Link to post
Share on other sites
  • 0

Hi D@n, I am an architect and ASIC designer inside a Si company, so I only use FPGAs for pre-Si validation, demos, and some prototype work. So, I would not be the right person to discuss terms since whatever I use, it is only hit and run. 
I understand your views on this, but I am unclear how GPL helps your goals or finances? BSD would require attribution if used in a product, but does not require funds any more than GPL does.

This is always a tough area. There may be scope for a licensable low cost core, but you would be competing with whatever Xilinx/Altera throws on anyway. I do not know if RISC/V has done an FPGA version. I know when I was at ARM, we did the Cortex-M1 for FPGA and real ASIC cores do not perform as well on FPGA due to the difference between cost factors (e.g. fan-in/fan-out vs. flop cost). But, I have no idea if there is scope for more especially with the modern crop of FPGAs. Good luck!

Regards, Paul
 

Share this post


Link to post
Share on other sites
  • 0

Hi Asmi and Notarobot. I will note that I have slowly worked out how to get this working. But, that was my point. This is a painful and complex flow with a lot of steps. You can make it work (you can always make anything work) but it takes way too much trial an error. The Diligent site is far friendlier and more helpful, but I am just shocked at how hard it is to do something simple. The Block-RAM page was conceptual unless I missed something? A lot of things are way harder than they should be, and so you always have to find weird tricks. For example, the board file features from the Diligent board cannot just be picked up and used except as pre-built blocks. So, I had to add these as GPIOs and then steal their wires and then connect them to my design after changing my port to exactly match since you cannot split up such nets. That does not seem very friendly. 

I think Xilinx has gone overboard on this IP-XACT model. If they had at least better considered hybrid models so I could just create a custom "block" which I could wire up and then they provide the port list, that would be perfect. That is how Altera does it (or used to, have not used their stuff in a while). It is very backwards and very painful to do this since they are not even using the SystemVerilog modport/interface scheme which would have been easier - instead you have to use these mapping dialogs in the packagers. 

Thanks for help from all of you.

Share this post


Link to post
Share on other sites
  • 0

Posted (edited)

47 minutes ago, Paul_kimelman said:

I think Xilinx has gone overboard on this IP-XACT model. If they had at least better considered hybrid models so I could just create a custom "block" which I could wire up and then they provide the port list, that would be perfect. That is how Altera does it (or used to, have not used their stuff in a while). It is very backwards and very painful to do this since they are not even using the SystemVerilog modport/interface scheme which would have been easier - instead you have to use these mapping dialogs in the packagers. 

You can absolutely do that - there is a wizard that allows you to generate AXI-wrapper for whatever interface (or interfaces, as it's commonly the case). It's somewhat hidden (Tools -> Create or Package New IP, then pick "Create a new AXI peripheral" option, the rest is pretty self-explanatory). This will generate a separate Vivado project which you can customize to your heart's content, after that you wire your own modules to generated wrappers, package IP - and you're good to go! Here is the video which shows this flow and explains the steps (he does just what you want - creates an AXI-lite wrapper and wires his own custom module to it):

 

As for the general approach - it seems that Xilinx's idea for how design process is set up is this:

1. Modules are developed much more rarely than they are used in designs.

2. Engineer who integrates modules into the system, and engineer who develops custom modules - are two separate persons. Hence separate Vivado projects for the module and the system, and the concept of "packages".

A agree it's not very user-friendly, but once you understand the logic behind it it starts to make some sense. I was very apprehensive to it as well in the beginning, but than after realizing that Xilinx is the only FPGA vendor that gives so much IP cores for free, I took my time to learn it, and more or less learnt to love it :) 

Good luck with your designs!

Edited by asmi

Share this post


Link to post
Share on other sites
  • 0

Hi Paul,

1. The block RAM picture was conceptial. More details are in the picture. GPIOs are on the left.

2. You can create the new port on the block diagram by clicking right mouse button (or Ctrl+K) and then defining its direction, etc.

3. Constraints file in Vivado has .xdc extention. Digilent supplies definition .xdc for their boards which makes life easier.

Capture.PNG

Share this post


Link to post
Share on other sites
  • 0

HI Asmi, thans for the response. Be aware that you still have to create your own package and then keep playing with that and repackaging and so on. In a normal flow, I could edit my source file and generate the bit file. One click and done. Instead, I have to keep messing with the "package". It looks like the best bet is to make a copy of the system wrapper and then edit in place, but then you cannot use the designer to change anything. That is probably OK. I am just saying it is a cumbersome flow that is much messier and less obvious than it needs to be. I just do not understand the reasoning.

Share this post


Link to post
Share on other sites
  • 0

Posted (edited)

37 minutes ago, Paul_kimelman said:

HI Asmi, thans for the response. Be aware that you still have to create your own package and then keep playing with that and repackaging and so on. In a normal flow, I could edit my source file and generate the bit file. One click and done. Instead, I have to keep messing with the "package". It looks like the best bet is to make a copy of the system wrapper and then edit in place, but then you cannot use the designer to change anything. That is probably OK. I am just saying it is a cumbersome flow that is much messier and less obvious than it needs to be. I just do not understand the reasoning.

Hmmm I see what is the problem. I always work on components first, and only once complete & verified, integrate them into the main system. Because components use standard AXI bus, there is no need to debug the actual communications as if they both follow spec, it will just work. This is obviously the flow that Xilinx wants us to use, so I chose to adapt it in my design process (and I used similar flow before anyways, because debugging system with several half-implemented pieces is much harder as there are too many moving parts, and often it's not clear where the problem is). 

But what do I know - I'm just a hobbyist who loves building things just for the heck of it. I've studied this stuff in the university 10 years ago, but then went for a somewhat different career (software development) :) So maybe it's different in professional environment, but I use the same approach in my professional software development, so it seems very natural to me.

Edited by asmi

Share this post


Link to post
Share on other sites
  • 0

Asmi, I understand. If you end goal is this FPGA, then following their flow is OK. I do verify blocks in sim before bringing them to FPGA, but I would not be using AXI ever. I may find it easier in the end to create my own bridge since that is half the problem. Xilinx clearly did not consider that not everyone uses AXI and their flow when not is a joke. 
It still seems to me that this is more of a hobbyist flow though, so maybe it makes more sense for you. I am just using these boards as an engine to run things and this interface is in the way. I only went this way to try out the notion of using MicroBlaze for simple Firmware vs. having to use fly wire from an MCU as I normally do. If I can get one custom wrapper and then insert different RTL under it, that may still work out. That is how I would do things on Spartan 3 and then 6. I have a standard top and then insert different instantiations and just reuse the .ucf file for the pin mappings. But, in this flow it would still mean going through constant repackaging. Worse, it seems determined to copy files vs. leaving them in my standard SVN source control locations, which is not helpful. It is a shame, but I can see why you are OK with it. Regards, paul

Share this post


Link to post
Share on other sites
  • 0

Posted (edited)

I don't understand why would I not want to use AXI in my designs because it's very convenient, but if so - you may want to take a look at their Microblaze MCS IP to see if it will fit your needs. It is AXI-less so to speak too. It can be configured with simple handshake-based IO bus which is memory-mapped into MCU's address space, or you can use GPIO to interface with your modules. You can forego the use of designer and directly instantiate it in your HDL code too :) Give it a go.

Edited by asmi

Share this post


Link to post
Share on other sites
  • 0

@asmi, @Paul_kimelman,

So ... I've been thinking about this problem from a different standpoint, and perhaps a different viewpoint might be valuable ... perhaps not, but I won't know unless I speak up.  Here was my thought: after now having built designs several times over, the various components within a design generally fall into a couple categories. 

Top level: Every component tends to have some top level ports, and port declarations, which then get passed to a second module holding the non-vendor specific stuff.  Some cores require vendor specific logic, and these require variable declarations to be at the top of the file, and logic somewhere past the variable declarations.

The vendor independent module(main): Most components within a design then need to be placed within a main module.  These would also need access to their external I/O ports, a place to declare their variables before they are used (and possibly referenced by other cores), and a place for their logic to sit.

This main level might also contain any bus interconnect, since components tend to want to be placed on a bus for access by a local processor.  Something is needed, then, to 1) allocate addresses, 2) allocate interrupts to interrupt controllers, 3) handle the bus decode logic for the various peripherals, etc.  Further, as addresses are allocated, some .h/.c/.cpp files need to be written so that the processor can know 1) what components are connected to the system, 2) what peripheral addresses have been given to each, and 3) what interrupts have been assigned to each of them.

The end result should also remain something that is human readable Verilog.

This has been my current approach for building a design for the Nexys-Video.  I have put together a set of core definition files, each containing snippets of Verilog code that would be cut and pasted where needed.  These are then used to create a top level design, and even a vendor-independent main module containing any bus interactions.  So far, it is only working for this one processor, although it could easily be ported to others.

It's not done, but my goal was to make it so that the end result would be entirely in Verilog, and so could be evaluated and debugged as such.  Indeed, I'd also like to get it to where it supports multiple busses (AXI ?, WBv3, WBv4/pipelined, etc), and even bus hierarchies, but ... it's still a work in progress, and not nearly as pretty as Xilinx's tool flow.

It's a thought.  Perhaps it's closer to what you are looking for, since it leaves you with all the Verilog code that you can then investigate on your own as you see fit.

Dan

P.S.  The license is intended to apply only to the code within, not the code of yours that you might apply it to.  (Like GCC)

Share this post


Link to post
Share on other sites
  • 0

Posted (edited)

@D@n With all due respect, I think Microblaze ICS would be a much better fit for his needs as this MCU is also supported by Xilinx SDK toolchain, so writing/compiling/debugging code for it would be just as easy as for "full-blown" Microblaze (or Zynq ARM for that matter). MCU is as much about hardware as it is about software, and just about all hand-made MCU cores I've come across have no toolchain to develop code for it. Me being a software developer, having a good toolchain this is a biiig thing :) Sorry, but writing assembly code in year 2017 is a no-go, and I know if from my own experience since asm projects tend to become an unmanageable mess of "write-only" code way too quickly.

Edited by asmi

Share this post


Link to post
Share on other sites
  • 0

Posted (edited)

Also many people don't seem to realize that many Xilinx IP cores can be generated and used outside of "designer" as simple HDL modules with no AXI intefaces. You just need to invoke the wizard from "IP Catalog" button as opposed to from within a diagram. For example if you want to use MIG to create DDR3 memory controller but for some reason don't want to use AXI - you can do just that! Since Microblaze MCS IP exposes memory-mapped IO bus, if you're THAT persistent, you can even implement some kind of "glue" module to connect non-AXI DDR3 controller to that MCU as well! :) Or you can implement any other bus you want - the actual IO bus protocol is simple enough to be bridged to just about anything:

output IO_addr_strobe;
output [31:0]IO_address;
output [3:0]IO_byte_enable;
input [31:0]IO_read_data;
output IO_read_strobe;
input IO_ready;
output [31:0]IO_write_data;
output IO_write_strobe;

 

Edited by asmi

Share this post


Link to post
Share on other sites
  • 0

@asmi,

Understood regarding the toolchain.  Unlike many hobbiest built CPU's, the ZipCPU has GCC, binutils, and most recently newlib (C library) support.  Admittedly, it does not (yet) have floating point support, neither does it have anything more than a rudimentary O/S ... yet.  I do foresee Linux running on it by the end of the year.  Granted, it's not there yet.  But if all you want is a simple micro-controller (which is what the ZipCPU was designed for), then you have the basic toolchain support.

I have some problems, though, with MicroBlaze that turn me off from it: Because it is a Xilinx IP black box, I can not examine nor test with it using such open tools as Verilator or Gtkwave.  Whereas, I can test and run the ZipCPU with no hardware on my desk other than my desktop computer.  I can verify that the ZipCPU's interfaces and peripherals (flash, uart, I2C, ethernet, and others, most recently an OLEDrgb, and soon to be HDMI) work before I even purchase the FPGA or the peripherals that will be on it.  I can create programs that then interact with the simulation as though they were interacting with the actual FPGA, and set it up so that those programs cannot tell whether or not they are working with the real FPGA or not.  Even more, I can build scope's that exist both within my FPGA simulation and even within my FPGA allowing me to debug my own cores or even someone else's proprietary IP.  Further, because of Verilator's structure (it doesn't support x or z bits, only 1 or 0), I can get about 300k clock cycles per second out of a simulation.  Can you do that with Xilinx's simulator?

Tell me, could I do all of that with MicroBlaze?  Or would I be constrained to run within Xilinx's proprietary test setup, unable to examine the inner workings of why one thing happened versus something else?

Dan

Share this post


Link to post
Share on other sites
  • 0
3 minutes ago, D@n said:

@asmi,

Tell me, could I do all of that with MicroBlaze?  Or would I be constrained to run within Xilinx's proprietary test setup, unable to examine the inner workings of why one thing happened versus something else?

Dan

Well, here you go, I knew this was coming. Here is my position on all that - I'm just fine with "Xilinx's proprietary test setup" (I wonder how can you even use their ICs as their are also proprietary ASICs with no source code in sight), I don't need to "verilate" anything as I already have a board. I do, however, have a professional hate for GPL license so I always steer clear from anything that use it - even (or maybe especially so) in hobby projects. For me this is a very clear-cut concept - if I want to publish my code (however small of big it is), I do so under MIT-like license, if I want to get any money for it - I don't publish it at all.

And yes - I'm just fine with AXI bus and "full" Microblaze IP, in this topic I'm just trying to help out a person who for some reason doesn't want to use it in his designs. That's all there's to it - I don't mean to offend anyone or anything like that, so if it did came across too hard - I'm sorry.

Share this post


Link to post
Share on other sites
  • 0

Hi guys. Asmi, I am unaware of this MicroBlaze MCS. I assume it exists for Artix7. Is there an example app with it. I find starting from an example is simplest as I can just modify what I need. For what I need, I do not care about licensing or any such since I am only using this processor core for simple demo uses and the like. 

I am very interested in that I keep finding more and more bugs with the Xilinx designer flow. The latest, which wasted hours was that I had my sources where I wanted them and the packager kept messing up over and over (suddenly deciding the file is missing, losing info it had from before, making a port re-appear that does not exist, giving a warning on a port long gone, etc). They obviously have never heard of source control and so they think copying files is appropriate, which I find ridiculous (especially as it is not like they are checking if the original file changed). I also found that when I deleted some ports from the source file, it just will not make them go away from the packager which makes it painful. I will have to start over and their automatic scheme is very messed up (does not recognize buses it knows even when I have the exact same names, thinks scan_no_rst is a reset signal and scan_single_clk is a clock, but not recognizing PCLK as a clock). I do not know how people use this who are not doing only FPGA development. It is quite shocking. ISE was not super advanced but it worked very well. Sigh.

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