VHDL: Concatenation Operator

       Many VHDL programmers doesnt know that there is an operator available in VHDL for doing concatenation. But there is one. It is written as &.

Lets explore this operator through a lot of practical examples...

Example 1:


signal x, y : std_logic := '0';
signal var1 : unsigned(1 downto 0); 
signal var2 : unsigned(0 to 1);
var1 <= x & y;
var2 <= x & y;

--the above statements are the same as:
var1(1) <= w and x; --this is the MSB
var1(0) <= y and z; --this is the LSB
var2(0) <= w and x; --this is the MSB
var2(1) <= y and z; --this is the LSB

Note how the variable on the left side of the concatenation operator is assigned to the MSB of the result.

Example 2:


    Integers cannot be concatenated directly, but they can be converted to signed or unsigned type first and then concatenate. But you should make sure that the integers doesn't overflow when you convert them to binary format. Otherwise your design won't work as expected.

signal x, y : integer;  --two integers
signal var1 : unsigned(15 downto 0);  --16 bit
signal var2 : unsigned(7 downto 0);   --8 bit
--Lets do the type conversions and concatenations as follows:
var1 <= to_unsigned(x,8) & to_unsigned(y,8);
var2 <= to_unsigned(x,4) & to_unsigned(y,4);

Tests:

--For:
x <= 100;  y <= 20;  --x is "64" in hex and y is "14" in hex.
--The result is 
var1 <= x"6414";  --x takes MSB 8 bits and y takes LSB 8 bits.
var2 <= x"44";  --Note how the MSB 4 bits from x and y are removed here. 
--That is because x and y are converted to 4 bit binary first before assigning to var2.

--For:
x <= 10;  y <= 5;  --x is "0A" in hex and y is "05" in hex.
--The result is 
var1 <= x"0A05";  --x takes MSB 8 bits and y takes LSB 8 bits.
var2 <= x"A5";  --Here we didnt loose any bits.

--For:
x <= 10;  y <= 17;  --x is "0A" in hex and y is "11" in hex.
--The result is 
var1 <= x"0A11";  --x takes MSB 8 bits and y takes LSB 8 bits.
var2 <= x"A1"; --Again, MSB bits from y was lost because it had more than 4 bits.
    

Example 3:


    This helps to set some bits zero in a longer vector of bits. An example would be:

--var1 is initialized with hexadecimal value of "ff" here
signal var1 : unsigned(7 downto 0) := x"ff";  

--after the below statement, var2 will become "0000_0001" 
var1 <= x"0" & x"1";

Example 4:


    This operator is very useful when it comes to checking a group of bits inside a case statement. The following example illustrates this concept:

signal var : integer;
process(bit0,bit1,bit2,bit3)
    variable bitcat : std_logic_vector(3 downto 0);
begin
    bitcat := bit0 & bit1 & bit2 & bit3; --concatenation
    case bitcat is
        when "0001" => var <= 1; --when bit3 is '1' and all else is '0'.
        when "0010" => var <= 3; --when bit2 is '1' and all else is '0'.
        when others => var <= 4; --for all other combinations.
    end case;
end process;

    These are some of the situations where the & operator can be used to achieve a more readable friendly code.
Let me know if I have missed some interesting use cases.

Post a Comment

3 Comments

  1. I think in cancatation t<= (x and w) & (y and z). result of y and z is assigned to LSB of t and result of x and w is assigned to MSM i.e.t(1)

    ReplyDelete
  2. @Ravindar : yeah.. you are right.Sorry for the typing mistake.I have corrected it.Some more examples are here...

    signal a : unsigned(1 downto 0);
    signal b : unsigned(0 to 1);
    a <= '1' & '0';
    b <= '1' & '0';
    --this is same as:
    a(1) <= '1';
    a(0) <= '0';
    b(1) <= '0';
    b(0) <= '1';

    thanks for the comment.

    ReplyDelete
  3. A useful tip -- watch out for operator order. eg "x & y and z & w" is the same as (x&y) and (z&w). Its easy to accidently read it as x & (y and z) & w. This usually results in a synthesis error, as its unlikely the dimensions will match.

    ReplyDelete