Concatenate/De-Concatenate

Discussion in 'VHDL' started by Carlos, Oct 12, 2012.

  1. Carlos

    Carlos Guest

    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.
     
    Carlos, Oct 12, 2012
    #1
    1. Advertising

  2. Carlos

    Guest

    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
     
    , Oct 12, 2012
    #2
    1. Advertising

  3. Carlos

    Guest

    That's pretty much what I was looking for, thanks! :D
     
    , Oct 12, 2012
    #3
  4. Carlos

    Guest

    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?
     
    , Oct 12, 2012
    #4
  5. Carlos

    rickman Guest

    On 10/12/2012 2:53 AM, 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
     
    rickman, Oct 13, 2012
    #5
  6. Carlos

    HT-Lab Guest

    On 12/10/2012 19:49, 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
     
    HT-Lab, Oct 13, 2012
    #6
  7. Carlos

    Andy Guest

    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
     
    Andy, Oct 15, 2012
    #7
  8. Carlos

    Guest

    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.
     
    , Oct 17, 2012
    #8
  9. Carlos

    KJ Guest

    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.
     
    KJ, Oct 18, 2012
    #9
  10. Carlos

    Guest

    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.
     
    , Oct 18, 2012
    #10
  11. Carlos

    Andy Guest

    On Wednesday, October 17, 2012 11:57:46 AM UTC-5, wrote:
    > 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
     
    Andy, Oct 24, 2012
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike James
    Replies:
    1
    Views:
    1,843
    Jim Gibson
    Sep 19, 2003
  2. Luis E Valencia

    Concatenate Hyperlink with databinder

    Luis E Valencia, May 27, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    1,718
    Luis E Valencia
    May 27, 2004
  3. =?Utf-8?B?TWlrZSBNb29yZQ==?=

    Concatenate

    =?Utf-8?B?TWlrZSBNb29yZQ==?=, Nov 24, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    4,235
    Mark Rae
    Nov 24, 2004
  4. Luis Esteban Valencia

    Concatenate datalist variables with javascript and html

    Luis Esteban Valencia, Jan 20, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    2,659
    Luis Esteban Valencia
    Jan 20, 2005
  5. =?Utf-8?B?am9uZWZlcg==?=

    Can't concatenate for data adapters

    =?Utf-8?B?am9uZWZlcg==?=, Oct 11, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    412
    S. Justin Gengo
    Oct 17, 2005
Loading...

Share This Page