TWiki
>
P1076/Ballots Web
>
Vhdl2019CollectedRequirements
>
HeterogeneousInterfaces
>
HeterogeneousInterfacesWithReuse
(revision 7) (raw view)
Edit
Attach
---+ Heterogeneous Interfaces with Emphasis on Reusing Existing VHDL Concepts %TOC% ---++ Proposal Details * Who Updates: Main.ErnstChristen * Date Proposed: 2015-11-05 * Date Last Updated: * Priority: * Complexity: * Focus: Flexibility, reuse of existing VHDL concepts ---++ Bundles and Interfaces A _bundle_ is an ordered collection of objects. This makes it different from a signal of a record type or of an array type, which each are a single object. The difference is significant for bundles at ports: According to LRM 6.4.2.3: %TABLE{ databg="#ffffff" tableborder="0" }% | | A signal may have one or more _sources_. For a signal of a scalar type, each source is either a driver (see 14.7.2) or an *out*, *inout*, *buffer*, or <strong>linkage </strong>port of a component instance or of a block statement with which the signal is associated. For a signal of a composite type, each composite source is a collection of scalar sources, one for each scalar subelement of the signal. | Consequently, if an actual signal is associated with more than one formal signal of mode *out*, *inout*, *buffer*, or *linkage*, then the actual must be of a resolved type. Conversely, each signal that is part of a bundle has its own source (if any) that is independent of the sources of the other signals of the bundle. This makes it possible to combine resolved and unresolved signals in a bundle. A bundle doesn’t have a type; it’s the elements of a bundle that have a type. The properties of a bundle, such as its elements, are specified by an _interface_: <sticky><pre>interface_unit_declaration ::= <B>interface</B> identifier <B>is</B> { interface_element_declaration } <B>end</B> [ <B>interface</B> ] [ interface_simple_name ] ; interface_element_declaration ::= signal_declaration | bundle_declaration bundle_declaration ::= <B>bundle</B> identifier_list : interface_mark ; interface_mark ::= interface_name </pre></sticky> A bundle declaration declares a bundle, which includes the creation of the objects that are elements of the bundle. In this regard a bundle behaves like a macro: it provides a convenient shorthand to work with a collection of objects. The following basic operations apply to an interface: * A selected name, an indexed name, or a slice name A selected name whose prefix is a bundle denotes an element of a bundle. Note that assignment is not a basic operation of an interface. Any assignment must be made to the elements of a bundle individually, as each element is a separate object. Interfaces may be composite, in particular arrays. This makes it possible to specify different modes for different elements of a bundle of an array interface. The syntax to declare an array interface is similar to the declaration of an array type, and the semantics parallel each other. A bundle can be associated as an actual in whole with a formal bundle port. Association in parts will require further investigations. ---++ Interface Bundles and Port Views The bundle concept also applies to ports. An interface bundle is declared to be of a particular _port view_. The primary function of a port view is to define the mode of each element of the bundle port. Therefore, the port view is related to an interface. A port view may be declared, in which case it is named. An anonymous port view may be created by specifying its properties as part of the interface bundle declaration. <sticky><pre>interface_bundle_declaration ::= <B>bundle</B> interface_list : <B>view</B> port_view_indication port_view_indication ::= port_view_name [ generic_map_clause ] | interface_name port_view_header port_view_declaration ::= <B>port view</B> identifier <B>of</B> interface_name <B>is</B> port_view_header <B>end</B> [ <B>port view</B> ] [ port_view_simple_name ] ; port_view_header ::= mode_map_clause | [ generic_clause ] [ port_clause [ port_map_clause ]] mode_map_clause ::= <B>mode map</B> ( mode_association_list ) mode_association_list ::= mode_association_element { , mode_association_element } mode_association_element ::= [ choices => ] mode </pre></sticky> A secondary function of a port view is to specify those elements of the interface that are visible in the design unit. This is accomplished with a port clause in the definition of the port view. In the absence of a port clause all elements of the interface are visible in the scope of the port declaration. In this case their mode is specified with a port map clause. Conversely, if a port clause appears in a port view, the port clause defines the port properties. Each element listed in the port clause is a member of the interface bundle. If these members differ from those of the interface, a port map clause is required. For each association element, the formal in the port map clause is the local name for the corresponding actual. ---++ Properties New reserved words: *interface*, *bundle*, *view*, *mode* Properties of a signal, including a composite signal, are untouched. The effective value of a signal is the same everywhere the signal is visible. Syntax reuse where possible. ---++ Examples ---+++ Complex RTL Example Many aspects of theis approach are demonstrated by the following 3 examples. The files not presented here are similar. The complete collection of files is available [[%ATTACHURL%/ComplexRTLWithBundle.tar.gz][here]]. ---++++ The Generic Package cpu_bus_pkg <sticky><pre> <B>library</B> ieee; <B>use</B> ieee.std_logic_1164.<B>all</B>; <B>package</B> cpu_bus_pkg <B>is</B> <B>generic</B> ( masters_max_jg : positive; slaves_max_jg : positive; awidth_jg : positive; dwidth_jg : positive ); <B>subtype</B> masters_total_jrt <B>is</B> natural <B>range</B> masters_max_jg - 1 <B>downto</B> 0; <B>constant</B> slaves_total_jc: positive := slaves_max_jg -- individual slaves + masters_max_jg -- master's slave return + 1; -- arbiter's slave return <B>subtype</B> slaves_total_jrt <B>is</B> natural <B>range</B> slaves_total_jc - 1 <B>downto</B> 0; <B>subtype</B> addr_jrt <B>is</B> natural <B>range</B> awidth_jg - 1 <B>downto</B> 0; <B>subtype</B> data_jrt <B>is</B> natural <B>range</B> dwidth_jg - 1 <B>downto</B> 0; <B>subtype</B> master_ctrl_vst <B>is</B> std_logic_vector(masters_total_jrt); <B>subtype</B> slave_ctrl_vst <B>is</B> std_logic_vector(slaves_total_jrt); <B>subtype</B> addr_vst <B>is</B> std_logic_vector(addr_jrt); <B>subtype</B> data_vst <B>is</B> std_logic_vector(data_jrt); <B>type</B> master_r <B>is</B> -- Master record <B>record</B> addr_vl : addr_vst; -- Address bus to slave devices data_vl : data_vst; -- Data bus from master to slave we_l : std_logic; -- Write enable from master to slave en_vl : slave_ctrl_vst; -- Slave enables from master to slave <B>end record</B> master_r; <B>type</B> slave_r <B>is</B> -- Slave record <B>record</B> data_vl : data_vst; -- Data bus from slave to master ack_l : std_logic; -- Acknowledge to master from slave err_l : std_logic; -- Error report to master from slave <B>end record</B> slave_r; <B>interface</B> slave_i <B>is</B> <B>signal</B> slave_rl : slave_r; <B>end interface</B> slave_i; <B>interface</B> slave_a <B>is</B> <B>array</B> (slaves_total_jrt) <B>of</B> slave_i;-- Array of slave interfaces <B>interface</B> arbiter_i <B>is</B> -- Arbiter bundle <B>signal</B> master_rl : master_r; -- Master record to the arbiter <B>signal</B> bus_req_l : std_logic; -- Bus request from master <B>signal</B> bus_grnt_l : std_logic; -- Bus grants to master <B>end interface</B> arbiter_i; <B>interface</B> arbiter_a <B>is</B> <B>array</B>(masters_total_jrt) <B>of</B> arbiter_i;-- Array of arbiter interfaces <B>interface</B> cpu_bus_i <B>is</B> -- Bus interface record <B>bundle</B> arbiter_al : arbiter_a; -- Arbiter array of arbiter master -- control records <B>signal</B> master_rl : master_r; -- Master record to slaves <B>bundle</B> slave_al : slave_a; -- Array of slave records to master <B>end record</B> cpu_bus_i; <B>port view</B> slave_ivw <B>of</B> cpu_bus_i <B>is</B> <B>generic</B> ( slave_id_jg : slaves_total_jrt ); <B>port</B> ( <B>signal</B> master_rl : <B>in</B> master_r; <B>signal</B> slave_rl : <B>buffer</B> slave_r ); <B>port map</B> ( master_rl => master_rl, slave_rl => slave_al(slave_id_jg) ); <B>end port view</B> slave_ivw; <B>port view</B> arbiter_v_in <B>of</B> arbiter_i <B>is</B> <B>mode map</B> (master_rl => <B>buffer</B>, bus_req_l => <B>buffer</B>, bus_grnt_l => <B>in</B>); -- This is equivalent to -- <B>port</B> ( -- <B>signal</B> master_rl : <B>buffer</B> master_r; -- <B>signal</B> bus_req_l : <B>buffer</B> std_logic; -- <B>signal</B> bus_grnt_l : <B>in</B> std_logic -- ); <B>end port view</B> arbiter_v_in; <B>port view</B> arbiter_v_out <B>of</B> arbiter_i <B>is</B> <B>mode map</B> (master_rl => <B>in</B>, bus_req_l => <B>in</B>, bus_grnt_l => <B>buffer</B>); <B>end port view</B> arbiter_v_out; <B>port view</B> master_ivw <B>of</B> cpu_bus_i <B>is</B> <B>generic</B> ( slave_id_jg : slaves_total_jrt; master_id_jg : masters_total_jrt ); <B>port</B> ( <B>bundle</B> arbiter_rl : <B>view</B> arbiter_v_in; <B>signal</B> master_rl : <B>in</B> master_r; <B>bundle</B> slave_al : <B>view</B> slave_a <B>mode map</B> (slave_id_jg => <B>buffer</B>, <B>others</B> => <B>in</B>) ); <B>port map</B> ( arbiter_rl => arbiter_al(master_id_jg), master_rl => master_rl, slave_al => slave_al }; <B>end port view</B> master_ivw; <B>port view</B> a_arbiter_avw <B>of</B> arbiter_a <B>is</B> <B>mode map</B> ( <B>others</B> => <B>view</B> arbiter_v_out ); <B>end port view</B> a_arbiter_avw; <B>port view</B> arbiter_ivw <B>of</B> cpu_bus_i <B>is</B> <B>generic</B> ( slave_id_jg : slaves_total_jrt ); <B>port</B> ( <B>bundle</B> arbiter_al : <B>view</B> a_arbiter_avw; <B>signal</B> master_rl : <B>buffer</B> master_r; <B>signal</B> slave_rl : <B>buffer</B> slave_r ); <B>port map</B> ( arbiter_al => arbiter_al, master_rl => master_rl, slave_rl => slave_al(slave_id_jg) ); <B>end port view</B> arbiter_grnt_ivw; <B>end package</B> cpu_bus_pkg; </pre></sticky> ---++++ The slave_ent design unit <sticky><pre> <B>library</B> ieee; <B>use</B> ieee.std_logic_1164,<B>all</B>; <B>use</B> work.cpu_bus_2m8s_pkg.<B>all</B>; <B>entity</B> slave_ent <B>is</B> <b>generic</B> ( slave_id_jg : slaves_total_jrt ); <B>port</B> ( <B>signal</B> rst_i : <B>in</B> std_logic; <B>signal</B> clk_i : <B>in</B> std_logic; <B>bundle</B> cpu_bus_rif : <B>view</B> slave_ivw <B>generic map</B> ( slave_id_jg => slave_id_jg ) ); <B>end entity</B> slave_ent; <B>architecture</B> rtl_arch <B>of</B> slave_ent <B>is</B> <B>alias</B> add_vs <B>is</B> cpu_bus_rif.master_rl.addr_vl; <B>alias</B> data_in_vs <B>is</B> cpu_bus_rif.master_rl.data_vl; <B>alias</B> we_s <B>is</B> cpu_bus_rif.master_rl.we_l; <B>alias</B> en_s <B>is</B> cpu_bus_rif.master_rl.en_vl(slave_id_jg); <B>alias</B> data_out_vs <B>is</B> cpu_bus_rif.slave_rl.data_vl; <B>alias</B> ack_s <B>is</B> cpu_bus_rif.slave_rl.ack_l; <B>alias</B> err_s <B>is</B> cpu_bus_rif.slave_rl.err_l; <B>begin</B> ... <B>end architecture</B> rtl_arch; </pre></sticky> The master and arbiter design units are similar. ---++++ The !AMandS design unit <sticky><pre> <B>library</B> ieee; <B>use</B> ieee.std_logic_1164.<B>all</B>; <B>use</B> work.cpu_bus_2m8s_pkg.<B>all</B>; <B>entity</B> AMandS_ent <B>is</B> <B>port</B> ( <B>signal</B> rst_i : <B>in</B> std_logic; <B>signal</B> clk_i : <B>in</B> std_logic; <B>bundle</B> cpu_bus_rif : <B>view</B> cpu_bus_i <B>mode map</B> (arbiter_al => <B>view</B> a_arbiter_avw, master_rl => <B>buffer</B> master_r; slave_al => <B>view</B> slave_a <B>mode map</B> (3|7|9|10 => <B>buffer</B>, <B>others</B> => <B>in</B>) ) ); <B>end entity</B> AMandS_ent; <B>architecture</B> rtl_arch <B>of</B> AMandS_ent <B>is</B> <B>begin</B> arbiter_inst : <B>entity</B> work.arbiter_ent <B>generic map</B> ( slave_id_jg => 10 ) <B>port map</B> ( rst_i => rst_i, clk_i => clk_i, cpu_bus_rif => cpu_bus_rif ); master_inst2 : <B>entity</B> work.master_ent <B>generic map</B> ( slave_id_jg => 9, master_id_jg => 1 ) <B>port map</B> ( rst_i => rst_i, clk_i => clk_i, cpu_bus_rif => cpu_bus_rif ); slave_inst4 : <B>entity</B> work.slave_ent <B>generic map</B> ( slave_id_jg => 3 ) <B>port map</B> ( rst_i => rst_i, clk_i => clk_i, cpu_bus_rif => cpu_bus_rif ); slave_inst8 : <B>entity</B> work.slave_ent <B>generic map</B> ( slave_id_jg => 7 ) <B>port map</B> ( rst_i => rst_i, clk_i => clk_i, cpu_bus_rif => cpu_bus_rif ); <B>end architecture</B> rtl_arch; </pre></sticky> The !MplusS and !Sonly design units are similar. ---++ Questions ---++ Comments In the meeting on November 5, 2015, the following comments were made: * The syntax of port_view_header allows an empty production.<br />[[Main.ErnstChristen]]: Yes. There must be either a semantic rule to prevent that, but more likely is that the port clause may not be optional. Investigation pending. * It seems that the generic map should be part of the interface, not of the port view.<br />[[Main.ErnstChristen]]: Not for the functionality required in the Complex RTL example, for this it must be part of the port view. However, there are at this time a number of inconsistencies whose resolution may provide an answer. * It seems there is a lot of repetition/duplication. Elements have to be declared as part of the interface and again in the port clause of a port view. Finally, their names also appears in the port map clause. This is reminiscnent of the definnition of a block, but nobody uses a block this way.%BR%%ICON{"person"}%<span style="color: green;"> I have a faint recollection that some of the models in the Free Model Foundary may use the 'port map' technique in block structures. </span>[[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-07%BR%<br />[[Main.ErnstChristen]]: The port clause of a port view defines the elements of the formal bundle, which is the subset of the actual that is visible in a DU whose entity has a port with this port view. This use is quite similar to the port clause of an entity. The port map clause maps the elements of the bundle actual to the elements of the bundle formal. This is quite similar to a port map clause of a component instantiation statement. * It should be possible to combine port clause and port map clause, maybe by extending the semantics of an association element in a port map clause to include a mode.<br />[[Main.ErnstChristen]]: This is an approach with a different emphasis, less on reuse of existing concepts and more on adding new ones. It should be investigated and presented as a different proposal. * Several syntax and typographical errors were pointed out.<br />[[Main.ErnstChristen]]: These have now been corrected. ---+++!! Some thoughts on *bundle* semantics - [[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-09 * The bundle is an "ordered collection of objects" a kind of composite object ( as opposed to a composite type). <br />[[Main.ErnstChristen]] - 2015-11-10: Not quite. A composite object in VHDL terminology is an object of a composite type. A bundle is not a composite object, but a named collection of objects. A bundle declaration declares all the objects that are contained in the interface.%BR%%ICON{"person"}%<span style="color: green;"> I think we may need to specify the semantics in the LRM a bit more thoroughly: %BR%%BR%"An object of a composite type represents a collection of objects, one for each element of the composite object. [LRM 5.3.1]" %BR%%BR%What is missing from the composite object definition in the LRM (above) is the implicit assumption that the elements of the composite object are all of the same object class, i.e. the class of the object that the composite type is associated with (e.g. class *signal*). %BR%We can and should use the terminology 'composite object', but when used with the new *bundle* concept we state that the 'composite object' may now have elements of differing object class. </span>[[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-12 <br />[[Main.ErnstChristen]] - 2015-11-17: Again "not quite". A bundle is not an object, it is a collection of objects. This puts it in some way above an object. There are many differences, as implied by comparing the basic operations of a type with those of an interface. A very important one is that a primary in an expression may denote an object, but not a bundle. A bundle may also not be the target of an assignment statement. %BR%%ICON{"person"}%<span style="color: green;"> This poses the important question: can a *signal* of composite type and associated with an interface *record view* (or *array view*) be the target of an assignment statement? </span>[[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-18<br />[[Main.ErnstChristen]] - 2015-11-18: Everything that a user can do with a signal is independent of whether the signal is an element of the bundle or not. The only difference is the name of the object. * A *signal* object is associated (when declared) with its *type*. * We need to associate a *bundle* with something, but it is not a *type*. Let's call it a structure for now. <br />[[Main.ErnstChristen]] - 2015-11-10: The properties of a bundle are described by an *interface*, that is, the interface takes the place of the type in a bundle declaration. For a bundle port the properties are defined by a *port view*. * We can order the structure and call it a cluster (can't use 'structure' - how many architectures in peoples code are called that!!!!) * We can now give it order by defining it as record cluster or an array cluster: <br />[[Main.ErnstChristen]] - 2015-11-10: As described above, there are array interfaces. Each element of a 1-dimensional interface array is a scalar interface, and the same applies to bundles.%BR%%ICON{"person"}%<span style="color: green;"> I guess what I was questioning was how you intend to define an *interface array*. As Jim mentioned (I think) the *interface* production is similar to a *record* type structure of objects in its format (without the keywords), so how do we specify the *array* form of the *interface* production? </span>[[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-12 <br />[[Main.ErnstChristen]] - 2015-11-17: As described in the text, the syntax to declare an interface array parallels the syntax of declaring an array type. There are examples in package cpu_bus_pkg.%BR%%ICON{"person"}%<span style="color: green;"> Does this mean that we cannot have an *array* of signals or an *array* of bundles? </span>[[Main.BrentHahoe][Brent Hayhoe]] - 2015-11-18<br />[[Main.ErnstChristen]] - 2015-11-18: You can have both, and each has its dedicated use. <sticky><pre> bundle_declaration ::= <B>bundle</B> identifier_list : structure_indication ; structure_definition ::= record_structure_definition | array_structure_definition record_stucture_definition ::= <B>cluster</B> identifier <B>is</B> <B>record</B> { cluster_element_declaration } <B>end</B> <B>record</B> [ record_cluster_simple_name ] array_stucture_definition ::= <B>cluster</B> identifier <B>is</B> <B>array</B> ( index_subtype_definition { , index_subtype_definition } ) <B>of</B> cluster_element_declaration ; cluster_element_declaration ::= signal_declaration | bundle_declaration </pre></sticky> * So what does this give us - just as a *bundle* is a composite group object of a signal, a signal is associated with a *type*, a *bundle* is now associated with a *cluster*. I feel it could give us better semantics/syntax, I'm just not sure which! * This could then lead on to a *record cluster view* and an *array cluster view* ---++ Arguments FOR ---++ Arguments AGAINST ---++ Supporters ---++ -- Main.ErnstChristen - 2015-11-05</sticky>
Attachments
Attachments
I
Attachment
Action
Size
Date
Who
Comment
gz
ComplexRTLWithBundle.tar.gz
manage
2.8 K
2015-11-17 - 21:42
ErnstChristen
VHDL files supporting this approach
Edit
|
Attach
|
P
rint version
|
H
istory
:
r9
<
r8
<
r7
<
r6
<
r5
|
B
acklinks
|
V
iew topic
|
Raw edit
|
More topic actions...
Topic revision: r1 - 2016-09-27 - 10:47:30 -
TWikiGuest
P1076/Ballots
Log In
or
Register
P1076/Ballots Web
Create New Topic
Index
Search
Changes
Notifications
RSS Feed
Statistics
Preferences
Webs
Main
P1076
Ballots
LCS2016_080
P10761
P1647
P16661
P1685
P1734
P1735
P1778
P1800
P1801
Sandbox
TWiki
VIP
VerilogAMS
Copyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki?
Send feedback