Allow subtypes of composite types where specific entries or fields are given a fixed constant value and cannot be changed.
Allow specified entries in a composite type (array or record) to be a fixed constant in a specified subtype.
This is not possible currently. Subtypes can only constrain ranges, it cannot force values. In verification scenarios it would be useful to throw an error if a user attempts to modify a value that should be fixed based on a certain standard, but is not constrained in the based standard. Example:
type some_rec_t is record a : std_logic_vector(7 downto 0); end record; subtype some_constrained_record_st is some_rec_t (a => x"FF"); ... variable s0 : some_record_t; variable s1 : some_constrained_record_st; s0.a := x"AA"; s1 := s0; -- error because s0.a is not x"FF"; s0.a := x"FF"; s1 := s0; -- this is fine because the value matches that of the subtype
Here, if a user attempts to assign the value that is not constrained in the subtype, it should throw a runtime error. The current workaround is to create initialization functions based, and hope the user does not try and change something that must not be changed:
function init_some_record_t_to_be_constrained return some_record_t is variable r : some_record_t := (a => x"FF"); begin return r; end function; s1 := some_record_t := init_some_record_t_to_be_constrained;
But this method would allow users to change the value of
s1.a. And if it is a serious requirement to keep
s1.a at a specific value, the user needs to build assertions into the testbench to ensure this rule is followed. If it is built into the subtype, then none of this (possibly complicated) code would be required - it is built into the subtype.
Use Models | Code Examples
RTP packets (https://datatracker.ietf.org/doc/html/rfc3550) are generic, but designed primarily to transport and synchronise media over a packet network. RFC 3550 does not define any restrictions, but rfc3551 (https://datatracker.ietf.org/doc/html/rfc3551) assigns certain protocols to specific payload type values that are in the RTP header. For example, mpeg2 transport stream must use a payload type value of 33 (0x21). As a user of VHDL for verification, I have often used record types for data encapsulation with each header as a record field. Some more recent standards also mandate a specific value for this field (for example, smpte 2022-6 requires payload type to be 98). There are other restrictions, like a 2022-6 packet must not have a header extension.
So for example, here is the base definition
-- Some fields not present for ease of example. type rtp_pkt_t is record payload_type : std_logic_vector(6 downto 0); payload : byte_array_t; end record rtp_pkt_t;
and then subtypes could be defined thus:
-- Mpeg2 transport stream subtype rtp_mp2t_pkt_t is rtp_pkt_t( payload_type => 7d"33", payload(0 downto 187) ); -- because mpeg 2 ts packets are always 188 bytes -- smpte 2022-6 packet type subtype rtp_2022_6_pkt_t is rtp_pkt_t( payload_type => 7d"98", payload(open) ); -- 2022-6 has some variability in payload size
then this way, specific header fields are already set when a user creates an object of specific subtypes. They can be used with any function created for the base type, like a to_string function.
variable ts_pkt : rtp_mp2t_pkt_t; variable smpte_2022_6_pkt : rtp_2022_6_pkt_t;
Because they are now distinct subtypes, it might be then be possible to pick up strange missmatches in syntax checks, rather than get a runtime error.