entity with defaulted generic constant vector

K

Ken Cecka

Hi All,

I was trying to get something similar to the following to compile today without success:

ENTITY ent IS
GENERIC
(
bits : INTEGER := 4;
val : STD_LOGIC_VECTOR((bits - 1) DOWNTO 0) := (OTHERS => '0')
);
PORT
(
reset : IN STD_LOGIC;
clk : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR((bits - 1) DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR((bits - 1) DOWNTO 0)
);
END ent;

The compilers don't seem to like me using 'bits' in the type for val (probably because bits is not considered defined while inside the GENERIC block?).

I can remove the dimensions on val, but then I can't default it to all 0s with (OTHERS => '0').

Is there any way to achieve what I'm trying to do here? I want a component with a generic bus width that also takes a generic constant which is required to match that bus width and defaults to all 0s.

I've considered passing the constant in as an integer and then using CONV_STD_LOGIC_VECTOR internally, but as I understand it, integers have a fixed width of 32 in the compiler, so the entity would not scale to designs with (bits > 32).

Thanks,
Ken
 
K

kennheinrich

Hi All,

I was trying to get something similar to the following to compile today without success:

ENTITY ent IS
  GENERIC
  (
    bits : INTEGER := 4;
    val : STD_LOGIC_VECTOR((bits - 1) DOWNTO 0) := (OTHERS => '0')
  );
  PORT
  (
    reset : IN STD_LOGIC;
    clk : IN STD_LOGIC;
    din : IN STD_LOGIC_VECTOR((bits - 1) DOWNTO 0);
    dout : OUT STD_LOGIC_VECTOR((bits - 1) DOWNTO 0)
  );
END ent;

The compilers don't seem to like me using 'bits' in the type for val (probably because bits is not considered defined while inside the GENERIC block?).

That's exactly right. The language effectively says that says the
names of the generics are visible until you get to the ports section.

I can remove the dimensions on val, but then I can't default it to all 0s with (OTHERS => '0').

Is there any way to achieve what I'm trying to do here?  I want a component with a generic bus width that also takes a generic constant which is required to match that bus width and defaults to all 0s.

I've considered passing the constant in as an integer and then using CONV_STD_LOGIC_VECTOR internally, but as I understand it, integers have a fixed width of 32 in the compiler, so the entity would not scale to designs with (bits > 32).

Thanks,
Ken

It's ugly, but the code below compiles OK.

- Kenn

-----------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity foo is

generic (
n : integer;
g1 : std_logic_vector
);
port (
pa : in std_logic_vector((n-1) downto 0));

end foo;

architecture aa of foo is

begin -- aa
assert g1'length = n report "bad generic width" severity error;
-- other stuff here...
end aa;


library IEEE;
use IEEE.std_logic_1164.all;


entity top is

end top;

architecture a of top is
signal sig : std_logic_vector(99 downto 0);
begin -- a

foo1: entity work.foo
generic map(n => 4, g1 => "1001")
port map (pa => sig(3 downto 0));

foo2: entity work.foo
generic map(n => 15, g1 => "111000111000111")
port map (pa => sig(14 downto 0));

end a;
 
K

Ken Cecka

That's exactly right. The language effectively says that says the
names of the generics are visible until you get to the ports section.



It's ugly, but the code below compiles OK.

- Kenn

-----------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity foo is

generic (
n : integer;
g1 : std_logic_vector
);

Thanks for the suggestion. That's pretty much what I finally settled on. I don't really mind the unconstrained vector - at least I can cover that with an assert. The piece that's still irritating me is the lack of a default value for g1. If you have any inspirations on how to fit that in, I'm all ears.

Ken
 
K

kennheinrich

Thanks for the suggestion.  That's pretty much what I finally settled on.  I don't really mind the unconstrained vector - at least I can cover that with an assert.  The piece that's still irritating me is the lack of a default value for g1.  If you have any inspirations on how to fit that in, I'm all ears.

Ken

Sorry, I sent the code before my brain totally connected with my
fingers. I forgot the initialization bit (compiles, but not otherwise
tested).

I use a std_logic_vector of length 0 to denote "default
initialization" but put the initialization explicitly inside the
architecture. Ugly, though. You could probably also do something
similar by defining a constant with value determined by a function
that takes g1 and n, too.

- Kenn

entity foo is

generic (
n : integer;
g1 : std_logic_vector := ""
);
port (
pa : in std_logic_vector((n-1) downto 0));

end foo;

architecture aa of foo is
signal def_val : std_logic_vector((n-1) downto 0) := (others =>
'0');
begin -- aa
assert (g1'length = n) or (g1'length = 0)
report "bad generic width" severity error;

initialize:if g1'length = n generate
def_val <= g1;
end generate;

-- other stuff here...
end aa;
 
M

Mike Treseler

Ken said:
The piece that's still irritating me is the lack of a default value for g1.
If you have any inspirations on how to fit that in, I'm all ears.

I use a package:

package stack_pkg is
constant reg_len_c : positive := 32;
subtype reg_t is std_logic_vector(reg_len_c-1 downto 0);
end package stack_pkg;


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.stack_pkg.all;

entity stack is
port (
clock : in std_ulogic;
reset : in std_ulogic;
push : in std_ulogic;
pop : in std_ulogic;
d : in reg_t;
q : out reg_t
);
end entity stack;
 
T

Tricky

Hi All,

I was trying to get something similar to the following to compile today without success:

ENTITY ent IS
  GENERIC
  (
    bits : INTEGER := 4;
    val : STD_LOGIC_VECTOR((bits - 1) DOWNTO 0) := (OTHERS => '0')
  );
  PORT
  (
    reset : IN STD_LOGIC;
    clk : IN STD_LOGIC;
    din : IN STD_LOGIC_VECTOR((bits - 1) DOWNTO 0);
    dout : OUT STD_LOGIC_VECTOR((bits - 1) DOWNTO 0)
  );
END ent;

The compilers don't seem to like me using 'bits' in the type for val (probably because bits is not considered defined while inside the GENERIC block?).

I can remove the dimensions on val, but then I can't default it to all 0s with (OTHERS => '0').

Is there any way to achieve what I'm trying to do here?  I want a component with a generic bus width that also takes a generic constant which is required to match that bus width and defaults to all 0s.

I've considered passing the constant in as an integer and then using CONV_STD_LOGIC_VECTOR internally, but as I understand it, integers have a fixed width of 32 in the compiler, so the entity would not scale to designs with (bits > 32).

Thanks,
Ken

Personally, I would probably do what Mike suggested and put it in a
package, but theres nothing to stop you declaring constants inside an
entity:

ENTITY ent IS
GENERIC
(
bits : INTEGER := 4;
);
PORT
(
reset : IN STD_LOGIC;
clk : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR((bits - 1) DOWNTO 0);
dout : OUT STD_LOGIC_VECTOR((bits - 1) DOWNTO 0)
);

constant val : STD_LOGIC_VECTOR((bits - 1) DOWNTO 0) := (OTHERS =>
'0');
END ent;

This constant is visible anywhere inside the entity. But unless you
have multiple architectures, you may aswell just put it inside the
architecture.


As to your conv_std_logic_vector commenet: this function takes 2
arguments:

my_slv <= conv_std_logic_vector( my_int, length);
So you limit the integer's length to the "length" variable, not 32
bits.
But then you should use:
my_slv <= conv_std_logic_vector( my_int, my_slv'length) to always
match the length of "slv";

But then its recommended you dont use std_logic_arith/unsigned
packages (because they are not an IEEE standard, and were last
modified byt synopsys in 1992), use numeric_std instead (the IEEE
standard, last modified 1995):

my_slv <= std_logic_vector( to_unsigned( my_int, my_slv'length));
 
A

Andy

Try the following:

ENTITY ent IS
GENERIC
(
bits : INTEGER := 4;
val : STD_LOGIC_VECTOR := (3 downto 0 => '0');
);
...

This defines the val generic as unconstrained slv (so its width can
still be changed at instantiation), but the default value is a 4 bit
slv with all '0's (which matches the bits default). You could still
have the concurrent assertion to make sure bits = val'length.

But perhaps you don't really need both bits and val? If you had val,
then you can use its length instead of bits. I think can use
val'length in the port declarations.

Andy
 
K

Ken Cecka

Sorry, I sent the code before my brain totally connected with my
fingers. I forgot the initialization bit (compiles, but not otherwise
tested).

I use a std_logic_vector of length 0 to denote "default
initialization" but put the initialization explicitly inside the
architecture. Ugly, though. You could probably also do something
similar by defining a constant with value determined by a function
that takes g1 and n, too.

- Kenn

entity foo is

generic (
n : integer;
g1 : std_logic_vector := ""
);
port (
pa : in std_logic_vector((n-1) downto 0));

end foo;

architecture aa of foo is
signal def_val : std_logic_vector((n-1) downto 0) := (others =>
'0');
begin -- aa
assert (g1'length = n) or (g1'length = 0)
report "bad generic width" severity error;

initialize:if g1'length = n generate
def_val <= g1;
end generate;

-- other stuff here...
end aa;

Thanks - I think that would do the trick. Andy's suggestion further down in the thread gives an even cleaner solution which I think I'll go with.
 
K

Ken Cecka

Tricky said:
Personally, I would probably do what Mike suggested and put it in a
package, but theres nothing to stop you declaring constants inside an
entity:

Neither of those would allow me to create multiple instances of ent with different constants. That was the goal - to make ent configurable for use in several places, but still allow for a default of all zeros if a custom value is not needed.
As to your conv_std_logic_vector commenet: this function takes 2
arguments:

my_slv <= conv_std_logic_vector( my_int, length);
So you limit the integer's length to the "length" variable, not 32
bits.
But then you should use:
my_slv <= conv_std_logic_vector( my_int, my_slv'length) to always
match the length of "slv";

Understood. But if the integer type is limited to 32-bits, wouldn't any attempt to pass in a 64-bit constant through an integer result in a truncated value before it ever gets to conv_std_logic_vector?
But then its recommended you dont use std_logic_arith/unsigned
packages (because they are not an IEEE standard, and were last
modified byt synopsys in 1992), use numeric_std instead (the IEEE
standard, last modified 1995):

Guilty as charged. Been on my mental TODO list to figure out the new libraries and start updating our codebase, but it's a ways down on the list.

Ken
 
K

Ken Cecka

Andy said:
Try the following:

ENTITY ent IS
GENERIC
(
bits : INTEGER := 4;
val : STD_LOGIC_VECTOR := (3 downto 0 => '0');
);
...

This defines the val generic as unconstrained slv (so its width can
still be changed at instantiation), but the default value is a 4 bit
slv with all '0's (which matches the bits default). You could still
have the concurrent assertion to make sure bits = val'length.

But perhaps you don't really need both bits and val? If you had val,
then you can use its length instead of bits. I think can use
val'length in the port declarations.

Andy

At first glance, I liked this solution, except I don't think it quite meets my needs. As coded above, there's an assumption that bits=4, and if a user tried to change bits, but didn't provide a value for val, then there'd be a mismatch. so there wouldn't be any point in providing the default for val in the first place.

Getting rid of bits as you suggested, would remove any chance for a width mismatch, but again, it defeats the purpose of having a default as you'd be required to provide a val for any custom width.

Probably will end up using Kenn's earlier suggestion of an empty vector acting as a flag to indicate default.

Ken
 
T

Tricky

At first glance, I liked this solution, except I don't think it quite meets my needs.  As coded above, there's an assumption that bits=4, and if a user tried to change bits, but didn't provide a value for val, then there'd be a mismatch. so there wouldn't be any point in providing the default for val in the first place.


Where are you hoping that the "val" generic comes from? It will
ultimately come from a constant (signals/variables are not
appropriate) that you could quite easily set up in a package like Mike
said. It would remove any possibilities of a size missmatch.
Understood. But if the integer type is limited to
32-bits, wouldn't any attempt to pass in a 64-bit
constant through an integer result in a truncated
value before it ever gets to conv_std_logic_vector?

yes integer is limited to 32 bits, but normally you wouldnt use larger
values if it was really intended as an integer. If its intended as a
bus, write it as such, with meningful index names.

If you really want to use integers for assigning std_logic_vectors,
then concatentate them:

my_slv <= std_logic_vector( to_unsigned(top_int, top'length) &
to_unsigned(bottom_int, bottom'length) );

If its going to be variable widths, you'll have to write functions
that know when to concatenate and when not to.
VHDL is generic and flexible, but sometimes its just best to stick
sensible limits in what you are doing.
 
K

KJ

Where are you hoping that the "val" generic comes from? It will
ultimately come from a constant (signals/variables are not
appropriate) that you could quite easily set up in a package like Mike
said. It would remove any possibilities of a size missmatch.

Using a package though prevents you from using the entity multiple
times with different configuration in the same design. I think this
is addressed by VHDL-2008 by allowing packages to have parameters.

Example:
U1 : entity work.ent generic map(bits => 4...);
U2 : entity work.ent generic map(bits => 8...);

Kevin Jennings
 
K

Ken Cecka

Tricky said:
Where are you hoping that the "val" generic comes from? It will
ultimately come from a constant (signals/variables are not
appropriate) that you could quite easily set up in a package like Mike
said. It would remove any possibilities of a size missmatch.

It would most likely be hard-coded in the instance or come from a constant. But the point is that there may be more than one instance of ent in the same design, both using different constant values. I don't see how moving bits and val into a package would let me achieve this.

E1: ent GENERIC MAP(bits => 8, val => X"12");
E2: ent GENERIC MAP(bits => 12, val => X"321");
yes integer is limited to 32 bits, but normally you wouldnt use larger
values if it was really intended as an integer. If its intended as a
bus, write it as such, with meningful index names.

Yep - that's why I'm not using an integer.
 
A

Andy

At first glance, I liked this solution, except I don't think it quite meets my needs.  As coded above, there's an assumption that bits=4, and if a user tried to change bits, but didn't provide a value for val, then there'd be a mismatch. so there wouldn't be any point in providing the default for val in the first place.

Getting rid of bits as you suggested, would remove any chance for a width mismatch, but again, it defeats the purpose of having a default as you'd be required to provide a val for any custom width.

Probably will end up using Kenn's earlier suggestion of an empty vector acting as a flag to indicate default.

Ken- Hide quoted text -

- Show quoted text -


Pick your poison...

You're still only providing one generic (ever).

-- assume the data width of the signals is really what's driving this
signal d,q : std_logic_vector(7 downto 0);

myent: entity work.ent(arch)
generic map (val => (d'range => '0')
port map (rst => rst, clk => clk, din => d; dout => q);

Andy
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top