Many of our modules use an array of configuration descriptor records to configure a Configurable
component. The array type, record type and configurable component are declared in a global package that everybody uses.
type config_descriptor_type is record
config0 : integer;
config1 : boolean;
end record;
type config_type is array(natural range <>) of config_descriptor_type;
component Configurable is
generic (
g_CONFIG : config_type
);
end component;
Every module that uses this Configurable
has a package containing the configuration information for that module (all existing such configurations must remain unchanged).
constant c_config : config_type(0 to 3) := (
(1, true),
(2, false),
(8, false),
(4, true)
);
This per-module constant is passed to the Configurable instance (the instantiation must also remain unchanged).
config_inst : Configurable
generic map (
g_CONFIG => c_config
);
I am adding some features to Configurable
that require an additional field in the config_descriptor_type
record.
type new_config_descriptor_type is record
config0 : integer;
config1 : boolean;
config2 : integer; -- this field was added
end record;
I am free to make any changes I like to the global configurable package and entity, as well as to any new modules that use the new feature, but I should not touch any of the existing modules that use the configurable. The new field should obtain some default value if instantiated by an old module.
Is there some way to add such a field without having to modify all of the existing modules that use a configurable?
A type cannot contain a default value, that only comes from an object (signal, variable, constant). And when assigning a value to an object (like the initial value for a constant) all fields will need to be defined.
There is a workaround for this, but will require a code change for all previously defined constants as a one off, which should not need changing again. If you define a basic "init" function where all paramters have a default value, then if you add any more items to the base type then existing code will always return a legal object with all fields assigned.
type config_descriptor_type is record
config0 : integer;
config1 : boolean;
config2 : integer;
end record;
type config_type is array(natural range <>) of config_descriptor_type;
function init_config_descriptor_type( config0 : integer := 0;
config1 : boolean := true;
config2 : integer := 0 ) return config_descriptor_type is
variable r : config_descriptor_type;
begin
r.config0 := config0;
r.config1 := config1;
r.config2 := config2;
return r;
end function;
-- Now you can create configs from the function. Config2 will be default value (0)
constant c_config : config_type(0 to 3) := (
init_config_descriptor_type(1, true),
init_config_descriptor_type(2, false),
init_config_descriptor_type(8, false),
init_config_descriptor_type(4, true)
);