[Edit of Image1]
Introduction
Hey it's a me again @drifter1!
Today we continue with the Logic Design series on SystemVerilog in order to cover Interfaces. The topic will be split into two parts!
So, without further ado, let's get straight into it!
Getting Into Interfaces
In the context of object-oriented programming (OOP), interfaces are groups of related methods mostly left unimplemented (abstract), which the "implementing" class then implements. Similarly, for logic design, interfaces group together signals and ports which are related, representing them as a single entity. That way it's possible to avoid repetition and simplify port lists in module definitions and instantiations, improving maintainability, readability etc.
Interface Definition
An interface is defined within the interface
and endinterface
keywords, as shown below.
interface [interface_name] ([port_list]);
[signal_list]
endinterface
Port and Signal Lists
The signals defined within the interface allow for communication within the interface (intra-communication), but when communication with other interfaces (inter-communication) is required then those signals should be defined in the port list.
The ports can be defined as any type, but signals within the interface should be declared as the new logic
type, that SystemVerilog provides. This type allows driving both via assign
statements and in procedural blocks (e.g. always
block), and supports 4-states: 0, 1, X, Z values.
Additional Features
Interfaces that only have such port and signal lists are the simplest form of interfaces. In addition to those, SystemVerilog's interfaces can also become closer to class templates by consisting of functions, tasks, variables, parameters and more. Interfaces can also contain initial
and always
blocks, as well as assign
statements.
And let's not forget to mention:
- Modports : used to define signal direction policies
- Clocking Blocks : used to define testbench synchronization capabilities
which will be covered in the next sections...
Using Interfaces
Interfaces can be used in port lists or within the main body of the design or testbench.
In the port list, the name of the interface has to followed by an identifier:
module module_name (
interface_name [identifier],
...
);
// main body
endmodule
Using simple dot notation (.
) it's then possible to access the various signals and ports within the module's body.
Passing interfaces to module instantiations is also quite easy. For example, passing the interface by name is done as follows:
interface_name [identifier];
module_name [instance_id] (.[identifier]([identifier]));
Modports
The access to the signals defined within the interface can be restricted using a number of modport
lists, which specify the port directions for each signal. These are of course not required, and when not used the nets and variables declared within the interface are simply accessed like inout
ports. But, specifying the direction can allow us to have a different access restriction scheme for cases like the system, the testbench, the master and the slave in specific protocols etc. without having to specify a whole new interface for each case.
The syntax of a modport
is as follows:
modport [identifier] ([port_list]);
where the port list contains the corresponding input
, output
and inout
ports, as well as ref
ports.
Using Modports
Accessing the required modport
definition from the interface is done using dot notation:
.[modport_identifier]
Thus, it's possible to completely restrict the module, by specifying the corresponding modport when declaring the interface port:
module module_name (
interface_name.[modport_identifier] [identifier],
...
);
// main body
endmodule
or only restrict the port access when connecting to the port of the module using:
[identifier].[modport_identifier]
Generic Interface
It's possible to define a generic interface in a module's port list. Such a port basically allows any interface and any modport definition to be passed to it when instantiating it.
The syntax of such a port within a module is:
module module_name (
interface [identifier],
...
);
// main body
endmodule
RESOURCES:
References
- https://www.chipverify.com/systemverilog/systemverilog-tutorial
- https://www.asic-world.com/systemverilog/tutorial.html
Images
Block diagrams and other visualizations were made using draw.io
Previous articles of the series
Verilog
- Introduction → Basic Syntax, Data Types, Operators, Modules
- Combinational Logic → Assign Statement, Always Block, Control Blocks, Gate-Level Modeling and Primitives, User-Defined Primitives
- Combinational Logic Examples → One Circuit - Four Implementations, Encoder, Decoder, Multiplexer
- Sequential Logic → Procedural Blocks (Initial, Always), Blocking and Non-Blocking Assignments, Statement Groups
- Sequential Logic Examples → Flip Flops (DFF, TFF, JKFF, SRFF), N-bit Counter, Single-Port RAM
- Finite-State Machines → Finite-State Machine (FSM), FSM Types, State Encoding, Modeling FSMs in Verilog
- Finite-State Machine Examples → Moore FSM Example (1 and 2 always blocks), Mealy FSM Example (1, 2 and 3 always blocks)
- Testbenches and Simulation → Testbenches (DUT / UUT, Syntax, Test Cases), System Tasks, Simulation Tools
- Combinational Logic Testbench Example → Half Adder Implementation, Testbench and Simulation
- Sequential Logic Testbench Example → Sequence Detector FSM Implementation, Testbench and Simulation
- Functions and Tasks → Function and Task Syntax, Calling, Rules, Examples
- Module Parameters and Generate Block → Parameterized Module (Parameters, Instantiation and Overriding Parameters), Generate Blocks (For, If, Case)
- Compiler Directives → Summary of Verilog's Compiler Directives (Include, Macros, Timescale, Conditional Compilation, etc.)
- Switch Level Modeling → Transistors, Switch Primitives (NMOS, PMOS, CMOS, Bidirectional, Resistive), Signal Strengths
SystemVerilog
- From Verilog To SystemVerilog → Data Types, Arrays, Structures, Operators and Expressions
- Control Flow → Additional Procedural Blocks, Loops, Conditional Statements, Functions and Task Features
- Processes → Fork - Join in Verilog and SystemVerilog, Process Control (wait fork, disable fork)
- Events → Interprocess Communication, Events (Definition, Triggering, Waiting, Sequencing, Merging, as Arguments)
- Semaphores and Mailboxes → Semaphores (Creation, Methods), Mailboxes (Definition, Methods)
Final words | Next up
And this is actually it for today's post!
Next time we will continue with part 2, which will cover Clocking Blocks...
See Ya!
Keep on drifting!