Search code examples
variable-assignmentvhdl

How to assign multiple values to multiple ports in VHDL


I'm writing a small bit of VHDL to rotate the values on eight 7-segment displays.

I have something like this:

-- handle the rotation of displays
process(rot_select, d0, d1, d2, d3, d4, d5, d6, d7)
begin
    case rot_select is
        when "000" => -- rotate by 0
        when "001" => -- rotate by 1
        when "010" => -- rotate by 2
        when "011" => -- rotate by 3
        when "100" => -- rotate by 4
        when "101" => -- rotate by 5
        when "110" => -- rotate by 6
        when "111" => -- rotate by 7
    end case;
end process;

Where rot_select is a selector to figure out the size of the rotation (first display moves to the second display, etc) and d0-d7 represent 7-bit vectors that are the inputs of each display.

I was wondering if instead of doing manual assignment like d1 <= d0; d2 <= d1; ... every time, I could make it more automatic and use less code? Possibly something like (d0,d1,d2,d3,d4,d5,d6,d7) <= (d7,d0,d1,d2,d3,d4,d5,d6); or anything that makes more sense.


Solution

  • Aggregate assignment is more capable in VHDL-2008, so if you are using VHDL-2008, you can write:

    (d0,d1,d2,d3,d4,d5,d6,d7) <= d7 & d0 & d1 & d2 & d3 & d4 & d5 & d6;
    

    Assuming that d0, etc. are declared as std_logic_vector or similar.

    Note that if you are using VHDL-2008, you can also write the sensitivity list as (all), instead of listing all signals explicitly.

    But as Josh writes, a representation as array is more suitable, and that will also work with previous versions of VHDL. Code could look something like:

      ...
    
      -- 7-segment display
      subtype ssd_t is std_logic_vector(1 to 7);  -- Type for display
      type ssd_arr_t is array(natural range <>) of ssd_t;  -- Type for array of display
      signal d_cur : ssd_arr_t(0 to 7);  -- Current value
      signal d_nxt : ssd_arr_t(0 to 7);  -- Next value
      -- Rotation
      signal rot_select : std_logic_vector(2 downto 0);
    
    begin
    
      -- Handle the rotation of displays
      process (rot_select, d_cur)
        variable idx_cur_v : unsigned(2 downto 0);
      begin
        for idx in d_nxt'range loop
          idx_cur_v := to_unsigned(idx, 3) - unsigned(rot_select);  -- Handles modulo  operation
          d_nxt(idx) <= d_cur(to_integer(idx_cur_v));
        end loop;
      end process;
    
      ...