Conditional Interpretation of VHDL

D

David Wade

Guest
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

Dave Wade
 
David Wade <dave.g4ugm@gmail.com> wrote:
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

For verilog, there is `ifdef, similar to the C #ifdef.

It seems that VHDL has if/generate, but I haven't tried it.

Otherwise, most synthesis tools are good at removing unused logic.
If you code such that the unneeded signals aren't used, the logic
to generate them won't be, either.

But it looks to me like if/generate should do what you want.

-- glen

> Dave Wade
 
In article <mm9ub8$qlq$1@dont-email.me>,
GaborSzakacs <gabor@alacron.com> wrote:
glen herrmannsfeldt wrote:
David Wade <dave.g4ugm@gmail.com> wrote:
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

For verilog, there is `ifdef, similar to the C #ifdef.

It seems that VHDL has if/generate, but I haven't tried it.

Otherwise, most synthesis tools are good at removing unused logic.
If you code such that the unneeded signals aren't used, the logic
to generate them won't be, either.

But it looks to me like if/generate should do what you want.

-- glen

Dave Wade

I'm not sure if if/generate will help if what you want is to define a
different set of module ports. `ifdef is pre-processed, so you can slap
it anywhere in the code to conditionally include or leave out items.

--
Gabor

Speaking VERY generally here, but I think it's appropriate...

The usual way to solve this sort of thing is to group the requisite
shared logic in shared files. Then have two unique top levels
which just feed the approprate signals down to the shared
modules.

Pretty straightforward really; shared code lives in shared files. Unique code
lives in unique files. If you find yourself cut/pasting code too much, you
need to rethink the code organization.

Also, do rely on synthesis optimizations, as Glen indicated. These tools are
VERY mature, and very good at their job. If your shared code includes some
redundant (or unused) information in a certain solution, that's ok - leave it
dangling unused. The optimizer will remove the unusued logic just fine.
Similarly for inputs to shared modules - tied constants at inputs are optimized
just as easily (through sequential stages too).

Regards,

Mark
 
Mark Curry <gtwrek@sonic.net> wrote:
> In article <mm9ub8$qlq$1@dont-email.me>,

(snip on optional logic for two choices)

I'm not sure if if/generate will help if what you want is to define a
different set of module ports. `ifdef is pre-processed, so you can slap
it anywhere in the code to conditionally include or leave out items.

Yes, it probably doesn't do that.

I was thinking of the case where the ports have different signals
for the two cases, or aren't used for one.

Speaking VERY generally here, but I think it's appropriate...

The usual way to solve this sort of thing is to group the requisite
shared logic in shared files. Then have two unique top levels
which just feed the approprate signals down to the shared
modules.

That sounds about right to me, though it depends on the actual goal.

With big FPGAs, it is almost as easy to generate logic and use
only the parts you need.

Pretty straightforward really; shared code lives in shared files.
Unique code lives in unique files. If you find yourself
cut/pasting code too much, you need to rethink the code organization.

Also, do rely on synthesis optimizations, as Glen indicated.
These tools are VERY mature, and very good at their job.
If your shared code includes some redundant (or unused)
information in a certain solution, that's ok - leave it dangling
unused. The optimizer will remove the unusued logic just fine.

I remember all those times where a tiny logic mistake causes the
tools to remove everything. It takes some tracing back to see
why it did that.

Similarly for inputs to shared modules - tied constants at inputs
are optimized just as easily (through sequential stages too).

-- glen
 
glen herrmannsfeldt wrote:
David Wade <dave.g4ugm@gmail.com> wrote:
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

For verilog, there is `ifdef, similar to the C #ifdef.

It seems that VHDL has if/generate, but I haven't tried it.

Otherwise, most synthesis tools are good at removing unused logic.
If you code such that the unneeded signals aren't used, the logic
to generate them won't be, either.

But it looks to me like if/generate should do what you want.

-- glen

Dave Wade

I'm not sure if if/generate will help if what you want is to define a
different set of module ports. `ifdef is pre-processed, so you can slap
it anywhere in the code to conditionally include or leave out items.

--
Gabor
 
On 6/22/2015 2:33 PM, David Wade wrote:
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

I'm not sure you will find much difference keeping two projects up to
date and keeping one project with two projects nested within "if"
statements. I've tried this before and found it to be a royal PITA.
The size of each file grows and the conditionals make the code much
harder to read.

What I ended up with was to encapsulate the two varieties in two
separate files (rather than letting the differences be spread across the
project) and built two separate projects. They were still 90+% the same
so a lot of testing could be reused.

--

Rick
 
Mark Curry <gtwrek@sonic.net> wrote:
Also, do rely on synthesis optimizations, as Glen indicated. These tools are
VERY mature, and very good at their job. If your shared code includes some
redundant (or unused) information in a certain solution, that's ok - leave it
dangling unused. The optimizer will remove the unusued logic just fine.

Except when it doesn't.

For instance, I have a toplevel model that defines some ports that are
driven by transceivers. The pins are configured with appropriate I/O
standards etc in the project configuration.

Let's say I change my PCIe port from 4x to 1x, which is a simple dropdown on
the PCIe core. If I have the ports on my toplevel module, but don't connect
them to anything, I get an error. If I remove the ports from my toplevel
module, but leave the transceiver settings alone, it compiles.

The result is I have to do:

module toplevel (
output PCIE_TX0_p,
input PCIE_RX0_p,
`ifdef PCIE_LANES_2X
output PCIE_TX1_p,
input PCIE_RX1_p,
`ifdef PCIE_LANES_4X
output PCIE_TX2_p,
input PCIE_RX2_p,
....
`endif
`endif
)

This is an unusual corner case, but there's an unusual case around every
corner.

Theo
 
Thanks for all the suggestions. More posts in-line,,,,

On 22/06/2015 23:14, Mark Curry wrote:
In article <mm9ub8$qlq$1@dont-email.me>,
GaborSzakacs <gabor@alacron.com> wrote:
glen herrmannsfeldt wrote:
David Wade <dave.g4ugm@gmail.com> wrote:
I have a small project that produces a clone of the "BABY" computer at
MOSI. I want to be able to produce two versions of the code, one which
displays on a VGA screen and another which uses a Luminescent display.

To do this I need to be able to set different output signals depending
on the way its built.

At present I am building two different projects and keeping them both up
to date is a bit of a pain.

For verilog, there is `ifdef, similar to the C #ifdef.

It seems that VHDL has if/generate, but I haven't tried it.

Otherwise, most synthesis tools are good at removing unused logic.
If you code such that the unneeded signals aren't used, the logic
to generate them won't be, either.

But it looks to me like if/generate should do what you want.

-- glen

Dave Wade

I'm not sure if if/generate will help if what you want is to define a
different set of module ports. `ifdef is pre-processed, so you can slap
it anywhere in the code to conditionally include or leave out items.

--
Gabor

Speaking VERY generally here, but I think it's appropriate...

The usual way to solve this sort of thing is to group the requisite
shared logic in shared files. Then have two unique top levels
which just feed the approprate signals down to the shared
modules.

Pretty straightforward really; shared code lives in shared files. Unique code
lives in unique files. If you find yourself cut/pasting code too much, you
need to rethink the code organization.

I think I need to do that any way, but I am finding it mildly
challenging. I probably need to re-organize the code...

Also, do rely on synthesis optimizations, as Glen indicated. These tools are
VERY mature, and very good at their job. If your shared code includes some
redundant (or unused) information in a certain solution, that's ok - leave it
dangling unused. The optimizer will remove the unusued logic just fine.
Similarly for inputs to shared modules - tied constants at inputs are optimized
just as easily (through sequential stages too).

OK I am sure I can do that but I.

Regards,

Mark

Dave
 
Theo Markettos <theom+news@chiark.greenend.org.uk> wrote:

(snip)

The optimizer will remove the unusued logic just fine.

Except when it doesn't.

For instance, I have a toplevel model that defines some ports that are
driven by transceivers. The pins are configured with appropriate I/O
standards etc in the project configuration.

Let's say I change my PCIe port from 4x to 1x, which is a simple dropdown on
the PCIe core. If I have the ports on my toplevel module, but don't connect
them to anything, I get an error. If I remove the ports from my toplevel
module, but leave the transceiver settings alone, it compiles.

This might depend on VHDL or veriog, but sometimes I assign Z to I/O
ports, which will make the tools happy, and I can still use them as
input ports. It might be that you can still also assign output values.

Or you could use `ifdef or IF/GENERATE to assign them either the
real value or a constant value. I usually assign constants instead
of remove ports. (It makes it easier to add back later.)


The one that keeps bothering me, is that you can't have lines in
the UCF file for ports you aren't using.

It would be really nice to include the whole UCF, and have it ignore
the ports that your design didn't need (yet).

-- glen
 
On 6/23/2015 4:08 PM, glen herrmannsfeldt wrote:
Theo Markettos <theom+news@chiark.greenend.org.uk> wrote:

(snip)

The optimizer will remove the unusued logic just fine.

Except when it doesn't.

For instance, I have a toplevel model that defines some ports that are
driven by transceivers. The pins are configured with appropriate I/O
standards etc in the project configuration.

Let's say I change my PCIe port from 4x to 1x, which is a simple dropdown on
the PCIe core. If I have the ports on my toplevel module, but don't connect
them to anything, I get an error. If I remove the ports from my toplevel
module, but leave the transceiver settings alone, it compiles.

A standard way to do this without `ifdef is to make the ports vectors
and use a parameter to define the port width. At least that's how the
xilinx cores do it, and it works for either VHDL or Verilog. It's
a bit clunky to refer to a lane as TXn[3] / TXp[3] (one bit slice
of each of two "vectors" to make a differential pair) but it works.

This might depend on VHDL or veriog, but sometimes I assign Z to I/O
ports, which will make the tools happy, and I can still use them as
input ports. It might be that you can still also assign output values.

Or you could use `ifdef or IF/GENERATE to assign them either the
real value or a constant value. I usually assign constants instead
of remove ports. (It makes it easier to add back later.)


The one that keeps bothering me, is that you can't have lines in
the UCF file for ports you aren't using.

You can certainly leave constraints for unused ports in Xilinx tools.
There's a couple of command line options, -aul and -aut IIRC to allow
unmatched LOC constraints and unmatched timing constraints. In some
versions of ISE, you can place all constraints for a port, LOC, IO
Standard, Slew, Pullup, etc. on one line using | between constraints
and the -aul will ignore the full line. In other versions the -aul
just ignores some of the constraints and errors out on others.
Oh, well...

It would be really nice to include the whole UCF, and have it ignore
the ports that your design didn't need (yet).

-- glen

--
Gabor
 
Gabor <gabor@szakacs.org> wrote:

(snip, I wrote)
The one that keeps bothering me, is that you can't have lines in
the UCF file for ports you aren't using.

You can certainly leave constraints for unused ports in Xilinx tools.
There's a couple of command line options, -aul and -aut IIRC to allow
unmatched LOC constraints and unmatched timing constraints. In some
versions of ISE, you can place all constraints for a port, LOC, IO
Standard, Slew, Pullup, etc. on one line using | between constraints
and the -aul will ignore the full line. In other versions the -aul
just ignores some of the constraints and errors out on others.
Oh, well...

So far, I use the GUI, but sometime should switch to the
command line version. Maybe the GUI allows it, too, but I
didn't see where.

-- glen
 
Gabor <gabor@szakacs.org> wrote:
On 6/23/2015 4:08 PM, glen herrmannsfeldt wrote:
Theo Markettos <theom+news@chiark.greenend.org.uk> wrote:

Let's say I change my PCIe port from 4x to 1x, which is a simple
dropdown on the PCIe core. If I have the ports on my toplevel module,
but don't connect them to anything, I get an error. If I remove the
ports from my toplevel module, but leave the transceiver settings
alone, it compiles.

A standard way to do this without `ifdef is to make the ports vectors
and use a parameter to define the port width. At least that's how the
xilinx cores do it, and it works for either VHDL or Verilog. It's
a bit clunky to refer to a lane as TXn[3] / TXp[3] (one bit slice
of each of two "vectors" to make a differential pair) but it works.

That works if I'm changing the width of a port, but what if I'm not using
PCIe at all today? I don't believe you can do:

`parameter PCIE_WIDTH -1

output [`PCIE_WIDTH:0] PCIE_TX_p;

and hope that it'll delete PCIE_TX_p completely.

You can certainly leave constraints for unused ports in Xilinx tools.
There's a couple of command line options, -aul and -aut IIRC to allow
unmatched LOC constraints and unmatched timing constraints. In some
versions of ISE, you can place all constraints for a port, LOC, IO
Standard, Slew, Pullup, etc. on one line using | between constraints
and the -aul will ignore the full line. In other versions the -aul
just ignores some of the constraints and errors out on others.
Oh, well...

Most of the time this works for Altera too, it's the case of transceivers
where it doesn't. I have no idea why, it's arguably a bug in the tools.

The tools don't like partitions or LogicLock regions which aren't
associated with logic, but that's more likely to be a bug that you want to
be alerted of. It's a pain when the list of modules in your design is
configurable, though.

Theo
 
glen herrmannsfeldt wrote:
Gabor <gabor@szakacs.org> wrote:

(snip, I wrote)
The one that keeps bothering me, is that you can't have lines in
the UCF file for ports you aren't using.

You can certainly leave constraints for unused ports in Xilinx tools.
There's a couple of command line options, -aul and -aut IIRC to allow
unmatched LOC constraints and unmatched timing constraints. In some
versions of ISE, you can place all constraints for a port, LOC, IO
Standard, Slew, Pullup, etc. on one line using | between constraints
and the -aul will ignore the full line. In other versions the -aul
just ignores some of the constraints and errors out on others.
Oh, well...

So far, I use the GUI, but sometime should switch to the
command line version. Maybe the GUI allows it, too, but I
didn't see where.

-- glen

In the GUI you go to translate properties --> "Other NGDBuild
command line options" and there you can add any options you
want. However more recent versions of the GUI have -aul
and -aut as check boxes as well.

--
Gabor
 
GaborSzakacs <gabor@alacron.com> wrote:

(snip on ignoring UCF entries for pins that don't exist.)

So far, I use the GUI, but sometime should switch to the
command line version. Maybe the GUI allows it, too, but I
didn't see where.

In the GUI you go to translate properties --> "Other NGDBuild
command line options" and there you can add any options you
want. However more recent versions of the GUI have -aul
and -aut as check boxes as well.

OK, I did that.

Thanks!

This is especially useful for starter boards which have a lot of
pins that you aren't using, but also for general purpose boards,
again with extra pins that you might not be using.

-- glen
 
Gabor wrote:
The one that keeps bothering me, is that you can't have lines in
the UCF file for ports you aren't using.

You can certainly leave constraints for unused ports in Xilinx tools.
There's a couple of command line options, -aul and -aut IIRC to allow
unmatched LOC constraints and unmatched timing constraints. In some
versions of ISE, you can place all constraints for a port, LOC, IO
Standard, Slew, Pullup, etc. on one line using | between constraints
and the -aul will ignore the full line. In other versions the -aul
just ignores some of the constraints and errors out on others.
Oh, well...

<rant>
I never got why the DEFAULT behaviour is to quit with an error when
there's LOC constraints for non-existant ports, but only issue a warning
(which easily gets lost amongst thousands others in the logs) if an
existing port is NOT location constrained.
The tool then places the IO randomly, and this is most certainly not the
desired behaviour, since you could potentially damage hardware when
you're driving an IO that connects to something that should not be
driven. Unlikely, but possible.

The only exception I can think of is in the hardware concept phase, when
you want to let the tools chose a valid pin out for you that you can
then copy to your schematic. But that is a rare case that IMHO would
justify an extra mouse click or an added command line switch.

This DEFAULT behaviour is stupid IMHO. Of course you can change it with
obscure command-line switches or a setting hidden away in some
"Advanced" tab, but someone at Xilinx must have deliberately chosen to
make this the default behaviour for whatever reason, and I don't get it.
I think this is one of these things that got introduced in a very early
software release, and even though it doesn't make any sense at all, it
was never fixed because people would get confused if the default
behaviour changed.

I think Vivado now issues a "Critical Warning" by default for
unconstrained ports.
Sounds better, but when you think about it, it doesn't help a lot, since
critical warnings also do not stop the flow (unless you promote that
warning to an error).
Unless you use the GUI, those critical warnings can also easily get lost
in the log files if you don't specifically look for them, especially
when you use a purely command-line driven flow like me.

Not to mention that I don't understand what the hell a "Critical
Warning" is supposed to be. Either it's a warning, or it's critical, and
then it'd better be an error. What sense does it make to introduce
another severity level in between "warning" and "error"? I personally
have not seen a "critical warning" that did not cause me to re-run the
entire flow, and then it would have been better to stop the flow right
the moment the critical warning occured as not to waste my time. That's
why I've promoted all critical warning to errors, which fortunately is
easy enough in Vivdao via Tcl.

</rant>,
Sean
 

Welcome to EDABoard.com

Sponsor

Back
Top