How to convert 8 bits to 16 bits in VHDL?
Asked Answered
C

5

17

I have an input signal from ADC convertor that is 8 bits (std_logic_vector(7 downto 0)). I have to convert them to a 16 bits signal (std_logic_vector(15 downto 0)) for 16 bits signal processing to the 16 bits system.

Chandlery answered 3/7, 2013 at 15:1 Comment(0)
T
33

If the 8 bit value is interpreted as signed (2's complement), then the general and standard VHDL conversion method is to use the IEEE numeric_std library:

library ieee;
use ieee.numeric_std.all;

architecture sim of tb is
    signal slv_8  : std_logic_vector( 8 - 1 downto 0);
    signal slv_16 : std_logic_vector(16 - 1 downto 0);
begin
    slv_16 <= std_logic_vector(resize(signed(slv_8), slv_16'length));
end architecture;

So first the std_logic_vector is converted to a signed value, then the resize is applied, which will sign extend the signed value, and the result is finally converted back to std_logic_vector.

The conversion is rather lengthy, but has the advantage that it is general and works even if the target length is changed later on.

The attribute 'length simply returns the length of the slv_16 std_logic_vector, thus 16.

For unsigned representation instead of signed, it can be done using unsigned instead of signed, thus with this code:

    slv_16 <= std_logic_vector(resize(unsigned(slv_8), slv_16'length));
Tradition answered 3/7, 2013 at 17:19 Comment(4)
I was trying to resize from 16 to 8 bits as: resized_var1 :=std_logic_vector(resize(unsigned(Kp)*unsigned(integration1)),8); I was getting error as : "Type conversion (to std_logic_vector) can not have aggregate operand." Why doesn't it work?Disapproval
Because the ,8 should be inside the parens for resize() and not std_logic_vector().Mentholated
I think it's important to note that resize does not change the numeric value. Zeroes are added to the left when resizing to a larger vectorAmmoniate
@Damo: Your comment is only correct if resize makes an unsigned type longer. If resize is used to make a unsigned or signed type shorter, then MSBs are truncated, which can alter value, and if resize is used to make a signed value longer, then the sign (MSB) is used for filling, and not 0.Tradition
L
7
architecture RTL of test is
    signal s8: std_logic_vector(7 downto 0);
    signal s16: std_logic_vector(15 downto 0);
begin
    s16 <= X"00" & s8;
end;
Lamont answered 3/7, 2013 at 15:11 Comment(6)
What is 'X' in line 5 mean ?Chandlery
The 'x' is for "hexadecimal". So x"00" is basicly "00000000" binary.Bushwhacker
If i want convert "11111111" to "1111111111111111"Chandlery
Wait, so do you want to prepend ones all the time, or just when the number is "negative"? If the former, you should do s16 <= x"ff" & s8 or s16 <= (7 downto 0 => '1') & s8. If the latter, you should pull out bit 7 of s8 and replace the '1' in the second statement with that.Prisage
This actually is a wrong answer, for negative signal, then you will end up getting a wrong signal after this extension.Dyer
@Passepartout, this answer about x"00 is really usefull. I was looking all over the internet about it.Hendrika
M
4

This handles the conversion without having to edit the widths of the zeroes if either std_logic_vector changes:

architecture RTL of test is
    signal s8: std_logic_vector(7 downto 0);
    signal s16: std_logic_vector(15 downto 0) := (others => '0');
begin
    s16(s8'range) <= s8;
end;
Meares answered 27/10, 2015 at 15:29 Comment(0)
L
4

With the newly released VHDL-2019 standard you can do

larger_vec <= extend(shorter_vec);

where extend is a function defined as follows

function extend(vec : std_logic_vector) return target_vec of std_logic_vector is
  variable result : std_logic_vector(target_vec'length - 1 downto 0) := (others => '0');
begin
  assert vec'length <= target_vec'length report "Cannot extend to shorter vector";
  result(vec'length - 1 downto 0) := vec;
  return result;
end function;

Tool support is still a bit limited but at least one simulator supports this (Riviera-PRO).

Laraelaraine answered 28/6, 2020 at 14:2 Comment(0)
M
3

For completeness, yet another way which is occasionally useful:

--  Clear all the slv_16 bits first and then copy in the bits you need.  
process (slv_8)
begin
    slv_16 <= (others => '0');
    slv_16(7 downto 0) <= slv_8;
end process;

I've not had to do this for vectors that I can recall, but I have had need of this under more complex circumstances: copying just a few relevant signals into a bigger, more complex, record was one time.

Macfadyn answered 4/7, 2013 at 11:0 Comment(2)
And sign extension is done with the first assign as slv_16 <= (others => slv_8(7));Tradition
That's correct functionally, but I'd argue that if you are wanting sign-extension, you should be using proper numeric types (ie signed) and then using the resize function - as you proposed in your answer :)Macfadyn

© 2022 - 2024 — McMap. All rights reserved.