2

is there a way to synthesize an architecture in verilog such that a deeply nested endpoint can access some top level pins (from a .ucf) without expressly routing the pins through every module of the hierarchy.

In my case i have a PCIe block with a deeply nested endpoint. AT the endpoint there have an address decoder that needs to provide some signal information from pins at the top level.

I'd rather not modify every intervening module to carry the necessary wires.

my web searches are frustrated because the terms 'net' and 'bus' already have alternative meanings in verilog.

I have tried specific hierarchical naming like (for example) top.button and top.LED but have only succeeded in getting access to readable pins, but not writeable pins, leading me to assume i'm missing something fundamental here.

UPDATE I can simulate this http://www.edaplayground.com/x/AAq

and synthesize (a similar construct) without error (Xilinx XST) but there is no output on the LED when it is run in real hardware so i'm wondering if upwards name reference is not supported for synthesis?

david binette
  • 51
  • 1
  • 7
  • My guess is that no, it's not possible for synthesis, but even if you could then I would strongly advise against going down this path. While you might just want a quick shortcut to save yourself from having to add the correct port lists to modules, in the long run this could become a maintenance and debugging headache if taken too far. When you look at a module, you really want to be able to see what signals go into that module via the port list, in order to more easily understand the design. It's a really bad idea for anything but the most small and trivial designs. – Tim Jul 06 '14 at 05:53

3 Answers3

1

Yes, this is possible and synthesisable using some tools. The only mechanism I'm aware of is to use a static variable in a function to create the "connection", calling the function once to set the value and once to get the value.

For an example of this, check out my proof-of-concept on Github

SystemVerilog proof-of-concept for using static variables inside functions to communicate between modules.

This allows connections to be made without having to add wiring through the hierarchy. Possible applications include pulling signals out to logic analyser, writing to global resources (event log, statistics, UART etc.)

This synthesises correctly in Quartus 13, I haven't tried it with other tools so YMMV.

UPDATE: Not currently supported by Xilinx Vivado, see this thread for details.

Community
  • 1
  • 1
Chiggs
  • 2,824
  • 21
  • 31
  • Very interesting! If synthesis is not a concern, one should be able to do this using class static variables too, right? – Ari Jul 07 '14 at 18:43
  • @Ari Yup, there are probably many ways to achieve the same result if you don't need to synthesise. It's also possible that some synthesis tools will correctly synthesise static class variables - see also this answer: http://stackoverflow.com/a/22711967/579887 for using static class functions to allow parameterisation of functions. Unfortunately I currently only have access to Altera/Xilinx tools so can't experiment with the synthesisable possibilities of classes. – Chiggs Jul 07 '14 at 18:53
1

Have you tried explicitly naming the complete hierarchical path of the pin you want to access?

For example, lets say your top module instance name is top, and then five level down the hierarchy you need to access top's pin x and assign it to the local variable y:

//At level 5:
assign y = top.x

Some synthesis tools support $top. In that case, you can try:

//At level 5:
assign y = $top().x

Here is a working example on edaplayground.com (I have not tried synthesis).

For more info, see "Upwards name referencing" in Section 23.8 of IEEE 1800-2012

Ari
  • 7,251
  • 11
  • 40
  • 70
  • The fragment in edaplayground is interesting but it is reading from the top level port, i'm trying to write to a net pin at the top level from the lower level. – david binette Aug 28 '14 at 22:19
  • The method is not that different. Why don't you try something like `assign top.net=xxx` at the lower level? – Ari Aug 28 '14 at 23:17
-2

If known about at the time of implementation, using SystemVerilog Interfaces Section 3.5 and 25 of IEEE 1800-2012 can solve this issue.

An interface is a named bundle of nets, so if everything in the path connects to the interface, adding an extra net to the interface means all instances of that interface get the extra wire.

Adding signals to the interface allows low level modules to be instantly connected to everything else (top level) using that bus, without any additional port work to connect once the interface is connected through the hierarchy.

Interfaces vs Structs has been discussed previously.
A Doulos Tutorial on interfaces.

For a slightly more complete answer I include the example given in 25.3.3 IEEE 1800 showing to modules connected via an interface:

// memMod and cpuMod can use any interface
module memMod (interface a, input logic clk);
  ...
endmodule

module cpuMod(interface b, input logic clk);
  ...
endmodule

interface simple_bus; // Define the interface
  logic req, gnt;
  logic [7:0] addr, data;
  logic [1:0] mode;
  logic start, rdy;
endinterface: simple_bus

module top;
  logic clk = 0;

  simple_bus sb_intf(); // Instantiate the interface
  // Reference the sb_intf instance of the simple_bus
  // interface from the generic interfaces of the
  // memMod and cpuMod modules
  memMod mem (.a(sb_intf), .clk(clk));
  cpuMod cpu (.b(sb_intf), .clk(clk));
endmodule

Using modports (Section 25.5 of IEEE 1800) you can specify master slave sections of the interface to define port directions.

As Tim has mentioned I avoid using this as it becomes very difficult to debug. I have worked on one project where interfaces were heavily used. The connections were not one to one, but propagated everywhere through the hierarchy. Imagine register writes happening over LBUS, using WiredOR bus or tristate for the readback. The tools we had at the time would not let you see which module was driving the bus. Therefore if it went X from multiple drives it was a guessing game as to what was causing it.

We were not using interfaces only for standard protocols like LBUS but new ones which were being altered on the fly, which meant modules that had not been fixed for protocol changes corrupted the bus. Using interfaces greatly sped up the implementation as extra signal were quick to integrate. The cost was almost impossible to debug as the source of issues on the interface could not be traced.

Community
  • 1
  • 1
Morgan
  • 19,934
  • 8
  • 58
  • 84
  • sounds like a problem with the tools/team rather than interfaces per se. For typical point-to-point buses without multiple drivers then interfaces should definitely be an improvement, or if tool support for interfaces is not complete then structures are a good compromise. I'm still not convinced this answers the OP though as you assume there is already interface based wiring between the modules. – Chiggs Jul 07 '14 at 10:56
  • @Chiggs, not assuming the interface exists but rather they would be willing to do the work required to make it easier in the future. Or looking for an approach to take when wanting this functionality. – Morgan Jul 07 '14 at 11:05
  • **Thanks for the comments so far..** Some clarification is in order. 1) Im using verilog, not SystemVerilog so i dont have some of those niceties 2) the 'deeply nested endpoint' I am using is part of an IP package that can be 'regenerated', which causes any modifications to be overwritten. If I add interfaces, or structures or in any way modify the IP to carry additional signals they are fragile and can be lost. – david binette Aug 28 '14 at 22:07
  • @user3637453 Thanks For the feedback, hopefully it might help someone else looking to automate there connectivity. Dealing with IP generated by others does limit what is possible, hopefully some of the other answers are more appropriate for your situation. Good luck on your quest (upvotes if you found it useful are always appreciated). – Morgan Aug 29 '14 at 07:09