Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Concatenate/De-Concatenate

Reply
Thread Tools

Concatenate/De-Concatenate

 
 
Carlos
Guest
Posts: n/a
 
      10-12-2012
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.
 
Reply With Quote
 
 
 
 
goouse99@gmail.com
Guest
Posts: n/a
 
      10-12-2012
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
 
Reply With Quote
 
 
 
 
carloshyneman@gmail.com
Guest
Posts: n/a
 
      10-12-2012
That's pretty much what I was looking for, thanks!
 
Reply With Quote
 
carloshyneman@gmail.com
Guest
Posts: n/a
 
      10-12-2012
On Friday, October 12, 2012 2:53:16 AM UTC-4, (unknown) wrote:
> 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


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?
 
Reply With Quote
 
rickman
Guest
Posts: n/a
 
      10-13-2012
On 10/12/2012 2:53 AM, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> 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



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
 
Reply With Quote
 
HT-Lab
Guest
Posts: n/a
 
      10-13-2012
On 12/10/2012 19:49, (E-Mail Removed) wrote:
> 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
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      10-15-2012

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

 
Reply With Quote
 
carloshyneman@gmail.com
Guest
Posts: n/a
 
      10-17-2012
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.
 
Reply With Quote
 
KJ
Guest
Posts: n/a
 
      10-18-2012
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.

 
Reply With Quote
 
carloshyneman@gmail.com
Guest
Posts: n/a
 
      10-18-2012
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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments