Logic Design - Interfaces in SystemVerilog (part 2)

in STEMGeeks5 months ago

[Edit of Image1]

Introduction

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!


Interface Parameters

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.

Importing

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.

Exporting

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

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 clocking and 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];

In these [delay_or_edge] is either of the following:

  • #delay
  • posedge
  • negedge

When no 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;

where sig1 would now be sampled 5ns before the positive edge of clock clk, and 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.


RESOURCES:

References

  1. https://www.chipverify.com/systemverilog/systemverilog-tutorial
  2. https://www.asic-world.com/systemverilog/tutorial.html

Images

  1. https://www.flickr.com/photos/creative_stock/5227842611

Block diagrams and other visualizations were made using draw.io


Previous articles of the series

Verilog

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)
  • 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...

See Ya!

Keep on drifting!

Posted with STEMGeeks