Thoughts on IC development, EDA, and hardware design languages.

SystemVerilog Insights Series: Using the (controversial?) .* Shortcut

Posted by: Trent McClements | Posted on: January 20th, 2015 | 1 Comments

Share on LinkedIn36Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

The last post in the series was about the .name SystemVerilog syntax and, a bit to my surprise, it generated a lot of great commentary, and even a bit of controversy on the value, origins and use of the .* syntax! So I figured we’d dive into .* and look at it’s benefits, downsides, and perferred usage in today’s post!

It’s easy to think of the .* syntax as a wildcard match of instance pinouts to their associated signals or ports within the instantiating module, or even as a wildcard-matching shorthand layered on top of the .name notation. But this isn’t really true as there are some subtle differences between the notations that you have to be aware of! First, let’s take a look at the .* usage with a quick example.

Let’s assume we have a module addr and a toplevel module, ‘top’:

module addr (input [1:0] in0 = 2'b00, input [1:0] in1 = 2'b00, output [2:0] sum);
assign sum = in0 + in1;

module top (input [1:0] in0 = 2'b00, input [1:0] in1 = 2'b00, output [2:0] sum);

With the addition of the .* notation we now have four ways to instantiate and connect the module addr within top:

1) Positional Connection: addr addr(in0, in1, sum);
2) Explicit Named Connection: addr addr(.in0(in0), .in1(in1), .sum(sum));
3) Implicit Named Connection: addr addr(.in0, .in1, .sum);
4) Implicit Wildcard Connection: addr addr(.*);

As we’re focusing on the .* syntax let’s take a look at its use in a module “top”:

module top(input [1:0] in0, input [1:0] in1, output [2:0] sum);
addr addr(.*)

Similar to the .name notation you can mix syntax. Your SystemVerilog parser will be happy if you place the .* anywhere in the port connection list:

addr addr(.in0(2'b01), .*, .sum);

Though generally the .* is placed at the end. Note that the named port connection will override the implicit .* connection. In the above example addr port in0 will be connected to 2′b01 and not to the top module port in0.

According to the SystemVerilog LRM the .name and .* notations are equivalent outside of two differences. First, the .* notation will use the default value of a port on the addr instance whereas the .name notation will not. So, the following code is valid using the .* notation with the addr port in1 getting the default value of 2′b00 (Note — This is just for illustrative purposes. I am not advocating the use of default values on ports!):

module top(input [1:0] in0, output [2:0] sum);
addr addr(.*);

The second difference has to do with package imports. The .* syntax cannot resolve anything imported via a wildcard import from a package. In the case of a wildcard import the .name notation would have to be used. For example:

package addr_pkg;
wire [1:0] in1;

module top(input [1:0] in0, output [2:0] sum);
import addr_pkg::*;
addr addr(.in1, .*);

In the above the .* syntax alone would be insufficient to match the wire in1 to the addr port in1 because the wire is imported via the wildcard. As such, the .name syntax is required for the in1 port connection. However, if the wire in1 was imported via:

import add_pkg::in1

Then the .* syntax alone would have been sufficient to match the addr’s in1 port to the wire in1.

OK, so now we have a handle on how to use the .* syntax and how it differs from the other implicit connection syntax within SystemVerilog. But what are the plusses and minuses of using .*? The big issue against .* for me is that I find it obfuscates the code. Instance pinouts help to clarify what a certain instance does and how it was intended to be used. The .name notation preserves this information. Second, as was pointed out in the comments section of a previous post, .* does not seem to be well supported by the tools and can lead to less productivity when your users try using the code. Clearly that will change as SystemVerilog support grows over time, but the .* shorthand was designed to help the code writer and some tools may not have caught up to how the code usage should be presented — think design browser and trying to access pins connected via .*.

With that said, I do see areas where .* can be very helpful. Certainly when making wrappers or doing other passthru style connectivity there can be a significant code reduction. Also, .* allows you to specify port names in a single location, the module definition, and then allow the tools to infer the connection through the design. When a change needs to be made the user only has to modify the module definition and not every instantiation of the module. This is clearly a lot cleaner and prevents typo style connection bugs, which can be annoying to track down. As Cliff Cummings pointed out in the comments on the .name blog post, the .* (and .name) syntax brings with them strong type checking for port connectivity. This is because both the name and data type have to match for a connection to be inferred. Cliff has also written a great paper on SystemVerilog connection syntax that you can find here. It’s definitely worth a read.

In the end, as with all tools in your toolbox, the .* notation has it’s place. Convenient and useful in certain circumstances with the downside perhaps not industry wide support for the syntax and a loss of code clarity. I’d love to hear if you have used the .* notation and if so what issues, vendor related or otherwise, that you’ve run into!


Share on LinkedIn36Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

Comments (1)

  1. Pingback: SystemVerilog Insights Series: Alias vs Assign - Invionics - Invionics

Leave a Comment