[Edit of Image1]
Hey it's a me again @drifter1!
Today we continue with the Logic Design series on SystemVerilog in order to continue with Interfaces. This is part 2 and so I highly suggest checking out the previous part beforehand, which can be found here.
So, without further ado, let's dive straight into it!
Interfaces can be parameterized the same way as modules do. So, the syntax is simply a
#([parameter_list]) after the interface name and before the port list, as shown below.
interface [interface_name] #([parameter_list]) ([port_list]); [signal_list] endinterface
Of course, something similar also has to be added when instantiating such interfaces. Otherwise, the default values (if defaults have been defined) will be used instead.
Tasks and Functions within Interfaces
Interfaces can also use tasks and functions. These can reside within the interface, or outside the interface but within the calling module.
When declared within the interface they are known as importing, which also means that they have to be declared as
import within modport lists, as shown below.
interface [interface_name] ([port_list]); [signal_list] task [task_name] ([port_list]); [task_statements] endtask modport [modport_identifier] ( ..., import task [task_name] ); endinterface
In other words, the module can now use the tasks and functions that have been declared within the interface using simple dot notation.
When declared outside of the interface, and so within the implementing module, they are known as exporting, which also requires adding the keyword
export within the modport list. Of course, modules can't export the same task twice!
interface [interface_name] ([port_list]); [signal_list] modport [modport_identifier] ( ..., export task [task_name] ); endinterface module [module_name] (interface [interface_name]); ... task [interface_name].[task_name] ([port_list]); [task_statements] endtask ... endmodule
Because the task or function is declared with a dot notation name, it can be called as usual from the interface object.
Clocking blocks are another great feature of SystemVerilog that can be used for timing and synchronization. Such blocks basically identify a clock signal, and then assemble signals which are synchronous to that particular clock. Of course, multiple clocking blocks can be specified, but only one per clock!
A clocking block is defined within the
endclocking keywords, and has the following syntax:
[default] clocking [identifier] @ [event]; [in_and_out_skews] endclocking
Input and Output Skews
Normally, inputs are sampled and outputs are driven at a clock edge, which is known as cycle-based code. But, SystemVerilog allows us to specify input and output skews, which allow us to sample input before the clock edge and drive the output after the clock edge, respectively.
Within a clocking block, we define these input and / or output skews for a list of signals. These are of the form:
input [delay_or_edge] [signal_list]; output [delay_or_edge] [signal_list];
It's also possible to define a default skew, which is of the form:
default input [delay_or_edge] output [delay_or_edge];
[delay_or_edge] is either of the following:
default skew is specified, then all input signals are sampled
#1 simulation step before and all outputs are driven
0ns after the event specified.
For example, if the event that drives a clocking block is
posedge clk, then we could define signals of the following form:
input #5ns sig1; output negedge sig2;
sig1 would now be sampled
5ns before the positive edge of clock
sig2 be driven to the output at the negative edge (
negedge) of clock
clk instead of the positive edge.
Clocking Blocks within Interfaces
When used in interfaces, a clocking block basically bundles together signals, so that they share a common clock. This can sometimes help reduce the code required while connecting the design to a testbench.
Of course, when modport lists are defined, the direction of the signals in the clocking block should be the same as the one in the modport definition for the testbench.
Block diagrams and other visualizations were made using draw.io
Previous articles of the series
- 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
- 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)
- Interfaces (part 1) → Interfaces (Definition, Port and Signal Lists, Instantiation), Modports
Final words | Next up
And this is actually it for today's post!
From next time on we will start getting into Classes. I'm also thinking about examples, but it's difficult to come up with easy-to-follow use-cases for most of these features! We shall see...
Keep on drifting!
Posted with STEMGeeks