SV Interfaces: best coding style to encapsulate functionality?

I’m coding the functionality of rx and tx of an interface in the interface it self.
This iterface needs to be synthesizable.

My question is: what is the best practice way to code it?

I’ve tried it and interfaces support both methods (task/functions) and procedural logic coding styles.

I see two options to code it:

  • automatic tasks and/or functions
  • or procedural logic (always_ff, always_comb, etc)

I can see myself either coding tasks/functions or coding an FSM with procedural blocks to achieve the same functionality.

My question is: is there a best practice to do it?

Thank you for the advice you can provide :)

Based on your requirements.
In VLSI industry, most important part is to extract the info/features from spec sheet. In other word, unserstand your design requirement first.

If requirement regarding send/receive packet or configuring the interface (High-level abstraction) than better to follow task/function.Because they have ability to code in simpler and effective manner.

But if requirement is only signal manipulation or state-machine (Low-level Abs), better to use “procedural logic” because this approach is suitable for synthesizable RTL design.

I’m coding the functionality of rx and tx of an interface in the interface it self.
This interface needs to be synthesizable.

[Ben] Why are you coding a synthesizable model of a RX/TX design in interface? SHouldn’t it be in a module?
Getting back to your question, if you want it in an interface, then procedural logic (always_ff, always_comb, etc) is the only way to go since tasks are typically dynamic, though you can declare them as static. It has been a long time since I used a synthesis tool, but I don’t believe that tasks are allowed.

Based on your requirements.
In VLSI industry, most important part is to extract the info/features from spec sheet. In other word, unserstand your design requirement first.
If requirement regarding send/receive packet or configuring the interface (High-level abstraction) than better to follow task/function.Because they have ability to code in simpler and more effective manner.

[Ben] I would use assertions, possibly with support logic, instead of tasks.

Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog

In reply to ben@SystemVerilog.us:

@Ben, hi

Regarding why:
The reason why i want to code the reception/transmission of bits in the interface, is two fold.
First, because as far as i understand this is the benefit of using interfaces: to encapsulate the functionality of send and receive of the protocol in the interface itself, not only a bundle of signals.
Second, cuz else i’d have to code it in every single slave module, or master module connected to that protocol bus. But if i code it in the interface then the code is centralized for all modules which use the interface and protocol. Future changes to the protocol are centralized in the interface code, and not distributed all over my design.
Q1. Would you agree?

Also the reason why i ask, is cuz in the SV-LRM all examples use tasks to code functionality in the interfaces. I am used to code procedural logic, but seeing all examples were with tasks made me think twise.

Regarding synthesizable code:
Now regarding synthesizable code, to my understanding both procedural logic (always…) and automatic tasks and functions are synthesizable (emphasizing the automatic).
Q2. Would you agree?

Thank you for your help.
Let me know your comments,

In reply to stefaniemcg:

In reply to ben@SystemVerilog.us:
Regarding why:
The reason why i want to code the reception/transmission of bits in the interface, is two fold.
First, because as far as i understand this is the benefit of using interfaces: to encapsulate the functionality of send and receive of the protocol in the interface itself, not only a bundle of signals.
Second, cuz else i’d have to code it in every single slave module, or master module connected to that protocol bus. But if i code it in the interface then the code is centralized for all modules which use the interface and protocol. Future changes to the protocol are centralized in the interface code, and not distributed all over my design.
Q1. Would you agree?

If I understand you correctly, you want to so something like this demo example:

interface Mux2to1Interface;
  logic [1:0] data_in;   // 2-bit input data
  logic select;          // Selection signal
  logic data_out;        // Output data
  always_comb begin
    if (select == 1'b0)
      data_out = data_in[0];
    else
      data_out = data_in[1];
  end
endinterface

// Implement a 2-to-1 multiplexer using the interface
module Mux2to1 (Mux2to1Interface ifc, logic clk); 
  logic[1:0] data_out_r; 
  logic[1:0] data_in_r;
  always @(posedge clk) data_in_r <= ifc.data_in; 
  always @(posedge clk) data_out_r <= ifc.data_out; 
  
endmodule

You now expect that the synthesis tools will merge into the Mux2to1 module the logic defined in the interface. I am not sure if this is acceptable by synthesis tools.
In SystemVerilog, interfaces are primarily used for design abstraction, code organization, and testbench modeling, and they are not typically used for synthesis. Interfaces provide a way to bundle signals together, define a set of methods (functions and tasks) that operate on those signals, and create hierarchical connections between modules. They are mainly used to improve code readability, reusability, and maintainability.

Synthesis tools typically do not support the direct synthesis of interfaces into hardware. Instead, synthesis is performed on modules or entities that use the interface. When you synthesize a module or entity that contains an interface, the synthesis tool will generate the appropriate hardware logic based on how the interface signals are used within that module/entity.

Because you want your code to be synthesizable, a better methodology would be to create separate modules for the master and slave protocols.
For assertions, you can create checkers or modules and bind them to the design units.

Also the reason why i ask, is cuz in the SV-LRM all examples use tasks to code functionality in the interfaces. I am used to code procBen Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.
http://systemverilog.us/vf/Cohen_Links_to_papers_books.pdf
or Links_to_papers_books - Google Docs
Getting started with verification with SystemVerilog
Free URL Shortener | Powered by Rebrandly logic, but seeing all examples were with tasks made me think twice.

That work is for verification, not for synthesis.

Regarding synthesizable code:
Now regarding synthesizable code, to my understanding both procedural logic (always…) and automatic tasks and functions are synthesizable (emphasizing the automatic).
Q2. Would you agree?

NO. Automatic tasks are not synthesizable; how do you dynamically create/destroy logic in silicon? That is why tasks are not synthesizable. Synthesis requires a template of acceptable constructs.

In reply to ben@SystemVerilog.us:
It has been a very very long time since I did any real designs and synthesis, thus I am not fully aware of newer technologies in this field. A search on documentation revealed this link:
https://docs.xilinx.com/search/all?query=synthesis&content-lang=en-US

Targeting SystemVerilog for a Specific File
By default, the Vivado synthesis tool compiles *.v files with the Verilog 2005 syntax and *.sv files with the SystemVerilog syntax.

Interfaces provide a way to specify communication between blocks. An interface is a group of nets and variables that are grouped together to make connections.

[Ben] This is followed by an example where 2 modules use an interface as a connection
only; basically, it looks to me that an interface, for synthesis, is just a bunch of wires used for connection only. Any code inside the interface is ignored (?? need to verify this) The example:


interface my_int 
  logic sel;
  logic [9:0] data1, data2, result; 
endinterface : my_int
// In the two bottom-level modules, you can change to:
module bottom1 (
 my_int int1,  // <------------- the interface for the bundle
 input clk,
 input [9:0] d1, d2,
 input s1,
 output logic equal);
endmodule

module bottom2 ( 
  my_int int1, 
  input clk);
  // Ben code 
  always #(posedge clk) 
   if (int1.sel) int1.result <= int1.data1;
endmodule

module top( 
  input clk, 
  input s1,
  input [9:0] d1, d2, 
  output equal);
  my_int int3(); //instantiation, <------------- the interface for the bundle
  bottom1 u0 (int3, clk, d1, d2, s1, equal); 
  bottom2 u1 (int3, clk);
endmodule

Modeports are also supported


interface my_int;
 logic sel;
 logic [9:0] data1, data2, result;
  modport b1 (input result, output sel, data1, data2); 
  modport b2 (input sel, data1, data2, output result);
endinterface : my_int
// In the bottom modules, use when declared:
module bottom1 ( 
my_int.b1 int1,

also supported


Class
Instances	Supported
Member and method access	Supported
Constructors	Supported
Static class member and methods	Supported
Access using 'this' and 'super'	Supported
Object assignment	Supported
Inheritance	Supported
Data hiding and encapsulation	Supported
Scope and resolution operator (::)	Supported
Nested classes	Supported
Objects inside structs	Supported

Tasks
// Be careful when using these tasks; Vivado synthesis treats all tasks as automatic.
Coverage control functions	Not Supported
Static and Automatic task	Supported
Tasks memory usage and concurrent activation	Not Supported
Functions
Return values and void functions	Supported
Static and Automatic function	Supported
Constant function	Supported



I have been dated as I am still stuck on Verilog syntax for synthesis.
My emphasis is on assertions though.
Thanks for bringing the issue.
Ben

In reply to ben@SystemVerilog.us:

Though formal tools may support tasks in RTL designs, they typically are not used by customers; got that info from an expert in the field of FV. Thus, as a practical recommendation, it would be best to avoid tasks in RTL and instead use state machines.
Ben

In reply to ben@SystemVerilog.us:

Inputs and discussions from LinkedIN on this topic:
A question I have: Which is a better methodology? Tasks or user-defined FSM?
Your opinion?
[User]The first one is the most clean way of doing things IMO. The second is making it explicit but takes way more code to implement. I am a big fan of clean code and leave the hard work to the tool(s). In 2016, I wrote everything withinterfaces and modports which was supported by the synthesis tools already. No problem. Simulation? No problem.

But the formal equivalence check of rtl vs pre and post layout failed because the tools weren’t able to deal with that “advanced” construct. They have a slightly different parser than synthesis tools if I remember correctly. And for FPGA prototyping it was also an issue. In short, the tools, it is always the tools.
[Ben]Any issue with FV?
[User]Theoretically FV tools do support tasks in many cases, but I’ve never seen a customer actually use this feature!

@Ben, thank you for your feedback :)