automated converting records to std_logic_vector

V

V.

Guest
Hello,

First off, thank you everyone for contributing to this discussion group, it has been very helpful and informative to me as I progress with learning VHDL.


I'm looking to convert a record that contains 16 std_logic types into a 16 bit std_logic_vector. I currently have a function call that manually assigns each element in the record to a specific bit location in the std_logic_vector :


function rec2slv(x : rec_type) return std_logic_vector is
variable result : std_logic_vector(15 downto 0) := (others => '0');
begin
result(15) := x.element1;
...
...
result(0) := x.element16;

return result;
end;


===


I have a large amount of records that I'd like to do this on, and it is very tedious to have to write a function for each of the record.

Is there something similar to the following that could automate it? :

for i in x'range loop
result := x(i);
end loop;


Thank you all!
 
On Tuesday, December 16, 2014 11:51:23 AM UTC-5, V. wrote:
I'm looking to convert a record that contains 16 std_logic types into a 16
bit std_logic_vector. I currently have a function call that manually assigns
each element in the record to a specific bit location in the std_logic_vector :

There is no way to iterate through the elements of a record, so what you are doing is basically the way it needs to be done. However, to decrease the tedium a bit, if you define the record in the right fashion you can make it so an editor macro can munch on it and produce the functions quick enough.. What I do is to define the record like this...

type t_IMG_DMA_IMG_SIZE is record
Reserved1: std_ulogic_vector(31 downto 28);
HSize: std_ulogic_vector(27 downto 16);
Reserved2: std_ulogic_vector(15 downto 12);
VSize: std_ulogic_vector(11 downto 0);
end record t_IMG_DMA_IMG_SIZE;

Then create functions that convert between the record and a std_ulogic_vector like this...

function To_Std_ULogic_Vector(L: t_IMG_DMA_IMG_SIZE) return std_ulogic_vector is
variable RetVal: std_ulogic_vector(31 downto 0);
begin
RetVal(L.Reserved1'range) := L.Reserved1;
RetVal(L.HSize'range) := L.HSize;
RetVal(L.Reserved2'range) := L.Reserved2;
RetVal(L.VSize'range) := L.VSize;

return(RetVal);
end function To_Std_ULogic_Vector;

function From_Std_ULogic_Vector(L: std_ulogic_vector(31 downto 0)) return t_IMG_DMA_IMG_SIZE is
variable RetVal: t_IMG_DMA_IMG_SIZE;
begin
RetVal : (
Reserved1 => L(RetVal.Reserved1'range),
HSize => L(RetVal.HSize'range),
Reserved2 => L(RetVal.Reserved2'range),
VSize => L(RetVal.VSize'range)
);

return(RetVal);
end function From_Std_ULogic_Vector;

Note that the functions themselves do not need to be edited if all you do is change the bit positions. In that situation, you simply edit the record definition. If you have one bit fields, you simply define them as one bit vectors like this
xyz: std_ulogic_vector(28 downto 28);

Adding/removing a field from the record does require function editing.

Kevin Jennings
 
On Tue, 16 Dec 2014 08:51:20 -0800 (PST)
"V." <mr.jay.diem@gmail.com> wrote:

Hello,

First off, thank you everyone for contributing to this discussion group, it has been very helpful and informative to me as I progress with learning VHDL.


I'm looking to convert a record that contains 16 std_logic types into a 16 bit std_logic_vector. I currently have a function call that manually assigns each element in the record to a specific bit location in the std_logic_vector :


function rec2slv(x : rec_type) return std_logic_vector is
variable result : std_logic_vector(15 downto 0) := (others => '0');
begin
result(15) := x.element1;
...
...
result(0) := x.element16;

return result;
end;


===


I have a large amount of records that I'd like to do this on, and it is very tedious to have to write a function for each of the record.

Is there something similar to the following that could automate it? :

for i in x'range loop
result := x(i);
end loop;


Thank you all!

Not really. I wrote pack/unpack functions that I get a lot of use of
when I have to cast a record type into an SLV, usually because I have
to work with some generated core. Then I wind up writing functions for
each direction as:

function TO_SLV(rec : t_pvme_request) return
t_pvme_request_slv is variable slv : t_pvme_request_slv;
variable idx : integer;
begin
slv := (others => 'U');
idx := 0;
pack(slv, idx, rec.data);
pack(slv, idx, rec.address);
pack(slv, idx, rec.timing);
pack(slv, idx, rec.am);
pack(slv, idx, rec.dm);
pack(slv, idx, rec.req);
return slv;
end function TO_SLV;

function TO_REQUEST (slv : t_pvme_request_slv) return
t_pvme_request is variable rec : t_pvme_request;
variable idx : integer;
begin
idx := 0;
unpack(slv, idx, rec.data);
unpack(slv, idx, rec.address);
unpack(slv, idx, rec.timing);
unpack(slv, idx, rec.am);
unpack(slv, idx, rec.dm);
unpack(slv, idx, rec.req);
return rec;
end function TO_REQUEST;

I'll put all my overloads on the pack/unpack functions here in case
anyone ever wants them.

-----------------------------------------------------------------------
-- Record conversion functions
-----------------------------------------------------------------------

procedure pack(
target : inout std_logic_vector;
idx : inout integer;
nd : in std_logic_vector
) is
begin
target(idx + nd'length - 1 downto idx) := nd;
idx := idx + nd'length;
end procedure pack;

procedure pack(
target : inout std_logic_vector;
idx : inout integer;
nd : in std_logic
) is
begin
target(idx) := nd;
idx := idx + 1;
end procedure pack;

procedure pack(
target : inout std_logic_vector;
idx : inout integer;
nd : in unsigned
) is
begin
target(idx + nd'length - 1 downto idx) :=
STD_LOGIC_VECTOR(nd); idx := idx + nd'length;
end procedure pack;

procedure pack(
target : inout std_logic_vector;
idx : inout integer;
nd : in signed
) is
begin
target(idx + nd'length - 1 downto idx) :=
STD_LOGIC_VECTOR(nd); idx := idx + nd'length;
end procedure pack;

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

procedure unpack (
source : in std_logic_vector;
idx : inout integer;
dat : out std_logic_vector
) is
begin
dat := source(idx + dat'length - 1 downto idx);
idx := idx + dat'length;
end procedure unpack;

procedure unpack (
source : in std_logic_vector;
idx : inout integer;
dat : out std_logic
) is
begin
dat := source(idx);
idx := idx + 1;
end procedure unpack;

procedure unpack (
source : in std_logic_vector;
idx : inout integer;
dat : out unsigned
) is
begin
dat := UNSIGNED(source(idx + dat'length - 1 downto
idx)); idx := idx + dat'length;
end procedure unpack;

procedure unpack (
source : in std_logic_vector;
idx : inout integer;
dat : out signed
) is
begin
dat := SIGNED(source(idx + dat'length - 1 downto idx));
idx := idx + dat'length;
end procedure unpack;


--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order. See above to fix.
 
Actually, there is another way for your particular case. Your case happens to have 16 named bits that you want to turn into a vector. Instead of a record then you can use an enumerated type.

Type mytype is (element1, element2, ... element16);

Type arr_mytype is array (mytype) of std_ulogic;

Then you would refer to elements as x(element1) instead of x.element1.

More important though you can iterate through the enumerations with
For i in mytype loop
Sulv(mytype'pos(i) := Inp(i);
End loop;

Where Inp is of type mytype, Sulv is the output std_ulogic_vector.

Kevin Jennings
 
On Tuesday, December 16, 2014 4:51:23 PM UTC, V. wrote:
I'm looking to convert a record that contains 16 std_logic types
into a 16 bit std_logic_vector. I currently have a function call
that manually assigns each element in the record to a specific
bit location in the std_logic_vector

Sadly as other contributors have mentioned there's no way to do this
without explicitly rolling your own pack/unpack functions for each
record type.

There is however a proposal for the next VHDL revision to add
functionality that would remove the need to write functions that
are specific to each record:

http://www.eda.org/twiki/bin/view.cgi/P1076/RecordIntrospection


Thanks,

Chris
 
On Tuesday, December 16, 2014 8:22:38 PM UTC-6, KJ wrote:
Actually, there is another way for your particular case. Your case happens to have 16 named bits that you want to turn into a vector. Instead of a record then you can use an enumerated type.

Type mytype is (element1, element2, ... element16);

Type arr_mytype is array (mytype) of std_ulogic;

Then you would refer to elements as x(element1) instead of x.element1.

More important though you can iterate through the enumerations with
For i in mytype loop
Sulv(mytype'pos(i) := Inp(i);
End loop;

Where Inp is of type mytype, Sulv is the output std_ulogic_vector.

Kevin Jennings

Thanks Kevin ... Yes, that will work for about half of my records, which is good news!

Unfortunately the other half contains a mix of logic types that won't play as nicely.

Thank you Chris for the link, glad to know it's been brought up before.
 

Welcome to EDABoard.com

Sponsor

Back
Top