Concatenate/De-Concatenate

C

Carlos

Hello,

I sometimes have to concatenate/de-concatenate vectors for example to feed them to a common FIFO (see below).

signal Ain, Aout : std_logic_vector(I-1 downto 0);
signal Bin, Bout : std_logic_vector(J-1 downto 0);
signal Cin, Cout : std_logic_vector(K-1 downto 0);
signal FIFOin, FIFOout : std_logic_vector(I+J+K-1 downto 0);
-- ...

FIFOin <= Ain & Bin & Cin;
-- ...
Aout <= FIFOout(Aout'length + Bout'length + Cout'length-1 downto Bout'length + Cout'length);
Bout <= FIFOout(Bout'length + Cout'length-1 downto Cout'length);
Cout <= FIFOout(Cout'length-1 downto 0);

This works fine, but my question would be, is there a neater way of doing the same thing since the code becomes quite lengthy and hard to follow when the number of vectors increases?
*** (Ideally something like a de-concatenate sort of operation would be nice, as shown below)
*** Aout & Bout & Cout <= FIFOout; -- INCORRECT

Thanks.
 
G

goouse99

Am Freitag, 12. Oktober 2012 05:57:29 UTC+2 schrieb Carlos:
Hello,



I sometimes have to concatenate/de-concatenate vectors for example to feed them to a common FIFO (see below).



signal Ain, Aout : std_logic_vector(I-1 downto 0);

signal Bin, Bout : std_logic_vector(J-1 downto 0);

signal Cin, Cout : std_logic_vector(K-1 downto 0);

signal FIFOin, FIFOout : std_logic_vector(I+J+K-1 downto 0);

-- ...



FIFOin <= Ain & Bin & Cin;

-- ...

Aout <= FIFOout(Aout'length + Bout'length + Cout'length-1 downto Bout'length + Cout'length);

Bout <= FIFOout(Bout'length + Cout'length-1 downto Cout'length);

Cout <= FIFOout(Cout'length-1 downto 0);



This works fine, but my question would be, is there a neater way of doing the same thing since the code becomes quite lengthy and hard to follow when the number of vectors increases?

*** (Ideally something like a de-concatenate sort of operation would be nice, as shown below)

*** Aout & Bout & Cout <= FIFOout; -- INCORRECT



Thanks.

hi,
yes, I think it can simply be done like this:

(Aout, Bout, Cout) <= FIFOout;

Of course the sum of bits of A,B,C has to match the number of bits of the FIFO signal. And the basic types must match too.

Have a nice synthesis
Eilert
 
C

carloshyneman

Am Freitag, 12. Oktober 2012 05:57:29 UTC+2 schrieb Carlos:




hi,

yes, I think it can simply be done like this:



(Aout, Bout, Cout) <= FIFOout;



Of course the sum of bits of A,B,C has to match the number of bits of the FIFO signal. And the basic types must match too.



Have a nice synthesis

Eilert

Woops, I was a bit hasty when I replied! I just tried out your suggestion and here's what I concluded.
The above code only works if Aout, Bout, Cout are of type STD_LOGIC.
If they are of type STD_LOGIC_VECTOR (as in the above mentioned example), the parentheses trick does not seem to work.
Also, the concatenation "&" is not allowed to be on the left hand side of the assignment.

Any other suggestions or workarounds?
 
R

rickman

Am Freitag, 12. Oktober 2012 05:57:29 UTC+2 schrieb Carlos:

hi,
yes, I think it can simply be done like this:

(Aout, Bout, Cout)<= FIFOout;

Of course the sum of bits of A,B,C has to match the number of bits of the FIFO signal. And the basic types must match too.

Have a nice synthesis
Eilert


Using the & operator is called concatenation. This is an expression
producing a result and can not be used on the left side of an assignment.

The grouping of signals in parentheses as above is called an aggregate.
It makes a larger signal from small ones and can be used on the left
side of an assignment.

In the old days tools had a difficult time with aggregates on the left
side of assignments, but I think they all support this now.

Rick
 
H

HT-Lab

On Friday, October 12, 2012 2:53:16 AM UTC-4, (unknown) wrote: ...

Woops, I was a bit hasty when I replied! I just tried out your suggestion and here's what I concluded.
The above code only works if Aout, Bout, Cout are of type STD_LOGIC.
If they are of type STD_LOGIC_VECTOR (as in the above mentioned example), the parentheses trick does not seem to work.
Also, the concatenation "&" is not allowed to be on the left hand side of the assignment.

Any other suggestions or workarounds?

Left hand side array aggregate is part of VHDL2008, Modelsim is happy
with it but I suspect your synthesis tool might not yet support it. Open
a service request with your vendor and ask for it.

Good luck,

Hans
www.ht-lab.com
 
A

Andy

Are you sure? (a,b,c) describes an aggregate expression of three elements (could be a record or an array), each of which is an array. That is a lot different than concatenating three arrays into one array.

As a solution to the original problem, I offer two:

1) define a, b, c with ranges that indicate where they will go in FIFO. I have done somthing like this before:

subtype a_range is natural I-1 downto 0;
subtype b_range is natural a_range'high + J downto a_range'high + 1;
subtype c_range is natural b_range'high + K downto b_range'high + 1;
subtype fifo_range is natural c_range'high downto a_range'low;

signal a, a_out : unsigned(a_range);
signal b, b_out : unsigned(b_range);
signal c, c_out : unsigned(c_range);
signal fifo_in, fifo_out: unsigned(fifo_range);

fifo_in(a_range) <= a;
....
a_out <= fifo_out(a_range);



2) Why fight it? make fifo an array (or record) of arrays. (this depends on how you need to access the fifo elsewhere).

Andy
 
C

carloshyneman

Hello,

Thanks for your input guys!
I am currently using VHDL93 (in order to remain rather compatible with the whole team; plus I did not have much time to venture on my own).
Some still believe that VHDL2008 is not well supported etc... (But I guess I would keep that for a different thread).

- If am using VHDL93 with ISE 13.2, the "aggregate" of std_logic_vector does not work, it only works for std_logic types.
- 1) The "range" tip and using the "high/low" attributes of the previous range seems to be a good enough approach for me (at least it does not cascade into infinitely long lines).
- 2) This does seem more intuitive for some cases. But it happens to be that I am using a generic fifo (depth and width) and the data ports are of std_logic_vector type.

Andy, I do have some questions concerning your 2nd suggestion.
- Did you mean, to have the FIFO's ports as records? Or to cast the std_logic_vector into a record in the top-level where the FIFO is instantiated?
- The way I see it, to have a rather generic FIFO of records, we would have to declare the record type in an external package and change that according to the design.
But then again, my FIFO will no longer be generic enough to be reused differently in the same design (e.g. if I need to use 2 different FIFOs)
- Also, I had previously had some trouble inferring block RAM using records (I had to "un-wrap/re-wrap" the record into an std_logic_vector type). Note that I might have been using older tools at the time.

C.
 
K

KJ

Or to cast the std_logic_vector into a record in the top-level where the FIFO is instantiated? - The way I see it, to have a rather generic FIFO of records, we would have to declare the record type in an external package and change that according to the design.

That's one way. The other way is to convert to/from std_logic_vector rightnear where the record is first generated and then used. That makes those conversion functions part of a package that is local to the design and the FIFO is completely oblivious to the records.

As soon as you talk about wanting a 'generic' widget of any sort, the interface to that widget almost immediately becomes std_logic_vector because that is the common denominator, 'specially for something is inherently genericlike memory. If your widget happens to perform some form of mathematical function your interface might be 'signed/unsigned' or 'sfixed/ufixed' depending on what you're computing. But store those results in memory someplaceand even those types will get converted to/from slv. It's still a good idea to define a widget with signal interface types that are appropriate for what function is being performed, but don't gack just because it needs to be converted to/from std_logic_vectors at some point. Re-using a component is usually a 'good' thing.

An example of the way I do this with records is shown in the example at theend of the post. If the problem you're working doesn't lend itself to fixed sized fields (i.e. the bit numbers in the field definitions vary depending on usage), then the solution can get a bit more complicated but in general I've found that a particular design 'usually' gets by just fine with a fixed record definition so the solution below works.

Kevin Jennings

--- Example of a record type and to/from std_logic_vector functions
type t_CNTL_PORT is record
Reserved: std_ulogic_vector(7 downto 3);
Hcard_Empty: std_ulogic_vector(2 downto 2);
Hopper_Empty: std_ulogic_vector(1 downto 1);
Feeder_Exit: std_ulogic_vector(0 downto 0);
end record t_CNTL_PORT;
function To_Std_ULogic_Vector(L: t_CNTL_PORT) return std_ulogic_vector is
variable RetVal: std_ulogic_vector(31 downto 0);
begin
RetVal(L.Reserved'range) := L.Reserved;
RetVal(L.Hcard_Empty'range) := L.Hcard_Empty;
RetVal(L.Hopper_Empty'range) := L.Hopper_Empty;
RetVal(L.Feeder_Exit'range) := L.Feeder_Exit;

return(RetVal);
end function To_Std_ULogic_Vector;

function From_Std_ULogic_Vector(L: std_ulogic_vector) return t_CNTL_PORT is
variable Lx: std_ulogic_vector(L'length - 1 downto 0);
variable RetVal: t_CNTL_PORT;
begin
Lx := L;

RetVal.Reserved := Lx(RetVal.Reserved'range);
RetVal.Hcard_Empty := Lx(RetVal.Hcard_Empty'range);
RetVal.Hopper_Empty := Lx(RetVal.Hopper_Empty'range);
RetVal.Feeder_Exit := Lx(RetVal.Feeder_Exit'range);

return(RetVal);
end function From_Std_ULogic_Vector;



But then again, my FIFO will no longer be generic enough to be reused differently in the same design (e.g. if I need to use 2 different FIFOs) - Also, I had previously had some trouble inferring block RAM using records (I had to "un-wrap/re-wrap" the record into an std_logic_vector type). Note thatI might have been using older tools at the time. C.
 
C

carloshyneman

Kevin, thanks for the suggestion!
I guess that it can be also coded as Andy said in 1), in order to have the generic (non-fixed) type fields with relative ranges even inside the record.

C.
 
A

Andy

Hello, Thanks for your input guys! I am currently using VHDL93 (in order to remain rather compatible with the whole team; plus I did not have much time to venture on my own). Some still believe that VHDL2008 is not well supported etc... (But I guess I would keep that for a different thread). - If am using VHDL93 with ISE 13.2, the "aggregate" of std_logic_vector does notwork, it only works for std_logic types. - 1) The "range" tip and using the "high/low" attributes of the previous range seems to be a good enough approach for me (at least it does not cascade into infinitely long lines). - 2) This does seem more intuitive for some cases. But it happens to be that Iam using a generic fifo (depth and width) and the data ports are of std_logic_vector type. Andy, I do have some questions concerning your 2nd suggestion. - Did you mean, to have the FIFO's ports as records? Or to cast the std_logic_vector into a record in the top-level where the FIFO is instantiated? - The way I see it, to have a rather generic FIFO of records, we would have to declare the record type in an external package and change that according to the design. But then again, my FIFO will no longer be generic enough to be reused differently in the same design (e.g. if I need to use 2 different FIFOs) - Also, I had previously had some trouble inferring block RAM using records (I had to "un-wrap/re-wrap" the record into an std_logic_vector type). Note that I might have been using older tools at the time. C.

You have just hit onto one of the advantages of records on ports. You can use them like an electrical conduit in a building. Route the conduit throughthe walls first, then decide later what wires need to be pulled through the conduit.

Note that the subranges can also make converting between the record and theSLV easier. Just define the record elements with ranges that reflect theirlocation in the corresponding all-in-one SLV.

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,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top