FPGARelated.com
Forums

How do you handle build variants in VHDL?

Started by Mike Harrison July 20, 2009
rickman wrote:

> You should also look up GENERATE. That is how to do actual code > "defines". GENERICS only get you parameters.
I found a dusty example in the stacks: ________________________________________________ architecture synth of e3dsu is -- constant disabled_for_test : boolean := true; constant disabled_for_test : boolean := false; begin verify : if disabled_for_test generate rx_clk_dis_cooked <= rx_clk_dis_raw; bitstream_o <= bitstream_i; end generate verify; normal : if not disabled_for_test generate overhead : process (rx_clk, reset) is -- pipelined cooking logic ... ________________________________________________ I find that leaving in live, but unused or obsolescent code like this is sometimes more informative to my future self, than is tiding up. It covers some of the whyDidHe, whyDidntHe questions, and can simplify maintenance. -- Mike Treseler
Mike Harrison wrote:

> Of course I realise that all FPGA tools have a great deal of 'history' > dating way before FPGAs, and everything is now probaly just too > ingrained and hard to change to suit the current state of the art. Sort > of like QWERTY keyboards....
I suspect that you've really hit the nail on the head with this statement right here. I also suspect you have a software background (as I do), or at least spend a significant amount of time writing software. Pre-processors (together with project build tools) are very powerful tools, as many multi-platform software projects can attest to. Of course, software has a much longer history of concepts such as cross-platform development, re-use (at the macro level) and layers of abstraction and (more recently) emulation/virtualisation. IMHO the hardware/firmware world (and their tools) have a bit of catching up to do in this area - not through any fault of the practitioners but rather due the very nature of the work and the technologies involved. As we see the line increasingly blur between hardware and software, I'd hope that cross-pollination benefits both areas of engineering. Regards, -- Mark McDougall, Engineer Virtual Logic Pty Ltd, <http://www.vl.com.au> 21-25 King St, Rockdale, 2216 Ph: +612-9599-3255 Fax: +612-9599-3266
Mike Treseler wrote:

> I find that leaving in live, but unused > or obsolescent code like this > is sometimes more informative > to my future self, than is tiding up.
So I'm not the only one!!! Good to know! ;) Regards, -- Mark McDougall, Engineer Virtual Logic Pty Ltd, <http://www.vl.com.au> 21-25 King St, Rockdale, 2216 Ph: +612-9599-3255 Fax: +612-9599-3266
On Jul 22, 5:45 pm, Mike Harrison <m...@whitewing.co.uk> wrote:
<snip>

> >Then, OK the #ifdef lets you make this edit quicker. But that means > >either that you also have to edit the type definition to remove the > >'Blah' state or leave it in and let the 'when others' pick it up and > >hope that this state bit synthesizes away so it doesn't cost you. The > >other way to code this would be... > > A few extra unused states probably wouldn't be a big deal compared to the logic generated to deal > with them. >
I disagree that extra states are not a big deal, but not because of logic resource concerns but due to debug methodology. Typical hardware design flows rely (or should rely) on simulation for logic validation. You setup a testbench (more VHDL that stimulates all the inputs and check the outputs) and run a test case (or cases) that exercises the logic that is under test. When something is 'not right', you enter debug mode but that effort typically would not involve writing or changing code in the thing you're testing (i.e. adding the 'debug' state in your example). Instead it mostly involves eyeballing the time history of signals leading up to the bad thing, all of this information is available in the simulator [1]. Once you find the root cause, you change and re-run the sim. Adding the extra state functionally changes the behaviour of the design, it delays things by a clock cycle or two, it changes the thing you're trying to debug. At worst, this change 'fixes' the problem that you were trying to find...but you don't know why it 'fixed' it At best it is not much more than a waste of time because the entire history of every signal is already available at your disposal, there really is nothing more needed to debug any functional problem. The software methodolgy of adding extra tracing/debug code to home in on the root cause of the problem is not really the right mindset here. In simulation you have access to the entire history of every signal. Software debug typically does not have this entire history at your fingertips. There is also debug on real hardware, but the methodology here is to use logic analyzer resources to get a clue as to what signal(s) seem to be at the root cause of the problem without functionally changing the design at all (i.e. you're passively viewing internal design signals). There's more to it than that, but again if you put functional changes in (like your state machine example) in order to debug a problem...you're probably not debugging in a very effective manner...and you'll be slogging it for a long time. [1] Some people prefer to restart and then step through code, I typically don't, it's a preference thing.
> >I don't see any inherent advantage in the situation you alluded to > >where #ifdef-ing the entire 'when xxx' statement versus using other > >coding styles...but you and others might disagree...that's fine. > > The point was really that one construct - #ifdef etc. - could be used for pretty much all aspects > that may be variable - state-machine behaviour, signal sizes, clock dividers, outputting debug data, > pin assignments whatever.
Well signal sizes and clock dividers are very easily changable via a 'debug' parameter or any other parameter so those don't really fly [2], [3]. Changing functional behaviour and outputting debug data are things that you should eventually come to realize are not needed as I noted above. Right now you may not be at that realization point. You could 'improve' the language by adding #ifdef, but in the end you'll likely find that it's not nearly as useful as you once thought. There probably are some good use cases for #ifdef being more effective than what is in the language today...I just don't think you've described one where there isn't a more effective mechanism already available without it. [2] Signal size example: signal xyz: std_logic_vector(sel(debug, 15, 7) downto 0); where 'sel' is a function you can write that is basically equivalent to something like the following in C x <= debug ? 15, 7; [3] signal Timer_Counter: natural range 0 to MAX_TIME / CLOCK_PERIOD; where 'MAX_TIME' is a parameter that defines whatever you want the timer to count up to; CLOCK_PERIOD would be the period of the input clock...both are simply parameters that get passed into and control the entity. You could also use the above mentioned 'sel' function to select between two upper ranges as well.
> This seems a more logical way to do it, as the 'C' guys seem to have > figured out a long tome ago....
C guys also brought us buffer overruns.
> I think the problem is that VHDL dates back before FPGAS, and ASICs don't tend to have many > variants... >
Maybe...but VHDL is derived from Ada which is a software language. Ada probably has roots that go back to something earlier too, but the point is that VHDL was birthed from a software language not a hardware one.
> >> or servicing peripheral devices which are not present in some variants > >> Obviously 'others' will catch things that are conditionally excluded and take it to the 'idle' > >> state. > > >If the peripherals are not there in some variants, then simply not > >connecting any of the output signals from the entity that produces the > >unneeded signals to any of the top level entity outputs is > >sufficient. The synthesis tool will not produce any logic to > >implement anything that doesn't affect an output pin. > > there may be input-only peripherals, and you may want to make sure no logic is generated as that > variant may have alternative functionality that needs the space.
Not sure what you mean by an 'input-only' peripheral, but the bottom line is that entity outputs that do not affect any output pins will get optimized away...take your existing design and connect the clock input to some entity to '0' or leave it unconnected and run ISPLever and watch that entire entity disappear.
> The particular design I'm > considering is going to end up in the smallest EC1 device and so this may be an issue. >
If paranoid surrounding an entity within a generate statement will do the trick.
> > > >> Yes they will - I have a prototype running on a devboard with a 484BGA with tons of extra IOs for > >> debug outputs, and the production board will be the same device in 144QFP. > >> It is also quite plausible that changes in production boards need pin allocations to change for > >> layout reasons, as the board is only 4 layer.. > > >That would be an example of two different boards with two different > >parts...as I mentioned previously either of these two conditions is > >not an example of ever having to 'move' a signal, it is an example of > >two different designs. > > Two different designs that share the same subset of functionality, which should also share the same > source files, to minimise the effort switching between them/. >
It's pretty darn easy to switch to (or open in parallel) multiple projects via 'File->Open'...'specially if they're in the MRU list. How is that more difficult than changing some other build setting? Once you've done so (change some build setting), how do you keep track of how a given file was built? You can't exactly peruse the binary output file to check to see how that setting was set. Now you've created a configuration management issue, the only way to know how a particular xyz.bin file was built is to rebuild it. It's that type of thing that then evolves into the design suddenly having some magic read only port that returns some information so you'd know how something was set during the build. Yes you can do that...or you can simply have better configuration management, build procedures and source file control/archiving...that's how you handle it properly. Using the GUI to change settings should only be a more convenient mechanism then directly editing the project file with a text editor. But the end result of that changed file should be under source control management. <snip>
> Wherever they belong, the ability to easily switch versions would make things a whole lot easier.
See above
> > >Kevin Jennings > > I will need to look further into what can be done with the project system - I'm fairly new to this, > need to get something working in a hurry but am conscious that there will be variants in the future. > The IDE and number of files created by my (currently) two source files (VHDL and prefs) is somewhat > bewildering - hopefully when I've got this prototype running I'll have time to sit down with all the > documentation.... >
Sounds good...just keep in mind that VHDL is used to describe logic. If you're considering entering 'non-logic' things into those particular source files, you're probably not going about it quite right.
> It just seems to me from a 'common sense' viewpoint that although the processes of compiling a C > program and syntesising for an FPGA are very different, the requirements for managing variants are > almost identical, so a means of doing it in the same way would seem to be a sensible way to do it. > A preprocessor which preprocessed all source files in a project, be they VHDL, pin mappings, timing > constraints, memory contents in a uniform fashion just seems to be an obvious way to do it... >
OK, but even in the C software world you want to have source file control, config management practices in place. All of what I mentioned above would still apply. Hope I've given you some things to ponder, good luck on your design. Kevin Jennings
On Jul 22, 8:43=A0pm, Mark McDougall <ma...@vl.com.au> wrote:
> Mike Treseler wrote: > > I find that leaving in live, but unused > > or obsolescent code like this > > is sometimes more informative > > to my future self, than is tiding up. > > So I'm not the only one!!! Good to know! ;) >
No you're not alone, at least three of us now...but then you also said earlier that you leave in some "obsolete/experimental/irrelevant code without it passing elaboration"...that's a bit different. You're not alone there either, but if I keep something like that around it's commented out. I'd much rather it be live code that really does elaborate and sim. Kevin Jennings
>> Mike Treseler wrote: >>> I find that leaving in live, but unused >>> or obsolescent code like this >>> is sometimes more informative >>> to my future self, than is tidying up.
> On Jul 22, 8:43 pm, Mark McDougall <ma...@vl.com.au> wrote: >> So I'm not the only one!!! Good to know! ;)
KJ wrote:
> No you're not alone, at least three of us now...but then you also said > earlier that you leave in some "obsolete/experimental/irrelevant code > without it passing elaboration"...that's a bit different. You're not > alone there either, but if I keep something like that around it's > commented out. I'd much rather it be live code that really does > elaborate and sim.
I agree. If some of my "switched off" code does not elaborate, that means I have changed or eliminated the target of some identifier that previously make the code usable. I would either fix up the option or take it all out. The advantage of leaving the dependency in, is, that I'll get a warning if I unintentional rule out future use of the option. Even if the option is never again used, it is an effective way to document ambiguity by letting the code talk about itself. -- Mike Treseler
On Jul 22, 2:09=A0am, Mike Harrison <m...@whitewing.co.uk> wrote:
> On Tue, 21 Jul 2009 06:08:46 -0700 (PDT), Andy <jonesa...@comcast.net> wr=
ote:
> >Unfortunately, the generate statement only allows conditionally > >including concurrent statements. > > so does that mean that, for example, you couldn't use it to conditionally=
exclude particular case
> branches in a case structure? > > > > >You must use subprograms or if- > >statements based on generics for conditionally executing sequential > >code. And while you can't conditionally declare objects, you can make > >unconditional declarations dependent upon generic parameters > >(constants can be initialized by a function call that takes a > >generic). Generate does allow a local declarative region for the > >concurrent statement(s) that are included, but those declarations are > >not visible outside of it. > > >In most cases you can use a constant anywhere you could use a generic. > >You can use a generic anywhere you could use a deferred constant > >(beware locally static restrictions). > > >With generic driven packages in the new standard, the (dis)advantages > >of generics vs package of constants may get more blurred. > > >Andy > > The replies so far suggest to me that it could get far more complicated t=
han it would be if a #ifdef
> type feature were available, which would be universally applicable to any=
type of construct.
> I've yet to look in detail but it seems like the code/project structure h=
as to be significantly
> designed around the need to handle variants. > > ISPLever can specify pin mapping within the VHDL, so this would also prov=
ide a way to handle pinout
> differences between boards. > I can't immediately see any way to make ISPLever select different prefere=
nces files based on a
> simple option - any suggestions/examples on this would be appreciated.
Looks like something like ifdef's in the preference file might be helpful. ispLever has this, a user can have many options inside one preference file. This is called 'preference scripts' in ispLever help. Please have have a look at : Design Flow User Guide>Design Implementation>Applying Design Constraints> Using Preference Scripts in ispLever html help. You can have a single preference file for different boards/FPGA targets and/or for DEBUG or release, for example. You will still have to do a simple edit for the .lpf, however it can be done in a clearly defined 'header' region with main (verbose) variables. Alex
Mike Treseler wrote:

> I agree. If some of my "switched off" code does not elaborate, > that means I have changed or eliminated the target of some identifier > that previously make the code usable. > I would either fix up the option or take it all out.
I have a project suite that I've been attempting to perfect for some time. It consists of a "framework" if you like, comprising a hierarchy of entities, some of which may be substituted with project-specific variants, whilst others may be provided by generic, cross-project architectures. The suite itself is used in "many" projects, each of which may be targeted to "many" hardware platforms. I use records as far as possible when defining the ports of entities within the framework. Each entity can have up to a dozen records as ports, as each record contains only closely-related signals. In general thus far, record declarations are "global" across projects - they never change. Recently however, I've introduced a record that may be defined on a per-project basis. This record is used in a number of entities throughout the suite. This doesn't cause problems with entity ports so much - it's when, for example, those (variable) record members are accessed directly in "generic" modules within the framework. Now, this is all very much WIP, and I'm not claiming that the problem can't better be solved (I've tried to use configurations but either they just don't seem to suit my purpose, result in redundant coding effort which complicates maintenance, or I can't work out how to use them properly), but it is in these cases that it would be very useful to be able to exclude code segments, based on a constant or generic or compiler directive, that wouldn't - for this project - pass compilation. And again, this is only one example. Anyway, I offer this explanation not for any justification of my methods, but merely an explanation of what I am trying to achieve. I would acknowledge that this is far from the typical or perhaps even intended use of VHDL. Regardless, I'm not convinced that my goal is ultimately realisable using current VHDL standards and current-gen tools (happy to be proven wrong). What I _do_ know is that I could easily achieve this in software. Regards, -- Mark McDougall, Engineer Virtual Logic Pty Ltd, <http://www.vl.com.au> 21-25 King St, Rockdale, 2216 Ph: +612-9599-3255 Fax: +612-9599-3266
On Jul 23, 8:16=A0am, KJ <kkjenni...@sbcglobal.net> wrote:
> OK, so what is inherently better about this... > > case xyz is > =A0 when Blah =3D> > =A0 =A0 #ifdef DEBUG > =A0 =A0 =A0 -- Put your debug code here > =A0 =A0 #end if > =A0 =A0...etc... > end case; > > Compared to this... > case xyz is > =A0 when Blah =3D> > =A0 =A0 if DEBUG > =A0 =A0 =A0 -- Put your debug code here > =A0 =A0 end if; > =A0 =A0...etc... > end case;
Try this: When the #IFDEF is used as a block comment, to remove declarations, or whole chunks of source code, that do not fit inside a case (or similar) statement. That's why many languages use separate syntax for the Flow (conditional compile) stuff : even tho you can cover many instances with constants, you cannot cover all... -jg
On Jul 22, 4:45=A0pm, Mike Harrison <m...@whitewing.co.uk> wrote:
> It just seems to me from a 'common sense' viewpoint that although the pro=
cesses of compiling a C
> program and syntesising for an FPGA are very different, the requirements =
for managing variants are
> almost identical, so a means of doing it in the same way would seem to be=
a sensible way to do it. =A0
> A preprocessor which preprocessed all source files in a project, be they =
VHDL, pin mappings, timing
> constraints, memory contents in a uniform fashion just seems to be an obv=
ious way to do it... When the only tool in your toolbox is a hammer, you tend to treat every problem like a nail, and pound it into submission. Pre-processors were developed to handle deficiencies in existing programming languages. Some later languages built in many/most of those features so that the language itself controlled the semantics, not an external text processing step. Seems some SW developers also have a lot of "history" and...
> everything is now probaly just too ingrained and hard to change to suit t=
he current state of the
> art.
With modern, optimizing compilers (for both software and hardware languages) constants (and generics in VHDL) can be used to optimize away whole chunks of code, just as if it had been ifdef'd out of existence before it hit the compiler, with or without the limitations of the generate statement. But with the language controlling the semantics, you don't get awkward ifdef constructs that arbitrarily cross language semantic structures (like an ifdef statement mixed around when statements). For example, if you gate all the interface signals to a module with a generic/constant, the synthesis tool will not implement one gate/flop of it (leave the clock and reset alone, they'll go away by themselves). Any simulator worth it's salt will likewise optimize it away (if you care about simulation). On the other hand, if a HW hacker (that's what I'd call an "FPGA developer" that neither simulates nor believes his code will ever be seen/used/maintained by anyone else again) wants to abandon the capabilities of the language for his pre-processor comfy crutches, to each his folly. Andy