convert hex number to std_logic_vector - vhdl

I have a question on converting a hex number into a std_logic_vector. I need the bit representation of the hex numbers because they are my data the simulated keyboard is sending to my board (later). At now i am in development phase:
Here is the code example that doesn't work within ISE:
Subtype ScanCode is std_logic_vector(39 downto 0);
variable binaryRep : ScanCode;
binaryRep := std_logic_vector(16#70F070#);
the conversion in the last line is where the problem appears the Compiler tells me Cannot convert type universal_integer to type std_logic_vector
I have also tried that code but got another error i don't understand
binayRep <= to_stdlogicvector(x"FC");
this was the error message i got:
Near to_stdlogicvector ; 2 visible identifiers match here
I also searched the web for other solutions but i couldn't solve the problem.
Has anyone an Idea how to fix the code ?

16#70F070# is a numerical literal and isn't appropriate directly, it needs a conversion routine. You don't have an appropriate conversion routine that matches the signature [integer return std_logic_vector].
This
binaryRep <= to_stdlogicvector(x"FC");
wouldn't work anyway because the equivalent bit string to x"FC" has a length of 8, while binaryRep has a length of 40 and you don't specify the length std_logic_vector to produce. (And x"FC" already get's converted to an equivalent bit map).
The only to_stdlogicvector function declarations I found are in package fixed_generic_pkg and aren't appropriate.
you could:
binaryRep <= x"00000000FC";
Which matches the bit string length.
Or by including package numeric_std in a use clause:
binaryRep <= std_logic_vector(to_unsigned(16#70F070#,binaryRep'length));
Which converts a natural (an integer subtype) to an unsigned which is then type converted to std_logic_vector with the length derived from binaryRep.
Or using Mentor's std_logic_arith package
binaryRep <= to_std_logicvector(16#70F070#,binaryRep'length);
Which takes an integer argument and a natural length and converts the result to a std_logic_vector.
Or using Synopsys's std_logic_arith package
binaryRep <= conv_std_logic_vector(16#70F070#,binaryRep'length);
Where both arguments are type integer.
(And there are a couple more ways, dependent on VHDL-2008 support).

According to:
https://www.altera.com/support/support-resources/design-examples/design-software/vhdl/v_hex.html
signal A : std_logic_vector(31 downto 0) := x"00000017";
Worked for me :)

Related

Integer Range to vector

I've had an issue converting a vectors inputs to integers in my code. I am new to VHDL but the below code works with the integer RANGE commented out code but there is an error when I try to convert the vector values to an integers. Here is a copy of my code and error:
Update1:
I've tried your fix and it takes care of one of the errors but the new error message and code looks like this:
In according to your declaration in follow line type mem is array (...) of std_logic_vector(...) your memory waits for std_logic_vector type rather than unsigned like in your assignment RAMArray(unsigned(addr)) <= unsigned(din).
Here it is not sufficient to only use a type conversion to unsigned, but you have to add type conversion function to_integer in the argument. In other words
RAMArray(to_integer(unsigned(addr))) <= din
The second error is in the follow line qout <= RAMArray(addr). Here you should also use both the type conversion to unsigned as well as the type conversion function to_integer. The location parameter would be of the integer type. Example:
qout <= RAMArray(to_integer(unsigned(addr)))
Try to fix your code with my suggestions and I think it will work.

Convert enum type to std_logic_vector VHDL

I want to know if it is possible to convert a enum type, like FSM states to std_logic_vector or integer. I'm doing a testbench with OSVVM for a FSM and I want to use the scoreboard package to automatically compare the expected state with the actual one.
Thanks!
To convert to integer, use:
IntVal := StateType'POS(State) ;
From there, it is easy to convert to std_logic_vector, but I prefer to work with integers when possible as they are smaller in storage than std_logic_vector. For verification, it will be easier if you start to think more about integers when the value is less than 32 bits.
If you need it as std_logic_vector, using only numeric_std you can:
Slv8Val := std_logic_vector(to_unsigned(IntVal, Slv8Val'length)) ;
For verification, I liberally use numeric_std_unsigned, so the conversion is a easier:
Slv8Val := to_slv(IntVal, Slv8Val'length) ;
In the event you have an integer and want to convert it back to a enumerated value, you can use 'VAL.
State := StateType'VAL(IntVal) ;
In OSVVM, we use records with resolved values to create a transaction interface. We have a resoled types for integers (osvvm.ResolutionPkg.integer_max). We transfer enumerated values through the record using 'POS (as we put it in) and 'VAL (as we get it out).
Note don't confuse 'VAL with 'VALUE. 'VALUE converts a string to a value - opposite to 'IMAGE.
You of course learn all of this in SynthWorks' OSVVM class :).
Maybe like this...
function my_func(inp : t_my_enum) return integer is
begin
case inp is
when stateA =>
return 1;
when stateB =>
return 2;
when others =>
return 0;
end case;
end function my_func;
... <= my_func(stateB);`

Why couldn't I convert this integer into a logic_vector?

I have been trying to convert this Signal of type integer into an std_logic vector and assign the converted value into another signal that has the same width as a VHDL integer
signal temp : std_LOGIC_VECTOR(31 downto 0) := (others => '0');
signal FrameCumulative : integer :=0;
temp <= to_stdlogicvector(to_unsigned(FrameCumulative));
However I get this error:
Error (10346): VHDL error at vga.vhd(107): formal port or parameter
"SIZE" must have actual or default value
I am using use IEEE.NUMERIC_STD.ALL; and use IEEE.STD_LOGIC_1164.ALL;
First I made the mistake of not checking the integer size within VHDL and tried to assign an integer into a 14-bit vector but after I gave it some thought I relised my mistake.
Now according to many on-line resources, what I am doing should work but my synthesiser complains about it.
If you do know the cause for this would you mind ellaborating on your answer rather than just posting the correct code, Thanks!
The function to_unsigned must be provided with a parameter specifying the width of the vector that you want it to produce. The function to_stdlogicvector is also not the correct thing to be using. Your line should look like this:
temp <= std_logic_vector(to_unsigned(FrameCumulative, temp'length));
The function to_unsigned is a conversion function, it must be provided with the target width. Here, as suggested by #BrianDrummond, the width is specified by taking the length attribute from the target vector itself (temp). The std_logic_vector is a type cast, where the unsigned value is simply interpreted directly as an std_logic_vector.

Address of array provided as std_logic_vector

I'm trying to construct a ROM, which has as declaration a : in std_logic_vector(5 downto 0) for the access address. My problem its that I don't know how to access the ROM array with a std_logic_vector, Should I use a cast to integer or what else can I do?
My code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--------------------------------------------------------------------------------
entity imem is
GENERIC(CONSTANT N : INTEGER := 32);
port (a : in std_logic_vector(5 downto 0);
result : out std_logic_vector(N-1 downto 0));
end imem;
architecture behavior of imem is
signal addres : integer;
type memory is array (0 to 64) of std_logic_vector(N-1 downto 0) ;
constant myrom : memory := (
2 => x"11111111" , --255
3 => x"11010101" ,
4 => x"01101000" ,
6 => x"10011011" ,
8 => x"01101101" ,
9 => x"00110111" ,
others => x"00000000" ) ;
begin
addres <= signed(a);
result <= memory(addres);
end behavior;
With this code as shown I get the following error:
imem.vhd:25:21: can't match type conversion with type integer
imem.vhd:25:21: (location of type conversion)
imem.vhd:26:21: conversion not allowed between not closely related types
imem.vhd:26:21: can't match type conversion with type array type "std_logic_vector"
imem.vhd:26:21: (location of type conversion)
ghdl: compilation error
Assuming that a is an unsigned address value, then you must first cast it to unsigned, and then to integer. Note that the result should access myrom and not memory type. The code can then be:
addres <= to_integer(unsigned(a));
result <= myrom(addres);
And you can even skip the intermediate addres signal and do:
result <= myrom(to_integer(unsigned(a)));
The memory type is also one longer than required, since the 6-bit a input can only cover 0 .. 63, and not 0 .. 64. A better way to declare the memory type would be through use the the 'length attribute for a, like:
type memory is array (0 to 2 ** a'length - 1) of std_logic_vector(N-1 downto 0);
ghdl semantics are by default strict -1993 which has an impact on Morten's answer's changes
For:
type memory is array (0 to 2 ** a'length - 1) of
std_logic_vector(N-1 downto 0);
we get:
ghdl -a imem.vhdl
imem.vhdl:15:29:warning: universal integer bound must be numeric literal or attribute
Tristan Gingold the author of ghdl authored an Issue Report leading to a Language Change Specification in 2006, which gave explicit permission to then current (-2002) implementations to treat a range with an expression as one bound as convertible to an integer range when the other bound is a universal integer (a literal). The LCS didn't give permission to do the conversion in implementations conforming to earlier versions of the standard. Tristan's ghdl is strictly by the book here and by default is -1993 compliant and generates an error.
There are two ways to deal with the error. Either use the command line option to ghdl during analysis to specify a version of the standard where the range can be converted to type integer or provide the range directly.
From ghdl --help-options we see:
--std=87/93/00/02/08 select vhdl 87/93/00/02/08 standard
Where this command line flag can be passed as in ghdl -a --std=02 imem.vhdl.
Also the range type can be declared directly as in:
type memory is array (natural range 0 to 2 ** a'length - 1) of
std_logic_vector(N-1 downto 0);
Both methods of analyzing type memory work.
And the moral of all this is that VHDL is a tightly typed language.
Notes
-2008 compliance is not fully implemented in current versions of ghdl.)
There's historical support for interpreting the standard to support the conversion anyway. The LCS overcomes ambiguity.
See IEEE Std 1076-1993 3.2.1.1 Index constraints and discrete ranges para 2 and IEEE Std-1076-2008 5.3.2.2 Index constraints and discrete ranges para 2.
Tristan has since changed the --std= options eliminating -2000 compliance as well as the default standard to 93c which introduces a set of standard relaxations to more closely match industry practices of VHDL tool vendors. The user of a more recent version of ghdl can use --std=93 for strict standard compliance. The issue originally hinged on the VASG (VHDL Analysis and Standardization Group) sponsored by DAC not being allowed to issued Interpretations of standards after -1987. It's safe to say there is no single implementation of any VHDL standard that completely adheres to a particular revision.

What VHDL datatype should I use for a memory address?

I'm developing a description of a BIST engine, and I've been asked by my manager to transition from Verilog to VHDL. I'm very rusty with VHDL, and I can't figure out the right datatype to give to the address register in my code. Most of the time, the address is used to index into arrays.
data : std_logic_vector (2**W-1 downto 0);
...
output = data(addr);
Sometimes though, I need to perform bitwise operations (for example, this code that finds the least-significant 1 in the address):
least_one(0) <= addr(0);
PRIORITY_ENCODER : for i in 1 to (W-1) generate
least_one(i) <= addr(i) and not or_reduce(addr(i-1 downto 0));
end generate PRIORITY_ENCODER;
least_one(W) <= not or_reduce(addr);
Finally, I also rely on the address wrapping around without problem when it overflows (i.e. 1111+1 = 0, and 0-1 = 1111).
So, given all these different uses, what datatype or subtype do I give to the address? When I use integer and the related types, I get errors when I perform the bitwise operations:
ncvhdl_p: *E,APNPFX (filename,17|20): can not make sense of P(...)
When I use std_logic_vector or similiar, I get errors trying to use the address as an array index:
ncvhdl_p: *E,INTYMM (filename,52|17): array index type mismatch [6.4]
I seem to be in a no-win situation here. What data type do I use? Please note, the solution must be synthesizable. Thanks
You want bitwise access and wrapping behaviour:
make addr fundamentally an unsigned vector.
Then you need access to it as an integer:
If you need it as an integer on just one line, use the to_integer call on just that line.
If you need it as an integer in more than one place, create another signal to "shadow" it and put a continuous assignment in the architecture
Like this:
signal addr_int:natural;
....
addr_int <= to_integer(addr);
In this case I would use unsigned type.
This will work very similar to how you are used to std_logic_vector operating in terms of generic bit access, but you can also do arithmetic operations on the address and easily convert to/from integer type, if necessary. Plus it doesn't dirty the sense of std_logic_vector with the "dreaded" std_logic_unsigned package.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
architecture myarch of myent is
signal address : unsigned(numbits-1 downto 0);
...
begin
-- as an example
addr_counter : process(sysclk, reset)
begin
if reset = '1' then
address <= (others => '0');
elsif rising_edge(sysclk) then
address <= address + 1;
end if;
end process addr_counter;
...

Resources