padding out std_logic_vector with leading zeros
Asked Answered
S

5

17

ok, what I would like to do is assign a smaller std_vector to a large one, padding out the upper bits with zeros. But, I want something generic and simple that doesn't involve knowing the size of each first.

for instance if I have:

signal smaller_vec: std_logic_vector(15 downto 0);
signal larger_vec: std_logic_vector(31 downto 0);

I could do:

larger_vec <= X"0000" & smaller_vec;

But what if I don't know the size of the smaller vector. Is there a was of specifying that all upper bits are zero.

I know about the others clause, but that would get messy as I'd need a couple of lines:

larger_vec(smaller_vec'high downto 0) <= smaller_vec;
larger_vec(31 downto smaller_vec'length) <= (others => '0');

I thought I could use:

larger_vec <= "" & smaller_vec;

but this didn't work. any ideas?

Shardashare answered 18/3, 2015 at 12:58 Comment(3)
I think this previous question pretty much answers it #17451992Bircher
Watch out though, that answer will sign-extended, replace 'signed' with 'unsigned' for zeros...Roydd
Possible duplicate of How to convert 8 bits to 16 bits in VHDL?Camargo
E
10

Have you tried:

larger_vec <= (31 downto smaller_vec'length => '0') & smaller_vec;

In the past I have had synthesis tool issues with code like that, so I have used:

constant ZERO : std_logic_vector(larger_vec'range) := (others => '0');
. . .
larger_vec <= ZERO(31 downto smaller_vec'length) & smaller_vec;
Endoskeleton answered 18/3, 2015 at 14:36 Comment(2)
While using ieee.std_logic_unsigned.all, you could also tried : larger_vect <= ZERO + smaller_vec;.Minima
You could also do larger_vec <= (larger_vec'left downto smaller_vec'length => '0') & smaller_vec; thereby you don't even have to specify the 31.Inane
F
4

James0's 2nd post was close, but the <= is facing the wrong direction, see below for a working example from duolos. I would edit, but at the time of this post I did not have enough reputation.

In https://www.doulos.com/knowhow/vhdl_designers_guide/vhdl_2008/vhdl_200x_ease/ in the Vectors in aggregates section it says:

    variable V : std_logic_vector(7 downto 0);
  begin
    V := (others => '0');                    -- "00000000"
    V := ('1', '0', others => '0');          -- "10000000"
    V := (4 => '1', others => '0');          -- "00010000"
    V := (3 downto 0 => '0', others => '1'); -- "11110000"
    -- V := ("0000", others => '1');         -- illegal!
larger_vec <= (smaller_vec'high downto 0 => smaller_vec, others => '0');

should work.

Favors answered 22/2, 2019 at 6:24 Comment(1)
Sadly, while this seems entirely logical, it doesn't actually work (in at least one tool) -- it will always output 0 and completely ignores smaller_vec. Safer to use one of the alternatives.Schrader
S
2

in my case I also like the following:

larger_vec <= (smaller_vec'high downto 0 <= smaller_vec, others => '0');

Which does my final answer in one line. This works, yes?

Shardashare answered 18/3, 2015 at 13:14 Comment(0)
G
1

I have encountered similar issues and tried the following:

larger_vec <= (larger_vec'range => '0') + shorter_vec;

You need to use IEEE.std_logic_unsigned.all for this approach.

Glycoprotein answered 1/6, 2018 at 9:58 Comment(1)
std_logic_unsigned is deprecated. Use numeric_std_unsigned.Camargo
E
0

Zero-Pad or Truncate any std_logic_vector or std_logic to exactly 16 bits:

function pad16(x: std_logic_vector) 
    return std_logic_vector is 
    constant ZERO : std_logic_vector(15 downto 0) := (others => '0');
begin
    if (x'length < 16) then
        return ZERO(15 downto x'length) & x;
    else
        return x(15 downto 0);
    end if;
end function;

--overload function for single bit
function pad16(x: std_logic)
    return std_logic_vector is
    constant ZERO : std_logic_vector(15 downto 0) := (others => '0');
begin
    return ZERO(15 downto 1) & x;
end function;

-- USAGE:
--
--    reg16 <= pad16(X"3");

Electroencephalograph answered 15/5, 2019 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.