Why is the wired or signal type (wor) disallowed for typedefs in SystemVerilog - system-verilog

In SystemVerilog I CAN do
typedef logic [15:0] bus16;
typedef reg [15:0] reg16;
interface myif;
bus16 mybus;
wor [15:0] myotherbus;
endinterface
But I CAN'T do
typedef wor [15:0] wor16;
interface myif;
wor16 myotherbus;
endinterface
I get "unknown variable declaration type"
It seems, at least in my Synplicity version, typedefs of 'wor' is not permitted.
Is this a limitation defined in the IEEE1800 spec or is it perhaps a bug?

SystemVerilog separates the concepts of network/net types (which are like resolved signals in VHDL) and variables (unresolved) from data types. The net types wire, wand, wor, etc. have built-in resolution functions with a default data type of logic. The following net declarations are equivalent:
wor [15:0] w;
wor logic [15:0] w;
typedef logic [15:0] bus16;
wor bus16 w;
Similarly the following variable declarations are equivalent:
logic [15:0] v;
var logic [15:0] v;
typedef logic [15:0] bus16;
var bus16 v;
bus16 v;
In most places, the var keyword is implicit when declaring variables.
There is a nettype declaration that binds a data type with a user-defined resolution function. Unfortunately there no way to define a nettype with one of the built-in resolution functions, so you would have to write your own or function.

It is disallowed because System Verilog Standard does not allow using nets in typedefs. Sorry, no other explanation.
You can look at the syntax in paragraph 6.18. Follow data_type definition. It is based on system verilog vars but does not include nets (6.8).
You can define a new net type using the nettype construct, but it still does no allow you to use other net types. However, you can create them with a custom resolution behavior (check 6.6.7). It is a special syntax and does not fit for simple renaming. BTW, neither wor nor this are synthesizable.
So, your best bet is to use macros: `define wor16 wor[15:0]

Related

Is a struct packed allowed to be used in ports?

Most of the tools I use allow it but one doesn't. I've read the specs, IEEE1800-2017 I couldn't find it.
module mymod (
input logic clk,
input logic reset,
input struct packed {
logic [1:0] var0;
logic [1:0] var1;
logic [8:0] var2;
} addr,
...
I saw some examples here and there, using even typedef structures in ports.
Is it allowed by the specs? Where?
Cf. 7.2 Structures and 7.2.1 Packed structures
A port can be any data type. (section 23.2.2) There are some restrictions on whether that datatype can be represented by a variable or net signal that interact with the port direction.
But I would strongly discourage the use of an anonymous type (struct in your example) and instead declare a user defined type with a typedef in a common package and use that typedef when declaring that port. That eliminates type compatibility issues when trying to connect unpacked struct and enums.

-svinputport option in modelsim

I am using modlesim for my design and in this we are passing an option -svinputport=var, what is the use of this option? we are passing `default_nettype none before compiling each design files. Does these both are dependent? Could anyone help me with an example.
The description is as below for the option
svinputport=net|var|compat|relaxed
Select the default kind for an input port that is
declared with a type, but without the var keyword.
Select 'net' for strict LRM compliance, where the
kind always defaults to wire. Select 'var' for
non-compliant behavior, where the kind always defaults
to var. Select 'compat', where only types compatible with
net declarations default to wire. The default is 'relaxed',
where only a type that is a 4-state scalar or 4-state single
dimension vector type defaults to wire.
Question (2)
Thank you very much for the detailed explanation. I have one more doubt related to this. I am getting a warning when I run the following code:
`default_nettype none
module test(
input reg sig1,
output logic sig2);
reg [1:0] ab;
endmodule
xmvlog: *W,NODNTW (test.sv,4|14): Implicit net port (sig1) is not allowed since `default_nettype is declared as 'none'; 'wire' used instead [19.2(IEEE 2001)]. why it is referring input reg sig1 as an implicit net port, I already explicitly declared it as reg? As per the message it is changing to wire so will the statement be like "input wire reg sig1" ?
Can we declare input reg a; in systemverilog(input port with reg type) ? Is this implicitly equivalent to input wire reg a; (if I dont use `default_nettype none)
Verilog is littered with implicit defaults all over the place. When you write
module m(a);
initial $disaply(a);
endmodule
this is implicitly the same as
// direction kind type range signal
module m(inout wire logic [0:0] a);
initial $disaply(a);
endmodule
For inout and input directions, if you omit the kind the default is wire or taken from the `default_nettype setting. The none setting generates an error. However, the default kind for an output is different. As soon as you add a datatype to an output, the default kind goes to var, which is similar to non-port declarations. See this post for more details and examples.
However, very early versions of SystemVerilog/Superlog had input and inout with the same kind default as output. The -svinputport=var switch was added for a very large microprocessor developer customer whose name I cannot mention who did not want to change their code. The =net options is the behavior I mentioned above and is the way current LRM is defined.
The other two options are hybrids between the var/net options, mainly for lazy people using the default_nettype none options and don't want to see errors in their port declarations.

passing generated modports to instances of the same module

I'm pretty sure there is no way to do what I am trying, but just in case there is an interesting clever solution, I thought I'd ask around. I have a parameterized SystemVerilog interface, inside of which I am generating modports
interface some_interface #(parameter NUM_READERS=3);
logic [`kBitsPerProgramCounter-1:0] read_addr[NUM_READERS];
logic [`kBitsPerProgramCounter-1:0] write_addr;
genvar i;
generate
// generates Reader[n].Modport
for (i = 0; i < NUM_READERS; ++i) begin : Reader
modport Modport
(
output .read_addr(read_addr[i])
);
end
endgenerate
endinterface
Using this is easy if I have different module types taking different modports. However, what I wanted to try doing is to have multiple instances of the same module. I tried this by parameterizing on type
module some_block#(parameter type SOMETYPE) (
input logic CLK200MHZ,
SOMETYPE aarrgghh);
But getting it to work syntactically has been challenging. Giving SOMETYPE a default value doesn't work because Vivado complains about not allowing hierarchical types, so right off the bat I don't think this will work. When instantiating, I tried using the full modport name, the full modport name with the instantiated interface, and a few others, but nothing seems to work.
So I am curious if there is a clever way I can have multiple instantiations of some_block, each taking a different generated modport. And if not, is there some fun clever trick I can do to use the generated modports? The idea in the first place was that I have a thing that has one writer and multiple readers. I wanted to generate a modport for each reader so that it could only touch it's own read address. I guess I could always just parameterize some_block on an integer, pass some_block the whole interface, and then rely on some_block to only touch the read address corresponding to the passed in integer, but that might be error prone.
Assuming that 'generate' works, there is nothing to be concerned about modules. There is no need to pass a type parameter. The module port is just supposed to be of the type of your interface.
module top();
some_interface ifc;
for (genvar gi = 0; gi < NUM_REASDERS; gi++) begin: inst
some_block sb(ifc.Reader[gi].Modport);
end
endmodule
module some_block (some_interface ifc);
always_comb myvar = ifc.read_addr;
some_block just always references the 'read_addr' which is the modport var. You can use a generate block in the 'top' module.

Parameterized interface in systemverilog

I have a full AXI interface and a lite AXI interface as shown below:
interface axi_full ();
logic [63:0] wdata;
logic . wid;
logic wcredit;
endinterface
interface axi_lite();
logic [63:0] wdata;
logic wcredit;
endinterface
Is there a way I can use only one interface with a parameter lite something like below instead of two separate interfaces? The only difference is there is no wid in the case of AXI lite.
interface axi #(bit Lite = 1'b0) ();
...
...
endinterface
Unfortunately not. You should be able to use the axi_full and leave the wid signal unused.
There is nothing in the standard that would prevent from using generate blocks inside the interfaces. So, the following is supposed to work:
interface axi #(FULL=1)();
logic [63:0] wdata;
logic wid;
if (FULL != 0) begin: fff
logic wcredit;
end
endinterface
module top;
axi#(1) full();
axi#(0) lite();
imod fm(full);
//imod lm(lite);
endmodule
module imod(axi i);
initial begin
$display(i.wdata, i.wid, i.fff.wcredit);
end
endmodule
The problem as always is in vendor implementation. The above seems to work nicely in the cadence's nc. Uncommenting the 'lite' string will cause it to generate an error.
However, synopsys vcs, at least the one in eda playground refuses to compile it complaining about unimplemented feature of xmrs into interfaces.
Synthesis might have their own thoughts about this. So, the best way is to use separate definitions.
Also it depends on how you use them, modports can be handy. They are implemented better and the following example should work everywhere:
interface axi_if;
logic [63:0] wdata;
logic wid;
logic wcredit;
modport full (input wdata, wid, wcredit);
modport lite(input wdata, wid);
endinterface
module top;
axi_if intf();
fmod fm(intf);
lmod lm(intf);
endmodule
module fmod(axi_if.full i);
initial begin
$display(i.wdata, i.wid, i.wcredit);
end
endmodule
module lmod(axi_if.lite i);
initial begin
$display(i.wdata, i.wid); //, i.wcredit);
end
endmodule
What you are saying is not possible, but you can place wid signal inside `ifdef compile directive like following
interface axi();
logic [63:0] wdata;
`ifdef AXI_FULL
logic wid;
`endif
logic wcredit;
endinterface
define AXI_FULL when you are not using AXI-Lite
also take this thing into consideration while connecting axi interface

How to use a parameter to add or remove a signal from a system verilog interface and modport

Here is a snippet of some interface code that has some parameterized sizes to it. The fourth parameter, HAS_BURST is something I have experimented with, but it has only resulted in compilation errors.
Effectively I am looking for a way to ADD/REMOVE a signal from a interface based on parameter. Is there a way to have a generic interface with removable signals?
interface axi_if
#(parameter ID_WIDTH = 4,
ADDR_WIDTH = 40,
DATA_WIDTH = 64,
HAS_BURST = 0)
();
logic aw_ready;
logic aw_valid;
logic [ID_WIDTH-1:0] aw_bits_id;
logic [ADDR_WIDTH-1:0] aw_bits_addr;
logic [7:0] aw_bits_len;
logic [2:0] aw_bits_size;
generate
if (HAS_BURST)
logic [1:0] aw_bits_burst;
endgenerate
logic [2:0] aw_bits_size;
modport slave (
output aw_ready,
input aw_valid,
input aw_bits_id,
input aw_bits_addr,
input aw_bits_len,
generate
if (HAS_BURST)
input aw_bits_burst,
endgenerate
input aw_bits_size
);
modport master (
input aw_ready,
output aw_valid,
output aw_bits_id,
output aw_bits_addr,
output aw_bits_len,
generate
if (HAS_BURST)
output aw_bits_burst,
endgenerate
output aw_bits_size
);
endinterface
`endif
No, there isn't. Ports aren't valid in generate blocks. Parameters can be used to asjust the width of a port but not remove it entirely. You could use an `ifdef to compile it conditionally but that's an all-or-none solution. There can't be some instances with the signal and others without it.
Having the signal unconditionally present is fine in many situations and it's the easiest way to handle this problem. Tie any unused inputs to logic 0 and unused outputs can remain unconnected.
If neither of these options work there's no other way than to define two different interfaces. Doing this by hand quickly becomes unmaintainable. If there are two variations now you can be sure a third one will be needed soon, then a fourth, a fifth... Many chip design companies have SystemVerilog code generators which create customized modules for each instance.