Using abstract generic

H

hssig

Hi,

I am trying to use a generic to select a width of an implemented
signal:

entity xy is
generic ( gIC : integer := 1); -- 1: IC type x ; -- 2 IC type y
port ...
end;

architecture impl of xy is

signal sig : std_logic_vector(8 downto 0); -- when gIC = 1
-- signal sig: std_logic_vector(11 downto 0); -- when gIC = 2

end impl;

As I do not want to pass the max width of "sig" as a generic, how can
I use gIC directly to
distiniguish the declaration of "sig" ?

Cheers,
hssig
 
J

Jonathan Bromley

I am trying to use a generic to select a width of a signal:

entity xy is
generic ( gIC : integer := 1);      -- 1: IC type x ; -- 2 IC type y ....
architecture impl of xy is ....
signal sig : std_logic_vector(8 downto 0);   -- when gIC = 1
-- signal sig: std_logic_vector(11 downto 0);  -- when gIC = 2 ....
As I do not want to pass the max width of "sig" as a generic, how can
I use gIC directly to distiniguish the declaration of "sig" ?

Sorry it sounds as though I'm stuck in a rut here, but my
standard VHDL answer applies: Functions are your friend.

architecture impl of xy is

-- Given the generic value, work out the signal size
function kind_to_sig_width(design_kind: integer)
return integer is
begin
case design_kind is
when 1 => return 9;
when 2 => return 12;
when others =>
report "Unknown design kind "
& integer'image(design_kind)
severity failure;
return 0;
end case;
end function kind_to_sig_width;

constant sig_width: integer := kind_to_sig_width(gIC);

signal sig: std_logic_vector(sig_width-1 downto 0);

By using the function to construct a constant's value,
you guarantee that the function is called early enough
to allow the signal declaration to work correctly.

The function also provides a brilliant opportunity to
sanity-check the generic values that have been provided.
This is quite important if you're creating re-usable
designs, because the re-user may do something goofy
with the generics and then blame you because the
code doesn't work. Running assertion checks on the
generic values allows you to export the blame to its
rightful owner - the user :)

Finally, it may be possible/appropriate to put the
function(s) into a package, ready for use by more
than one entity that has this configurability.

HTH
 
P

Paul Uiterlinden

hssig said:
Hi,

I am trying to use a generic to select a width of an implemented
signal:

entity xy is
generic ( gIC : integer := 1); -- 1: IC type x ; -- 2 IC type y
port ...
end;

architecture impl of xy is

signal sig : std_logic_vector(8 downto 0); -- when gIC = 1
-- signal sig: std_logic_vector(11 downto 0); -- when gIC = 2

end impl;

First question I always have when I see a generic constant of type integer:
why integer?

I doubt you want to allow negative values. So use type natural instead of
integer. Or even positive. Use the smallest type that is possible.

Continuing on that path: use a range:

generic ( gIC : integer range 1 TO 2 := 1)

The advantage of all this is of course early error reporting. Errors in
supplying impossible values are caught at analysis time, they are not
delayed until simulation time.

Better still: use an enumeration type. The names of the enumeration literals
can be chosen in a way so they become self documenting (meaningful names
instead of the magical values 1 and 2). The only drawback perhaps is that
you need a package. But I hardly would call that a drawback.

Elaborating on Jonathan's function:

package xy_pkg is
type gIC_type is
(
ic_x,
ic_y
);

function gIC_to_sig_width
(
gIC: gIC_type
) return positive;
end package xy_pkg;


package body xy_pkg is
function gIC_to_sig_width
(
gIC: gIC_type
) return positive is
begin
case gIC is
when ic_x => return 9;
when ic_y => return 12;
end case;
end function gIC_to_sig_width;
end package body xy_pkg;

This shows another advantage of using an enumeration type: no "others"
needed in the case statement. This again results in another early (analysis
time) error check. Whenever you add another enumeration literal to gIC_type
and you forget to add it in gIC_to_sig_width: bzzzzzzt, analyze error!

The earlier the error, the better!

And now that I come to think of it: I think that you could skip the function
an use a table instead. That way the package body is not needed, only the
package:

package xy_pkg is
type gIC_type is
(
ic_x,
ic_y
);

type gIC_to_sig_width_type is array(gIC_type) of positive;

constant gIC_to_sig_width: gIC_to_sig_width_type :=
(
ic_x => 9,
ic_y => 12
);
end package body;


In either case, the construction of sig_width is the same:

constant sig_width: positive := gIC_to_sig_width(gIC);

All the above is untested, so syntax errors are left as an exercise to the
reader (not to mention the egg on the writer's face).
 
J

Jonathan Bromley

Better still: use an enumeration type. The names of the enumeration literals
can be chosen in a way so they become self documenting (meaningful names
instead of the magical values 1 and 2).

Historically I've always avoided suggesting the use of
non-integer generics on design entities, because some
synthesis tools did not accept them (of course, this
is nothing more than a hangover from Verilog-95 where
everything looks pretty much like an integer).

I don't do much synthesis these days. Is it now safe
to use enum generics? If so, I totally agree with Paul.

For testbench, of course, enum generics are A Good Thing
without any qualification at all.

Named integer constants (in a package) are a useful
second best, but of course they impose an obligation
on the design to check that the supplied generic is
indeed one of the legal constant values. Again I would
emphasise that this is easy to do with an assertion in
the mapping function (and is one good reason why functions
may be preferable to lookup tables-of-constants).
 
A

Allan Herriman

Historically I've always avoided suggesting the use of non-integer
generics on design entities, because some synthesis tools did not accept
them (of course, this is nothing more than a hangover from Verilog-95
where everything looks pretty much like an integer).

I don't do much synthesis these days. Is it now safe to use enum
generics? If so, I totally agree with Paul.

The only downside I've found is that they don't work on the very top
level, e.g. in Modelsim, I can't say:

vsim -Gid=value ...

unless value is of a predefined type (e.g. integer, std_logic_vector, but
not an enum). I imagine other (e.g. synth) tools have a similar
limitation.

Regards,
Allan
 
P

Paul Uiterlinden

To be honest, I don't do much synthesis either. But I would expect Altera
Quartus to handle this correctly. But again, I don't have first hand
experience and there are other synthesizers.
The only downside I've found is that they don't work on the very top
level, e.g. in Modelsim, I can't say:

vsim -Gid=value ...

unless value is of a predefined type (e.g. integer, std_logic_vector, but
not an enum).

I don't know where you got this from, but it is not mentioned in the manual:

"
Limitation: In general, generics/parameters of composite type (arrays and
records) cannot be set from the command line. However, you can set string
arrays, std_logic vectors, and bit vectors if they can be set using a
quoted string.
....
"

Which version are you using? I verified this to be working correctly in 6.3i
and 6.6a.

Code:

PACKAGE id_pkg IS
TYPE id_type IS
(
id_x,
id_y,
id_z
);
END PACKAGE id_pkg;

USE work.id_pkg.ALL;

ENTITY top IS
GENERIC
(
id : id_type
);
END ENTITY top;

ARCHITECTURE arch OF top IS
BEGIN
ASSERT false
REPORT "id=" & id_type'IMAGE(id)
SEVERITY note;
END ARCHITECTURE arch;


Compile and run:

vcom -quiet top.vhd
vsim -quiet -c -gid=id_y -do 'run; quit' top


Output:

# ** Note: id=id_y
# Time: 0 ps Iteration: 0 Instance: /top
# quit
I imagine other (e.g. synth) tools have a similar
limitation.

If that really is the case, than you should harass your vendor. If nobody
ever does that, then all these silly limitation keep existing.
 
A

Allan Herriman

To be honest, I don't do much synthesis either. But I would expect
Altera Quartus to handle this correctly. But again, I don't have first
hand experience and there are other synthesizers.


I don't know where you got this from, but it is not mentioned in the
manual:

"
Limitation: In general, generics/parameters of composite type (arrays
and records) cannot be set from the command line. However, you can set
string arrays, std_logic vectors, and bit vectors if they can be set
using a quoted string.
...
"
[snip]

Excellent news! I guess I tried that a long time ago (Modelsim 5.x?) and
it didn't work, and I didn't realise that it had been fixed in later
versions.

Cheers,
Allan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top