Consider a type
type foo is array (0 downto 0) of std_logic_vector(7 downto 0);
Why do I get a compiler error when I try to create a constant value of this type, for example. Note that I have only tried using Altera's Quartus II.
constant cFoo : foo := ( x"11" );
Error: VHDL Type mismatch error at [filename.vhd](line number): cFoo type does not match string literal.
However everything is ok if my type is
type foo is array (0 downto 0) of std_logic_vector(7 downto 0);
with an example assignment to a constant of:
constant cFoo : foo := ( x"00", x"11" );
Moreover consider that I try to assign index 0 with another constant. For example.
type foo is array (0 downto 0) of std_logic_vector(7 downto 0);
constant cBar : std_logic_vector(7 downto 0);
constant cFoo : foo := ( cBar );
To which the error the compiler spits out is now:
VHDL error at [filename.vhd](line number): type of identifier "cBar" does not agree with its usage as "foo" type.
So basically its telling me that the compiler does not realize that the assignment is to the index of 0 but instead an assignment to the the array type.
How can I let the compiler know that the assignment is to only index 0?
IEEE Std 1076 9.3.3 Aggregates, 9.3.3.1 para 4:
Both named and positional associations can be used in the same aggregate, with all positional associations appearing first (in textual order) and all named associations appearing next (in any order, except that it is an error if any associations follow an others association). Aggregates containing a single element association shall always be specified using named association in order to distinguish them from parenthesized expressions.
With an MCVE:
library ieee;
use ieee.std_logic_1164.all;
package ceefoo is
type foo is array (0 downto 0) of std_logic_vector(7 downto 0);
-- constant cFoo : foo := ( x"11" );
constant cfoo: foo := (0 => x"11");
-- or
constant cefoo: foo := (others => x"11");
end package;
You need to use named association with a single element. The first example specifies index 0, the second any elements.
Para 3 of the above quoted subsection:
Each element association associates an expression with elements (possibly none). An element association is said to be named if the elements are specified explicitly by choices; otherwise, it is said to be positional. For a positional association, each element is implicitly specified by position in the textual order of the elements in the corresponding type declaration.
It's helpful to see the BNF:
aggregate ::=
( element_association { , element_association } )
element_association ::=
[ choices => ] expression
choices ::= choice { | choice }
choice ::=
simple_expression
| discrete_range
| element_simple_name
| others
Related
Consider the following VHDL code:
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', others => '0');
Here, the indices 7 and 6 are important: they indicate which elements should be 1, and from that, the compiler can derive which ones should be 0.
Question 1
If I understand correctly, this can also be written as
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
Now I am wondering how exactly this works, and whether the indices still matter or only the difference between them. The way I understand it, the expression (x downto y => z) creates an array with indices x downto y, whose elements are all equal to z (and have the same type). But do these indices matter when arrays are concatenated? I.e., could I also write any of the following:
constant c : std_logic_vector(7 downto 0) := (1 downto 0 => '1') & (5 downto 0 => '0');
constant c : std_logic_vector(7 downto 0) := (99 downto 98 => '1') & (4 downto -1 => '0');
Of course one could say that those statements, esp. the last one, aren't really clear, but my question is: Would they have the same result? Or would they cause some kind or error?
The reason I am wondering about this is that you could also write
constant c : std_logic_vector(7 downto 0) := "11" & "000000";
and the literal "11" doesn't have any range specified, so I'm not sure what exactly the type of this literal would be, but certainly not std_logic_vector(7 downto 6).
Question 2
Finally, I am wondering what is the difference between
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1') & (5 downto 0 => '0');
and
constant c : std_logic_vector(7 downto 0) := (7 downto 6 => '1', 5 downto 0 => '0');
By this I mean: Is there any reason you would want/need to write the former (which seems more error-prone because it will give unexpected results if you e.g. swap the 2 aggregates) instead of the latter? Or is it just a matter of taste?
Lets start with literals. When you specify a literal, the default range is (type_index'low to type_index'low + len-1). The easiest way to see this is when specifying a constant, where the range is not required in the subtype:
constant SOME_CONSTANT : std_logic_vector := x"00";
Here, if you check the range of SOME_CONSTANT, you'll see its (0 to 7). This is because std_logic_vector is declared as:
type std_ulogic_vector is array(natural range <>) of std_logic;
The 'low value of natural is 0, which is the start point.
Lets say you went a bit crazy, and this:
type my_crazy_array_t is array(std_logic range <>) of integer;
and you declared a constant:
constant CRAZY : my_crazy_array_t := (0, 22);
The results are:
CRAZY('U') = 0
CRAZY('X') = 22
CRAZY'left = 'U'
CRAZY'right = 'X'
CRAZY'low = 'U'
CRAZY'high = 'X'
Because 'U' is the low value of std_logic, followed by 'X'.
On the other questions, it all works because VHDL is always context driven, and for arrays as long as the lengths match, the resulting arrays can always be mapped from 'left to 'right. In your examples the length is correct, and the subtype is know from the declaration, so mapping can occur as you specified.
NOTE: (4 downto -1 => '0'); is illegal, because -1 is not a valid index value for a std_logic_vector, so you would get an error (probably from the & function because it cannot work out what type you meant, because it cannot be std_logic_vector).
The difference is that the first one is a concatenation of a 2 bit and 6 bit bit string, and the 2nd is a complete 8 bit bit string. Which you use will probably be a matter of style. But usually, for this, I would use literals eg: constant c : std_logic_vector(7 downto 0) := x"C0"; what you use and when may depend on what is clearest to the user(s).
I am trying to create an array of std_logic_vectors with reducing lengths. I have tried making an array with a generic std_logic_vector and then using a generate statement to make the vectors.
architecture behavioral of dadda_mul_32bit is
type and_planes is array (0 to 31) of std_logic_vector;
begin
generate_and_plane:
for i in 0 to 31 generate
and_planes(i) <= and_vector(a, b(i), i);
end generate generate_and_plane;
end behavioral;
along with a function that returns a generic std_logic_vector:
function and_vector(vec: std_logic_vector; x: std_logic; length: natural) return std_logic_vector is
variable result: std_logic_vector(length - 1 downto 0);
begin
for i in 0 to length - 1 loop
result(i) := vec(i) and x;
end loop;
return result;
end function;
Am I using the generate statement incorrectly?
and_planes is a type not a signal, so you can't assign to it!
More over you are creating a partially constrained type, which needs to be constrained in a object (e.g. signal) declaration.
VHDL doesn't support ragged arrays. (Arrays wherein each element is of different size). If you need this for simulation, you can use access types and emulate ragged arrays like in C. If you need it for synthesis, then you can emulate a ragged array with a one-dimensional array and some functions to compute the bounds of a nested vector.
See this answer of me:
VHDL Multidimensional arrays with different internal size
vhdl port declaration with different sizes
Btw. VHDL-2008 adds an overload: "and"(std_logic, std_logic_vector), so no function is needed to calculate the anding of a single bit with each bit in a vector.
-- slice 'a' and gate it by 'b(i)'
and_planes(i) <= a(i downto 0) and b(i);
INTENTION:
I am reading data from RAM on ZedBoard, the RAM consists of 32 bits long words so I use the following buffer
type mem_word is array (0 to 127) of std_logic_vector(31 downto 0);
signal buffer_word : mem_word;
but then, I would like to address data in a linear fashion, in an intermediary linear buffer
signal buffer_linear : std_logic_vector(4095 downto 0);
buffer_linear <= buffer_word; -- !!! PROBLEM
so I can easily address any bit in the buffer without recalculating the position in specific word (of the buffer_word).
QUESTION:
How do I get from array of std_logic_vectors into 1 long std_logic_vector ? Is there a way to avoid concatenating 128 words in a loop ? (something like above buffer_linear <= buffer_word;)
You need a function to convert from vector-vector to a 1-dimensional vector.
My following example uses the type name T_SLVV_32 to denote that it is a vector of vectors, wherin the inner vector is 32 bit long. (See my linked source file, for a true 2-dimensional STD_LOGIC matrix type called T_SLM). So T_SLVV_32 is equivalen to your mem_word type.
subtype T_SLV_32 is STD_LOGIC_VECTOR(31 downto 0);
type T_SLVV_32 is array(NATURAL range <>) of T_SLV_32;
function to_slv(slvv : T_SLVV_32) return STD_LOGIC_VECTOR is
variable slv : STD_LOGIC_VECTOR((slvv'length * 32) - 1 downto 0);
begin
for i in slvv'range loop
slv((i * 32) + 31 downto (i * 32)) := slvv(i);
end loop;
return slv;
end function;
Usage:
buffer_linear <= to_slv(buffer_word);
This function creates no logic, just wiring.
Note: Accessing all bits of a memory at once, prevents synthesis tools of inferring RAM or ROM memory blocks!
Source: PoC.vectors
See my vector package at GitHub for more examples on transforming vectors and matrices forth and backwards.
I'm trying to create a flexible array of constants. I want to use a 2D array which may sometimes be for example a 2x1, 2x2, 3x2 array etc. For example:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 1;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( (1) , (2) ); -- wrong
error: type int_2d_array does not match with the integer literal
If I do this, it doesn't complain:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 2;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( ( 0,1 ) , ( 2,2 )); -- accepted
Is the first example even possible using a 2D array?
The LRM (section 9.3.3 Aggregates) states:
Aggregates containing a single element association
shall always be specified using named association in order to distinguish them from parenthesized expressions.
So, this is OK:
constant n : int_1d_array(0 downto 0) := ( 0 => 1 );
and this is not:
constant n : int_1d_array(0 downto 0) := ( 1 );
http://www.edaplayground.com/x/6a4
I managed to compile the first example in the following ugly way:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 1;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( (others => 1) , (others => 2) );
Strange behavior, indeed.
Need to understand how to use Selected Signal Assignment and include a 4-bit internal signal, called WXYZ, by concatenating W with X with Y with Z for the following Boolean algebra expression F(W,X,Y,Z)=Y'Z'+W'X'+X'Y
ENTITY Part_2A IS
PORT(
W, X, Y, Z : IN STD_LOGIC;
G1 : OUT STD_LOGIC);
END Part_2A;
ARCHITECTURE sig OF Part_2A IS
SIGNAL inputs : STD_LOGIC_VECTOR(3 downto 0);
SIGNAL outputs: STD_LOGIC;
BEGIN
--Concatenate input ports into 4-bit signal
inputs <= W & X & Y & Z;
WITH inputs SELECT
outputs <= "1" when "0000",
"1" when "0001",
"1" when "0010",
"1" when "0011",
"1" when "0100",
"1" when "1000",
"1" when "1010",
"1" when "1011",
"1" when "1100",
"0" when others;
G1 <= outputs;
END sig;
You can't ask any better than
Need to understand how to use Selected Signal Assignment and include a 4-bit internal signal, called WXYZ, by concatenating W with X with Y with Z for the following Boolean algebra expression F(W,X,Y,Z)=Y'Z'+W'X'+X'Y
I don't even see a question mark there.
With the addition of a context clause referencing IEEE library std_logic_1164 and converting the string literals "1" and "0" to character literals '1' and '0' (character literals are acceptable enumeration literals, std_ulogic the base type of std_logic is an enumerated scalar type) and we have something like:
library ieee;
use ieee.std_logic_1164.all;
entity part_2a is
port (
w, x, y, z : in std_logic;
g1 : out std_logic
);
end entity part_2a;
architecture sig of part_2a is
signal inputs : std_logic_vector(3 downto 0);
signal outputs: std_logic;
begin
--concatenate input ports into 4-bit signal
inputs <= w & x & y & z;
with inputs select
outputs <= '1' when "0000",
'1' when "0001",
'1' when "0010",
'1' when "0011",
'1' when "0100",
'1' when "1000",
'1' when "1010",
'1' when "1011",
'1' when "1100",
'0' when others;
g1 <= outputs;
end architecture sig;
Which analyzes without error.
You may have been mislead by your VHDL tool. There are some VHDL implementations that specifically complain about the type mismatch. For instance ghdl:
ghdl -a part_2a.vhdl
part_2a.vhdl:21:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:22:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:23:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:24:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:25:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:26:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:27:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:28:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:29:21: can't match string literal "1" with type enumeration subtype "std_logic"
part_2a.vhdl:30:21: can't match string literal "0" with type enumeration subtype "std_logic"
ghdl: compilation error
While some quit at the first error:
nvc -a part_2a.vhdl
** Error: no one dimensional arrays of character type in context
File part_2a.vhdl, Line 21
outputs <= "1" when "0000",
^^^
If you have one that simply points at the beginning of the statement
WITH inputs SELECT
With no useful information you might think it's a concatenation problem (depending on what the actual error message said). Which explains why a Minimal, Complete, and Verifiable example can be valuable.
Error messages tend to be distinct to a particular vendor, and tell what you trying to do.