Splitting 16 bit vector into 2 bytes

D

David Perry

Guest
I have a 16 bit vector which I want to split into 2 8 bit vectors, I thought I would be able to do this:
(Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
I want to split the 16 bit voltage value into 2 bytes to be transmitted later.

Obviously I could avoid the problem by assigning (15:8) to byte 4 and (7:0) to byte 3 (I was doing this originally), but I am trying to avoid doing that, it's not quite as neat :)

Is there any decent reference to this stuff? I'm finding that I end up just trying things and see if it compiles and does what I think it does, which is a pain and obviously not the best way to find out how to do such things. Almost all of the documentation I find only deals with the absolute basics :(
 
I've ended up using alias's, the code is neater but there's still magic numbers in the alias's :(
 
On Monday, August 22, 2016 at 9:18:05 AM UTC-4, David Perry wrote:
I have a 16 bit vector which I want to split into 2 8 bit vectors, I thought I would be able to do this:
(Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
I want to split the 16 bit voltage value into 2 bytes to be transmitted later.

If Tx_Byte_4 happens to be defined as (15 downto 8) and Tx_Byte_3 defined as (7 downto 0), then you could write it as:

Tx_Byte_4 <= INV_Volts(Tx_Byte_4'range);
Tx_Byte_3 <= INV_Volts(Tx_Byte_3'range);

Kevin Jennings
 
On Tuesday, August 23, 2016 at 12:57:44 PM UTC+12, rickman wrote:
On 8/22/2016 1:57 PM, KJ wrote:
On Monday, August 22, 2016 at 9:18:05 AM UTC-4, David Perry wrote:
Or you can do some shifting...

Or you can hide the magic (numbers) in a package:

library ieee;
use ieee.std_logic_1164.all;

package byte_games is
subtype byte1_range is integer range 15 downto 8;
subtype byte0_range is integer range 7 downto 0;
subtype byte is std_logic_vector(byte0_range);
type two_byte is record
byte1: byte;
byte0: byte;
end record;
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.byte_games.all;

entity foo is
end entity;

architecture fum of foo is
signal tx_Byte_4: std_logic_vector (7 downto 0);
signal tx_Byte_3: std_logic_vector (7 downto 0);
signal INV_Volts: std_logic_vector (15 downto 0);

function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
process
begin
INV_Volts <= x"1234";
wait for 0 ns;
-- (Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
(Tx_Byte_4, Tx_Byte_3) <=
two_byte'(INV_Volts(byte1_range), INV_Volts(byte0_range));
wait for 0 ns;
report "Tx_Byte_4 = " & to_string(Tx_Byte_4);
report "Tx_Byte_3 = " & to_string(Tx_Byte_3);
wait;
end process;
end architecture;

ghdl -r foo
foo.vhdl:44:9:mad:0ms:(report note): Tx_Byte_4 = 00010010
foo.vhdl:45:9:mad:0ms:(report note): Tx_Byte_3 = 00110100

(The to_string function is predefined in -2008).
 
On 8/22/2016 1:57 PM, KJ wrote:
On Monday, August 22, 2016 at 9:18:05 AM UTC-4, David Perry wrote:
I have a 16 bit vector which I want to split into 2 8 bit vectors, I thought I would be able to do this:
(Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
I want to split the 16 bit voltage value into 2 bytes to be transmitted later.

If Tx_Byte_4 happens to be defined as (15 downto 8) and Tx_Byte_3 defined as (7 downto 0), then you could write it as:

Tx_Byte_4 <= INV_Volts(Tx_Byte_4'range);
Tx_Byte_3 <= INV_Volts(Tx_Byte_3'range);

Or you can do some shifting...

Tx_Byte_4 <=
RESIZE(srl(unsigned(INV_Volts),Tx_Byte_3'LENGTH),Tx_Byte_4'LENGTH);
Tx_Byte_3 <= INV_Volts(Tx_Byte_3'range);

Pretty groady. Or you can do some math without the numbers...

Tx_Byte_4 <= INV_Volts(Tx_Byte_4'HIGH+Tx_Byte_3'LENGTH downto
Tx_Byte_3'LENGTH);
Tx_Byte_3 <= INV_Volts(Tx_Byte_3'range);

Still far from compact. It would be simpler if there was a way to
specify a range plus an offset. Then the high byte assignment would be
just...

Tx_Byte_4 <= INV_Volts(Tx_Byte_4'RANGE+Tx_Byte_3'LENGTH);

Not quite as bad.

ranges in VHDL always get messy.

The simplest approach is something like KJ's suggestion or I would
define ranges to use...

subtype ByteRngHi is Integer range 15 downto 8;
subtype ByteRngLo is Integer range 7 downto 0;

Tx_Byte_4 <= INV_Volts(ByteRngHi);
Tx_Byte_3 <= INV_Volts(ByteRngLo);

I actually defined four such ranges for four bytes in a 32 bit word.
Here is my use of a couple.

IF (RamLobWr = '1') THEN
DataSramLo (RamAddr) <= DatTosReg(ByteRng0);
END IF;
IF (RamHibWr = '1') THEN
DataSramHi (RamAddr) <= DatTosReg(ByteRng1);
END IF;

--

Rick C
 
If you want to split INV_Volts between Tx_Byte_4 and Tx_Byte_3 you could express just that with a procedure call. For example

split(INV_Volts, between => Tx_Byte_4, \and\ => Tx_Byte_3);

Readable? I guess that depends who you're asking. The extended \and\ identifier is likely to confuse people and tools. Anyway, such a procedure would be somewhat generic with respect to the vector ranges and there are no magic numbers.

Example code/testbench is here: https://github.com/LarsAsplund/splitting_signals/blob/master/test/tb_split.vhd

The testbench report is here: https://travis-ci.org/LarsAsplund/splitting_signals
 
I have a 16 bit vector which I want to split into 2 8 bit vectors, I thought I would be able to do this:
(Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
I want to split the 16 bit voltage value into 2 bytes to be transmitted later.

If your tool supports VHDL-2008, that will work. Did you turn on the VHDL-2008 switch?

See KJ's solution for a good prior to VHDL-2008 solution.
 
You have all given me something to think about.
I didn't realise you can define a sybtype of range, suddenly all my code will look a lot neater!
I shall look into vhdl-2008, so far I've stayed with the default '93.
 
W dniu poniedziałek, 22 sierpnia 2016 15:18:05 UTC+2 użytkownik David Perry napisał:
I have a 16 bit vector which I want to split into 2 8 bit vectors, I thought I would be able to do this:
(Tx_Byte_4, Tx_Byte_3) <= INV_Volts; --this no worky
I want to split the 16 bit voltage value into 2 bytes to be transmitted later.

Obviously I could avoid the problem by assigning (15:8) to byte 4 and (7:0) to byte 3 (I was doing this originally), but I am trying to avoid doing that, it's not quite as neat :)

And Congratulations!! VHDL is a hardware description Language, and you should precisely assign wires to wires. VHDL is a strong typed HW description language enhirited from ADA. In fact, the declarations of signals and its types are very sensitive. Well, probably you have some bad behaviors taken from C language.
I strongly prefare STRONGLY TYPED HDL languages. And also programming languages. Your problem is 100+% a reason of looking on HDL from a point of view of a C educated/bemused. The problem you described, occurs very often in a very similar situations in software developement (C "youngsters").

C is an invitation to dissaster. Unfortunately, worldwide marketing made is a "standard". Pascal as a predecessor of C is a strong typed language. It's syntax is in fact quite similar to C, however it's more rigorous. What a f... for was C designed?! Well, not because programmers needed it, but just only because it was possible. Moreover, good marketing (C is high level language fast as assembler). Bul...t !! Final code is as good as the compiler is.

Returning back to the main topic, define precisely your input and output vectors.

For example:

a: in std_logic_vector(N downto 0);
b: out std_logic_vector(I downto 0);
c: out std_logic_vector(J downto 0);

Further assigment like:

b((I downto 0)) <= a( SameNumberOfBits);

The above is not 100% correct, but I hope you know what I mean.

=============
If any more questions, just ask. I'll try to explain as much as I can.
Stachu
 
On 06/09/2016 02:07, stchebel@gmail.com wrote:
W dniu poniedziałek, 22 sierpnia 2016 15:18:05 UTC+2 użytkownik David
Perry napisał:
I have a 16 bit vector which I want to split into 2 8 bit vectors,
I thought I would be able to do this: (Tx_Byte_4, Tx_Byte_3) <=
INV_Volts; --this no worky I want to split the 16 bit voltage value
into 2 bytes to be transmitted later.

Obviously I could avoid the problem by assigning (15:8) to byte 4
and (7:0) to byte 3 (I was doing this originally), but I am trying
to avoid doing that, it's not quite as neat :)


And Congratulations!! VHDL is a hardware description Language, and
you should precisely assign wires to wires. VHDL is a strong typed HW
description language enhirited from ADA. In fact, the declarations of
signals and its types are very sensitive. Well, probably you have
some bad behaviors taken from C language. I strongly prefare STRONGLY
TYPED HDL languages. And also programming languages. Your problem is
100+% a reason of looking on HDL from a point of view of a C
educated/bemused. The problem you described, occurs very often in a
very similar situations in software developement (C "youngsters").

C is an invitation to dissaster. Unfortunately, worldwide marketing
made is a "standard". Pascal as a predecessor of C is a strong typed
language. It's syntax is in fact quite similar to C, however it's
more rigorous. What a f... for was C designed?! Well, not because
programmers needed it, but just only because it was possible.

You need to have a look at the history of C. While it not as strongly
typed as some, it is better than assembler. The whole intention was
initially to move away from assembler.

Moreover, good marketing (C is high level language fast as
assembler). Bul...t !! Final code is as good as the compiler is.

I think C sold itself. Despite lots of marketing it hasn't changed much.

Returning back to the main topic, define precisely your input and
output vectors.

For example:

a: in std_logic_vector(N downto 0);
b: out std_logic_vector(I downto 0);
c: out std_logic_vector(J downto 0);

Further assigment like:

b((I downto 0)) <= a( SameNumberOfBits);

The above is not 100% correct, but I hope you know what I mean.

Assuming N GE I



--
Mike Perkins
Video Solutions Ltd
www.videosolutions.ltd.uk
 
On Tuesday, 6 September 2016 02:07:35 UTC+1, stch...@gmail.com wrote:
>Your problem is 100+% a reason of looking on HDL from a point of view of a C educated/bemused. The problem you described, occurs very often in a very similar situations in software developement (C "youngsters").

Actually, I'm moving from Schematic entry to VHDL. I will miss schematic entry, newer toolchains seem to be dropping it though :(
 

Welcome to EDABoard.com

Sponsor

Back
Top