Records in vhdl

D

Dave

Guest
I am currently using records to group signals together in some
synthesizable VHDL code, for readability as much as anything else. The
signals within the record are driven by one of three processes, with
each element of the record having only one driver. This synthesized
fine in ISE 9.2, but now that I want to simulate it, the ISE Lite
simulator is complaining about a signal having multiple drivers. Does
anyone know what the LRM says here? I know that the record is,
overall, decared as a signal, and could be seen as having multiple
drivers, but I'm finding this interpretation rather inconvenient right
now... and am surprised that the synthesizer and simulator aren't on
the same page with this.

Example code:

type recType is record
a: std_logic;
b: std_logic;
end record;

signal rec : recType;

process(clk)
if rising_edge(clk) then
rec.a <= input_1;
end if;
end process;

process(clk)
if rising_edge(clk) then
rec.b <= input_2;
end if;
end process;
 
On Nov 26, 2:32 pm, Dave <dhsch...@gmail.com> wrote:
I am currently using records to group signals together in some
synthesizable VHDL code, for readability as much as anything else. The
signals within the record are driven by one of three processes, with
each element of the record having only one driver. This synthesized
fine in ISE 9.2, but now that I want to simulate it, the ISE Lite
simulator is complaining about a signal having multiple drivers. Does
anyone know what the LRM says here? I know that the record is,
overall, decared as a signal, and could be seen as having multiple
drivers, but I'm finding this interpretation rather inconvenient right
now... and am surprised that the synthesizer and simulator aren't on
the same page with this.

Example code:

type recType is record
a: std_logic;
b: std_logic;
end record;

signal rec : recType;

process(clk)
if rising_edge(clk) then
rec.a <= input_1;
end if;
end process;

process(clk)
if rising_edge(clk) then
rec.b <= input_2;
end if;
end process;
Every process that drives any element of the record needs to drive
EVERY element of the record. With resolved data types (SLV),
"undriven" elements can be driven with 'Z'. I find it best to declare
a constant of that type with the type declaration, and that constant
defines every element to 'Z'. Assign the signal with the constant at
the top of each process that drives any part of the signal, and you're
done. Not very simulation efficient, but until we get user defined
modes for record type ports, I don't know of another way, except to
break out different parts of the record as separate signals/ports.
Note that continuous assignments to 'Z' are optimized out in
synthesis.

Andy
 
On Nov 26, 4:17 pm, Andy <jonesa...@comcast.net> wrote:
On Nov 26, 2:32 pm, Dave <dhsch...@gmail.com> wrote:





I am currently using records to group signals together in some
synthesizable VHDL code, for readability as much as anything else. The
signals within the record are driven by one of three processes, with
each element of the record having only one driver. This synthesized
fine in ISE 9.2, but now that I want to simulate it, the ISE Lite
simulator is complaining about a signal having multiple drivers. Does
anyone know what the LRM says here? I know that the record is,
overall, decared as a signal, and could be seen as having multiple
drivers, but I'm finding this interpretation rather inconvenient right
now... and am surprised that the synthesizer and simulator aren't on
the same page with this.

Example code:

type recType is record
a: std_logic;
b: std_logic;
end record;

signal rec : recType;

process(clk)
if rising_edge(clk) then
rec.a <= input_1;
end if;
end process;

process(clk)
if rising_edge(clk) then
rec.b <= input_2;
end if;
end process;

Every process that drives any element of the record needs to drive
EVERY element of the record. With resolved data types (SLV),
"undriven" elements can be driven with 'Z'. I find it best to declare
a constant of that type with the type declaration, and that constant
defines every element to 'Z'. Assign the signal with the constant at
the top of each process that drives any part of the signal, and you're
done. Not very simulation efficient, but until we get user defined
modes for record type ports, I don't know of another way, except to
break out different parts of the record as separate signals/ports.
Note that continuous assignments to 'Z' are optimized out in
synthesis.

Andy- Hide quoted text -

- Show quoted text -
This makes sense. I left out the fact that some of the elements are of
integer type, and this seems important because there's no resolution
function for that type. If everything were based on std_logic, I think
I'd be fine.
 
Dave,
This makes sense. I left out the fact that some of the elements are of
integer type, and this seems important because there's no resolution
function for that type. If everything were based on std_logic, I think
I'd be fine.
For integers, you can use something like the following. I have
only used this for records in testbenches and not RTL code. I
always thought this is a testbench only thing, but some of Andy's
comments got me thinking. In my testbenches, I initialize all
resolved integers to 0 at the point of signal declaration or on
the port. Since synthesis mostly ignores initialization, it may
squeek by, but I would caution you that even if it works on one
synthesis tool, it may not work on others.

Cheers,
Jim
SynthWorks VHDL Training


package ResolutionPkg is

type integer_array is array (natural range <>) of integer ;
function summing ( s : integer_array ) return integer ;
function resolved ( s : integer_array ) return integer ;
subtype resolved_integer is resolved integer ;

end ResolutionPkg ;

package body ResolutionPkg is

function resolved ( s : integer_array ) return integer is
variable result : integer := 0 ;
begin
for i in s'RANGE loop
if s(i) /= 0 then
if result /= 0 then
report "Multiple driving signals on integer" severity error ;
end if ;
result := s(i) ;
end if ;
end loop ;
return result ;
end resolved ;
end ResolutionPkg ;
 
P.S.
In the previous post, delete the line:
function summing ( s : integer_array ) return integer ;
I got caught extracting things from an existing file.
"Summing" is another resolution function I have toyed around
with, but would not recommend at all for your application.
 
On Mon, 26 Nov 2007 13:25:56 -0800 (PST), Dave <dhschetz@gmail.com>
wrote:

On Nov 26, 4:17 pm, Andy <jonesa...@comcast.net> wrote:
On Nov 26, 2:32 pm, Dave <dhsch...@gmail.com> wrote:

I am currently using records to group signals together in some
synthesizable VHDL code, for readability as much as anything else. The
signals within the record are driven by one of three processes, with
each element of the record having only one driver.
Every process that drives any element of the record needs to drive
EVERY element of the record. With resolved data types (SLV),
"undriven" elements can be driven with 'Z'.
This makes sense. I left out the fact that some of the elements are of
integer type, and this seems important because there's no resolution
function for that type. If everything were based on std_logic, I think
I'd be fine.
The simplest answer is to use the IEEE.numeric_std library, and use
unsigned (or signed) for any integers you need to share in this way.
This is pretty close to basing everything on std_logic.

It will simulate (marginally) slower but IMO it's easier than writing
resolution functions for integer, and it is fully supported for synth
and sim.

Converting to/from integer needs conversion functions (to_integer and
to_unsigned) but you can freely mix integer and unsigned in arithmetic
(the result of any mixed expression is unsigned).

- Brian
 
On Nov 27, 11:02 am, Brian Drummond <brian_drumm...@btconnect.com>
wrote:
On Mon, 26 Nov 2007 13:25:56 -0800 (PST), Dave <dhsch...@gmail.com
wrote:

On Nov 26, 4:17 pm, Andy <jonesa...@comcast.net> wrote:
On Nov 26, 2:32 pm, Dave <dhsch...@gmail.com> wrote:
I am currently using records to group signals together in some
synthesizable VHDL code, for readability as much as anything else. The
signals within the record are driven by one of three processes, with
each element of the record having only one driver.
Every process that drives any element of the record needs to drive
EVERY element of the record. With resolved data types (SLV),
"undriven" elements can be driven with 'Z'.
This makes sense. I left out the fact that some of the elements are of
integer type, and this seems important because there's no resolution
function for that type. If everything were based on std_logic, I think
I'd be fine.

The simplest answer is to use the IEEE.numeric_std library, and use
unsigned (or signed) for any integers you need to share in this way.
This is pretty close to basing everything on std_logic.

It will simulate (marginally) slower but IMO it's easier than writing
resolution functions for integer, and it is fully supported for synth
and sim.

Converting to/from integer needs conversion functions (to_integer and
to_unsigned) but you can freely mix integer and unsigned in arithmetic
(the result of any mixed expression is unsigned).

- Brian
That was what I meant - anything based on std_logic (which signed and
unsigned are) gets resolved. Unfortunately, one of the elements of the
record was a memory (array of std_logic), so the assign-high-impedance
trick causes ISE to no longer be able to infer the block RAM the way I
want, so I think I've got no choice but to break up the record into
individual signals.
 

Welcome to EDABoard.com

Sponsor

Back
Top