"I meant to use two different types ifc1 and ifc2 as an example, both of which are possibly record types or other composite types, to illustrate that the types may be different." Sorry, I meant to say: I meant to use two different *bundles* ifc1 and ifc2 as an example, to illustrate that the *bundles* may be different. -Dan On 2 July 2015 at 22:58, Daniel Kho <daniel.kho@gmail.com> wrote: > Hi Ernst, > Thank you for taking the time to reply. I have written my comments inline, > hopefully that gives a clearer picture of what I have in mind. > > More comments are welcome, of course. > > Cheers, Daniel > > > On 29 June 2015 at 22:15, Ernst Christen <christen.1858@comcast.net> > wrote: > >> Hi Daniel, >> >> >> >> Thank you for taking a look at what I put together. I read through your >> email, and I have a number of observations, comments and questions. See >> below. I have not yet looked through the twiki page you created; I'll do >> this ASAP and will respond separately. >> >> >> >> Regards. >> >> Ernst >> >> >> >> *From:* owner-vhdl-200x@eda.org [mailto:owner-vhdl-200x@eda.org] *On >> Behalf Of *Daniel Kho >> *Sent:* Friday, June 26, 2015 4:02 PM >> *To:* vhdl-200x@eda.org >> *Subject:* Re: [vhdl-200x] Heterogeneous Interfaces in VHDL >> >> >> >> Hi Ernst, >> >> Thank you for taking your time to come up with such an excellent white >> paper. >> >> Of late, I have been working with some SystemVerilog interfaces. One >> thing I found different was that in SVI, one needs to "instantiate" the >> interface before interconnections can be made between several modules. E.g. >> (adapted from Twiki example on SVInterfaces): >> >> module top; >> >> logic clk = 0; >> >> >> >> // "instantiate" the interfaces - well these look like instances to >> me. >> >> // Assume these interfaces are different (ifc1 and ifc2). >> >> ifc1 #(.DWIDTH(16)) wide_intf1(.clk(clk), .reset(reset)); >> ifc2 #(.DWIDTH(16)) wide_intf2(.clk(clk), .reset(reset)); >> >> [EC] Indeed, ifc1 and ifc2 refer to different interface declarations, >> each of which has two formal ports named clk and reset, respectively. >> wide_intf1 and wide_intf2 are names of the corresponding interface >> instances. The port list associates the local signals clk and reset with >> the formal ports of the same name. They may now be referenced with their >> interface-based names anywhere the interface is available. >> ... >> >> // instantiate the modules. >> >> block1 u_block1(.reset(reset), .clk(clk), .ifc(wide_intf1)); >> >> block2 u_block2(.reset(reset), .clk(clk), .ifc(wide_intf2)); >> >> [EC] The example skips over the specification of the modes, which is >> possible in SV (it's at best advisory) but has to be addressed in VHDL. >> >> Also, it isn't necessary to have ports for clk and reset since these are >> also brought into the instances of block1 and block2 through the ifc port, >> but it's not wrong. >> >> >> // make the connections. >> >> assign wide_intf2.data = wide_intf1.data; >> ... >> >> endmodule >> >> I still prefer the existing VHDL way, just declare the interface instead >> of "instantiating" it. Currently, one would do the following (assuming we >> use record structures with custom-resolved members): >> >> entity top is end entity top; >> >> architecture sim of top is >> >> signal ifc1: wide_intf1; >> signal ifc2: wide_intf2; >> >> begin >> >> -- instantiate the components >> >> u_block1: entity work.block1(rtl) port map(reset=>reset, clk=>clk, >> ifc=>wide_intf1); >> u_block2: entity work.block2(rtl) port map(reset=>reset, clk=>clk, >> ifc=>wide_intf2); >> >> >> -- make the connections. >> >> wide_intf2.data <= wide_intf1.data; >> ... >> >> end architecture sim; >> >> [EC] This doesn't seem to line up. In the declarations the signal names >> are ifc1 and ifc2, but I surmise ifc1 and ifc2 should refer to the >> interface declarations and wide_intf1 and wide_intf2 to the signal names. >> That is, the declarations should probably read >> >> signal wide_intf1 : ifc1; >> >> signal wide_intf2 : ifc2; >> >> This could work for a simple interface, but the meaning here is different >> from the SV code above because clk and reset are not made part of the >> interface. The capability to include external signals in an interface was >> considered important at the last WG meeting I attended, so I believe we >> have to find a way to make such associations possible. >> >> >> >> For the component instantiation statement I surmise the modes for the ifc >> ports of block1 and block2 are available in the corresponding entity >> declarations. Also, for the concurrent signal assignment statement I assume >> that the data members of ifc1 and ifc2 have the same type. >> > > [DK] Yes, you're right. I meant to write "signal wide_intf1: ifc1" like > you did. The example makes the assignment "wide_intf2.data <= > wide_intf1.data" which implies that the signal names are wide_intf* while > the types are ifc1 and ifc2. > > I meant to use two different types ifc1 and ifc2 as an example, both of > which are possibly record types or other composite types, to illustrate > that the types may be different. However, we can still make signal > assignments for members having the same type. In our case, > "wide_intf1.data" and "wide_intf2.data" must be of the same type. > >> >> >> I feel declaring the interfaces the usual VHDL way is simpler than what >> is used in SVI. However, SVI has the concept of modports. What we usually >> do is to write custom resolution functions to ensure there are no multiple >> drivers on the interface. >> >> The modport concept is perhaps a bit too bulky IMO, as one usually needs >> to define a pair of modports for a pair of blocks to interconnect with each >> other. This makes the concept rather prone to human error, as one could >> define one of the pairs incorrectly. I still like the concept of conjugated >> ports for this purpose. >> >> I feel it necessary to define mixed modes within an interface, so the >> conjugated port concept fits nicely with interfaces having members with >> different modes (again shamelessly adapted from the Bundles Twiki): >> >> -- I prefer to maintain the syntax to be consistent with records. >> >> -- Also, a signal declaration expects a type and an optional resolution >> -- function preceding the type, e.g.: >> >> -- signal s: resolved some_type; >> >> -- so defining bundles as a type makes some sense. >> >> type b is bundle >> >> generic (type t); >> >> port ( >> signal clk, reset: in std_ulogic; >> >> -- master to slave direction. >> >> signal data: mst_to_slv t; >> >> -- both master and slave can drive at >> >> -- different times. >> >> signal serial: inout std_ulogic; >> >> >> -- slave to master direction. >> >> signal resp: slv_to_mst t; >> >> signal ack: slv_to_mst std_ulogic; >> >> signal busy: slv_to_mst std_ulogic >> ); >> >> signal s1: std_ulogic := '0'; -- Permanent objects of the bundle >> >> signal s2: std_ulogic_vector(ub downto 0) := (others => '0'); >> >> shared variable sv : my_protected_type; >> >> end bundle b; >> >> [EC] Are you suggesting to deal with the mode as something like a macro, >> to be replaced in one situation with *in*, in another with *out*? If so, >> I don't understand how a situation like the following would be handled: >> >> architecture rtl of dut is >> >> -- some declaration of an interface named ifc >> >> begin >> >> m: master port map (ifc); >> >> s: slave port map (ifc); >> >> end; >> >> Of course you and I know what the intent is, but does the compiler? >> >> >> >> There is another issue with the bundle declaration: It seems to merge the >> functionality of the SV interface declaration and the modport declaration >> into one. I believe that doing so may reduce what a user has to write in >> simple cases, but it will stand in the way of more advanced uses. I'll keep >> it in mind but will remain skeptical of this approach. >> >> >> > [DK] This is where the compiler takes care of the intricacies of making > sure there are no multiple drivers on the bus. If this can be ensured, then > there can be only one direction for every interconnecting signal. In this > case, there is no need to specify "in" or "out" modes. Just a simple > declaration that m.ifc and s.ifc are conjugated bundles would be sufficient > IMO. > > For example, say we have a signal "signal1" within the bundle for both > master and slave. > If "m.ifc.signal1" is being driven by the master "m", then the > interconnecting "s.ifc.signal1" must be at the receiving side. It will be > an error if both m and s were driving the same signal. > > This applies even to "inout" signals, as no two drivers are allowed to > drive the same signal at the same time. > > In my Twiki example, we can also specify which signals have opposite > directions from which other signals. (E.g. i_bundle.m2s.data is having > opposite direction from i_bundle.s2m.resp). Interconnecting bundles are > implicitly conjugated, and checks are made sure that the direction rules > follow the conjugated mode specification. > > Long story short. The compiler checks for > 1) Only a single driver per net at any single instance of time. Resolution > functions are implicitly attached to ensure this. > 2) Signal direction follows the custom mode specification (E.g. "mode > slv_to_mst is conjugated of mst_to_slv". > 3) It doesn't matter which interconnecting block is the driver for any one > signal, as long as rules 1) and 2) are followed. > > >> Here, mst_to_slv and slv_to_mst are conjugated modes. I was thinking in >> the lines of: >> >> package modes is >> >> mode mst_to_slv is default; -- or perhaps, just "mode mst_to_slv"? >> >> mode slv_to_mst is conjugated of mst_to_slv; >> >> end package modes; >> >> [EC] What/who is deciding what "default" means? >> > [DK] I meant to just have a simple declaration that slv_to_mst and > mst_to_slv are conjugated modes (modes having opposite directions), so we > can use them in the specification of the bundle. It doesn't matter which > block is the driver for a signal - if one is sourcing, the other must be > sinking. > > Internally, the implementation should use resolution functions which >> errors out whenever there are multiple drivers driving the same net. Also, >> in the implementation of bundles, should we require users to always use >> unresolved types for all signals? Is there a use case where multiple >> drivers are allowed in a bus interface (I mean, multiple drivers at the >> same instance of time)? >> >> For example, in the declaration: >> signal resp: slv_to_mst t; >> >> I was thinking that a custom resolution function be attached implicitly >> to each member of the bundle, e.g.: >> signal resp: resolved slv_to_mst t; >> >> where the "resolved" function is written such that multiple drivers are >> not allowed: >> >> [EC] I don't quite follow your thought here. I would argue that the >> definition of a bundle should ensure that the bundle is not treated as a >> composite type, but rather that each element of the bundle stands by >> itself. In this case the resolved type issue you are referring to is the >> same as if each element of the bundle had been part of the port list >> individually. >> > [DK] I intend to make the implementation of resolution functions implicit, > i.e. the user does not need to worry about applying their own resolution. > The reason for this I believe, is because probably all bus specifications > does not allow multiple drivers on a signal of the bus. This should be > handled implicitly by the language and the tool. > > >> [Example resolution function for std_logic]: >> >> function resolve(s: std_ulogic_vector) return std_logic is >> variable result: std_logic; >> begin >> for i in s'range loop >> if is_LH01(s(i)) then -- checks for 'L', 'H', '0', or '1'. >> assert not is_LH01(result) report "Multiple driving >> signals detected." severity error; >> >> if is_LH01(result) then >> result := 'X'; >> else result := s(i); >> end if; >> end if; >> end loop; >> return result; >> end function resolve; >> >> >> >> Let me know your thoughts. Have a great weekend ahead! >> >> >> >> Best regards, >> >> Daniel >> >> >> >> -- >> This message has been scanned for viruses and >> dangerous content by *MailScanner* <http://www.mailscanner.info/>, and >> is >> believed to be clean. >> > > -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.Received on Thu Jul 2 08:30:40 2015
This archive was generated by hypermail 2.1.8 : Thu Jul 02 2015 - 08:30:49 PDT