Minimal RTL Record Based Interface Use Case
Assumptions
- This use case is intended to propose a minimal implementation of an enhanced interface support for RTL use based on the standard record type.
- Existing designs can use record types to encapsulate an interface, but propagating a record through a port (or parameter) structure limits the record signal to a common mode for all of its elements.
This can be overcome by changing the port mode to inout and ensuring that all record elements are of a resolved type.
However this could be viewed as ignoring the mode concept and in many companies (especially designing with FPGAs) it would break coding guidelines (example rule: "do not use resolved types within core designs").
- This use case proposes a new construct for named directional mode control on entity/function/procedure declarations.
Various proposals have suggested the following options:
- port configuration
- advantage? uses existing VHDL keywords
- disadvantage? too verbose
- disadvantage? suggests entity only use
- modport
- advantage? meaning generally understood
- disadvantage? too Verilog'ish
- view
- advantage? concise
- advantage? use as record view
- advantage? extensible to array view and bundle view
- disadvantage? new VHDL keyword
- This use case proposes using a new view keyword to describe a new VHDL construct in order to hierarchically control modes for each element of a composite type when used in an entity or subprogram interface structure (termed in BNF definitions as an "interface_object_declaration").
- Objects associated with a composite type will need to allow elements of said composite type to be driven independently from the object as a whole (e.g. a signal).
Use Case Example
- A simple parallel data interface with an assumed protocol (not defined here).
The Package
- In order to make declarations visible across hierarchies, they are defined within a package:
package if_pkg
generic(
dwidth_jg : positive
);
is
constant dwidth_jc : positive := dwidth_jg;
subtype dwidth_jrt is natural range dwidth_jc - 1 downto 0;
subtype data_vst is std_logic_vector(dwidth_jrt);
- Define the record type and include generically controlled data width.
type if_bus_r is record
enbl_e : std_logic;
strt_e : std_logic;
data_ve : std_logic_vector(dwidth_jrt);
ack_e : std_logic;
err_e : std_logic;
end record if_bus_r;
- Use a new record view construct to specify a hierarchical named mode view of this record type at the transmitter.
record view if_bus_tx_rvw of if_bus_r is
enbl_e : out std_logic;
strt_e : out std_logic;
data_ve : out std_logic_vector(dwidth_jrt);
ack_e : in std_logic;
err_e : in std_logic;
end record view if_bus_tx_rvw;
- Use a new attribute to specify the opposite hierarchical named mode view of this record type at the receiver.
Use the converse attribute to reverse the mode directions.
record view if_bus_rx_rvw of if_bus_r is
if_bus_tx_rvw'converse;
end record view if_bus_rx_rvw;
- Use a new attribute to specify a named mode view of this record type at the monitoring point.
Use the monitor attribute to set all mode directions to 'in'.
record view if_bus_chk_rvw of if_bus_r is
if_bus_tx_rvw'monitor;
end record view if_bus_chk_rvw;
end package if_pkg;
The new attribute value equivalent mode views are shown below:
- The converse record view 'if_bus_rx_rvw' is equivalent to:
record view if_bus_rx_rvw of if_bus_r is
enbl_e : in std_logic;
strt_e : in std_logic;
data_ve : in std_logic_vector(dwidth_jrt);
ack_e : out std_logic;
err_e : out std_logic;
end record view if_bus_rx_rvw;
- The monitor record view 'if_bus_chk_rvw' is equivalent to:
record view if_bus_chk_rvw of if_bus_r is
enbl_e : in std_logic;
strt_e : in std_logic;
data_ve : in std_logic_vector(dwidth_jrt);
ack_e : in std_logic;
err_e : in std_logic;
end record view if_bus_chk_rvw;
The Structural Interconnect Level
The structural interconnect now becomes almost trivial, but that is the intent:
- Instantiate the interface package and use it.
- This creates an 8 bit data bus version of the record.
package if_8_pkg is new if_pkg
generic map(
dwidth_jg => 8
);
use work.if_8_pkg.all;
- Declare a trivial test bench top entity:
entity if_tb_ent is
end entity if_tb_ent;
- Define the test bench architecture and declare the necessary signals:
architecture RecordInterfaceTop of if_tb_ent is
signal rst_s : std_logic;
signal clk_s : std_logic;
signal if_bus_rs : if_8_pkg.if_bus_r;
- Declare the monitor procedure:
procedure monitor_prcd(
signal rst_si : in std_logic;
signal clk_si : in std_logic;
signal if_bus_rsif : view if_8_pkg.if_bus_chk_rvw
) is
begin
...
end procedure monitor_prcd;
- Instantiate the transmitter
begin
transmit_inst : component transmit_cmp
port map(
rst_i => rst_s,
clk_i => clk_s,
if_bus_tx_rif => if_bus_rs
);
receive_inst : component receive_cmp
port map(
rst_i => rst_s,
clk_i => clk_s,
if_bus_tx_rif => if_bus_rs
);
monitor_inst : monitor_prcd(rst_s, clk_s, if_bus_rs);
end architecture RecordInterfaceTop;
The Entities
The Transmitter
- First '*use*' the 8 bit interface package
use work.if_8_pkg.all;
- The transmitter entity.
N.B. It does not need a generic declaration for the data bus width as that is defined within the package.
The new view keyword is now used to specify a new mode. It indicates that it wil be followed by the hierarchical mode and in this case that is defined using the named record view declared in the interface package for the transmitter terminus of the interface:
entity transmit_ent is
port(
rst_i : in std_logic;
clk_i : in std_logic;
if_bus_tx_rif : view if_8_pkg.if_bus_tx_rvw
);
end entity transmit_ent;
- Declare the internal signals.
architecture rtl of transmit_ent is
signal enbl_s : std_logic;
signal strt_s : std_logic;
signal data_vs : std_logic_vector(if_8_pkg.dwidth_jrt);
signal ack_s : std_logic;
signal err_s : std_logic;
begin
- Compose/decompose the interface record:
- Transmit the data with the enable and start control signals.
- Receive the acknowledge and error status signals.
if_bus_tx_rif.enbl_e <= enbl_s;
if_bus_tx_rif.strt_e <= strt_s;
if_bus_tx_rif.data_ve <= data_vs ;
ack_s <= if_bus_tx_rif.ack_e;
err_s <= if_bus_tx_rif.err_e;
end architecture rtl;
The Receiver
- First '*use*' the 8 bit interface package
use work.if_8_pkg.all;
- The receiver entity
N.B. This also does not need a generic declaration for the data bus width as it is defined within the package:
entity receive_ent is
port(
rst_i : in std_logic;
clk_i : in std_logic;
if_bus_rx_rif : view if_8_pkg.if_bus_rx_rvw
);
end entity receive_ent;
- Declare the internal signals.
architecture rtl of transmit_ent is
signal enbl_s : std_logic;
signal strt_s : std_logic;
signal data_vs : if_8_pkg.data_vst;
signal ack_s : std_logic;
signal err_s : std_logic;
begin
- Compose/decompose the interface record:
- Receive the data with the enable and start control signals.
- Return the acknowledge and error status signals.
enbl_s <= if_bus_rx_rif.enbl_e;
strt_s <= if_bus_rx_rif.strt_e;
data_vs <= if_bus_rx_rif.data_ve;
if_bus_rx_rif.ack_e <= ack_s;
if_bus_rx_rif.err_e <= err_s;
end architecture rtl;
Conclusions
- The main additions to the language are used to provide enhanced mode control at entity, function and procedure interfaces.
- This is achieved using a new view reserved keyword.
- The view keyword is used to declare named hierarchical interface mode views for composite types.
- The composite type views can be defined as a named record view or a named array view, for example:
record view if_bus_tx_rvw of if_bus_r is
enbl_e : out std_logic;
strt_e : out std_logic;
data_ve : out std_logic_vector(dwidth_jrt);
ack_e : in std_logic;
err_e : in std_logic;
end record view if_bus_tx_rvw;
- These named views are then associated with elements in an interface list using the new view keyword as a mode indicator to identify the named mode view and associate it with a constant, signal or variable object, for example:
rst_i : in std_logic;
clk_i : in std_logic;
if_bus_rx_rif : view if_8_pkg.if_bus_rx_rvw
- Additionally, two new attributes are proposed, namely converse and monitor, which are used with named mode views to provide inverted in/out and all in mode views respectively, for example:
(Refer to proposal: Interfaces: Attributes for Interfaces)
record view if_bus_rx_rvw of if_bus_r is
if_bus_tx_rvw'converse;
end record view if_bus_rx_rvw;
- The monitor attribute generating an all in record view or array view is essentially redundant.
A connection object with a composite type can be passed through an entity object interface using the in mode operating on the complete composite type.
- The converse attribute generating opposite modes would need a parameter to be able to select between an out port transformation or a buffer port transformation :
- out ports selected:
- in mode transforms to out mode
- out mode transforms to in mode
- buffer mode transforms to in mode
- buffer ports selected:
- in mode transforms to buffer mode
- buffer mode transforms to in mode
- out mode transforms to in mode
- inout modes are not transformed in either port selections, they remain as inout modes.
- Refer to proposal: Interfaces: Attributes for Interfaces
- Connection objects associated with composite types are in effect composite objects.
This new hierarchical view mode will require that each element of a composite type be capable of being driven indepentently from the object as a whole, i.e. as if it were a composite object.
This is a new requirement for the composite type, i.e. not just at the interface termini where the view mode dictates the driving or reading of the individual element, but also on the connection object (e.g. signal) which has no association with a mode, just with the composite type.
- Events may still be generated on the object as a whole, but may benefit from being associated individually with the composite type elements.
This would give the enhanced ability of being able to use indivdual elements of a composite type within sensitivity lists.
- The ability to introspcetively analyse records, specifically to be able to loop through element names of a record.
Refer to proposals: