Search code examples
arraysrangevhdlalias

Disjoint ranges in VHDL


I have a bit vector like this

subtype alarms_type : std_logic_vector(1 to 8)
signal alarms : alarms_type := (others => '0');

and the purpose of each bit is defined like this

constant sys1_temp_hi_al : integer := 1;
constant sys1_temp_lo_al : integer := 2;
constant sys1_crnt_hi_al : integer := 3;
constant sys1_cnrt_lo_al : integer := 4;
constant sys2_temp_hi_al : integer := 5;
constant sys2_temp_lo_al : integer := 6;
constant sys2_crnt_hi_al : integer := 7;
constant sys2_cnrt_lo_al : integer := 8;

I would like to be able to access subsets of the alarms_type with a short, readable notation. For example

alarms(SYS2_ALS) <= (others => '0');  -- set multiple values
temp_alarm <= or(alarms(TEMP_ALS));   -- or together multiple values to a std_logic
temp_alarms <= alarms(TEMP_ALS));     -- extract a subset to a suitably sized vector
alarms(TEMP_ALS) := (others => '1');  -- set (or clear) multiple disjoint values

I would like to know if the alias keyword will help me, like this:

alias HI_ALARMS is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;
alias LO_ALARMS is sys1_temp_lo_al|sys1_crnt_lo_al|sys2_temp_lo_al|sys2_crnt_lo_al;
alias TEMP_ALS  is sys1_temp_hi_al|sys1_temp_lo_al|sys2_temp_hi_al|sys2_temp_lo_al;
alias CRNT_ALS  is sys1_crnt_hi_al|sys1_crnt_lo_al|sys2_crnt_hi_al|sys2_crnt_lo_al;
alias SYS1_ALS  is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;
alias SYS2_ALS  is sys1_temp_hi_al|sys1_crnt_hi_al|sys2_temp_hi_al|sys2_crnt_hi_al;

It appears from the Alias chapter of the Ashenden book that this is not how an alias should be used, but hopefully I am missing something.

If there is a correct way to use alias to achieve my goal, please provide examples.

Alternatively, if there is a different or better way using constant or some other aspect of VHDL, please show me how.

Or just tell me that it can't be done, and if it is appropriate, please confirm that I could write functions to get and procedures to set the different subsets.

If I use functions and procedures, is there a cleaner notation than this? (I may need lots of this functions and procedures).

function get_temp_als(alarms : alarms_type)
  return alarms(sys1_temp_hi_al) & alarms(sys1_temp_lo_al) & alarms(sys2_temp_hi_al) & alarms(sys2_temp_lo_al);

function get_combined_temp_als(alarms : alarms_type)
  return alarms(sys1_temp_hi_al) or alarms(sys1_temp_lo_al) or alarms(sys2_temp_hi_al) or alarms(sys2_temp_lo_al);

procedure set_temp_als(alarms: alarm_type, value:std_logic)
begin
  alarms(sys1_temp_hi_al) <= value;
  alarms(sys1_temp_lo_al) <= value;
  alarms(sys2_temp_hi_al) <= value;
  alarms(sys2_temp_lo_al) <= value;;
end;

I would like this to work with VHDL 2002 and it is intended for synthesis.


Solution

  • You are correct in that aliases do not work like that. They are an alias to a single object (or slice thereof) and cannot be used to make new compounded objects like you might do with a pointer in another language.

    A procedure is likely the only way you can achieve this. The alarms paramter should be a signal and mode out:

    procedure set_temp_als(signal alarms: out alarm_type; value:std_logic)
    begin
      alarms(sys1_temp_hi_al) <= value;
      alarms(sys1_temp_lo_al) <= value;
      alarms(sys2_temp_hi_al) <= value;
      alarms(sys2_temp_lo_al) <= value;
    end;
    

    so you can assign the alarms with: set_temp_als(alarms, '1');

    Your functions are the right idea, but syntactically wrong:

    function get_temp_als(alarms : alarms_type) return std_logic_vector is
    begin
      return alarms(sys1_temp_hi_al) & alarms(sys1_temp_lo_al) & alarms(sys2_temp_hi_al) & alarms(sys2_temp_lo_al);
    end function;
    
    signal some_other_slv : std_logic_vector(3 downto 0);
    
    some_other_slv <= get_temp_als(alarms);