Default value for an unconstrained port

X

XYZ

Hi,

How to set a default value for an unconstrained port? Doing it this way
input : in std_logic_vector;
val : in std_logic_vector := (others => '0');
doesn't work as val'range is not known and obviously I end up with
ModelSim error "OTHERS choice can not be used in unconstrained array
aggregate."

I know, however, that val'range should be the same as input'range. Is
there any way to define a default value for val vector based on input
(input is constrained by higher entity). I need something like
val : in std_logic_vector := (input'range => '0')

I'm afraid that even if there exist different method than OTHERS to
create a vector I wouldn't be allowed to use input'range because of
"object 'input' cannot be used within the same interface as it is
declared" error.

Is it better to switch to generics rather than use unconstrained ports?

Thanks.
 
X

XYZ

Hi,

How to set a default value for an unconstrained port? Doing it this way
input : in std_logic_vector;
val : in std_logic_vector := (others => '0');
doesn't work as val'range is not known and obviously I end up with
ModelSim error "OTHERS choice can not be used in unconstrained array
aggregate."

I know, however, that val'range should be the same as input'range. Is
there any way to define a default value for val vector based on input
(input is constrained by higher entity). I need something like
val : in std_logic_vector := (input'range => '0')

I send the previous post too fast. It turns out that the above is a
valid VHDL syntax, so please skip the text above. Now, as expected, I
faced the error given below. Is there anything I can do?
I'm afraid that even if there exist different method than OTHERS to
create a vector I wouldn't be allowed to use input'range because of
"object 'input' cannot be used within the same interface as it is
declared" error.

Is it better to switch to generics rather than use unconstrained ports?

Thanks.
 
P

Paul Uiterlinden

XYZ said:
Hi,

How to set a default value for an unconstrained port? Doing it this way
input : in std_logic_vector;
val : in std_logic_vector := (others => '0');
doesn't work as val'range is not known and obviously I end up with
ModelSim error "OTHERS choice can not be used in unconstrained array
aggregate."

And rightfully so. If you leave an unconstrained port unconnected, what
width is it supposed to be? Or more general: what range should the index
be? It can not be determined from anything.

As a solutions, what you could do is something like this:

val : in std_logic_vector := (31 downto 0 => '0');

Now if you leave the port unconnected, it's width shall be 32.

And if you connect it to another signal of any width, it will take over the
index range of that signal.

Sweet and simple.
 
X

XYZ

And rightfully so. If you leave an unconstrained port unconnected, what
width is it supposed to be? Or more general: what range should the index
be? It can not be determined from anything.
I know, I thought it was clear from the post.
As a solutions, what you could do is something like this:

val : in std_logic_vector := (31 downto 0 => '0');

Now if you leave the port unconnected, it's width shall be 32.

And if you connect it to another signal of any width, it will take over the
index range of that signal.
I wrote that val is supposed to have input'range. If I do like that:

input : in std_logic_vector;
val : in std_logic_vector := (input'range => '0');

I get "object 'input' cannot be used within the same interface as it is
declared". In fact this is true that input is declared in the same
interface but is there any workaround for this, other than using generic
values?
 
B

backhus

I know, I thought it was clear from the post.





I wrote that val is supposed to have input'range. If I do like that:

        input : in std_logic_vector;
        val : in std_logic_vector := (input'range =>  '0');

I get "object 'input' cannot be used within the same interface as it is
declared". In fact this is true that input is declared in the same
interface but is there any workaround for this, other than using generic
values?

Hi,
using unconstrained ports will be a problem once you enter the
toplevel.
There are no chips with 'morphing' pacages that automatically adapt to
the socket or pcb, to make this feature useful. :)

But there is a (pragmatic) solution to your problem.
Write a function instead of a module (entity/architecture).
This functiion can have unconstrained parameters.
And when you want to apply this function in a real circuit you can
write a wrapper module that sets the port sizes and calls the
function.
If you need to do so more often and still want to avoid generics, a
perl script might be usefull that generates the wrappers.

Have a nice synthesis
Eilert
 
J

Jonathan Bromley

Hi,

How to set a default value for an unconstrained port? Doing it this way
input : in std_logic_vector;
val : in std_logic_vector := (others => '0');
doesn't work [...]
I know, however, that val'range should be the same as input'range.

As the discussion has shown, there doesn't seem to be any direct way
to handle this. However, how about this as an idea...?

val: in std_logic_vector(0 downto 1 => '0'); --- null range

Now, if you fail to connect "val", it gets a null-range input. We
can
detect that inside the design:

architecture....
--- Make a signal for "val" that is the known correct size
signal internal_val: std_logic_vector(input'range);
...
begin
missing_val_manager: if val'length = 0 generate
assert false
report "val not connected, defaulting to all-zero"
severity note;
end process;
--- Make the correct-sized default
internal_val <= (input'range => '0');
end generate;
provided_val_manager: if val'length > 0 generate
assert val'length = input'length
report "val was connected but its size doesn't match input"
severity fatal;
internal_val <= val;
end generate;

(and then, of course, use "internal_val" everywhere in your
design).

I'm pretty confident this is OK for simulation, but the null range
might cause some trouble for synthesis, so there might need to be some
business with synthesis-off pragmas. Alternatively you could cheat
and set the unconnected default to be one bit wide (0 downto 0) or,
perhaps, some other size that you know will never occur in practice.

VHDL-2008 "if generate else" could make the code just a little neater.
 
P

Paul Uiterlinden

XYZ said:
I know, I thought it was clear from the post.

Sorry, I missed that part. I should not post anything after midnight...
I wrote that val is supposed to have input'range. If I do like that:

input : in std_logic_vector;
val : in std_logic_vector := (input'range => '0');

I get "object 'input' cannot be used within the same interface as it is
declared". In fact this is true that input is declared in the same
interface but is there any workaround for this, other than using generic
values?

I think Jonathan's suggestion is quite elegant. The only issue might be the
null range (as Jonathan already pointed out for synthesis).

But also for simulation: by default a null-range gives a warning in
ModelSim. That can be suppressed again with the -nowarn 3 option, IIRC.

An alternative would be to use a special value, with bit values that
normally do not occur. For example: (31 DOWNTO 0 => '-'), or
(0 TO 0 => 'U'). This avoids the issue with the null-range warning.
 
A

Andy

Jonathan,

How would you go about declaring "internal_val" such that it has
either the length of input or the length of val? I think you would
have to declare it with input'range, then resize val as necessary to
fit if val was provided but did not match.

Andy
 
J

Jonathan Bromley

Andy,
How would you go about declaring "internal_val" such that it has
either the length of input or the length of val? I think you would
have to declare it with input'range, then resize val as necessary to
fit if val was provided but did not match.

I took the coward's way out and threw an assertion fatal
if 'val' is provided, but doesn't match the expected
size (input'length). (Didn't I? That was the idea,
anyhow.) That's something I regard as standard practice
when using unconstrained ports that must respect some
kind of size relationship. I had understood the OP to
mean that 'val' (or its default, if not supplied) should
match the size of 'input'. If that's not the case, then
clearly you're right: some resizing rule would be needed.
Whatever the requirement, I'm sure you could make it
happen with a sufficiently contorted "generate".

cheers
 
A

Andy

Jonathan,

Unfortunately, declarations within a generate statement are local to
the generate's block, and furthermore, generate statements cannot be
located in the declarative region. This is one glaring limitation to
the generate capability: conditional declarations useable outside the
generate statement.

You could use a function for the declaration initializer of
internal_val...? Similarly to what the OP was doing with unconstrained
ports, declare internal_val as unconstrained SLV, with a function call
to define an initial value which also sets the range of the variable/
signal. I don't think you could replace the generate statements with
the initializer function, since the generate statements created the
correct concurrent assignment also. OK, maybe you could get rid of one
of the generates...

Andy
 
J

Jonathan Bromley

Unfortunately, declarations within a generate statement are local to
the generate's block, and furthermore, generate statements cannot be
located in the declarative region. This is one glaring limitation to
the generate capability: conditional declarations useable outside the
generate statement.

right, although of course you can see the reasoning
behind that.
You could use a function for the declaration initializer of
internal_val...? Similarly to what the OP was doing with unconstrained
ports, declare internal_val as unconstrained SLV, with a function call
to define an initial value

That's fine for constants, but surely not for a signal
or variable?
I don't think you could replace the generate statements with
the initializer function, since the generate statements created the
correct concurrent assignment also.

I still think it's OK: the declaration of internal_val would
be outside any generate, determined by the properties
of other ports etc (not forgetting that functions can be
used to determine the values of constants that control
a signal's declaration). And then a generate could
conditionally create a process, in whose declarative
region there is a function used to build the signal's
value so that process can duly drive it.

I agree, though, that it's all a bit of a faff. Probably a
few generics on the entity would make for a neater job.

Have pity on me. As I complained earlier, I'm currently
in Verilog land, where such things are not permitted to
appear even in nocturnal fantasies.
 
A

Andy

That's fine for constants, but surely not for a signal
or variable?

True, you'd have to use a function to initialize an unconstrained
constant, then you could use the constant's range to declare the
variable/signal.

You have my sympathy. Somehow I think verilog must be more kind to
those who've never known the benefits of VHDL. Otherwise, who would
prefer it? But that's a different thread...

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top