Language Change Specification for Bidirectional Connections

LCS Number: LCS-2016-070 History
Version: 3
Date: 26-Mar-2017
Status: Voting
Author: Patrick Lehmann
Martin Zabel
Email: Main.PatrickLehmann
Main.MartinZabel
Source Doc: Bidirectional Connections
Summary: Adds bidirectional connections aka. Spaceship assignments.

Voting Results: Cast your votes here

Yes:

  1. Daniel Kho - 2017-02-03 - ver 1
  2. Jakko Verhallen - 2017-03-21 - ver 1. Even without conditional association
  3. Thomas Preusser - 2017-03-22 - ver 1 - would not support a quick, last-minute shot at conditional association for this round
  4. Rob Gaddi - 2017-03-23 - ver 2
  5. Lieven Lemiengre - 2017-03-23 - ver 2
  6. Patrick Lehmann - 2017-03-23 - ver 3
  7. Jim Lewis- 2017-03-30 - ver 3

No:

Abstain:

  1. Brent Hayhoe - 2017-02-16 Version 1 - Abstain due to lack of personal time for review.
  2. Martin Thompson - 2017-02-17 Version 2 - Abstain due to lack of personal time for the depth of review I would like to do.

Style Notes

Changes are shown in red font.
Deletions are crossed out.
Restructuring is shown in crossed out gray font somewhere else in gray font.
Editing or reviewing notes in green font.

Reviewing Notes

Version 3: 26-Mar-2017

  • Split of signal map aspect to LCS 070a to be delayed to VHDL-2020
  • Fixed current value vs. driving value issue in 14.7.3.2 item e) iv) 2)
    The list of sources includes drivers and these have no driving value (they have a current value).
  • Change "same subtype" to "compatible subtype"
  • Added check for cyclic dependency on sources

Version 2: 23-Mar-2017

  • Reworked association lists.
  • Allow signal maps in port maps.

Version 1: 19-Mar-2017
The new algorithm for clause 6.4.2.3 to determine the set of sources for a signal is supposed to work as follows:

library ieee;
use ieee.std_logic_1164.all;

entity top is
  port (
    clk  : in    std_ulogic;
    dbus : inout std_logic);
end entity top;

architecture a of top is
  component sub is
    port (
      clk  : in    std_ulogic;
      rx   : in    std_ulogic;
      tx   : out   std_ulogic;
      dbus : inout std_logic);
  end component sub;

  signal sub1_clk  : std_ulogic;
  signal sub1_rx   : std_ulogic;
  signal sub1_tx   : std_ulogic;
  signal sub1_dbus : std_logic;
  
  signal sub2_clk  : std_ulogic;
  signal sub2_rx   : std_ulogic;
  signal sub2_tx   : std_ulogic;
  signal sub2_dbus : std_logic;
begin

  sub1: sub
    port map (
      clk  => sub1_clk,
      rx   => sub1_rx,
      tx   => sub1_rx,
      dbus => sub1_dbus);

  sub2: sub
    port map (
      clk  => sub2_clk,
      rx   => sub2_rx,
      tx   => sub2_tx,
      dbus => sub2_dbus);

  sub1_clk  <=> clk;     -- clock distribution
  sub2_clk  <=> clk;
  sub1_rx   <=> sub2_tx; -- cross-over link
  sub2_rx   <=> sub1_tx;
  sub1_dbus <=> dbus;    -- shared data-bus
  sub2_dbus <=> dbus;

  d1: dbus <= 'H';       -- driver 'd1' generated by this statement
end architecture a;

Step 1: Primary Sources

For a signal of a scalar type, each primary source is either a driver (see 14.7.2) or an out, inout, buffer, or linkage port of a component instance or of a block statement with which the signal is associated.

primary_sources(clk)       = {}
primary_sources(dbus)      = { d1 }
primary_sources(sub1_clk)  = {}
primary_sources(sub1_rx)   = {}
primary_sources(sub1_tx)   = { sub1.tx }   -- sub1.tx   is the tx port of component instance sub1
primary_sources(sub1_dbus) = { sub1.dbus } -- sub1.dbus is the tx port of component instance sub1
primary_sources(sub2_clk)  = {}
primary_sources(sub2_rx)   = {}
primary_sources(sub2_tx)   = { sub2.tx }   -- sub2.tx   is the tx port of component instance sub2
primary_sources(sub2_dbus) = { sub2.dbus } -- sub2.dbus is the tx port of component instance sub2

Step 2: Secondary sources

For a signal of a scalar type, the subset of secondary sources is the union of all primary sources of all other signals in the same association group.

secondary_sources(clk)       = primary_sources(sub1_clk)  u primary_sources(sub2_clk)  = {}
secondary_sources(dbus)      = primary_sources(sub1_dbus) u primary_sources(sub2_dbus) = { sub1.dbus, sub2.dbus }
secondary_sources(sub1_clk)  = primary_sources(clk)       u primary_sources(sub2_clk)  = {}
secondary_sources(sub1_rx)   = primary_sources(sub2_tx) = { sub2.tx }
secondary_sources(sub1_tx)   = primary_sources(sub2_rx) = {}
secondary_sources(sub1_dbus) = primary_sources(dbus)      u primary_sources(sub2_dbus) = { d1, sub2.dbus }
secondary_sources(sub2_clk)  = primary_sources(clk)       u primary_sources(sub1_clk)  = {}
secondary_sources(sub2_rx)   = primary_sources(sub1_tx) = { sub1.tx }
secondary_sources(sub2_tx)   = primary_sources(sub1_rx) = {}
secondary_sources(sub2_dbus) = primary_sources(dbus)      u primary_sources(sub1_dbus) = { d1, sub1.dbus }

Step 3: Final Set of Sources

A signal may have one or more sources. For a signal of a scalar type, the set of sources is the union of the subset of primary sources and of the subset of secondary sources.

sources(clk)       = primary_sources(clk) u secondary_sources(clk) = {}
sources(dbus)      = { d1, sub1.dbus, sub2.dbus }
sources(sub1_clk)  = {}
sources(sub1_rx)   = { sub2.tx }
sources(sub1_tx)   = { sub1.tx }
sources(sub1_dbus) = { d1, sub1.dbus, sub2.dbus }
sources(sub2_clk)  = {}
sources(sub2_rx)   = { sub1.tx }
sources(sub2_tx)   = { sub2.tx }
sources(sub2_dbus) = { d1, sub1.dbus, sub2.dbus }

Driving Values

The computation of the driving values according to clause 14.7.3.2 can now be done in the following order. Note, ports of mode in do not have a source, the value of the actual is passed using the effective value. The outputs of the sub-component will have sources inside the sub-components as well, these are denoted as "...". If the source is a driver, than the driving value of this source is the current value of the driver. The driving values of all signals within a list item can be computed in parallel:

1. clk, sub1_clk, sub2_clk, d1, ...
2. sub1.tx, sub1.dbus, sub2.tx, sub2.dbus
3. dbus, sub1_rx, sub1_tx, sub1_dbus, sub2_rx, sub2_tx, sub2_dbus

The new values of sub1_dbus and sub2_dbus are passed into the sub-components using the effective values as described in clause 14.7.3.3.

Details of Language Change

6.4.2.3 Signal declarations

[Editor note: 1st paragraph on page 69]

A signal may have one or more sources. For a signal of a scalar type, the set of sources is the union of the subset of primary sources and of
the subset of secondary sources. each source is either a driver (see 14.7.2) or an out, inout, buffer, or linkage port of a component instance
or of a block statement with which the signal is associated.
The subsets are determined as follows:

  • For a signal of a scalar type, each primary source is either a driver (see 14.7.2) or an out, inout, buffer, or linkage port of a component
    instance or of a block statement with which the signal is associated.
  • For a signal of a scalar type, the subset of secondary sources is the union of all primary sources of all other signals in the same association
    group (see 11.7).

Itís an error if after elaboration the calculation of driving values in a signal association group contains a cyclic dependency on the sources.

For a signal of a composite type, each composite source is a collection of scalar sources, one for each scalar subelement of the signal.
It is an error if, after the elaboration of a description, a signal has multiple sources and it is not a resolved signal. It is also an
error if, after the elaboration of a description, a resolved signal has more sources than the number of elements in the index range of the
type of the formal parameter of the resolution function associated with the resolved signal.

If a subelement or slice of a resolved signal of composite type is associated as an actual in a port map aspect (either in a component
instantiation statement, a block statement, or in a binding indication), and if the corresponding formal is of mode out, inout, buffer, or
linkage, then every scalar subelement of that signal shall be associated exactly once with such a formal in the same port map aspect, and
the collection of the corresponding formal parts taken together constitute one primary source of the signal. If a resolved signal of composite type
is associated as an actual in a port map aspect, that is equivalent to each of its subelements being associated in the same port map aspect.

If a subelement of a resolved signal of composite type has a driver in a given process, then every scalar subelement of that signal shall
have a driver in the same process, and the collection of all of those drivers taken together constitute one primary source of the signal.

The default value associated with a scalar signal defines the value component of a transaction that is the initial contents of each driver
(if any) of that signal. The time component of the transaction is not defined, but the transaction is understood to have already occurred
by the start of simulation.

11.1 General

concurrent_statement ::=
    block_statement
  | process_statement
  | concurrent_procedure_call_statement
  | concurrent_assertion_statement
  | concurrent_signal_assignment_statement
  | concurrent_signal_association_statement
  | component_instantiation_statement
  | generate_statement
  | PSL_PSL_Directive

11.7 Concurrent signal association statements [NEW, inserted between 11.6 and 11.7]

[Editor note: New main paragraph]

A concurrent signal association statement represents an association between two signals. Associated signals are said to
compose an association group. An association group can comprise multiple signals.

concurrent_signal_association_statement ::=
  [ label : ] concurrent_simple_signal_association

concurrent_simple_signal_association ::=
  lhs_signal_association_target <=> rhs_signal_association_target ;

signal_association_target ::=
  signal_name

A signal association implies no direction of information exchange between signal association targets (henceforth referred to as targets).
If the target in the concurrent signal association statement is a name, then the name shall denote a signal.

The signals are associated as follows:

  • If the left-hand side target is a scalar signal and the right-hand side target is also a scalar signal, then both signals are associated.
  • If the left-hand side target is a composite signal and the right-hand side target is also a composite signal, then each subelement in the right-hand
    side target shall be associated with the corresponding subelement in the left-hand side target.
  • All other cases are an error.

All signals in an association group are either resolved or unresolved signals. The targets' subtypes shall be compatible to each other. Moreover, the resolution function
corresponding to the subtypes shall be the same, if any.

If a subelement or slice of a resolved signal of a composite type is associated as the right-hand side target, then every scalar subelement of that
signal shall be associated exactly once with the corresponding left-hand side target in the same concurrent signal association statement.

Note 1 -- A signal association target, denoting a signal name, can also denote an attribute name returning an implicit signal.

14.7.3.2 Driving values [Exposed hidden list with a new list hierarchy]

A basic signal is a signal that has all of the following properties:
  • It is either a scalar signal or a resolved signal (see 6.4.2.3).
  • It is not a subelement of a resolved signal.
  • Is not an implicit signal of the form S'STABLE(T), S'QUIET(T), or S'TRANSACTION (see 16.2).
  • It is not an implicit signal GUARD (see 11.2).

Basic signals are those that determine the driving values for all other signals.

The driving value of any signal S is determined by the following steps:

  1. If a driving-value release is scheduled for S or for a signal of which S is a subelement, S becomes driving-value released, that is, no
    longer driving-value forced. Proceed to step b).
  2. If a driving-value force is scheduled for S or for a signal of which S is a subelement, S becomes driving-value forced and the driving value
    of S is the driving force value for S or the element of the driving force value for the signal of which S is a subelement, as appropriate; no
    further steps are required. Otherwise, proceed to step c).
  3. If S is driving-value forced, the driving value of S is unchanged from its previous value; no further steps are required. Otherwise, proceed
    to step d).
  4. If a driving-value deposit is scheduled for S or for a signal of which S is a subelement, the driving value of S is the driving deposit value
    for S or the element of the driving deposit value for the signal of which S is a subelement, as appropriate; no further steps are required.
    Otherwise, proceed to step e), if S is a basic signal, otherwise proceed to or f), as appropriate.
  5. If S is a basic signal:
    • If S has no source, then the driving value of S is given by the default value associated with S (see 6.4.2.3).
    • If S has one source that is a driver and S is not a resolved signal (see 6.4.2.3), then the driving value of S is the current value of
      that driver.
    • If S has one source that is a port and S is not a resolved signal, then the driving value of S is the driving value of the formal part of
      the association element that associates S with that port (see 6.5.7.1). The driving value of a formal part is obtained by evaluating the
      formal part as follows: If no conversion function or type conversion is present in the formal part, then the driving value of the formal
      part is the driving value of the signal denoted by the formal designator. Otherwise, the driving value of the formal part is the value
      obtained by applying either the conversion function or type conversion (whichever is contained in the formal part) to the driving value of
      the signal denoted by the formal designator.
      [Changed hidden nested item list into a sublist for better readablility]
      • If no conversion function or type conversion is present in the formal part, then the driving value of the formal part is the driving
        value of the signal denoted by the formal designator.
      • Otherwise, the driving value of the formal part is the value obtained by applying either the conversion function or type conversion
        (whichever is contained in the formal part) to the driving value of the signal denoted by the formal designator.
    • If S is a resolved signal and has one or more sources, then the driving values of the sources of S are examined. It is an error if
      any of these driving values is a composite where one or more subelement values are determined by the null transaction (see 10.5.2.2) and
      one or more subelement values are not determined by the null transaction. If S is of signal kind register and all the sources of S have
      values determined by the null transaction, then the driving value of S is unchanged from its previous value. Otherwise, the driving value
      of S is obtained by executing the resolution function associated with S, where that function is called with an input parameter consisting
      of the concatenation of the driving values of the sources of S, with the exception of the value of any source of S whose current value is
      determined by the null transaction.
      [Changed hidden nested item list into a sublist for better readablility]
      • If S is of signal kind register and all the sources of S have values determined by the null transaction, then the driving value of S is
        unchanged from its previous value.
      • Otherwise, the driving value of S is obtained by executing the resolution function associated with S, where that function is called
        with an input parameter consisting of the concatenation of the current driving values of the drivers sources of S and the driving
        values of the OUT, INOUT, BUFFER, and LINKAGE ports with which S is associated
        , with the exception of the value of any source
        of S whose current value is determined by the null transaction.
  6. If S is not a basic signal:
    • If S is a subelement of a resolved signal R, the driving value of S is the corresponding subelement value of the driving value of R.
    • Otherwise (S is a nonresolved, composite signal), the driving value of S is equal to the aggregate of the driving values of each of the
      basic signals that are the subelements of S.

15.3 Lexical elements, separators, and delimiters

[...]

A delimiter is either one of the following special characters (in the basic character set):

& ' ( ) * + , - . / : ; < = > ` | [ ] ? @
or one of the following compound delimiters, each composed of two or more adjacent special characters:
=> ** := /= >= <= <> <=> ?? ?= ?/= ?< ?<= ?> ?>= << >>
[...]

NOTE 2 -- The following names are used when referring to compound delimiters:

Delimiter Name
=> Arrow
** Double star, exponentiate
:= Variable assignment
/= Inequality (pronounced "not equal")
>= Greater than or equal
<= Less than or equal; signal assignment
<> Box
<=> Signal association
?? Condition conversion
?= Matching equality
?/= Matching inequality
?< Matching less than
?<= Matching less than or equal
?> Matching greater than
?>= Matching greater than or equal
<< Double less than
>> Double greater than

Annex C

[Editor note: Add these rules]
[...]

concurrent_assertion_statement ::=
  [ label : ] [ postponed ] assertion ;

concurrent_signal_association_statement ::=
  [ label : ] concurrent_simple_signal_association

concurrent_conditional_signal_assignment ::=
  target <= [ guarded ] [ delay_mechanism ] conditional_waveforms ;

concurrent_procedure_call_statement ::=
  [ label : ] [ postponed ] procedure_call ;

concurrent_selected_signal_assignment ::=
  with expression select [ ? ]
    target <= [ guarded ] [ delay_mechanism ] selected_waveforms ;

concurrent_signal_assignment_statement ::=
    [ label : ] [ postponed ] concurrent_simple_signal_assignment
  | [ label : ] [ postponed ] concurrent_conditional_signal_assignment
  | [ label : ] [ postponed ] concurrent_selected_signal_assignment

concurrent_simple_signal_association ::=
  lhs_signal_association_target <=> rhs_signal_association_target ;

concurrent_simple_signal_assignment ::=
  target <= [ guarded ] [ delay_mechanism ] waveform ;

concurrent_statement ::=
    block_statement
  | process_statement
  | concurrent_procedure_call_statement
  | concurrent_assertion_statement
  | concurrent_signal_assignment_statement
  | concurrent_signal_association_statement
  | component_instantiation_statement
  | generate_statement
  | PSL_PSL_Directive

[...]

signal_association_target ::=
  signal_name

Comments

Draft

PL: Can <=> work for aggregates too?

TBP: This operator is a handy alternative for an alias and allows to manipulate aliasing in the implementation rather than the declarative part. Especially composite associations with elements of different directions are valuable. Aggregates would really be another plus that would allow to easily alias individual local signals into composites.

Minor fixes: asso(z -> c)iate, capitalization in table of delimiters

-- Thomas Preusser - 2017-01-17

Minor fix, the following line's all tangled up:

"This allows all sources, gathered of each individual signal in the association group, can be resolved by the same resolution functions, if any."

Did you mean: "This allows all sources gathered from each individual signal in the association to be resolved by the same resolution function, if any."?

Other than that this all looks good. For all the work you've done here, I'm actually astonished how little additional language it takes to add the spaceship operator into VHDL.

-- Rob Gaddi - 2017-01-19

Also, before the sentence pointed out by Rob, there's a tiny typo: "either declared in a subtype declaration, or in a signal object declaration." Do we allow conditional and selected signal assignments as given by Jim? e.g.

BusA <=> BusB when Enable;
  with BusSelect select
    BusA <=> BusB when "00", BusC when "01", BusD when "10", NULL when others;

concurrent_bidirectional_signal_association_statement ::=
  [ label : ] concurrent_simple_bidirectional_signal_association
| [ label : ] concurrent_conditional_bidirectional_signal_association
| [ label : ] concurrent_selected_bidirectional_signal_association

[Comment Notes: Just added delay_mechanism here to be consistent with ordinary concurrent signal assignments.]
concurrent_simple_bidirectional_signal_association ::=
  lhs_signal_association_target <=> rhs_signal_association_target [ [delay_mechanism] <=> rhs_signal_association_target ] ;

[Comment Notes: Add these wordings]
concurrent_conditional_bidirectional_signal_association ::=
  lhs_signal_association_target <=> [delay_mechanism] rhs_signal_association_target [ [delay_mechanism] <=> rhs_signal_association_target ] conditional_waveforms ;

concurrent_selected_bidirectional_signal_association ::=
  with expression select [ ? ]
    lhs_signal_association_target <= [ delay_mechanism ] rhs_signal_association_target [ [delay_mechanism] <=> rhs_signal_association_target ] selected_waveforms ;

-- Daniel Kho - 2017-01-19

This LCS is still a draft and not finalized.

I don't see conditional associations working in a first revisions. I would wait for a first implementation in tools and see if it works. Then we can start to think about extensions.

@all Please keep in mind, we are altering the core of the elaboration process with this LCS. Any tiny mistake could break the complete language!

-- Patrick Lehmann - 2017-01-19

Agreed to implement in small changes. I'm voting for this proposal.

-- Daniel Kho - 2017-02-03

Version 1

The way to have it really beneficial is to have conditional associations, e.g. if you want to model a transmission gate. So a when clause is required in my opinion. Do we want to model delay too? e.g. d <=> e after 1 ns when enable?

-- Jakko Verhallen - 2017-03-21

@Jakko The purpose of <=> is to have no delay in Delta cycles. So your second idea doesn't fit the intend.

It's hard enough to bring this LCS into a correct form without breaking the simulation kernel. Currently, there hasn't been much review work from other person's except for Martin. No one I asked feels safe enough to talk to me about driving and effective values or sources. I won't add more features unless people are willing to dig into the simulation cycle part of the LRM.

Why would you need to model a transmission gate without Delta cycles? And why do you need to model such a low-level element at all?

-- Patrick Lehmann - 2017-03-22

Version 2

Jakko --

I agree in principle that both conditionals and delays would be useful. Delays especially, for when I need to model trace delay on bidirectional buses.

It's also a simple idea that has so far turned out to be jawdroppingly complex to wrap one's head around a suitable implementation, let alone write formal definitions for it. I look forward to the introduction of them both in VHDL-2020.

-- Rob Gaddi - 2017-03-23

Version 3

Topic revision: r1 - 2017-07-25 - 10:33:57 - JimLewis
 
Copyright © 2008-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback