简体   繁体   中英

How to get a slice of a VHDL unconstrained array?

I'm trying to model a RAM chip in VHDL with generic parameters for the address and data bus widths and for the base address where the RAM is placed in the address space. My problem is that I cannot figure out how to get a slice of an generic unconstrained array parameter to compare it against a std_logic_vector signal.

This the reduced code that is intended to compute the "chip select" signal:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity e is
    generic (
        BASE_ADDR :std_logic_vector := x"C000";
        CELL_ADDR_WIDTH :integer := 4
    );
    port (
        address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
    );
end;

architecture behavioral of e is

    constant ADDR_WIDTH :integer := BASE_ADDR'length;

    signal cs :std_logic;

begin

    cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';

end behavioral;

The Lattice ispLEVER VHDL compiler reports the following error:

23:64:23:110|Slice range direction does not match argument range

The message is caused by the expression BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) .

How is a slice of the generic unconstrained array BASE_ADDR accessed correctly in VHDL?

Both solutions suggested by @Paebbels and @user1155120 resolve the VHDL compilation error. I quote the suggestions here with the code updated accordingly.

@Paebbels: Use to in slice

Your unconstrained array defaults to a "to" range because the index type of std_logic_vector is integer and integer in turn is defined with a to range :). So use the to keyword in your slice.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity e is
    generic (
        BASE_ADDR :std_logic_vector := x"C000";
        CELL_ADDR_WIDTH :integer := 4
    );
    port (
        address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
    );
end;

architecture behavioral of e is

    constant ADDR_WIDTH :integer := BASE_ADDR'length;

    signal cs :std_logic;

begin

    cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 to CELL_ADDR_WIDTH) else '0';

end behavioral;

@user1155120: Declare an alias to define a direction

You'll could also add an alias to your architecture declarative region - alias BASEADDR: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR; to define a direction and use that - cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASEADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';

I used a more prominent name for the alias:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity e is
    generic (
        BASE_ADDR :std_logic_vector := x"C000";
        CELL_ADDR_WIDTH :integer := 4
    );
    port (
        address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
    );
end;

architecture behavioral of e is

    constant ADDR_WIDTH :integer := BASE_ADDR'length;

    signal cs :std_logic;

    alias BASE_ADDR_ALIAS: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR;

begin

    cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR_ALIAS(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';

end behavioral;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM