VHDL writing std_logic_vector as a signed integer in file - type-conversion

I wonder how to write a std_logic_vector as a signed integer in VHDL testbench?

Using numeric_std:
signal test_in : std_logic_vector(2 downto 0);
signal test_out : integer range -4 to 3;
test_out <= to_integer(signed(test_in));

You need to convert to an integer (using the use ieee.numeric_std.all;, which means you need to know if your std_logic_vector is representing a signed or unsigned number. Ideally, you'd use the relevant type rather than the bag-of-bits that std-logic_vector is.
Converting to an integer is as straightforward as:
int_variable := to_integer(some_vector);
If you must stick to a std_logic_vector you'll have to tell the compiler whether it is unsigned or signed like this:
int_variable := to_integer(unsigned(some_vector));
or this:
int_variable := to_integer(signed(some_vector));
Then you can write you integer to the file as you normally would.

Related

Converting arrays from signed to integer in VHDL?

I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);

Twincat 3: How to convert 4 HEX array to Float?

we are receiving (via UDP datagram) a float value codified by 4 bytes hex array.
We need to convert from 4 hex bytes to a float.
udp_data[0] = 'BE';
udp_data[1] = '7A';
udp_data[2] = 'E0';
udp_data[3] = 'F4';
In the given example, the correct equivalence, after transformation, udp_data is equivalent to -0.24499:
What is the optimal conversion in Twincat 3 PLC? maybe some library? We need to perform 52 transformation at once of this type.
I attached an example with an example taken from an online calculator:
Thanks!!
You can use a UNION type, which will at the same address hold a byte array (like the one you get from your UDP communication) and the real var which you want to convert to.
When you change the byte array, the real automatically reflects it. The conversion works the other way around also, in fact.
TYPE U_Convert :
UNION
arrUDP_Data: ARRAY [0 .. 3] OF BYTE; // Array must start with LSB
rReal : REAL;
END_UNION
END_TYPE
In MAIN you can declare the following var.
VAR
uConvert: U_Convert;
fValue : REAL;
END_VAR
And in the body of MAIN, update the byte array to requested values.
// Here we update the byte array
uConvert.arrUDP_Data[0] := 16#F4; // LSB
uConvert.arrUDP_Data[1] := 16#E0;
uConvert.arrUDP_Data[2] := 16#7A;
uConvert.arrUDP_Data[3] := 16#BE; // MSB
// Here we 'use' the converted value
fValue := uConvert.rReal;
I assume you have an array of bytes.
Header (put this in own function block if you want):
PROGRAM MAIN
VAR
aByteArray : ARRAY[1..4] OF BYTE := [16#F4, 16#E0, 16#7A, 16#BE];
pt : POINTER TO REAL;
fRealValue : REAL;
END_VAR
Body:
pt := ADR(aByteArray);
fRealValue := pt^;
Will give you the desired result:

Average value of input Data in Mitsubishi GX Works 2

I need to obtain an average value of my input signals from mitsubishi input module Q64AD. I'm working in GX Works 2 in structured text.
This is how i used to obtain average value in Codesys:
timer_sr(IN:= NOT timer_sr.Q , PT:= T#5s );
SUM1:= SUM1 + napr1;
Nsum:=Nsum + 1;
IF timer_sr.Q THEN
timer_sr(IN:= NOT timer_sr.Q , PT:= T#5s);
outsr := SUM1 /Nsum;
Nsum := 0;
SUM1 := 0;
END_IF;
napr1 - is value from module
This piece of code is not working in GX Works 2, and i think because SUM1 is not an INT data type, but just a Word[signed] type.
Is there a way to make SUM1 an INT type or may be there is another logic to that solution?
In other platforms it should work but the compiler gives a warning so I guess it will still compile? Of course, if the value is negative there will be problems.
You can convert a WORD to INT by the IEC function WORD_TO_INT. I'm not sure how well your system follows the standard but if it does, try the following:
WORD_TO_INT(SUM1). If the SUM1 > 65535 then there will be problems as the upper bound of INTis 32767.
If this doesn't help, could you provide more details? How is it not workin?
Ps. The WORD is unsigned data type, not signed as you wrote.

Variable std_logic_vector or array entry in vhdl

I'm currently working on AES encryption using keys of three different sizes (128,192, and 256 bit).
I was wondering if I can declare / use a std_logic_vector of a variable size? For example, can I just have one input port and I get to know wether it's 128,192, or 256 bit based on the user input?
Or else if I choose the max key length, which is 256 bit, can I assign a 128 or 192 bit key to that std_logic_vector? Or will an error message appear?
If the size of key changes at run-time, you will have to declare
the corresponding objects (signals, constants, variables) with the
maximum possible size. The actual key length will then be defined by another
signal or variable. The maximum size may be defined as below.
If you declare an object of type std_logic_vector with the maximum possible size, then assigning a shorter std_logic_vector will result in an error. You will have to extend the right-hand aside of the assignment to the size of the target object first, e.g. using the following resize function from the PoC Library where I'm one of the authors:
function resize(vec : std_logic_vector; length : natural; fill : std_logic := '0') return std_logic_vector is
constant high2b : natural := vec'low+length-1;
constant highcp : natural := imin(vec'high, high2b);
variable res_up : std_logic_vector(vec'low to high2b);
variable res_dn : std_logic_vector(high2b downto vec'low);
begin
if vec'ascending then
res_up := (others => fill);
res_up(vec'low to highcp) := vec(vec'low to highcp);
return res_up;
else
res_dn := (others => fill);
res_dn(highcp downto vec'low) := vec(highcp downto vec'low);
return res_dn;
end if;
end function;
For example, given a 128-bit std_logic_vector named source, this can be re-sized to 256 bit with:
resize(source, 256) -- returns a 256-bit std_logic_vector
The function works like the resize function on unsigned and signed from package numeric_std.
If the key size is known at compile (elaboraton) time, then you will
have two options. A usual approach is to define the key size by a
constant and passing the key size via generics to sub-components.
The following entity test has a generic SIZE specifying the key
size. The length of ports as well as other objects, can now be defined
depending on this generic.
library ieee;
use ieee.std_logic_1164.all;
entity test is
generic (
SIZE : positive := 128); -- the default value can be omitted
port (
x : in std_logic_vector(SIZE-1 downto 0);
y : out std_logic_vector(SIZE-1 downto 0));
end entity test;
architecture rtl of test is
begin -- architecture rtl
y <= not x;
end architecture rtl;
The generic can now be bound during the instantiation of this entity,
for example:
library ieee;
use ieee.std_logic_1164.all;
entity test_tb is
end entity test_tb;
architecture rtl of test_tb is
constant SIZE : positive := 192;
signal x : std_logic_vector(SIZE-1 downto 0) := (others => '0');
signal y : std_logic_vector(SIZE-1 downto 0);
begin -- architecture rtl
dut: entity work.test
generic map (
SIZE => SIZE)
port map (
x => x,
y => y);
end architecture rtl;
Of course, the length of the actuals (right side in port map) must
match the length of the formals (left side in port map). This approach
is supported by all (major) VHDL synthesis tools. If default values
for the generics are present, then test can be directly synthesized as
top-level module.
The second option, for a fixed key-size during elaboration, would be
to use unconstrained arrays (std_logic_vector) in the port
declaration of the entity. The actual size of the array can be
determined with the length atribute, and the actual range with the
range attribute, for example:
library ieee;
use ieee.std_logic_1164.all;
entity test2 is
port (
x : in std_logic_vector;
y : out std_logic_vector);
end entity test2;
architecture rtl of test2 is
signal z : std_logic_vector(x'range);
begin -- architecture rtl
z <= x;
y <= not z;
assert false report "x'length=" & integer'image(x'length) severity note;
end architecture rtl;
The range (and length) of the port signals will then be
constrained by the associated actual in the component instantiation.
library ieee;
use ieee.std_logic_1164.all;
entity test2_tb is
end entity test2_tb;
architecture rtl of test2_tb is
constant SIZE : positive := 192;
signal x : std_logic_vector(SIZE-1 downto 0) := (others => '0');
signal y : std_logic_vector(SIZE-1 downto 0);
begin -- architecture rtl
dut: entity work.test2
port map (
x => x,
y => y);
end architecture rtl;
This works in simulation. But, I'm not sure whether it is supported by
the (major) VHDL synthesis tools. Of course, for synthesis of test2
another top-level entity is required which instantiates test2 to
constraint the array ranges.

Illegal type conversion VHDL

I was trying to return type std_logic_vector by type conversion in vhdl.
Here is my code:
function mul(num1,num2 : in std_logic_vector(7 DOWNTO 0)) return std_logic_vector is
variable v_TEST_VARIABLE1 : integer;
variable v_TEST_VARIABLE2 : integer;
variable n_times: integer:=1;
variable product: integer:=0;
begin
for n_times in 1 to v_TEST_VARIABLE2 loop
product:=product + v_TEST_VARIABLE1;
end loop;
return std_logic_vector(product);
end mul;
It gives "Illegal type conversion from std.standard.integer to ieee.std_logic_1164.std_logic_vector (numeric to array)." on compilation.
How do I return std_logic_vector in such a code?
See Russell's post first. If you use the VHDL-2008, numeric_std_unsigned package, then you can use just one conversion:
use ieee.numeric_std_unsigned.all ;
...
return to_std_logic_vector(product, length) ; -- long form
-- alternate short form
return to_slv(product, length) ;
Usage warning: for synthesis, I consider VHDL-2008 items to be on the bleeding edge of support. Hence, while I use VHDL-2008 frequently in my testbenches, I try to limit the usage of it in my RTL code to what can't be done using other methods. However, if you ever want to use code like this, it is it is important to try it out in your synthesis tool and submit a bug report against it if it does not work - that is the only way change happens.
You must first convert it to an unsigned. I hope you're using numeric_std? If so, your code looks like this. Note that to use to_unsigned you must know the length of your output std_logic_vector. So this either needs to be an input to your function or you can bound the return vector:
return std_logic_vector(to_unsigned(product, length));
More information about how to convert std_logic_vector to integer.