I'm having some problems with the conv_std_logic_vector
function in Quartus. I'm using the function to convert a integer variable into a std_logic_vector
. When i compile the code below, Quartus shows the following error message:
Error (10344): VHDL expression error at counter_Wbits.vhd(32): expression has 3 elements, but must have 4 elements.
I have searched this function on the internet and people always use 2 parameters, what is happening?
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;
ENTITY counter_Wbits IS
GENERIC(W : NATURAL := 4);
PORT (portae : IN BIT;-- data input
portas : IN BIT;-- data input
clk : IN BIT; -- clock
clrn: IN BIT; -- clear
ena : IN BIT; -- enable
q : BUFFER STD_LOGIC_VECTOR(W-1 DOWNTO 0));-- data output
END counter_Wbits;
ARCHITECTURE arch_1 OF counter_Wbits IS
BEGIN
PROCESS(clk,clrn)
variable cont : integer range 0 to 15;
BEGIN
IF (clrn='0') THEN
q <= (OTHERS => '0');
ELSIF (clk'EVENT AND clk='1') THEN
IF (ena='1') THEN
IF(portae='1') THEN
cont := cont+1;
ELSIF (portas='1') THEN
cont := cont-1;
END IF;
END IF;
END IF;
q <= conv_std_logic_vector(cont, W-1); -- LINE 32
END PROCESS;
END arch_1;
The last parameter of the function conv_std_logic_vector
defines the length of the returned std_logic_vector
from this function. Specifying W-1
here, request that the function returns a 3 bit vector. But, the target signal q
has 4 bits, numbered from W-1 downto 0
. That's what the error message complains about.
You can fix this, by passing just W
as the last parameter. A better way is, to the specify the length of the target signal instead using q'length
:
q <= conv_std_logic_vector(cont, q'length);
This way, the function result will always have the correct length.
It is no problem as such, if the possible range of the first argument is greater than what can be represented by the number of bits given in the second argument. Of course, truncation will occur.
Please do not use, the non-standard std_logic_arith
and std_logic_unsigned
packages from Synopsys anymore. Problems will arise, when you have to use signed and unsigned numbers in the same entity later one. Use the standard ieee.numeric_std
package instead:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all; -- CHANGED THIS
ENTITY counter_Wbits IS
GENERIC(W : NATURAL := 4);
PORT (portae : IN BIT;-- data input
portas : IN BIT;-- data input
clk : IN BIT; -- clock
clrn: IN BIT; -- clear
ena : IN BIT; -- enable
q : BUFFER STD_LOGIC_VECTOR(W-1 DOWNTO 0));-- data output
END counter_Wbits;
ARCHITECTURE arch_1 OF counter_Wbits IS
BEGIN
PROCESS(clk,clrn)
variable cont : integer range 0 to 31;
BEGIN
IF (clrn='0') THEN
q <= (OTHERS => '0');
ELSIF (clk'EVENT AND clk='1') THEN
IF (ena='1') THEN
IF(portae='1') THEN
cont := cont+1;
ELSIF (portas='1') THEN
cont := cont-1;
END IF;
END IF;
END IF;
q <= std_logic_vector(to_unsigned(cont, q'length)); -- CHANGED THIS
END PROCESS;
END arch_1;
The conversion from integer
to std_logic_vector
requires 2 steps now. At first you will have to convert it to an unsigned
of length q'length
as specified in the second argument of to_unsigned
An unsigned
is also a vector of std_logic
elements, but the respective functions threats this "bit sequence" as an unsigned number. The second (outer) step, is a type conversion to std_logic_vector
.