Search code examples
parametersvhdlquartus

VHDL: conv_std_logic_vector parameter error


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;

Solution

  • 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.