Assign record elements of array

Guest
Hi VHDL gurus,

Below a few snippets from code which behaves not as expected. I am wondering if it is a tool issue or that it is forbidden by the language.

type rt_rec_type is record
data_i : std_logic_vector(31 downto 0);
busy : std_logic;
header : std_logic;
dest : std_logic_vector(3 downto 0);
end record rt_rec_type;

type t_channels is array (0 to 7) of rt_rec_type;

gen1 : for i in 0 to 7 generate
channels(i).data_i <= (others => ‘0’);
channels(i).header <= ‘0’;
end generate gen1;

p_data : process(clk) is
begin
if rising_edge(clk) then
if resetn = ‘0’ then
for i in 0 to 7 generate
channels(i).busy <= ‘0’;
channels(i).dest <= (others => ‘0’);
end for;
.....
end process;

What we see in Modelsim is that data_i and header are still ‘U’ and not initialised as expected. Modelsim steps through the lines of data_i and header at 0 ps + 0.
When we move these signals inside the process and add them to the reset they are initialised. Is it forbidden by the language to assign the record elements at different places?


Thanks, Devas
 
On 6/1/2016 4:25 AM, geve115@gmail.com wrote:
Hi VHDL gurus,

Below a few snippets from code which behaves not as expected. I am wondering if it is a tool issue or that it is forbidden by the language.

type rt_rec_type is record
data_i : std_logic_vector(31 downto 0);
busy : std_logic;
header : std_logic;
dest : std_logic_vector(3 downto 0);
end record rt_rec_type;

type t_channels is array (0 to 7) of rt_rec_type;

gen1 : for i in 0 to 7 generate
channels(i).data_i <= (others => ‘0’);
channels(i).header <= ‘0’;
end generate gen1;

p_data : process(clk) is
begin
if rising_edge(clk) then
if resetn = ‘0’ then
for i in 0 to 7 generate
channels(i).busy <= ‘0’;
channels(i).dest <= (others => ‘0’);
end for;
.....
end process;

What we see in Modelsim is that data_i and header are still ‘U’ and not initialised as expected. Modelsim steps through the lines of data_i and header at 0 ps + 0.
When we move these signals inside the process and add them to the reset they are initialised. Is it forbidden by the language to assign the record elements at different places?

Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
 
Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
Hi Rick,

Thank you for the answer, so it is a language issue and not a tool issue.
I modified the code and naming but it was to show that some record elements were assigned constants in the generate statement and others in the process statement. At this moment in the project some record elements are not used. The used elements are assigned in the process statement.

Best regards,

Devas
 
On 02/06/2016 07:49, geve115@gmail.com wrote:
Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
Hi Rick,

Thank you for the answer, so it is a language issue and not a tool issue.
I modified the code and naming but it was to show that some record elements were assigned constants in the generate statement and others in the process statement. At this moment in the project some record elements are not used. The used elements are assigned in the process statement.

Best regards,

Devas

Hi Devas,

This question comes up at least once every year. Have a look at this
question (taken from a presentation in the UK many years ago):

http://www.ht-lab.com/index_htm_files/question.jpg

the correct (for most unexpected) answer is here:

http://www.ht-lab.com/index_htm_files/answer.jpg

Luckily VHDL only has a few language quirks....

Hans
www.ht-lab.com
 
On Thursday, June 2, 2016 at 10:21:33 AM UTC+2, HT-Lab wrote:
Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
Hi Rick,

Thank you for the answer, so it is a language issue and not a tool issue.
I modified the code and naming but it was to show that some record elements were assigned constants in the generate statement and others in the process statement. At this moment in the project some record elements are not used. The used elements are assigned in the process statement.

Best regards,

Devas

Hi Devas,

This question comes up at least once every year. Have a look at this
question (taken from a presentation in the UK many years ago):

http://www.ht-lab.com/index_htm_files/question.jpg

the correct (for most unexpected) answer is here:

http://www.ht-lab.com/index_htm_files/answer.jpg

Luckily VHDL only has a few language quirks....

Hans
www.ht-lab.com

Hi Hans,

Thank you for pointing me to the right search item "longest static prefix". It is an interesting topic.
Mostly you write code without any issue, but sometimes you want to write it a little bit less complex/try new ideas and you get in conflict with the LRM.

Devas
 
HT-Lab <hans64@htminuslab.com> writes:

This question comes up at least once every year. Have a look at this
question (taken from a presentation in the UK many years ago):

http://www.ht-lab.com/index_htm_files/question.jpg

the correct (for most unexpected) answer is here:

http://www.ht-lab.com/index_htm_files/answer.jpg

Luckily VHDL only has a few language quirks....

Come to think of it, is someone maintaining the comp.lang.vhdl FAQ
still? I found a copy at
https://tams.informatik.uni-hamburg.de/vhdl/index.php?content=02-faq but
I don't know if it's the last version.

A lot of Google hits seem to point to vhdl.org or eda.org which point
today to accellera.org and they don't seem to have it.
 
On Friday, June 3, 2016 at 12:38:58 AM UTC+12, Devas wrote:
On Thursday, June 2, 2016 at 10:21:33 AM UTC+2, HT-Lab wrote:
Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
Hi Rick,

Thank you for the answer, so it is a language issue and not a tool issue.
I modified the code and naming but it was to show that some record elements were assigned constants in the generate statement and others in the process statement. At this moment in the project some record elements are not used. The used elements are assigned in the process statement.

Best regards,

Devas

Hi Devas,

This question comes up at least once every year. Have a look at this
question (taken from a presentation in the UK many years ago):

http://www.ht-lab.com/index_htm_files/question.jpg

the correct (for most unexpected) answer is here:

http://www.ht-lab.com/index_htm_files/answer.jpg

Luckily VHDL only has a few language quirks....

Hans
www.ht-lab.com

Thank you for pointing me to the right search item "longest static prefix". It is an interesting topic.

This isn't a longest static prefix issue This can be demonstrated by examining how a generate statement (a concurrent statement, not the mistaken use in the process statement where generate should be loop) is elaborated:

From IEEE Std 1076-2008 11.8 Generate Statements paragraph 10 (11. is Concurrent statements):

The elaboration of a generate statement is given in 14.5.3.

14.5.3 Generate statements, paragraph 2 (14.5 is Elaboration of a statement part):

For a for generate statement, elaboration consists of the elaboration of the
discrete range, followed by the generation of one block statement for each
value in the range. The block statements all have the following form:

a) The label of the block statement is the same as the label of the for
generate statement.
b) The block declarative part has, as its first item, a single constant
declaration that declares a constant with the same simple name as that
of the applicable generate parameter; the value of the constant is the
value of the generate parameter for the generation of this particular
block statement. The type of this declaration is determined by the base
type of the discrete range of the generate parameter. The remainder of
the block declarative part consists of a copy of the declarative items
contained within the generate statement.
c) The block statement part consists of a copy of the concurrent statements
contained within the gener- ate statement.

So the generate parameter (i) is declared as a constant in each of the generated block statements with the value of i for the particular generated block statement.

That takes this out of the running for a longest static prefix issue. See 8.. Names, 8.1 General paragraph 7:

A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. Similarly, a static variable name is a static name that denotes a variable, and the longest static prefix of a variable name is the name itself, if the name is a static variable name; otherwise, it is the longest prefix of the name that is a static variable name.

And to understand that channels(i).data_i or channels(i).header are static names we look to 9. Expressions, 9.4 Static expressions, 9.4.3 Globally static primaries:

d) A generate parameter

And back to 8.1 the paragraph 5:

A name is said to be a static name if and only if one of the following
conditions holds:
— The name is a simple name or selected name (including those that are
expanded names) that does not denote a function call, an object or value
of an access type, or an object of a protected type and (in the case of a
selected name) whose prefix is a static name.
— The name is an indexed name whose prefix is a static name, and every
expression that appears as part of the name is a static expression.
— The name is a slice name whose prefix is a static name and whose discrete
range is a static discrete range.
— The name is an attribute name whose prefix is a static signal name and
whose suffix is one of the pre- defined attributes 'DELAYED, 'STABLE,
'QUIET, or 'TRANSACTION.
— The name is an external name.

So the names used in the generate statements are static names. And as a result the longest static prefix is the entire selected name for channels(i).data_i or channels(i).header.

If it isn't a longest static prefix issue it's simply multiple drivers.

14.7.2 Drivers (pargraph 1, the first sentence):

Every signal assignment statement in a process statement defines a set of
drivers for certain scalar signals.

The processes elaborated from the concurrent assignment statements from the generate statement have drivers for their selected names specified by their static names (channels(i).data_i or channels(i).header) giving rise to your problem:

On Wed, 1 Jun 2016 01:25:41 -0700 (PDT), Devas wrote:

>What we see in Modelsim is that data_i and header are still ‘U’ and not initialised as expected. ...

A longest static prefix related issue derived from the generate statement would have unknown values on all the record elements and not just the two with drivers in the eight generated block statements two processes.

You should be counting on resetn to insure the state of channels. It's worth evaluating how channels is used in determining reset sequence (either asynchronous reset somewhere or reset duration of multiple clock cycles).
 
On Friday, June 3, 2016 at 12:38:58 AM UTC+12, Devas wrote:
On Thursday, June 2, 2016 at 10:21:33 AM UTC+2, HT-Lab wrote:
Hi,

I'm not certain but I have seen a similar thing where part of an array
is assigned in a process and the other part of the array is assigned in
another process or a concurrent statement. There is a rule that says
under certain circumstances an assignment to part of the array causes
the entire array to be assigned a value, in other words a driver is
created for every bit in a vector. You may be seeing something similar
for the entire record when you assign part of the record.

You don't show the rest of the code, so I can't understand why you would
want to assign the values to .data_i and .header in a generate
statement. This will create drives for at least this part of the record
that will always be fixed to '0', in other words a constant. a generate
statement can not be used for initialization of a signal that you wish
to change at other times.

So what are you really trying to do with the various fields of this record?

--

Rick C
Hi Rick,

Thank you for the answer, so it is a language issue and not a tool issue.
I modified the code and naming but it was to show that some record elements were assigned constants in the generate statement and others in the process statement. At this moment in the project some record elements are not used. The used elements are assigned in the process statement.

Best regards,

Devas

Hi Devas,

This question comes up at least once every year. Have a look at this
question (taken from a presentation in the UK many years ago):

http://www.ht-lab.com/index_htm_files/question.jpg

the correct (for most unexpected) answer is here:

http://www.ht-lab.com/index_htm_files/answer.jpg

Luckily VHDL only has a few language quirks....

Hans
www.ht-lab.com

Hi Hans,

Thank you for pointing me to the right search item "longest static prefix". It is an interesting topic.
Mostly you write code without any issue, but sometimes you want to write it a little bit less complex/try new ideas and you get in conflict with the LRM.

Devas

This isn't a longest static prefix issue This can be demonstrated by examining how a generate statement (a concurrent statement, not the mistaken use in the process statement where generate should be loop) is elaborated:

From IEEE Std 1076-2008 11.8 Generate Statements paragraph 10 (11. is Concurrent statements):

The elaboration of a generate statement is given in 14.5.3.

14.5.3 Generate statements, paragraph 2 (14.5 is Elaboration of a statement part):

For a for generate statement, elaboration consists of the elaboration of the
discrete range, followed by the generation of one block statement for each
value in the range. The block statements all have the following form:

a) The label of the block statement is the same as the label of the for
generate statement.
b) The block declarative part has, as its first item, a single constant
declaration that declares a constant with the same simple name as that
of the applicable generate parameter; the value of the constant is the
value of the generate parameter for the generation of this particular
block statement. The type of this declaration is determined by the base
type of the discrete range of the generate parameter. The remainder of
the block declarative part consists of a copy of the declarative items
contained within the generate statement.
c) The block statement part consists of a copy of the concurrent statements
contained within the gener- ate statement.

So the generate parameter (i) is declared as a constant in each of the generated block statements with the value of i for the particular generated block statement.

That takes this out of the running for a longest static prefix issue. See 8.. Names, 8.1 General paragraph 7:

A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. Similarly, a static variable name is a static name that denotes a variable, and the longest static prefix of a variable name is the name itself, if the name is a static variable name; otherwise, it is the longest prefix of the name that is a static variable name.

And to understand that channels(i).data_i or channels(i).header are static names we look to 9. Expressions, 9.4 Static expressions, 9.4.3 Globally static primaries:

d) A generate parameter

And back to 8.1 the paragraph 5:

A name is said to be a static name if and only if one of the following
conditions holds:
— The name is a simple name or selected name (including those that are
expanded names) that does not denote a function call, an object or value
of an access type, or an object of a protected type and (in the case of a
selected name) whose prefix is a static name.
— The name is an indexed name whose prefix is a static name, and every
expression that appears as part of the name is a static expression.
— The name is a slice name whose prefix is a static name and whose discrete
range is a static discrete range.
— The name is an attribute name whose prefix is a static signal name and
whose suffix is one of the pre- defined attributes 'DELAYED, 'STABLE,
'QUIET, or 'TRANSACTION.
— The name is an external name.

So the names used in the generate statements are static names. And as a result the longest static prefix is the entire selected name for channels(i).data_i or channels(i).header.

If it isn't a longest static prefix issue it's simply multiple drivers.

14.7 Execution of a model, 14.7.2 Drivers pargraph 1:

Every signal assignment statement in a process statement defines a set o
drivers for certain scalar signals. There is a single driver for a given scalar
signal S in a process statement, provided that there is at least one signal
assignment statement in that process statement and that the longest static
prefix of the target signal of that signal assignment statement denotes S or
denotes a composite signal of which S is a subelement. Each such signal
assignment statement is said to be associated with that driver. Execution of a
signal assignment statement affects only the associated driver(s).

The processes elaborated from the concurrent assignment statements from the generate statement have drivers for their selected names specified by their static names (channels(i).data_i or channels(i).header) giving rise to your problem:

On Wed, 1 Jun 2016 01:25:41 -0700 (PDT), Devas wrote:

>What we see in Modelsim is that data_i and header are still ‘U’ and not initialised as expected. ...

A longest static prefix related issue derived from the generate statement would have unknown values on all the record elements and not just the two with drivers in the eight generated block statements two processes.

You should be counting on resetn to insure the state of channels. It's worth evaluating how channels is used in determining reset sequence (either asynchronous reset somewhere or reset duration of multiple clock cycles).

You could also supply an initial value to the entire array of records as shown in the declaration of signal channels:

library ieee; -- added context clause
use ieee.std_logic_1164.all;

entity davos is -- added entity declaration
port (
signal clk: std_logic;
signal resetn: std_logic
);
end entity;

architecture foo of davos is -- added architecture

type rt_rec_type is record
data_i: std_logic_vector(31 downto 0);
busy: std_logic;
header: std_logic;
dest: std_logic_vector(3 downto 0);
end record rt_rec_type;

type t_channels is array (0 to 7) of rt_rec_type;

signal channels: t_channels := ( others => ( -- Added signal declaration
data_i => (others => '0'),
busy => '0',
header => '0',
dest => (others => '0')
)
);
begin

-- gen1:
-- for i in 0 to 7 generate
-- channels(i).data_i <= (others => '0');
-- channels(i).header <= '0';
-- end generate gen1;

p_data:
process(clk) is
begin
if rising_edge(clk) then
if resetn = '0' then
for i in 0 to 7 loop -- loop is exected instead of generate
channels(i).busy <= '0';
channels(i).dest <= (others => '0');
end loop; -- loop is expected instead of for
-- ....
end if; -- added end
end if; -- added end
end process;
end architecture;

-- Also substituted apostrophe for back tick in character literal '0' instances

Note this implies you simply chuck out the generate statement. The above code analyzes successfully.

Complexity comes from VHDL being a formal notation whose semantics covers both design models and simulation.
 

Welcome to EDABoard.com

Sponsor

Back
Top