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

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.

Related

write on invalid address to RAM in VHDL, Verilog, sim behaviour

Lets have a BRAM or any other memory under Verilog or VHDL.
For example this:
module raminfr (clk, we, a, di, do);
input clk;
input we;
input [4:0] a;
input [3:0] di;
output [3:0] do;
reg [3:0] ram [31:0];
always #(posedge clk) begin
if (we)
ram[a] <= di;
end
assign do = ram[a];
endmodule
Now lets assume that we have already write valid data to "ram".
Does simulators invavalidate all items in "ram" if address "a" will have invalid value (4'bxxxx) ("we"=1 and clk will have posedge)?
Or it lets values in ram as they were?
For Verilog
The IEEE Std 1800-2009 SystemVerilog standard subsumed both the IEEE Std 1364-2005 Verilog standard and the IEEE Std 1800-2005 SystemVerilog standard. The IEEE Std 1800-2012 SystemVerilog standard supplanted the -2009 version.
See IEEE Std 1800-2012 7.4.6 Indexing and slicing of array:
If an index expression is out of bounds or if any bit in the index expression is x or z, then the index shall be invalid. Reading from an unpacked array of any kind with an invalid index shall return the value specified in Table 7-1. Writing to an array with an invalid index shall perform no operation, with the exceptions of writing to element [$+1] of a queue (described in 7.10.1) and creating a new element of an associative array (described in 7.8.6). Implementations may issue a warning if an invalid index occurs for a read or write operation on an array.
For VHDL
An equivalent VHDL design description might be:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity raminfr is
port (
clk: in std_logic;
we: in std_logic;
a: in std_logic_vector(4 downto 0);
di: in std_logic_vector(3 downto 0);
do: out std_logic_vector(3 downto 0)
);
end entity;
architecture behave of raminfr is
type ram_type is array (0 to 15) of std_logic_vector (3 downto 0);
signal ram: ram_type;
begin
process (clk)
begin
if rising_edge(clk) then
if we = '1' then
ram(to_integer(unsigned(a))) <= di;
end if;
end if;
end process;
do <= ram(to_integer(unsigned(a)));
end architecture;
Where the numeric_std package to_integer function is used to convert the array value of a to an integer index. (VHDL is a bit more flexible here, array indexes can either be integer types or enumerated types, together referred to as discrete types).
Reading the source for to_integer we see it will convert an input unsigned array value containing an 'X' to all 'X's and the 'LEFT value of that being 'X' will return a natural integer subtype value of 0 and optionally report that:
if (XARG(XARG'left) = 'X') then
assert NO_WARNING
report "NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0"
severity warning;
return 0;
end if;
These warnings can be disabled implementation wide by changing the value of NO_WARNING which is locally static. Using to_integer (or with Synopsys package std_logic_arith and function conv_integer) the index will be 0.
Additionally VHDL implementations have the ability to stop simulation on severity warning reports.
While you could handle the result of an assignment with an index provided as an array value differently in (as in 2, 4, 8, 16 or 32 invalidated memory locations depending on the number of 'X' element values of a here), you've already compromised the integrity of your design model state and some corrective should be taken before counting on the simulation results for either a SystemVerilog or VHDL design model.
The overhead of complex fiddling doesn't seem worthwhile in general. These warnings are of a class of warnings that should be reviewed before synthesis.
These warning can occur before array values are reset when their default initial values are metavalues. You can prevent that in most FPGA designs by initializing a and any predecessors so a contains a binary representing value or simply ignoring reports at time 0 before a reset takes affect.
You can also prevent the write to address 0 by initializing we and any predecessor(s) to '0'.
Simulator will not invalidate anything. Instead the write will be ignored.
For reads in such a situation, it will return 'x' though.

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 hex number to std_logic_vector

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 :)

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