Complex RTL Record Based CPU Interface Use Case

Introduction

The concept of this use case is to arbitrarily introduce a fairly complex block and interface structure in order to try and identify requirements that have hitherto been unforeseen.

Assumptions

Additional

  • The composite mode view syntax has been expanded to specifically associate a view with its composite type or subtype.
    • record view <composite_view_identifier> of <composite_subtype_name> is
      ...
      end [ record ] view [ <composite_view_identifier> ] ;
    • array view <composite_view_identifier> of <composite_subtype_name> is
      ...
      end [ array ] view [ <composite_view_identifier> ] ;

  • Similar to the entity(architecture) syntax, the subtype name is linked to the view identifier with a bracketed syntax:
    • <composite_subtype_name> ( <composite_mode_view_identifier> )

  • The composite mode view syntax is required to support a generic functionality of the instantiated entity or component in order to provide instance identification.
  • To aid syntax parsing, a new keyword element has been added to differentiate the element view section from the generic section within a named mode view construct, e.g.:
      array view <composite_view_identifier> of <composite_subtype_name> is
         generic(
            <generic_name> : <generic_subtype_name>
         );
         element(
            <element_name> : view   <composite_subtype_view_name>;
            <element_name> : in     <element_subtype_name>;
            <element_name> : out    <element_subtype_name>
         );
      end array view <composite_view_identifier>;
  • In order to be able to link a composite mode view within a view declaration, the passing of a generic value through to the sub-view is done as an instantiation using a generic map syntax.

  • A new mode null is proposed to allow elements of a composite to be disconnected from a given instantiation. A null port may be driven or read from either side, but no information passes through a null port.

Use Case Example

A complex CPU bus interface with multiple slave entities, multiple master entities and an arbiter entity. The design is also split into hierarchical sublevel entities in order to try and identify extra support requirements for record and array based view modes. A compressed tarball with the VHDL files (both 2008 version and according to the proposal) can be found here.

CPU Bus Package

  • In order to make declarations visible across hierarchies, they are defined within a package:

   package cpu_bus_pkg
      generic(
         masters_max_jg : positive;
         slaves_max_jg  : positive;
         awidth_jg      : positive;
         dwidth_jg      : positive
      );
      is
      subtype  masters_total_jrt is natural range masters_max_jg - 1 downto 0;

      constant slaves_total_jc    : positive := slaves_max_jg     -- individual slaves
                                              + masters_max_jg    -- master's slave return
                                              + 1;                -- arbiter's slave return
      subtype  slaves_total_jrt  is natural range slaves_total_jc - 1 downto 0;

      subtype  addr_jrt          is natural range awidth_jg - 1 downto 0;
      subtype  data_jrt          is natural range dwidth_jg - 1 downto 0;

      subtype  master_ctrl_vst   is std_logic_vector(masters_total_jrt);
      subtype  slave_ctrl_vst    is std_logic_vector(slaves_total_jrt);

      subtype  addr_vst          is std_logic_vector(addr_jrt);
      subtype  data_vst          is std_logic_vector(data_jrt);

  • Having defined the subtypes relating to the package generic data, now define the various record types to be used.
  • The concept is to have a record data structure for each of the master, slave and arbiter interfaces and then incorporate these records hierarchically into a higher level CPU bus record structure.

Array and Record Structures

  • The master record defines all signals driven from the current master.
  • There is an array (vector) of slave enables :

      type master_r is                      -- Master record
         record
            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
         end record master_r;

  • The slave composite is an array of slave records. Each slave drives back its own set of signals to the current master.

      type slave_r is                        -- Slave record
         record
            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
         end record slave_r;

      type slave_a is
         array(slaves_total_jrt) of slave_r; -- Array of slave return records

  • The arbiter takes inputs from each master and allocates the bus to one master.
  • It then multiplexes this master record onto the main master record.
  • The arbiter composite is an array of records containing each master's record along with its bus grant/request signals.

      type arbiter_r is                      -- Arbiter record and array
         record
            master_rl   : master_r;          -- Master record to the arbiter
            bus_req_l   : std_logic;         -- Bus request from master
            bus_grnt_l  : std_logic;         -- Bus grants to master
         end record arbiter_r;

      type arbiter_a is
         arraymasters_total_jrt) of arbiter_r; -- Array of arbiter records

  • The main CPU bus record incorporates the arbiter array element, the master record element and the slave array element composites.

  • The arbiter array routes the various masters' outputs to the arbiter instance.
  • The arbiter grants the bus to the selected master and drives its outputs onto the CPU bus record's master record element.

  • The master record drives the control elements to each slave instance - address & data, write enable and an array of slave enables.

  • The slave array routes slave instance return elements to the selected master - return data, acknowledge and error controls

      type cpu_bus_r is                     -- Bus interface record
         record
            arbiter_al : arbiter_a;           -- Arbiter array of arbiter master control records
            master_rl  : master_r;            -- Master record to slaves
            slave_al   : slave_a;             -- Array of slave records to master
         end record cpu_bus_r;

Array and Record Mode Views

  • Define the mode views on the CPU Bus for each slave, master and the arbiter.

CPU Bus - Slave Mode View

  • Define an array and a record mode view for slave instances.

  • The array view needs a generic aspect that will be selected via a generic on the instantiation of the slave entity.
  • This generic controls which slave record element of the array is driven back to the master.
  • All other array elements instead of being left dangling/unconnected, are terminated using the new null mode.
  • The integer generic is instance related.

  • In order to achieve the propagation of generics through the mode view hierarchy, we need to be able to map the generic from the CPU bus record view declaration down to the slave array view declaration.
  • The hierarchical views can be seen as an instantiation of a declaration within another declaration and therefore use a generic map syntax to pass through generic values???

  • The null mode can be thought of using the analogy of an instance & component compared to a socket & chip on a PCB.
    A null port mode is equivalent to cutting the pin from the chip.
    Once inserted in the socket, the PCB still sees the node but it is not driven, allowing another instance to drive this element of the interface.
    Internally, the chip may drive the pin, but it is not passed through to the socket.
    Reading the port results in a default element type ('U' in Std_logic) as nothing can pass in either direction across a null mode port.

      array view s_slave_avw of slave_a is
         generic(
            slave_id_jg : slaves_total_jrt
         );
         element(
            slave_id_jg : buffer slave_r;
            others      : null   slave_r
         );
      end array view s_slave_avw;

  • Define top level slave record mode view for the CPU bus record.

      record view slave_rvw of cpu_bus_r is
         generic(
            slave_id_jg : slaves_total_jrt
         );
         element(
            arbiter_al : null   arbiter_a;
            master_rl  : in     master_r;
            slave_al   : view   slave_a(
                                   s_slave_avw(
                                      generic map(
                                         slave_id_jg => slave_id_jg
         )                      )  )  );
      end record view slave_rvw;

  • To be able to distinquish the generic section of the record view from the element mode views, add a new element keyword to encapsulate these as a new syntactical section.
  • The 'slave_avw' array view then has a generic map section to pass the 'slave_id_jg' integer generic through to this level.

CPU Bus - Master Mode View

  • Declare all mode views to define an interface for master instances.

  • Define master record mode view for the arbiter record.
  • The master record and bus request control are driven out to the arbiter.
  • The bus grant control is received back from the arbiter.

      record view m_arbiter_rvw of arbiter_r is
         element(
            master_rl  : buffer master_r;
            bus_req_l  : buffer std_logic;
            bus_grnt_l : in     std_logic
         );
      end record view m_arbiter_rvw;

  • Define master array mode view for the arbiter array.
  • The array element is selected by the intsance's master generic integer value.
  • All other array elements are connect as null modes.

      array view m_arbiter_avw of arbiter_a is
         generic(
            master_id_jg : positive
         );
         element(
            master_id_jg : view   arbiter_r(m_arbiter_rvw) ;
            others       : null   arbiter_r
         );
      end array view m_arbiter_rvw;

  • Define master array mode view for the slave array.
  • The array element is selected by the intsance's slave generic integer value and is driven out to the slected master (i.e. when this instance is not selected as master and is therefore acting as a slave instance).
  • All other array elements are connect as in modes (i.e. slave inputs when this instance is granted access as a master).

      array view m_slave_avw of slave_a is
         generic(
            slave_id_jg : slaves_total_jrt
         );
         element(
            slave_id_jg : buffer slave_r;
            others      : in     slave_r
         );
      end array view m_slave_rvw;

  • Define top level master record mode view for the CPU bus record.

      record view master_rvw of cpu_bus_r is
         generic(
            slave_id_jg  : slaves_total_jrt;
            master_id_jg : masters_total_jrt
         );
         element(
            arbiter_al : view   arbiter_r(
                                   m_arbiter_avw(
                                      generic map(
                                         master_id_jg => master_id_jg
                                )  )  );
            master_rl  : in     master_r;
            slave_al   : view   slave_a(
                                   m_slave_avw(
                                      generic map(
                                         slave_id_jg => slave_id_jg
         )                      )  )  );
      end record view master_rvw;

CPU Bus - Arbiter Mode View

  • Declare all mode views to define an interface for the arbiter instance.

  • Declare the individual record view from each master to the arbiter.
  • This arbiter record view includes a master record input element, a bus request input element and a return bus grant output element.

      record view a_arbiter_rvw of arbiter_r is
         element(
            master_rl  : in     master_r;
            bus_req_l  : in     std_logic;
            bus_grnt_l : buffer std_logic
         );
      end record view a_arbiter_rvw;

  • Define the array view of these arbiter records from each master.

      array view a_arbiter_avw of arbiter_a is
         element(
            others    : view    arbiter_r(a_arbiter_rvw)
         );
      end array view a_arbiter_rvw;

  • Define top level arbiter record mode view for the CPU bus record.

  • The arbiter array view interfaces to each master instance.
  • The master record element drives the master record out to all slave interfaces.
  • The slave array view acts identically to any other slave interface (in this case providing access to the arbiter instance).

      record view arbiter_rvw of cpu_bus_r is
         generic(
            slave_id_jg  : slaves_total_jrt
         );
         element(
            arbiter_al  : view   arbiter_r(a_arbiter_rvw);
            master_rl   : buffer master_r;
            slave_al    : view   slave_a(
                                    s_slave_avw(
                                       generic map(
                                          slave_id_jg => slave_id_jg
         )                       )  )  );
      end record view arbiter_grnt_rvw;

Master, slave and arbiter entities

  • Instantiate the interface package based on the top level hierarchy as detailed at the beginning of this document - 2 masters, 8 slaves and a single arbiter.

   package cpu_bus_2m8s_pkg is new cpu_bus_pkg
      generic map(
         masters_max_jg => 2,
         slaves_max_jg  => 8,
         awidth_jg      => 12,
         dwidth_jg      => 16
      );

Generic slave entity

  • Use the new instantiated package and declare a generic slave entity.

     use work.cpu_bus_2m8s_pkg.all
     entity slave_ent is
       generic (
         slave_id_jg : slaves_total_jrt
       );
       port(
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         cpu_bus_rif : view   slave_r(
                                 slave_rvw(
                                    generic map(
                                       slave_id_jg => slave_id_jg
         )                       )  )  );
     end entity slave_ent;

     architecture rtl_arch of slave_ent is
         signal addr_vs     : cpu_bus_2m8s_pkg.addr_vst;
         signal data_in_vs  : cpu_bus_2m8s_pkg.data_vst;
         signal we_s        : std_logic;
         signal en_s        : std_logic;

         signal data_out_vs : cpu_bus_2m8s_pkg.data_vst;
         signal ack_s       : std_logic;
         signal err_s       : std_logic;
   begin

  • Compose/decompose the interface record:
    • Receive the master data with write enable and slave enable signals from the arbiter.
    • Return the acknowledge and error status signals with the slave return data to the selected master.

      addr_vs    <= cpu_bus_rif.master_rl.addr_vl;
      data_in_vs <= cpu_bus_rif.master_rl.data_vl;
      we_s       <= cpu_bus_rif.master_rl.we_l;
      en_s       <= cpu_bus_rif.master_rl.en_vl(slave_id_jg);

      cpu_bus_rif.slave_al(slave_id_jg).data_vl <= data_out_vs;
      cpu_bus_rif.slave_al(slave_id_jg).ack_l   <= ack_s;
      cpu_bus_rif.slave_al(slave_id_jg).err_l   <= err_s;

      ...

     end architecture rtl_arch;

Generic master entity

  • Use the new instantiated package and declare a generic master entity.

     use work.cpu_bus_2m8s_pkg.all
     entity master_ent is
       generic (
         slave_id_jg  : slaves_total_jrt;
         master_id_jg : masters_total_jrt
       );
       port (
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         cpu_bus_rif : view   master_r(
                                 master_rvw(
                                    generic map(
                                       slave_id_jg  => slave_id_jg,
                                       master_id_jg => master_id_jg
         )                       )  )  );
     end entity master_ent;

     architecture rtl_arch  of master_ent is
         -- Master bus and controls to/from arbiter instance
         signal addr_vs     : cpu_bus_2m8s_pkg.addr_vst;
         signal data_vs     : cpu_bus_2m8s_pkg.data_vst;
         signal we_s        : std_logic;
         signal en_vs       : cpu_bus_2m8s_pkg.slave_ctrl_vst;

         signal bus_req_s   : std_logic;
         signal bus_grnt_s  : std_logic;

         -- Selected master bus input from arbiter instance
         signal addr_in_vs  : cpu_bus_2m8s_pkg.addr_vst;
         signal data_in_vs  : cpu_bus_2m8s_pkg.data_vst;
         signal we_in_s     : std_logic;
         signal en_in_vs    : cpu_bus_2m8s_pkg.slave_ctrl_vst;

         -- Return slave bus output when not selected as master
         signal data_out_vs : cpu_bus_2m8s_pkg.data_vst;
         signal ack_s       : std_logic;
         signal err_s       : std_logic;

         -- Input slave array when selected as master
         signal s_slave_as : cpu_bus_2m8s_pkg.slave_a;
   begin

  • Compose/decompose the interface record:
    • Transmit the master data with write enable and slave enable controls out to the arbiter, alongside a bus request control also to the arbiter instance. Receive the bus grant control back from the arbiter instance.
    • Receive the master data with write enable and slave enable signals from the arbiter.
    • Return the acknowledge and error status signals with the slave return data when not the selected master.

      -- Arbiter interface
      cpu_bus_rif.arbiter_al(master_id_jg).master_rl.addr_vl <= addr_vs;
      cpu_bus_rif.arbiter_al(master_id_jg).master_rl.data_vl <= data_vs;
      cpu_bus_rif.arbiter_al(master_id_jg).master_rl.we_l    <= we_s;
      cpu_bus_rif.arbiter_al(master_id_jg).master_rl.en_vl   <= en_vs;

      cpu_bus_rif.arbiter_al(master_id_jg).bus_req_l         <= bus_req_s;

      bus_grnt_s <= cpu_bus_rif.arbiter_al(master_id_jg).bus_grnt_l;


      -- Master interface from arbiter
      addr_in_vs <= cpu_bus_rif.master_rl.addr_in_vl;
      data_in_vs <= cpu_bus_rif.master_rl.data_in_vl;
      we_in_s    <= cpu_bus_rif.master_rl.we_in_l;
      en_in_s    <= cpu_bus_rif.master_rl.en_in_vl(slave_id_jg);


      -- Slave interface to other selected master 
      cpu_bus_rif.slave_al(slave_id_jg).data_vl <= data_out_vs;
      cpu_bus_rif.slave_al(slave_id_jg).ack_l   <= ack_out_s;
      cpu_bus_rif.slave_al(slave_id_jg).err_l   <= err_out_s;

      -- Slave interface from all slaves when selected as master
      s_slave_as <= cpu_bus_rif.slave_al;

      ...

     end architecture rtl_arch;

Arbiter entity

  • Use the new instantiated package and declare the arbiter entity.

     use work.cpu_bus_2m8s_pkg.all
     entity arbiter_ent is
       generic (
         slave_id_jg  : slaves_total_jrt
       );
       port (
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         cpu_bus_rif : view   arbiter_r(
                                 arbiter_rvw(
                                    generic map(
                                       slave_id_jg => slave_id_jg
         )                       )  )  );
     end entity arbiter_ent;

     architecture rtl_arch  of arbiter_ent is
         -- Master bus and controls to/from arbiter instance
         signal arbiter_as  : cpu_bus_2m8s_pkg.arbiter_a;
         signal bus_req_vs  : std_logic_vector(masters_total_jrt);
         signal bus_grnt_vs : std_logic_vector(masters_total_jrt);

         -- Selected master bus input from arbiter array
         signal addr_in_vs  : cpu_bus_2m8s_pkg.addr_vst;
         signal data_in_vs  : cpu_bus_2m8s_pkg.data_vst;
         signal we_in_s     : std_logic;
         signal en_in_vs    : cpu_bus_2m8s_pkg.slave_ctrl_vst;

         -- Return slave bus output when not selected as master
         signal data_out_vs : cpu_bus_2m8s_pkg.data_vst;
         signal ack_s       : std_logic;
         signal err_s       : std_logic;
   begin

  • Compose/decompose the interface record:
    • Receive each master's data, write enable and slave enable signals with its bus request signal.
    • Send the bus grant back to the selected master instance.
    • Transmit the master data with write enable and slave enable signals from the arbiter via the CPU Bus master record element.
    • Return slave data along with acknowledge and error status signals when accessed by the selected master.

      -- Arbiter interface
      arbiter_as <= cpu_bus_rif.arbiter_al

      -- Generate bus request vector and return bus grant vector
      for i_jv in masters_total_jrt loop
         bus_req_vs(i_jv - 1) <= cpu_bus_rif.arbiter_al(i_jv - 1).bus_grnt_l;

         if (i_jv - 1 = m_select_jg - 1) then
            cpu_bus_rif.arbiter_al(i_jv - 1).bus_grnt_l <= '1';
         else
            cpu_bus_rif.arbiter_al(i_jv - 1).bus_grnt_l <= '0';
         end if;
      end loop;

      -- Selected master bus for arbiter slave accesses
      addr_in_vs <= arbiter_as(m_select_jg - 1).master_rl.addr_vl;
      data_in_vs <= arbiter_as(m_select_jg - 1).master_rl.data_vl;
      we_in_s    <= arbiter_as(m_select_jg - 1).master_rl.we_l;
      en_in_vs   <= arbiter_as(m_select_jg - 1).master_rl.en_vl;


      -- Selected master interface from arbiter to slaves on CPU bus interface
      cpu_bus_rif.master_rl <= arbiter_as(m_select_jg - 1).master_rl;


      -- Arbiter slave access to selected master 
      cpu_bus_rif.slave_al(slave_id_jg).data_vl <= data_out_vs;
      cpu_bus_rif.slave_al(slave_id_jg).ack_l   <= ack_out_s;
      cpu_bus_rif.slave_al(slave_id_jg).err_l   <= err_out_s;

      ...

     end architecture rtl_arch;

Alternative mode view declared within an entity declaration

The bracketed syntax:

  • <composite_subtype_name> ( <composite_mode_view_identifier> )

is still maintained but without a composite mode view identifier. Instead the syntax starts with the new element keyword.

The generic section is not required here (should it be allowed/disallowed?) because of the scope of the instantiation generic making it visible throughout the whole of the entity declaration section.

Alternative slave entity declaration

   use work.cpu_bus_2m8s_pkg.all
   entity slave_ent is
      generic(
         slave_id_jg : slaves_total_jrt
      );
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : null arbiter_a;
                                    master_rl  : in   master_r;
                                    slave_al   : view slave_a(
                                                         element(
                                                            slave_id_jg  : buffer slave_r;
                                                            others    : null   slave_r
      )                       )  )                    )  );
   end entity slave_ent;

Alternative master entity declaration

   use work.cpu_bus_2m8s_pkg.all
   entity master_ent is
      generic(
         slave_id_jg  : slaves_total_jrt;
         master_id_jg : masters_total_jrt
      );
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : view arbiter_a(
                                                         element(
                                                            master_id_jg : view   arbiter_r;
                                                               element(
                                                                  master_rl   : buffer master_r;
                                                                  bus_req_l   : buffer std_logic;
                                                                  bus_grnt_l  : in     std_logic
                                                               );
                                                            others    : null   arbiter_r
                                                         );
                                    master_rl  : in   master_r;
                                    slave_al   : view slave_a(
                                                         element(
                                                            slave_id_jg  : buffer slave_r;
                                                            others    : in     slave_r
      )                       )  )                    )  );
   end entity master_ent;

Alternative arbiter entity declaration

   use work.cpu_bus_2m8s_pkg.all
   entity arbiter_ent is
      generic(
         slave_id_jg : slaves_total_jrt
      );
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : view arbiter_a(
                                                         element(
                                                            others : view   arbiter_r;
                                                               element(
                                                                  master_rl   : in     master_r;
                                                                  bus_req_l   : in     std_logic;
                                                                  bus_grnt_l  : buffer std_logic
                                                         )     );
                                    master_rl  : buffer master_r;
                                    slave_al   : view   slave_a(
                                                           element(
                                                              slave_id_jg  : buffer slave_r;
                                                              others       : null   slave_r
      )                       )  )                      )  );
   end entity arbiter_ent;

Top Level Hierarchy Instantiations

  • Instantiate the three second level hierarchies:

   use work.cpu_bus_2m8s_pkg.all
   entity CPU_Bus_top_ent
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic
      );
   end entity CPU_Bus_top_ent;

  • Define the test bench architecture and declare the necessary signals:

   architecture rtl_arch of CPU_Bus_top_ent is
      signal rst_s      : std_logic;
      signal clk_s      : std_logic;
      signal cpu_bus_rs : cpu_bus_2m8s_pkg.cpu_bus_r;

  • Instantiate the top level instances

   begin
      Sonly_inst : entity Sonly_ent
         port map(
            rst_i       => rst_s,
            clk_i       => clk_s,
            cpu_bus_rif => cpu_bus_rs
         );

      MplusS_inst : entity MplusS_ent
         port map(
            rst_i       => rst_s,
            clk_i       => clk_s,
            cpu_bus_rif => cpu_bus_rs
         );

      AMandS_inst : entity AMandS_ent
         port map(
            rst_i       => rst_s,
            clk_i       => clk_s,
            cpu_bus_rif => cpu_bus_rs
         );

      slave_inst2 : entity slave_ent
         generic map(
            slave_id_jg => 1
         )
         port map(
            rst_i       => rst_s,
            clk_i       => clk_s,
            cpu_bus_rif => cpu_bus_rs
         );

      slave_inst7 : entity slave_ent
         generic map(
            slave_id_jg => 6
         )
         port map(
            rst_i       => rst_s,
            clk_i       => clk_s,
            cpu_bus_rif => cpu_bus_rs
         );

      ...

     end architecture rtl_arch;

  • The second hierarchy level entities are better handled in terms of mode views within the entity declaration. Unlike the multiple master, and slave generic instances, there is only a single instance of each of these.

Slave only Hierarchy Level Entity

  • Declare the mode view within the entity:

   use work.cpu_bus_2m8s_pkg.all
   entity Sonly_ent is
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : null arbiter_a;
                                    master_rl  : in   master_r;
                                    slave_al   : view slave_a(
                                                         element(
                                                            0      : buffer slave_r;
                                                            5      : buffer slave_r;
                                                            others : null   slave_r
      )                       )  )                    )  );
   end entity Sonly_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of Sonly_ent is

   begin
      slave_inst1 : entity slave_ent
         generic map(
            slave_id_jg => 0
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      slave_inst6 : entity slave_ent
         generic map(
            slave_id_jg => 5
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );
     end architecture rtl_arch;

Master plus Slave Hierarchy Level Entity

  • Declare the mode view within the entity:

   use work.cpu_bus_2m8s_pkg.all
   entity MplusS_ent is
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : view arbiter_a(
                                                         element(
                                                            0      : view   arbiter_r;
                                                               element(
                                                                  master_rl   : buffer master_r;
                                                                  bus_req_l   : buffer std_logic;
                                                                  bus_grnt_l  : in     std_logic
                                                               );
                                                            others : null   arbiter_r
                                                         );
                                    master_rl  : in   master_r;
                                    slave_al   : view slave_a(
                                                         element(
                                                            2      : buffer slave_r;
                                                            4      : buffer slave_r;
                                                            8      : buffer slave_r;
                                                            others : in     slave_r
      )                       )  )                    )  );
   end entity MplusS_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of MplusS_ent is

   begin
      master_inst1 : entity master_ent
         generic map(
            slave_id_jg  => 8,
            master_id_jg => 0
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      slave_inst3 : entity slave_ent
         generic map(
            slave_id_jg => 2
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      slave_inst5 : entity slave_ent
         generic map(
            slave_id_jg => 4
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );
     end architecture rtl_arch;

Arbiter, Master and Slave Hierarchy Level Entity

  • Declare the mode view within the entity:

   use work.cpu_bus_2m8s_pkg.all
   entity AMandS_ent is
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : view arbiter_a(
                                                         element(
                                                            0 : view   arbiter_r;
                                                               element(
                                                                  master_rl   : in     master_r;
                                                                  bus_req_l   : in     std_logic;
                                                                  bus_grnt_l  : buffer std_logic
                                                            1 : null   arbiter_r
                                                         )     );
                                    master_rl  : buffer master_r;
                                    slave_al   : view   slave_a(
                                                           element(
                                                              10     : buffer slave_r;
                                                              9      : buffer slave_r;
                                                              3      : buffer slave_r;
                                                              7      : buffer slave_r;
                                                              others : in     slave_r
      )                       )  )                      )  );
   end entity AMandS_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of AMandS_ent is

   begin
      arbiter_inst : entity arbiter_ent
         generic map(
            slave_id_jg  => 10
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      master_inst2 : entity master_ent
         generic map(
            slave_id_jg  => 9,
            master_id_jg => 1
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      slave_inst4 : entity slave_ent
         generic map(
            slave_id_jg => 3
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );

      slave_inst8 : entity slave_ent
         generic map(
            slave_id_jg => 7
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            cpu_bus_rif => cpu_bus_rif
         );
     end architecture rtl_arch;

Conclusions

  • For simple RTL use, a new interface construct is not required.
    New interface named view constructs, along with their interface composite type declarations, can be grouped together using an existing package construct.

  • The generic functionality associated with the instantiation identification of an entity, requires the new composite type named mode view to be capable of supporting this at the instantiation construct level (as opposed to being handled within a generic package instantiation).

  • There might be some usefulness to be gained in providing an attribute to return a mode view for an hierarchical entity, based on the usage of the mode views within its instantiated structure (e.g. whether a driver is present on an interface type element).

  • The use of a non-named mode view (i.e. in situ declaration within the entity) provides visibility of the I/O structure at the entity/architecture source level and might be preferred by some.
    It can also provide a shorter form of mode view declaration for hierarchical level feed-through port declarations.

Appendices

Current VHDL-2008 Capability and Implementation

  • The current implementation of the VHDL language limits this design because of the lack of mode directionality within composite type elements when traversing port/parameter interface boundaries of an entity or subprogram respectively.

VHDL-2008 Slave Entity

  • The slave entity requires a master record as an input in order to drive an access and replies back with its own slave record as an output.

  • Use a VHDL-2008 version of the generic package and declare a generic slave entity.

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity slave_ent is
      generic (
         slave_id_jg : vhdl2008_cpu_bus_2m8s_pkg.slaves_total_jrt
      );
      port (
         rst_i     : in     std_logic
         clk_i     : in     std_logic;
         master_ri : in     vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_rb  : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
      );
      alias addr_vs     is master_ri.addr_vl;
      alias data_in_vs  is master_ri.data_vl;
      alias we_s        is master_ri.we_l;
      alias en_s        is en_vl(slave_id_jg);

      alias data_out_vs is slave_rb.data_vl;
      alias ack_s       is slave_rb.ack_l;
      alias err_s       is slave_rb.err_l;

   end entity slave_ent;

VHDL-2008 Master Entity

  • The master entity requires a master record as an input in order to respond to an access (when not selected as the current master) and replies back with its own slave record output.

  • When selected as the current master, it requires the array of all slave record replies as an input in order to process all slave accesses.

  • In order to gain control as master, the master record is grouped with the bus request control in an arbiter record output which is then routed to the arbiter instantiation.

  • The arbiter replies via the bus grant vector (array) input. The master's own bus grant is selected using the master_id_jg generic.

  • Use a VHDL-2008 version of the generic package and declare a generic slave entity.

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity master_ent is
      generic (
         slave_id_jg  : vhdl2008_cpu_bus_2m8s_pkg.slaves_total_jrt
         master_id_jg : vhdl2008_cpu_bus_2m8s_pkg.masters_total_jrt
      );
      port (
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         bus_grnt_vi : in     vhdl2008_cpu_bus_2m8s_pkg.master_ctrl_vst;
         arbiter_rb  : buffer vhdl2008_cpu_bus_2m8s_pkg.arbiter_r
         master_ri   : in     vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_ai    : in     vhdl2008_cpu_bus_2m8s_pkg.slave_a;
         slave_rb    : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
      );
      alias master_op_rs is arbiter_rb.master_rl;
      alias bus_req_s    is arbiter_rb.bus_req_l;

      alias bus_req_s    is bus_grnt_vi(master_id_jg);

      alias addr_vs      is master_ri.addr_vl;
      alias data_in_vs   is master_ri.data_vl;
      alias we_s         is master_ri.we_l;
      alias en_s         is master_ri.en_vl(slave_id_jg);

      alias data_out_vs  is slave_rb.data_vl;
      alias ack_s        is slave_rb.ack_l;
      alias err_s        is slave_rb.err_l;

   end entity master_ent;

VHDL-2008 Arbiter Entity

  • The arbiter entity responds to an access from its internally selected master record and replies back with its own slave record output.

  • The arbiter receives the array of all arbiter record elements (containing a master record and bus request element) as an input. These are used to process access requests and grant control to a single master.

  • The bus grant vector is output to all master instances.

  • The select master's master record is driven out to all slave instances.

  • Use a VHDL-2008 version of the generic package and declare a generic slave entity.

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity arbiter_ent is
      generic (
         slave_id_jg  : vhdl2008_cpu_bus_2m8s_pkg.slaves_total_jrt
         master_id_jg : vhdl2008_cpu_bus_2m8s_pkg.masters_total_jrt
      );
      port (
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         bus_grnt_vb : buffer vhdl2008_cpu_bus_2m8s_pkg.master_ctrl_vst;
         arbiter_ai  : in     vhdl2008_cpu_bus_2m8s_pkg.arbiter_a
         master_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_rb    : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
      );
      alias addr_vs      is master_rb.addr_vl;
      alias data_in_vs   is master_rb.data_vl;
      alias we_s         is master_rb.we_l;
      alias en_s         is master_rb.en_vl(slave_id_jg);

      alias data_out_vs  is slave_rb.data_vl;
      alias ack_s        is slave_rb.ack_l;
      alias err_s        is slave_rb.err_l;

   end entity arbiter_ent;

VHDL-2008 Slave-only Entity

  • The slave only entity is required to drive the two slave record outputs. They are composed into the slave array bus at the parent level and then routed to the currently selected master.

  • The master record is an input which drives accesses to the two slave instantiations.

  • Use a VHDL-2008 version of the generic package and declare a generic slave entity.

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity Sonly_ent is
      port(
         rst_i      : in     std_logic
         clk_i      : in     std_logic;
         master_ri  : in     vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_1_rb : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_6_rb : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
      );
   end entity Sonly_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of Sonly_ent is

   begin
      slave_inst1 : entity slave_ent
         generic map(
            slave_id_jg => 0
         )
         port map(
            rst_i     => rst_i,
            clk_i     => clk_i,
            master_ri => master_ri,
            slave_rb  => slave_1_rb
         );

      slave_inst6 : entity slave_ent
         generic map(
            slave_id_jg => 5
         )
         port map(
            rst_i     => rst_i,
            clk_i     => clk_i,
            master_ri => master_ri,
            slave_rb  => slave_6_rb
         );
     end architecture rtl_arch;

VHDL-2008 Master plus Slave Hierarchy Level Entity

  • The master plus slave entity is required to drive the three slave record outputs (two from its slaves and one from its master).
    They are composed into the slave array bus at the parent level and then routed to the currently selected master.

  • The slave array is an input to the internal master instantiation and provides access replies from all slave instantiations.

  • The arbiter record output bundles the internal master instantiation's master record and bus request control which is routed to the arbiter instance externally.

  • The returned bus grant vector input is routed internally to the master instance.

  • Declare the mode view within the entity:

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity MplusS_ent is
      port(
         rst_i        : in     std_logic
         clk_i        : in     std_logic;
         bus_grnt_vi  : in     vhdl2008_cpu_bus_2m8s_pkg.master_ctrl_vst;
         arbiter_1_rb : buffer vhdl2008_cpu_bus_2m8s_pkg.arbiter_r;
         master_ri    : in     vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_ai     : in     vhdl2008_cpu_bus_2m8s_pkg.slave_a;
         slave_3_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_5_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_9_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
   end entity MplusS_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of MplusS_ent is

   begin
      master_inst1 : entity master_ent
         generic map(
            slave_id_jg  => 8,
            master_id_jg => 0
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            bus_grnt_vi => bus_grnt_vi,
            arbiter_rb  => arbiter_1_rb,
            master_ri   => master_ri,
            slave_ai    => slave_ai,
            slave_rb    => slave_9_rb
         );

      slave_inst3 : entity slave_ent
         generic map(
            slave_id_jg => 2
         )
         port map(
            rst_i     => rst_i,
            master_ri => master_ri,
            slave_rb  => slave_3_rb
         );

      slave_inst5 : entity slave_ent
         generic map(
            slave_id_jg => 4
         )
         port map(
            rst_i     => rst_i,
            master_ri => master_ri,
            slave_rb  => slave_5_rb
         );
     end architecture rtl_arch;

VHDL-2008 Arbiter, Master and Slave Hierarchy Level Entity

  • The arbiter, master and slave entity is required to drive the four slave record outputs (two from its slaves, one from its master and one from the arbiter).
    They are composed into the slave array bus at the parent level and then routed to the currently selected master.

  • The slave array is an input to the internal master instantiation and provides access replies from all slave instantiations.

  • The master record is an output (from the internal arbiter instance) which drives accesses to the external (as well as internal) slave instantiations.

  • The arbiter record input bundles the external master instantiation's master record and bus request control which is routed to the arbiter instance internally.

  • The bus grant vector output is routed to the external master instance.

  • Declare the mode view within the entity:

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity AMandS_ent is
      port(
         rst_i        : in     std_logic;
         clk_i        : in     std_logic;
         bus_grnt_vb  : buffer vhdl2008_cpu_bus_2m8s_pkg.master_ctrl_vst;
         arbiter_1_ri : in     vhdl2008_cpu_bus_2m8s_pkg.arbiter_r;
         master_rb    : buffer vhdl2008_cpu_bus_2m8s_pkg.master_r;
         slave_ai     : in     vhdl2008_cpu_bus_2m8s_pkg.slave_a;
         slave_4_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_8_rb   : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_10_rb  : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r;
         slave_11_rb  : buffer vhdl2008_cpu_bus_2m8s_pkg.slave_r
   end entity AMandS_ent;

  • And instantiate the slave instances:

   architecture rtl_arch of AMandS_ent is

      signal arbiter_as : vhdl2008_cpu_bus_2m8s_pkg.arbiter_a;

   begin

      arbiter_as(0) <= arbiter_1_ri;

      arbiter_inst : entity arbiter_ent
         generic map(
            slave_id_jg  => 10
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            bus_grnt_vb => bus_grnt_vb,
            arbiter_ai  => arbiter_as,
            master_rb   => master_rb,
            slave_rb    => slave_11_rb
         );

      master_inst2 : entity master_ent
         generic map(
            slave_id_jg  => 9,
            master_id_jg => 1
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            bus_grnt_vi => bus_grnt_vb,
            arbiter_rb  => arbiter_as(1),
            master_ri   => master_rb,
            slave_ai    => slave_ai,
            slave_rb    => slave_10_rb
         );

      slave_inst4 : entity slave_ent
         generic map(
            slave_id_jg => 3
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            master_ri => master_rb,
            slave_rb  => slave_4_rb
         );

      slave_inst8 : entity slave_ent
         generic map(
            slave_id_jg => 7
         )
         port map(
            rst_i       => rst_i,
            clk_i       => clk_i,
            master_ri => master_rb,
            slave_rb  => slave_8_rb
         );
     end architecture rtl_arch;

VHDL-2008 Top Level Hierarchy Instantiations

  • Instantiate the three second level hierarchies and two slaves at the top level.

   use work.vhdl2008_cpu_bus_2m8s_pkg.all
   entity CPU_Bus_top_ent
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic
      );
   end entity CPU_Bus_top_ent;

  • Define the test bench architecture and declare the necessary signals:

   architecture rtl_arch of CPU_Bus_top_ent is
      signal rst_s        : std_logic;
      signal clk_s        : std_logic;
      signal bus_grnt_vs  : vhdl2008_cpu_bus_2m8s_pkg.master_ctrl_vst;
      signal arbiter_1_rs : vhdl2008_cpu_bus_2m8s_pkg.cpu_bus_r;
      signal master_rs    : vhdl2008_cpu_bus_2m8s_pkg.master_r;
      signal slave_as     : vhdl2008_cpu_bus_2m8s_pkg.slave_a;

   begin
      Sonly_inst : entity Sonly_ent
         port map(
            rst_i        => rst_s,
            clk_i        => clk_s,
            master_ri    => master_rs,
            slave_1_rb   => slave_as(0),
            slave_6_rb   => slave_as(5)
         );

      MplusS_inst : entity MplusS_ent
         port map(
            rst_i        => rst_s,
            clk_i        => clk_s,
            bus_grnt_vi  => bus_grnt_vs,
            arbiter_1_rb => arbiter_1_rs,
            master_ri    => master_rs,
            slave_ai     => slave_as,
            slave_3_rb   => slave_as(2),
            slave_5_rb   => slave_as(4),
            slave_9_rb   => slave_as(8)
         );

      AMandS_inst : entity AMandS_ent
         port map(
            rst_i        => rst_s,
            clk_i        => clk_s,
            bus_grnt_vb  => bus_grnt_vs,
            arbiter_1_r1 => arbiter_1_rs,
            master_rb    => master_rs,
            slave_ai     => slave_as,
            slave_4_rb   => slave_as(3),
            slave_8_rb   => slave_as(8),
            slave_10_rb  => slave_as(9),
            slave_11_rb  => slave_as(10)
         );

      slave_inst2 : entity slave_ent
         generic map(
            slave_id_jg => 1
         )
         port map(
            rst_i     => rst_s,
            clk_i     => clk_s,
            master_ri => master_rs,
            slave_rb  => slave_as(1)
         );

      slave_inst7 : entity slave_ent
         generic map(
            slave_id_jg => 6
         )
         port map(
            rst_i     => rst_s,
            clk_i     => clk_s,
            master_ri => master_rs,
            slave_rb  => slave_as(6)
         );

      ...

     end architecture rtl_arch;

Proposed Additional Syntax

  • This is an attempt to define the proposed syntax in BNF productions.

  • The BNF productions are for an RTL solution and define the syntax of directional mode control for elements of composite types based (initially) on an entity signal port interface.

  • This is a simplex format in that it does not include all the modifications to existing productions defining where these new productions may syntactically be used.


  • interface_signal_declaration: This is the start of the syntax changes and adds the additional signal view syntax as an option to that of the signal mode used in the definition of an interface port.

   interface_signal_declaration ::=
         [ signal ] identifier_list : [ mode ] subtype_indication [ bus ] [ := static_expression ]
         | [ signal ] identifier_list : view  composite_subtype_indication ( mode_view_clause )

  • The mode view is defined using the composite type identifier to reference a view associated with that type. The view is referenced as a mode view clause.


  • mode_view_clause: The mode view clause defines two options.

   mode_view_clause ::=
         mode_view_indentifier [ ( generic_map_aspect ) ]
         | formal_composite_element_clause

  • The first references a named mode view declaration with an option to include a generic map. This is to enable the passing of an entity based generic through to the named mode view.

   use work.cpu_bus_2m8s_pkg.all
   entity master_ent is
      generic (
         slave_id_jg  : slaves_total_jrt;
         master_id_jg : masters_total_jrt
      );
      port (
         rst_i       : in     std_logic
         clk_i       : in     std_logic;
         cpu_bus_rif : view   master_r(
                                 master_rvw(
                                    generic map(
                                       slave_id_jg  => slave_id_jg,
                                       master_id_jg => master_id_jg
         )                       )  )  );
     end entity master_ent;

  • The second object allows for an unnamed mode view to be declared in place within the entity declaration and is defined as a composite element clause.

   use work.cpu_bus_2m8s_pkg.all
   entity arbiter_ent is
      generic(
         slave_id_jg : slaves_total_jrt
      );
      port(
         rst_i       : in     std_logic;
         clk_i       : in     std_logic;
         cpu_bus_rif : view   cpu_bus_r(
                                 element(
                                    arbiter_al : view arbiter_a(
                                                         element(
                                                            others : view   arbiter_r;
                                                               element(
                                                                  master_rl   : in     master_r;
                                                                  bus_req_l   : in     std_logic;
                                                                  bus_grnt_l  : buffer std_logic
                                                         )     );
                                    master_rl  : buffer master_r;
                                    slave_al   : view   slave_a(
                                                           element(
                                                              slave_id_jg  : buffer slave_r;
                                                              others       : null   slave_r
      )                       )  )                      )  );
   end entity arbiter_ent;


  • mode_view_declaration: The mode view declaration defines a named mode view, usually within a package/package body structure. This enables it to be referenced within scope at differing hierarchical levels of a design.
    The mode view is defined as a named view of a composite type.
    It encapsulates the ability to include an optional generic clause section along with the composite element clause.

   mode_view_declaration ::=
         [ record | array ] view identifier of composite_subtype_indication is
                  [ formal_generic_clause ]
                  formal_composite_element_clause
         end [ record | array ] view [ mode_view_simple_name ] ;

  • These declarations can be recursive:

      record view slave_rvw of cpu_bus_r is
         generic(
            slave_id_jg : slaves_total_jrt
         );
         element(
            arbiter_al : null   arbiter_a;
            master_rl  : in     master_r;
            slave_al   : view   slave_a(
                                   s_slave_avw(
                                      generic map(
                                         slave_id_jg => slave_id_jg
         )                      )  )  );
      end record view slave_rvw;


  • composite_element_clause:
    composite_element_list:
    composite_element_declaration:

   composite_element_clause ::=
         element ( composite_element_list ) ;

   composite_element_declaration ::=
         identifier_list : [ mode ] subtype_indication [ bus ] [ := static_expression ]
         | identifier_list : view  composite_subtype_indication ( mode_view_clause )

   composite_element_list ::=
         composite_element_declaration { ; composite_element_declaration }

  • These productions define the mode of each element of the referenced composite type.


  • mode: The final production expands the mode kinds with the addition of the null mode.
    This provides the disconnection of the port within the entity from the parent hierarchy in which it is instantiated.
    The port appears to be connected but no information can be passed (in either direction) through it.

   mode ::= in | out | inout | buffer | linkage | null

  • Its use is intended to accommodate the termination of any unused 'dangling' elements of a complete composite type connection on a port mode view.

Additional and Modified BNF Productions

  • This is an alphabetical list of the additional and modified BNF productions.

   composite_element_clause ::=
         element ( composite_element_list ) ;

   composite_element_declaration ::=
         identifier_list : [ mode ] subtype_indication [ bus ] [ := static_expression ]
         | identifier_list : view  composite_subtype_indication ( mode_view_clause )

   composite_element_list ::=
         composite_element_declaration { ; composite_element_declaration }

   interface_signal_declaration ::=
         [ signal ] identifier_list : [ mode ] subtype_indication [ bus ] [ := static_expression ]
         | [ signal ] identifier_list : view  composite_subtype_indication ( mode_view_clause )

   mode ::= in | out | inout | buffer | linkage | null

   mode_view_clause ::=
         mode_view_indentifier [ ( generic_map_aspect ) ]
         | formal_composite_element_clause

   mode_view_declaration ::=
         [ record | array ] view identifier of composite_subtype_indication is
                  [ formal_generic_clause ]
                  formal_composite_element_clause
         end [ record | array ] view [ mode_view_simple_name ] ;

Real World Examples

In a recent WG meeting, an interest was expressed as to seeing how new directional composite objects could be used.

AMBA AHB-Lite Interface

Shown below is the standard block diagram as shown in the AMBA AHB-Lite Protocol Specification.

Example code for this block structure is MOVED TO...here.

The following diagram details the slave multiplexor function in more detail:

AHB-Lite Master Interface

The I/O structure of a master block is shown below:

AHB-Lite Slave Interface

The I/O structure of a slave block is shown below:

AHB-Lite Signal Descriptions

Global signals:    
Name Source Description
HCLK Clock source The bus clock times all bus transfers. All signal timings are related to the rising edge of HCLK.
HRESETn Reset controller The bus reset signal is active LOW and resets the system and the bus. This is the only active LOW AHB-Lite signal.
     
Master signals:    
Name Destination Description
HADDR[31:0] Slave and
decoder
The 32-bit system address bus.
HBURST[2:0] Slave The burst type indicates if the transfer is a single transfer or forms part of a burst.
Fixed length bursts of 4, 8, and 16 beats are supported. The burst can be incrementing or wrapping. Incrementing bursts of undefined length are also supported.
HMASTLOCK Slave When HIGH, this signal indicates that the current transfer is part of a locked sequence. It has the same timing as the address and control signals.
HPROT[3:0] Slave The protection control signals provide additional information about a bus access and are primarily intended for use by any module that wants to implement some level of protection.
The signals indicate if the transfer is an opcode fetch or data access, and if the transfer is a privileged mode access or user mode access. For masters with a memory management unit these signals also indicate whether the current access is cacheable or bufferable.
HSIZE[2:0] Slave Indicates the size of the transfer, that is typically byte, halfword, or word. The protocol allows for larger transfer sizes up to a maximum of 1024 bits.
| HTRANS[1:0] | Slave |>> Indicates the transfer type of the current transfer. This can be:
  • IDLE
  • BUSY
  • NONSEQUENTIAL
  • SEQUENTIAL <<|
    HWDATA[31:0] Slave The write data bus transfers data from the master to the slaves during write operations. A minimum data bus width of 32 bits is recommended. However, this can be extended to enable higher bandwidth operation.
    HWRITE Slave Indicates the transfer direction. When HIGH this signal indicates a write transfer and when LOW a read transfer. It has the same timing as the address signals, however, it must remain constant throughout a burst transfer.
         
    Slave signals:    
    Name Destination Description
    HRDATA[31:0] Multiplexor During read operations, the read data bus transfers data from the selected slave to the multiplexor. The multiplexor then transfers the data to the master.
    A minimum data bus width of 32 bits is recommended. However, this can be extended to enable higher bandwidth operation.
    HREADYOUT Multiplexor When HIGH, the HREADYOUT signal indicates that a transfer has finished on the bus. This signal can be driven LOW to extend a transfer.
    HRESP Multiplexor The transfer response, after passing through the multiplexor, provides the master with additional information on the status of a transfer.
    When LOW, the HRESP signal indicates that the transfer status is OKAY.
    When HIGH, the HRESP signal indicates that the transfer status is ERROR.
         
    Decoder signals:    
    Name Destination Description
    HSELx Slave Each AHB-Lite slave has its own slave select signal HSELx and this signal indicates that the current transfer is intended for the selected slave. When the slave is initially selected, it must also monitor the status of HREADY to ensure that the previous bus transfer has completed, before it responds to the current transfer.
    The HSELx signal is a combinatorial decode of the address bus.
         
    Multiplexor signals:    
    Name Destination Description
    HRDATA[31:0] Master Read data bus, selected by the decoder.
    HREADY Master and slave When HIGH, the HREADY signal indicates to the master and all slaves, that the previous transfer is complete.
    HRESP Master Transfer response, selected by the decoder.

    Modified AHB-Lite Interface Structure

    Single Master Interface Structure

    Below is this standard block diagram modified to provide a simpler structure at the top level by pushing the decoder and multiplexor down into the Master block. This adaption does require Slave blocks to have generic identifiers in order to be able to select their own elements within the interface composite structures.

    Example code for this modified block structure is MOVED TO...here.

    Advantages:

    • This gives a much cleaner and simpler interconnect code at the top structural level. (There may be many interfaces at the top level.)
    • Interfacing of the slaves to the bus is handled by each instance's generic ID.
    • Functional code is partitioned from the structural level down into the Master instance.
    • All component elements of the interface (including clock and reset) are now mapped through the interface boundaries with zero delta delay.
    • The Slave return functions have their own return array.
      Each Slave instance must only drive a single return array element and so the other unused elements could have their mode set to 'in'
      However, this may result in tool warning messages and user coding guidelines often require all warnings to be cleared or mitigate each in their documentation. The new null mode provides an explicit disconnect function for each unused composite element as opposed to the 'in' mode as a default.
    • Zero delta delay bus ripping should still be supported by the proposed bidirectional operator (aka the spaceship operator) and also the proposed new map subprograms.

    Multi-Master Interface Structure

    The diagram below shows a possible multi-master topology for the AMBA AHB-Lite interface:

    The important thing to note is that it still maintains the previous advantages by maintaining the decode and multiplexor function blocks inside the interface controller.

    • In the simple master/slave topology, the master instance is the interface controller.
    • In the multi-master topology, the arbiter instance takes on this role and includes the extra master multiplexor block.

    Importantly, their is no duplication in required functional logic and the top level is restricted to pure interconnectivity.

    A single bus signal means that all instances have access to all elements (clock and reset importantly) with zero delta delay.

    The top level net list can now be optimized easily by synthesis and/or, place and route tools.

    The NULL Mode

    The null mode as described already is shown diagrammatically in the slave mode view shown below:

    The diagram shows how mode views are used hierarchically and how the null mode disconnects unused items from the bus interface at the port/parameter interface boundary.

    The null mode on arrays can be thought of as the mirror image of allowing array slices to be set as open on port maps as requested in this proposal: Partially connected vectors on port map.

    Instead of disconnecting array slices externally to the entity (dangling actuals on interface map), it provides a method to explicitly disconnect array slices internally in the entity (dangling formals on interface map).

    Example of an 8 bit RAM Slave

    The block shows an 1Meg x8 RAM with parity:

    In order to accommodate the parity bit(s), we need to expand the AHB data bus from 32 bits to 36 bits.

    Connecting this using views starts to look complex but is built hierarchically and is well structured. First a diagram of the RAM inputs mode view:

    Secondly is the mode view structure of the outputs:

    -- Brent Hayhoe - 2016-09-09

    Comments

I Attachment Action Size Date Who Comment
PNGpng UC_BAH_AMBA_AHBLite.png manage 8.9 K 2016-10-09 - 14:50 BrentHahoe AMBA AHB-Lite Block Diagram
PNGpng UC_BAH_AMBA_AHBLiteRAMslaveModeViewIP.png manage 23.5 K 2016-10-12 - 18:39 BrentHahoe AMBA AHD-Lite Slave Mode View Inputs
PNGpng UC_BAH_AMBA_AHBLiteRAMslaveModeViewOP.png manage 18.7 K 2016-10-12 - 18:40 BrentHahoe AMBA AHD-Lite Slave Mode View Outputs
PNGpng UC_BAH_AMBA_AHBLite_Master.png manage 7.7 K 2016-09-08 - 11:02 BrentHahoe AMBA AHD-Lite Master Interface
PNGpng UC_BAH_AMBA_AHBLite_Modified.png manage 10.5 K 2016-10-09 - 14:52 BrentHahoe AMBA AHB-Lite Modified Block Diagram
PNGpng UC_BAH_AMBA_AHBLite_MultiMaster.png manage 14.4 K 2016-10-09 - 14:56 BrentHahoe AMBA AHB-Lite Multi-master Modified Block Diagram
PNGpng UC_BAH_AMBA_AHBLite_Multiplexor.png manage 9.9 K 2016-10-09 - 14:53 BrentHahoe AMBA AHB-Lite Multiplexor Diagram
PNGpng UC_BAH_AMBA_AHBLite_RAM1Mx8p.png manage 9.8 K 2016-10-12 - 14:12 BrentHahoe AMBA AHD-Lite Slave 1Mx8 plus parity RAM block
PNGpng UC_BAH_AMBA_AHBLite_Slave.png manage 8.4 K 2016-09-08 - 12:18 BrentHahoe AMBA AHD-Lite Slave Interface
PNGpng UC_BAH_AMBA_AHBLite_SlaveModeView.png manage 25.5 K 2016-10-12 - 17:29 BrentHahoe AMBA AHD-Lite Slave Mode View
PNGpng UC_BAH_CPUAMandSEntity.png manage 126.3 K 2015-09-09 - 19:12 BrentHahoe RTL CPU bus arbiter, master and slave hierarchy entity.
PNGpng UC_BAH_CPUArbiterArrayAndRecord.png manage 40.6 K 2015-08-17 - 17:57 BrentHahoe RTL CPU bus arbiter array and record structure.
PNGpng UC_BAH_CPUArbiterEntity.png manage 78.5 K 2015-09-09 - 19:13 BrentHahoe RTL CPU bus arbiter entity.
PNGpng UC_BAH_CPUBusArbiterModeView.png manage 79.7 K 2015-09-09 - 19:13 BrentHahoe RTL CPU bus arbiter mode view.
PNGpng UC_BAH_CPUBusMasterModeView.png manage 88.1 K 2015-09-09 - 19:14 BrentHahoe RTL CPU bus master mode view.
PNGpng UC_BAH_CPUBusRAMslaveModeViewIP.png manage 20.9 K 2016-10-12 - 14:55 BrentHahoe AMBA AHD-Lite Slave 1Mx8 plus parity RAM IP Mode View
PNGpng UC_BAH_CPUBusRecord.png manage 146.7 K 2015-08-17 - 17:56 BrentHahoe RTL CPU bus top record structure.
PNGpng UC_BAH_CPUBusSlaveModeView.png manage 62.2 K 2015-09-09 - 19:14 BrentHahoe RTL CPU bus slave mode view.
PNGpng UC_BAH_CPUInterfaceTop.png manage 46.3 K 2015-10-01 - 18:22 BrentHahoe RTL CPU bus interface top entity hierarchy structure.
PNGpng UC_BAH_CPUMasterEntity.png manage 90.0 K 2015-09-09 - 19:15 BrentHahoe RTL CPU bus master entity.
PNGpng UC_BAH_CPUMasterRecord.png manage 30.3 K 2015-08-17 - 17:55 BrentHahoe RTL CPU bus master record structure.
PNGpng UC_BAH_CPUMplusSEntity.png manage 123.4 K 2015-09-09 - 19:16 BrentHahoe RTL CPU bus master plus slave hierarchy entity.
PNGpng UC_BAH_CPUSlaveArrayAndRecord.png manage 43.7 K 2015-08-17 - 17:54 BrentHahoe RTL CPU bus slave record and array structure.
PNGpng UC_BAH_CPUSlaveEntity.png manage 114.3 K 2015-09-09 - 19:21 BrentHahoe RTL CPU bus slave entity.
PNGpng UC_BAH_CPUSonlyEntity.png manage 88.7 K 2015-09-09 - 19:17 BrentHahoe RTL CPU bus slave only hierarchy entity.
PNGpng UC_BAH_VHDL2008CPUAMandSEntity.png manage 60.3 K 2015-09-09 - 18:24 BrentHahoe Current VHDL2008 RTL CPU bus arbiter, master and slave hierarchy entity.
PNGpng UC_BAH_VHDL2008CPUArbiterEntity.png manage 70.3 K 2015-09-08 - 13:34 BrentHahoe Current VHDL2008 RTL CPU bus arbiter entity.
PNGpng UC_BAH_VHDL2008CPUInterfaceTop.png manage 82.5 K 2015-09-07 - 17:39 BrentHahoe Current VHDL2008 RTL CPU bus interface top entity hierarchy structure.
PNGpng UC_BAH_VHDL2008CPUMasterEntity.png manage 127.3 K 2015-09-09 - 13:11 BrentHahoe Current VHDL2008 RTL CPU bus master entity.
PNGpng UC_BAH_VHDL2008CPUMplusSEntity.png manage 55.1 K 2015-09-09 - 09:35 BrentHahoe Current VHDL2008 RTL CPU bus master plus slave hierarchy entity.
PNGpng UC_BAH_VHDL2008CPUSlaveEntity.png manage 44.0 K 2015-09-08 - 11:49 BrentHahoe Current VHDL2008 RTL CPU bus slave entity.
PNGpng UC_BAH_VHDL2008CPUSonlyEntity.png manage 35.7 K 2015-09-08 - 19:07 BrentHahoe Current VHDL2008 RTL CPU bus slave only hierarchy entity.
Topic revision: r63 - 2016-10-13 - 14:43:33 - BrentHahoe
 
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