VHDL 2019 Example

The following code illustrates the use of records and views. There are 4 files, top.vhd, interface.vhd, source.vhd, and sink.vhd.

The top module is defined as:

-- top.vhd   top-module
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.interfaces.all; -- USING PACKAGE HERE!

entity top is 
  port(clk, rst : in std_logic; data_1_in : in std_logic_vector(3 downto 0); 
    data_2_in : in std_logic_vector(7 downto 0); 
    data_1_out : out std_logic_vector(3 downto 0); 
    data_2_out : out std_logic_vector(7 downto 0););
end;

architecture top_a of top is
  signal bus_signal : streaming_bus;
begin
  producer : entity work.source  port map(clk, rst, data_1_in, data_2_in, bus_signal);
  consumer : entity work.sink    port map(clk, rst, data_1_out, data_2_out, bus_signal);
end;

interface.vhd defines the streaming_master and streaming_slave interfaces.

-- interface.vhd
-- Define the streaming_master and streaming_slave interfaces

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package interfaces is
  -- record definition
  type streaming_bus is record  
    data_1  : std_logic_vector(3 downto 0);
    data_2  : std_logic_vector(7 downto 0);
  end record;

-- Create an interface for the record streaming_bus in the streaming_master mode view
  view streaming_master of streaming_bus is
    data_1, data_2 : out;
  end view;
  
  -- Create an interface for the record streaming_bus in the streaming_master mode view
  alias streaming_slave is streaming_master'converse;
end;

source receives input data from the top module and sends it to sink using the streaming_master interface defined in interface.vhd.

-- source.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.interfaces.all; -- USING PACKAGE HERE!

-- source uses "master_interface" as the streaming_master interface
entity source is
    -- short form
    port(clk, rst : in std_logic; 
      data_1 : in std_logic_vector(3 downto 0); 
      data_2 : in std_logic_vector(7 downto 0); 
      master_interface : view streaming_master); 
end;

architecture source_a of source is
    signal data_1_net : std_logic_vector(3 downto 0) := (others => '0');
    signal data_2_net : std_logic_vector(7 downto 0) := (others => '0');
begin
    process(clk,rst)
    begin
        if rising_edge(clk) then
            if rst='1' then       -- synchronous reset
                data_1_net <= (others => '0');
                data_2_net <= (others => '0');
            else
                data_1_net <= data_1;
                data_2_net <= data_2;
            end if;
            master_interface.data_1 <= data_1_net;
            master_interface.data_2 <= data_2_net;
        end if;
    end process;  
end;

sink receives data from source through the streaming_slave interface defined in interface.vhd.

-- sink.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.interfaces.all; -- USING PACKAGE HERE!

entity sink is
  port(clk, rst : in std_logic; data_1 : out std_logic_vector(3 downto 0); 
      data_2 : out std_logic_vector(7 downto 0); 
      slave_interface: view streaming_slave);
end;

architecture sink_a of sink is
    signal data_1_net : std_logic_vector(3 downto 0) := (others => '0');
    signal data_2_net : std_logic_vector(7 downto 0) := (others => '0');
begin
    process(clk,rst)
    begin
        if rising_edge(clk) then
            if rst='1' then       -- synchronous reset
                data_1_net <= (others => '0');
                data_2_net <= (others => '0');
            else
                -- processor receives data_1 and data_2 signal from source and 
                -- inverts it before sending to sink
                data_1_net <= not slave_interface.data_1;
                data_2_net <= not slave_interface.data_2;
            end if;
            data_1 <= data_1_net;
            data_2 <= data_2_net;
        end if;
    end process;  
end;