2
votes

I am trying to change a port record based on a generic and don't know of a good way to do this. I am trying to avoid VHDL2008 constructs if possible as I want to avoid preventing backwards compatability with legacy code. Anyways, here is what I am trying to do:

--libs for pack256
package pack256 is
    type myDataT is record
        valid : std_logic;
        data  : std_logic_vector(255 downto 0);
    end record;
end package;

-- libs for pack128
package pack128 is
    type myDataT is record
        valid : std_logic;
        data  : std_logic_vector(127 downto 0);
    end record;
end package;

Now, I want to be able to choose which package I use in my entity as this record sits inside a port map. Is there some creative way I can use a VHDL configuration or something to determine which package to source components/records/types from in my top level? Unfortunately, we have a lot of code looking at something like the code below and need to be able to control which package gets used as some top levels use different data widths for the myDataT record. If there is no way to fix this without VHDL 2008 or creating two seperate entities, will Vivado AND Altera/Quartus support package generics/unconstrained records?

-- top level declaration stuff
library dataPack;
use dataPack.(pack128 or pack256).all; -- how to choose different package from top level?

entity myEntity is
    generic(
        -- generics);
    port(
        reset : in std_logic;
        clk   : in std_logic;

        ctrl : myDataT;
        -- other port stuff);
end myEntity;

Finally, I cannot declare the record signals in the entity port map and change widths via a generic as this will break thousands of legacy source code files.

1
Is there some creative way I can use a VHDL configuration or something to determine which package to source components/records/types from in my top level? Configuration declarations don't synthesize, architecture declarative item configuration specifications don't help. Define or something. Don't use different record types for a port otherwise the various VHDL solutions lead to 2008. If there is no way to fix this without VHDL 2008 or creating two seperate entities, will Vivado AND Altera/Quartus support package generics/unconstrained records? Not a practical answerable question here. - user1155120
Why do you need this? What is the actual value of this shared package? Isn't this just a "nice to have "? Even of this was possible, it would be like implementing C++ templates in normal C: a lot of work for little added value. If you really want package generics, use VHDL 2008 - JHBonarius
@JHBonarius To expand on my application, this is a DMA component that has been expanded to support legacy FW/SW interfaces. A bridge if you will. Anyways, we have numerous different FPGAs that require differnt bus widths for DMA and register space, so having an easy package selection using a generic preserves old designs and helps maintain ease of maintanibility. Without this, we will have to have numerous wrappers for all possible combinations. - nichollsg

1 Answers

1
votes

If you can't use VHDL2008 (10 years old, already, and still not fully supported by some EDA vendors...) I see only two options:

  1. Use only one record type where each field has its maximum width but use only part of these bit widths, defined by generics. Synthesizers should automatically discard the useless parts. Example:

    package pack is
        type myDataT is record
            valid : std_logic;
            data  : std_logic_vector(255 downto 0);
        end record;
    end package;
    ...
    library dataPack;
    use dataPack.pack.all;
    
    entity myEntity is
        generic(
            usefullWidth: natural := 128
        ):
        port(
            reset : in std_logic;
            clk   : in std_logic;
            ctrl  : in myDataT;
            -- other port stuff
        );
    end myEntity;
    ...
    architecture arc of myEntity is
        ...
    begin
        ...
        foobar <= ctrl.data(usefullWidth - 1 downto 0);
        ...
    
  2. Use several source files to define variants of the same package and select the one to use when compiling or synthesizing. Scripts and GNU make, when correctly used, can easily do this based on one single variable definition. Example (don't forget to make clean when changing the value of this key variable):

    $ cat pack256.vhd
    package pack is
        type myDataT is record
            valid : std_logic;
            data  : std_logic_vector(255 downto 0);
        end record;
    end package;
    
    $ cat pack128.vhd
    package pack is
        type myDataT is record
            valid : std_logic;
            data  : std_logic_vector(127 downto 0);
        end record;
    end package;
    
    $ cat Makefile
    .NOTPARALLEL:
    
    INIFILE      := modelsim.ini
    VLIB         := vlib
    VMAP         := vmap
    VCOM         := vcom
    VCOMFLAGS    :=
    
    USEFULLWIDTH := 128
    PACK         := pack$(USEFULLWIDTH)
    
    VHDS         := $(wildcard *.vhd)
    TAGS         := $(patsubst %.vhd,.%.tag,$(VHDS))
    LIBS         := myLib dataPack
    LIBDIRS      := $(patsubst %,.%.lib,$(LIBS))
    
    all: .myEntity.tag
    
    $(TAGS): .%.tag: %.vhd | $(INIFILE)
        $(VCOM) $(VCOMFLAGS) -work $(LIB) $<
        touch $@
    
    .myEntity.tag: .$(PACK).tag
    .myEntity.tag: LIB = myLib
    .$(PACK).tag:  LIB = dataPack
    
    $(INIFILE): | $(LIBDIRS)
        for l in $(LIBS); do \
            $(VMAP) $$l .$$l.lib; |
        done
    
    $(LIBDIRS):
        $(VLIB) $@
    
    clean:
        rm -rf $(TAGS)
    
    ultraclean: clean
        rm -rf $(LIBDIRS) $(INIFILE)
    
    $ make
    vlib .myLib.lib
    vlib .dataPack.lib
    vmap myLib .myLib.lib
    vmap dataPack .dataPack.lib
    vcom  -work dataPack pack128.vhd
    touch .pack128.tag
    vcom  -work myLib myEntity.vhd
    touch .myEntity.tag
    
    $ make clean
    rm -rf .pack256.tag .myEntity.tag .pack128.tag
    
    $ make USEFULLWIDTH=256
    vcom  -work dataPack pack256.vhd
    touch .pack256.tag
    vcom  -work myLib myEntity.vhd
    touch .myEntity.tag