Re: [vhdl-200x] Records with diectional subtypes

From: Brent Hayhoe <Brent.Hayhoe@Aftonroy.com>
Date: Thu Aug 30 2012 - 15:40:07 PDT

On 30/08/2012 14:15, Peter Flake wrote:
> Hi Brent,
>
> It turns out that SystemVerilog would be better if modports could be defined
> outside interfaces (which maybe should have been called channels). It is
> too late to change this, but we should not make the same mistake in VHDL.
>
> I think that the interface construct in your example can be removed, and we
> can just use the port config. I have done this below.
>
> BTW I do not understand exactly what comp is doing.
>
> Regards,
>
> Peter Flake
  <html>
  <pre>

Hi Peter,

To answer your question backwards: the 'comp' is a suggested additional syntax
to the port modes of 'in', 'out', 'inout', 'buffer' and 'linkage' (of which the
later I've never come across any usage). It is used to define an extra mode (not
a replacement) for ports connected to composite data types (records and arrays),
which is then sub-defined in a hierarchical manner as shown in the example.

The 'interface' mechanism postulated was just a stab at providing a VHDL'ish
mechanism for user-named port modes in order to simplify the port definitions in
entities and procedures.

Now, I am not very familiar with SystemVerilog, but as far as I understand it,
its interface structure is an instantiateable object. I'm not sure I like that,
because from a hardware perspective, interfaces are just interconnects. From a
system and test bench level, it would be useful to add pseudo-object structures
in order to check/provide protocol stimuli, etc. In the real world, one doesn't
instantiate an interface, instead it is used to interconnect objects.

I'd be interested to know why the SystemVerilog guys want to define modports
outside of the interface. As I see it, they should be integral to the interface.

The other point that I was concerned about was the way (in SystemVerilog
examples as well) that we discuss options in 2 port terms, normally master/slave
and this was one of the reasons I raised the complexity to include the arbiter
port. As far as I understand SystemVerilog, it does permit multi-port interface
modport definitions.

Having just read the minutes of today's meeting and noting Jim's request for a
block diagram, I am very, very tempted to shout "NO" because it was one of my
main issues which directional records would help solve. However, I soon realized
that I must have done this example very late at night and that it was riddled
with errors! Thank you Jim.

So here is a block diagram and the corrected VHDL example below:

-------------------------------------------------------------------
   | top_level |
   | ------------- --------------------- |
   | | | ---- | ---- |
   | | ----| S6 | ----| S1 | |
   | | | ---- | ---- |
   | ------------|---- ----|------------ ----|------------ |
   | | m_plus_s | | | | a_m_and_s | | | s_only | |
   | | | | | | | | | | |
   | | ---- | | | | --- | | | ---- | |
   | | | M0 |---- | | ----| A | | | ----| S5 | | |
   | | ---- | | | | --- | | | ---- | |
   | | ---- | | | | ---- | | | ---- | |
   | | | S2 |---- | | ----| M1 | | | ----| S0 | | |
   | | ---- | | | | ---- | | ---- | |
   | | ---- | | | | ---- | ----------------- |
   | | | S4 |---- | | ----| S3 | | |
   | | ---- | | | ---- | |
   | ----------------- | | ---- | |
   | | ----| S7 | | |
   | | ---- | |
   | ----------------- |
-------------------------------------------------------------------

The HTML archive may mangle this, but the reflected Emails should be OK. If
not, change the font to 'new courier' and hopefully all will be revealed.

The first time I worked on this example, I got a bit worried about the
structural block level interfaces with multiple drivers occurring from within
different blocks. However, upon further thought I realized that what should
happen is that the 'null' port assignments should propagate through as
no-connects and therefore there should be no problems. From this it became
obvious that a slave-only block should have a slave interface (with no
generic), a block with a master but no arbiter should have a master interface
(again with no generics, master or slave) and that a block with an arbiter
has an arbiter interface.

Package first:

   package cpu_bus_pkg is
     constant master_max_jc : positive := 2;
     subtype master_cs_jrt is natural range master_max_jc-1 downto 0;

     constant slave_max_jc : positive := 8+master_max_jc+1; --+1 for arbiter
slave return
     subtype slave_cs_jrt is natural range slave_max_jc-1 downto 0;

     subtype adr_vst is std_logic_vector(15 downto 0);
     subtype dat_vst is std_logic_vector(15 downto 0);
     subtype m_en_vst is std_logic_vector(master_cs_jrt);
     subtype s_en_vst is std_logic_vector(slave_cs_jrt);

     type master_rt is --Master record
       record
         adr_vl : adr_vst; --Address
         dat_vl : dat_vst; --Data from master to slave
         we_l : std_logic; --Write enable from master
         en_vl : s_en_vst; --Slave enable from master
       end record master_rt;

     type master_at is
       array(master_cs_jrt) of master_rt; --Array of master signals to arbiter

     type arbiter_rt is --Arbiter control record
       record
         master_al : master_at; --Array of hierarchical master
records to arbiter
         bus_req_vl : m_en_vst; --Bus requests from masters
         bus_grnt_vl : m_en_vst; --Bus grants to masters
       end record arbiter_rt;

     type slave_rt is --Slave record
       record
         sdt_vl : dat_vst; --Data from slave to master
         ack_l : std_logic; --Acknowledge from slave
         err_l : std_logic; --Error from slave
       end record slave_rt;

     type slave_at is
       array(slave_cs_jrt) of slave_rt; --Array of slave return records

     type cpu_bus_rt is
       record
         arbiter_rl : arbiter_rt; --Arbiter master control record
         master_rl : master_rt; --Bus master record from arbiter
         slave_al : slave_at; --Array of hierarchical slave records
       end record cpu_bus_rt;

     interface cpu_bus_if of cpu_bus_rt is
       port config slave_cfg is (
         generic (
             slave_cs_jg : slave_cs_jrt
           );
         port (
             arbiter_rl : null;
             master_rl : in;
             slave_al(slave_cs_jg) : buffer;
             slave_al(others) : null
           );
       end port config slave_cfg;

       port config master_cfg is (
         generic (
             master_cs_jg : master_cs_jrt
           );
         port (
             arbiter_rl : comp (
                 master_al(master_cs_jrt),
                 breq_vl(master_cs_jrt) : buffer;
                 bgrnt_vl(master_cs_jrt) : in;
                 master_al(others),
                 breq_vl(others),
                 bgrnt_vl(others) : null
               );
             master_rl : in;
             slave_sl : in
           );
       end port config master_cfg;

       port config arbiter_cfg is (
         port (
             arbiter_rl : comp (
                 master_al, --Array of hierarchical master
records into arbiter
                 breq_vl : in; --Bus requests from masters
                 bgrnt_vl : buffer; --Bus grants to masters
               );
             master_rl : out; --Bus master interface output
             slave_al : in --Bus slave interface input
           );
       end port config arbiter_cfg;

       port config blk_master_cfg is (
         port (
             arbiter_rl : comp (
                 master_al,
                 breq_vl : buffer;
                 bgrnt_vl : in
               );
             master_rl : in;
             slave_sl : in
           );
       end port config blk_master_cfg;

       port config blk_slave_cfg is (
         port (
             arbiter_rl : null;
             master_rl : in;
             slave_al : buffer
           );
       end port blk_config slave_cfg;
     end interface cpu_bus_if;
   end package cpu_bus_pkg;

Next entities:-

   --Arbiter entity
   use work.cpu_bus_pkg.all
   entity arbiter is
     generic (
       slave_cs_jg : slave_cs_jrt
     );
     port (
       clk_i : in std_logic;
       a_cpu_bus_h : cpu_bus_if(arbiter_cfg) --Arbitration output port
                       cpu_bus_rt;
       s_cpu_bus_h : cpu_bus_if(slave_cfg) --Slave access port
                       cpu_bus_rt;
       rst_i : in std_logic
     );
   end entity arbiter;

   --Master entity
   use work.cpu_bus_pkg.all
   entity master is
     generic (
       master_cs_jg : master_cs_jrt;
       slave_cs_jg : slave_cs_jrt
     );
     port (
       clk_i : in std_logic;
       m_cpu_bus_h : cpu_bus_if(master_cfg) --Master I/O port
                       cpu_bus_rt(
                         master_cs_jg => master_cs_jg);
       s_cpu_bus_h : cpu_bus_if(slave_cfg) --Slave access port
                       cpu_bus_rt;
       rst_i : in std_logic
     );
   end entity master;

   --Slave entity
   use work.cpu_bus_pkg.all
   entity slave is
     generic (
       slave_cs_jg : slave_cs_jrt
     );
     port (
       clk_i : in std_logic;
       cpu_bus_h : cpu_bus_if(slave_cfg)
                       cpu_bus_rt(
                         slave_cs_jg => slave_cs_jg);
       rst_i : in std_logic
     );
   end entity slave;

Structural block with master(s) with/without slaves:-

   --master plus slaves block
   use work.cpu_bus_pkg.all
   entity m_plus_s is
     port (
       clk_i : in std_logic;
       cpu_bus_h : cpu_bus_if(blk_master_cfg)
                       cpu_bus_rt;
       rst_i : in std_logic
     );
   end entity master;

   architecture rtl of m_plus_s is
   begin
     i_master_0 : master
       generic map (
         master_cs_jg => 0,
         slave_cs_jg => 8
       )
       port map (
         clk_i => clk_i,
         m_cpu_bus_h => cpu_bus_h,
         s_cpu_bus_h => cpu_bus_h,
         rst_i => rst_i
       );
     i_slave_2 : slave
       generic map (
         slave_cs_jg => 2 --internally 'cpu_bus_h.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(2)
         rst_i => rst_i
       );
     i_slave_4 : slave
       generic map (
         slave_cs_jg => 4 --internally 'cpu_bus_h.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(4)
         rst_i => rst_i
       );
   end architecture rtl;

Structural block with arbiter with/without masters and/or slaves:-

   --slaves only block
   use work.cpu_bus_pkg.all
   entity a_m_and_s is
     port (
       clk_i : in std_logic;
       cpu_bus_h : cpu_bus_if(arbiter_cfg)
                       cpu_bus_rt;;
       rst_i : in std_logic
     );
   end entity a_m_and_s;

   architecture rtl of a_m_and_s is
   begin
     i_master : arbiter --arbiter at top level
       generic map (
         slave_cs_jg => 10
       )
       port map (
         clk_i => clk_i,
         a_cpu_bus_h => cpu_bus_h,
         s_cpu_bus_h => cpu_bus_h,
         rst_i => rst_i
       );
     i_master_1 : master --2nd master at top level
       generic map (
         master_cs_jg => 1,
         slave_cs_jg => 9
       )
       port map (
         clk_i => clk_i,
         m_cpu_bus_h => cpu_bus_h,
         s_cpu_bus_h => cpu_bus_h,
         rst_i => rst_i
       );
     i_slave_3 : slave
       generic map (
         slave_cs_jg => 3 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(3)
         rst_i => rst_i
       );
     i_slave_7 : slave
       generic map (
         slave_cs_jg => 7 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(7)
         rst_i => rst_i
       );
   end architecture rtl;

Structural block with slave(s) only:-

   --slaves only block
   use work.cpu_bus_pkg.all
   entity s_only is
     port (
       clk_i : in std_logic;
       cpu_bus_h : cpu_bus_if(blk_slave_cfg)
                       cpu_bus_rt;
       rst_i : in std_logic
     );
   end entity s_only;

   architecture rtl of s_only is
   begin
     i_slave_5 : slave
       generic map (
         slave_cs_jg => 5 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(5)
         rst_i => rst_i
       );
     i_slave_0 : slave
       generic map (
         slave_cs_jg => 0 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_h, --and is mapped to cpu_bus.en(0)
         rst_i => rst_i
       );
   end architecture rtl;

Top level structure:-

   --Top level
   use work.cpu_bus_pkg.all
   entity top_level is
     port (
       clk_i : in std_logic;
       rst_i : in std_logic
     );
   end entity top_level;

   architecture rtl of top_level is
     signal cpu_bus_rs : cpu_bus_rt;
   begin
     i_m_plus_s : m_plus_s
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_rs,
         rst_i => rst_i
       );
     i_slave_6 : slave
       generic map (
         slave_cs_jg => 6 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_rs, --and is mapped to cpu_bus.en(6)
         rst_i => rst_i
       );
     i_a_m_and_s : a_m_and_s
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_rs,
         rst_i => rst_i
       );
     i_slave_1 : slave
       generic map (
         slave_cs_jg => 1 --internally 'bus.en(id)' is the
       ) --only enable port that exists
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_rs, --and is mapped to cpu_bus.en(1)
         rst_i => rst_i
       );
     i_s_only : s_only
       port map (
         clk_i => clk_i,
         cpu_bus_h => cpu_bus_rs,
         rst_i => rst_i
       );
   end architecture rtl;

  </pre>
  </html>

-- 
Regards,
         Brent Hayhoe.
Aftonroy Limited                            Telephone: +44 (0)20-8449-1852
135 Lancaster Road,
New Barnet,                                    Mobile: +44 (0)79-6647-2574
Herts., EN4 8AJ,  U.K.                          Email: Brent.Hayhoe@Aftonroy.com
Registered Number: 1744190 England.
Registered Office:
4th Floor, Imperial House,
15 Kingsway,
London, WC2B 6UN, U.K.
-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Thu Aug 30 15:40:54 2012

This archive was generated by hypermail 2.1.8 : Thu Aug 30 2012 - 15:41:24 PDT