Let us collect the changes required to harmonize ports and parameters and to minimize incompatibilities with EDA tools. Those changes will be breaking (as in "backwards-incompatible"), so let us make sure we get them right.
This is currently a draft and contributors are kindly asked to comment. Upon agreement, this information will be added to the Contribution Guidelines.
Preamble: The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
Parameters
Legal Types
Every parameter of a synthesizable module MUST be either:
(a) a type, or
(b) a (vector of) one of the following SystemVerilog types:
bit or logic, which MAY be signed (but are by default implicitly unsigned), or
byte, shortint, int, or longint, which MUST be followed by unsigned or signed, or
(c) a typedefed type of one of the types in (b).
In particular, structs and strings MUST NOT be used as parameter of a synthesizable module.
Rationale: Many tools do not properly implement complex types for parameters.
For non-synthesizable modules and classes, the key words MUST and MUST NOT in this section are relaxed to SHOULD and SHOULD NOT, respectively. (In particular, testbench modules MAY use time and string parameters.)
Signedness
If an integer parameter (i.e., byte, shortint, int, or longint) is not supposed to take negative values, it MUST be declared unsigned instead of signed.
Default Value
Every parameter MUST have a default value.
If possible, the default value SHOULD be a null value that is outside the legal range of the parameter (e.g., a signal width of zero). In this case, the module SHOULD contain an assertion to ensure that the parameter is set to a value other than the null value at instantiation.
Rationale: Many tools require parameters to have a default value, but in many cases a parameter that is not set at instantiation indicates an error that should be detected.
Derived Parameters
The parameter list of a module MUST NOT contain localparams. Rationale: Unsupported by some tools.
Instead, if the value of a parameter is derived from another parameter and should not be overridden at instantiation, the line above the derived parameter SHOULD be as follows:
/// Dependent parameter, DO NOT OVERRIDE!
Names
- The name of a non-
type parameter MUST be in UpperCamelCase.
Rationale: style guide.
- The name of a
type parameter MUST be in lower_snake_case and end with _t.
Rationale: style guide.
- The name of a non-
type parameter MUST NOT be prefixed with Axi.
Example: A module with a parametrizable data width has a parameter named DataWidth, not AxiDataWidth.
Rationale: Every module name starts with axi_ and prefixing parameters with Axi is redundant.
- If a
parameter only applies to one port, its name MUST start with the prefix of the port (converted to the casing dictated above and to singular if the port is an array) or with Num (see below) followed by the prefix of the port.
Example: For a crossbar, the ID width of each of its slave ports (part of an array prefixed slv_ports_) would be given by a parameter named SlvPortIdWidth, and the request type of each of its slave ports would be given by a parameter named slv_port_axi_req_t.
- Conversely, if a
parameter applies to more than one port, its name MUST NOT start with the prefix of one of the ports.
- If the name of a
type parameter does not have a port-specific prefix, it MUST be prefixed with axi_.
Rationale: Some tools do not properly scope type definitions, and adding a topic-specific prefix reduces the chance of type name collisions.
- If a
parameter defines the number of bits in a signal, its name SHOULD end with Width.
- If a
parameter defines a quantity other than bits in a signal, its name SHOULD contain Num followed by a noun in plural. No MUST NOT be used to denote a quantity parameter. (Rationale: easily mistaken for negation, e.g., "no registers").
- If a
parameter defines the maximum value of a quantity, its name SHOULD contain Max followed by a noun in plural.
- The name of every
parameter of a testbench module MUST start with Tb or tb_. The name of any parameter of a non-testbench module MUST NOT start with Tb or tb_.
Rationale: The name of each parameter of a top-level module that is to be assigned a value when the simulator is invoked must be unique among all simulated modules; see test: Prefix top-level TB parameters #152 (comment).
Examples
A crossbar with multiple slv_ports and mst_ports could have the following among its parameters:
/// Number of slave ports of the crossbar
parameter int unsigned NumSlvPorts = 0,
/// Number of master ports of the crossbar
parameter int unsigned NumMstPorts = 0,
/// AXI address width
parameter int unsigned AddrWidth = 0,
/// AXI data width
parameter int unsigned DataWidth = 0,
/// AXI ID width at the slave ports
parameter int unsigned SlvPortIdWidth = 0,
/// Maximum number of in-flight transactions at each slave port
parameter int unsigned SlvPortMaxTxns = 0,
/// Maximum number of in-flight transactions at each master port
parameter int unsigned MstPortMaxTxns = 0,
/// AXI4(+ATOPs) request struct of each slave port
parameter type slv_port_axi_req_t = logic,
/// AXI4 response struct of each slave port
parameter type slv_port_axi_rsp_t = logic,
/// AXI4(+ATOPs) request struct of each master port
parameter type mst_port_axi_req_t = logic,
/// AXI4 response struct of each master port
parameter type mst_port_axi_rsp_t = logic,
Ports
- Each input port MUST end with
_i (or _ni if it is active-low).
- Each output port MUST end with
_o (or _no if it is active-low).
- The name of each slave port MUST contain
slv_port_ (or slv_ports_ if the port is an array).
- The name of each master port MUST contain
mst_port_ (or mst_ports_ if the port is an array).
- The name of each request port MUST contain
_req directly before the input/output suffix.
- The name of each response port MUST contain
_rsp directly before the input/output suffix.
Examples
A module with a single AXI-Lite slave port could contain in its inputs and outputs:
input axi_lite_req_t slv_port_req_i,
output axi_lite_rsp_t slv_port_rsp_o,
A CDC from a src_clk_i to a dst_clk_i would contain in its inputs and outputs:
// Slave Port in Source Clock Domain
input axi_req_t src_slv_port_req_i,
output axi_rsp_t src_slv_port_rsp_o,
// Master Port in Destination Clock Domain
output axi_req_t dst_mst_port_req_o,
input axi_rsp_t dst_mst_port_rsp_i,
A crossbar with multiple slave and master ports would contain in its inputs and outputs:
// Slave Ports
input slv_port_axi_req_t [NumSlvPorts-1:0] slv_ports_req_i,
output slv_port_axi_rsp_t [NumSlvPorts-1:0] slv_ports_rsp_o,
// Master Ports
output mst_port_axi_req_t [NumMstPorts-1:0] mst_ports_req_o,
input mst_port_axi_rsp_t [NumMstPorts-1:0] mst_ports_rsp_i,
A protocol converter from AXI to AXI-Lite would contain in its inputs and outputs:
// AXI Slave Port
input slv_port_axi_req_t slv_port_req_i,
output slv_port_axi_rsp_t slv_port_rsp_o,
// AXI-Lite Master Port
output mst_port_axi_lite_req_t mst_port_req_o,
input mst_port_axi_lite_rsp_t mst_port_rsp_i,
Channel and Request/Response Types
In this section, X MUST be either axi or axi_lite in accordance with whether the type is part of full AXI or AXI-Lite.
- A channel type MUST end with
X_Y_t, where Y is one of aw, w, b, ar, or r and MUST correspond to the channel type.
- A request type MUST end with
X_req_t.
- A response type MUST end with
X_rsp_t.
Interfaces
- This repository defines four
interfaces: axi_if, axi_dv_if, axi_lite_if, and axi_lite_dv_if.
Rationale for naming: compliant with Google Verible's interface-name-style and consistent with the name of types in the style guide we follow (which does not have rules for naming interfaces).
- The
modports are named slv_port (for a slave port modport), mst_port (for a master port modport), and mon_port (for an all-input monitor modport).
Rationale: consistent with the naming of non-interface ports.
- The non-
dv interfaces MUST be synthesizable. The dv interfaces are used for design verification and MAY contain non-synthesizable code.
- All
parameters in an interface MUST obey the rules in the above Parameters section.
- The name of each slave port
interface MUST contain slv_port (or slv_ports if the interface port is an array).
- The name of each master port
interface MUST contain mst_port (or mst_ports if the interface port is an array).
- Arrays of
interfaces MUST be unpacked (i.e., dimensions after identifier). The dimensions MUST be in big-endian notation (e.g., [0:N-1]). Dimensions SHOULD be zero-based unless there are strong reasons against it. Zero-based dimensions SHOULD use the short [N] notation. There MUST NOT be a space between identifier and dimensions.
Examples
A crossbar (or rather, its _intf variant) with multiple slave and master ports would contain in its port list:
axi_if.slv_port slv_ports[NumSlvPorts],
axi_if.mst_port mst_ports[NumMstPorts],
Let us collect the changes required to harmonize ports and parameters and to minimize incompatibilities with EDA tools. Those changes will be breaking (as in "backwards-incompatible"), so let us make sure we get them right.
This is currently a draft and contributors are kindly asked to comment. Upon agreement, this information will be added to the Contribution Guidelines.
Preamble: The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
Parameters
Legal Types
Every
parameterof a synthesizablemoduleMUST be either:(a) a
type, or(b) a (vector of) one of the following SystemVerilog types:
bitorlogic, which MAY besigned(but are by default implicitlyunsigned), orbyte,shortint,int, orlongint, which MUST be followed byunsignedorsigned, or(c) a
typedefed type of one of the types in (b).In particular,
structs andstrings MUST NOT be used asparameterof a synthesizablemodule.Rationale: Many tools do not properly implement complex types for
parameters.For non-synthesizable
modules andclasses, the key words MUST and MUST NOT in this section are relaxed to SHOULD and SHOULD NOT, respectively. (In particular, testbenchmodules MAY usetimeandstringparameters.)Signedness
If an integer parameter (i.e.,
byte,shortint,int, orlongint) is not supposed to take negative values, it MUST be declaredunsignedinstead ofsigned.Default Value
Every
parameterMUST have a default value.If possible, the default value SHOULD be a null value that is outside the legal range of the parameter (e.g., a signal width of zero). In this case, the
moduleSHOULD contain an assertion to ensure that the parameter is set to a value other than the null value at instantiation.Rationale: Many tools require
parameters to have a default value, but in many cases aparameterthat is not set at instantiation indicates an error that should be detected.Derived Parameters
The parameter list of a
moduleMUST NOT containlocalparams. Rationale: Unsupported by some tools.Instead, if the value of a parameter is derived from another parameter and should not be overridden at instantiation, the line above the derived parameter SHOULD be as follows:
/// Dependent parameter, DO NOT OVERRIDE!Names
typeparameterMUST be inUpperCamelCase.Rationale: style guide.
typeparameterMUST be inlower_snake_caseand end with_t.Rationale: style guide.
typeparameterMUST NOT be prefixed withAxi.Example: A
modulewith a parametrizable data width has aparameternamedDataWidth, not.AxiDataWidthRationale: Every
modulename starts withaxi_and prefixingparameters withAxiis redundant.parameteronly applies to one port, its name MUST start with the prefix of the port (converted to the casing dictated above and to singular if the port is an array) or withNum(see below) followed by the prefix of the port.Example: For a crossbar, the ID width of each of its slave ports (part of an array prefixed
slv_ports_) would be given by aparameternamedSlvPortIdWidth, and the request type of each of its slave ports would be given by aparameternamedslv_port_axi_req_t.parameterapplies to more than one port, its name MUST NOT start with the prefix of one of the ports.typeparameterdoes not have a port-specific prefix, it MUST be prefixed withaxi_.Rationale: Some tools do not properly scope type definitions, and adding a topic-specific prefix reduces the chance of type name collisions.
parameterdefines the number of bits in a signal, its name SHOULD end withWidth.parameterdefines a quantity other than bits in a signal, its name SHOULD containNumfollowed by a noun in plural.NoMUST NOT be used to denote a quantityparameter. (Rationale: easily mistaken for negation, e.g., "no registers").parameterdefines the maximum value of a quantity, its name SHOULD containMaxfollowed by a noun in plural.parameterof a testbenchmoduleMUST start withTbortb_. The name of anyparameterof a non-testbenchmoduleMUST NOT start withTbortb_.Rationale: The name of each
parameterof a top-levelmodulethat is to be assigned a value when the simulator is invoked must be unique among all simulatedmodules; see test: Prefix top-level TB parameters #152 (comment).Examples
A crossbar with multiple
slv_portsandmst_portscould have the following among its parameters:Ports
_i(or_niif it is active-low)._o(or_noif it is active-low).slv_port_(orslv_ports_if the port is an array).mst_port_(ormst_ports_if the port is an array)._reqdirectly before the input/output suffix._rspdirectly before the input/output suffix.Examples
A module with a single AXI-Lite slave port could contain in its
inputs andoutputs:A CDC from a
src_clk_ito adst_clk_iwould contain in itsinputs andoutputs:A crossbar with multiple slave and master ports would contain in its
inputs andoutputs:A protocol converter from AXI to AXI-Lite would contain in its
inputs andoutputs:Channel and Request/Response Types
In this section,
XMUST be eitheraxioraxi_litein accordance with whether the type is part of full AXI or AXI-Lite.X_Y_t, whereYis one ofaw,w,b,ar, orrand MUST correspond to the channel type.X_req_t.X_rsp_t.Interfaces
interfaces:axi_if,axi_dv_if,axi_lite_if, andaxi_lite_dv_if.Rationale for naming: compliant with Google Verible's
interface-name-styleand consistent with the name of types in the style guide we follow (which does not have rules for naming interfaces).modports are namedslv_port(for a slave portmodport),mst_port(for a master portmodport), andmon_port(for an all-inputmonitormodport).Rationale: consistent with the naming of non-
interfaceports.dvinterfaces MUST be synthesizable. Thedvinterfaces are used for design verification and MAY contain non-synthesizable code.parameters in aninterfaceMUST obey the rules in the above Parameters section.interfaceMUST containslv_port(orslv_portsif theinterfaceport is an array).interfaceMUST containmst_port(ormst_portsif theinterfaceport is an array).interfaces MUST be unpacked (i.e., dimensions after identifier). The dimensions MUST be in big-endian notation (e.g.,[0:N-1]). Dimensions SHOULD be zero-based unless there are strong reasons against it. Zero-based dimensions SHOULD use the short[N]notation. There MUST NOT be a space between identifier and dimensions.Examples
A crossbar (or rather, its
_intfvariant) with multiple slave and master ports would contain in its port list: