连接分层模块:SystemVerilog中的struct vs interface

Ari*_*Ari 4 system-verilog

在SystemVerilog中,可以通过简单的数据类型,复杂的数据类型(结构,联合等)或接口来连接分层模块.我感兴趣的功能是在一个地方聚合两个模块之间的所有信号,这简化了代码的维护.

例如,在下面的一个更改s_point的定义而不更改m1,m2和top的声明:

 typedef struct {
  logic [7:0] x;
  logic [7:0] y;
} s_point; // named structure


module m1 (output s_point outPoint);
//
endmodule

module m2 (input s_point inPoint);
//
endmodule

module top ();
    s_point point;
    m1 m1_inst (point);
    m2 m2_inst (point);
endmodule
Run Code Online (Sandbox Code Playgroud)

或者,这可以使用接口完成.但是,我相信使用结构更容易,并且它们受到更多CAD工具的支持,并且它们不需要像接口那样被实例化(尽管仍然必须在顶层模块中声明它们).

我的问题是,对于可综合设计,是否只需要聚合信号(即对接口的任务,函数,模型,通用接口,内部总是块等没有兴趣),哪一个更受欢迎?

Gre*_*reg 12

interface 是优选的.

struct好使用当内的所有信号struct都遵循相同的端口方向; input,outputinout wire.当驾驶方向变得混杂时使用结构变得具有挑战性.混合方向是允许使用的ref关键字,但是ref关键字不是由许多综合工具的支持,.inout不能使用因为logic被认为是变量,IEEE Std1800-2012§6.5网络和变量.但是,inout wire可以用来struct作为网络.stuct的组件不能在always-block中分配,assign而是需要声明; 就像一个普通人wire.

interface所述端口的方向并不一致,应分组信号.需要将三态定义为,wire并且当与变量类型结合使用时,变量类型不需要显式的端口方向always_{ff|comb|latch}.如果信号是协议的一部分,也应该使用它.这样可以添加断言,并且可以将其连接到UVM测试平台或其他SVTB环境的类.

使用sturctwhen仅传递显式方向数据类型.使用一个interface用于传递共享信号.

Senario示例:

想象有信号的集合x,y,及z,其中,module m_x驱动器x和读出yz,module m_b驱动y并读取x&z以及模块m_z驱动器z和读取x&y.每个信号只有一个驱动器,always_ff可用于保证这一点.

如果我们尝试添加双向三态bus,那么就不能使用该结构.一个wire解决冲突的驱动程序,同时logic/ reg撞,并保持调度运行.

示例代码:

使用structref(无三态允许的):

typedef struct {logic [7:0] x, y, z, bus; } s_point;

module m_x_st (ref s_point point, input clk);
  always_ff @(posedge clk)
    point.x <= func(point.y, point.z);
  //assign point.bus = (point.y!=point.z) ? 'z : point.x; // NO tir-state
endmodule
module m_y_st (ref s_point point, input clk);
  always_ff @(posedge clk)
    point.y <= func(point.x, point.z);
  //assign point.bus = (point.x!=point.z) ? 'z : point.y; // NO tir-state
endmodule
module m_z_st (ref s_point point, input clk);
  always_ff @(posedge clk)
    point.z <= func(point.x, point.y);
  //assign point.bus = (point.x!=point.y) ? 'z : point.z; // NO tir-state
endmodule

module top_with_st (input clk);
    s_point point;
    m_x_st mx_inst (point,clk);
    m_y_st my_inst (point,clk);
    m_z_st mz_inst (point,clk);
endmodule
Run Code Online (Sandbox Code Playgroud)

使用struct使用inout wire(网必须用驱动assign,失去了一个驱动程序的担保):

typedef struct {logic [7:0] x, y, z, bus; } s_point;

module m_x_wst (inout wire s_point point, input clk);
  logic [$size(point.x)-1:0] tmp;
  assign point.x = tmp;
  always_ff @(posedge clk)
    tmp <= func(point.y, point.z);
  assign point.bus = (point.y!=point.z) ? 'z : point.x; // tir-state
endmodule
module m_y_wst (inout wire s_point point, input clk);
  logic [$size(point.y)-1:0] tmp;
  assign point.y = tmp;
  always_ff @(posedge clk)
    tmp <= func(point.x, point.z);
  assign point.bus = (point.x!=point.z) ? 'z : point.y; // tir-state
endmodule
module m_z_wst (inout wire s_point point, input clk);
  logic [$size(point.z)-1:0] tmp;
  assign point.z = tmp;
  always_ff @(posedge clk)
    tmp <= func(point.x, point.y);
  assign point.bus = (point.x!=point.y) ? 'z : point.z; // tri-state
endmodule

module top_with_wst (input clk);
    wire s_point point; // must have the 'wire' keyword
    m_x_wst mx_inst (point,clk);
    m_y_wst my_inst (point,clk);
    m_z_wst mz_inst (point,clk);
endmodule
Run Code Online (Sandbox Code Playgroud)

使用interface(带三态):

interface if_point;
  logic [7:0] x, y, z;
  wire  [7:0] bus; // tri-state must be wire
endinterface

module m_x_if (if_point point, input clk);
  always_ff @(posedge clk)
    point.x <= func(point.y, point.z);
  assign point.bus = (point.y!=point.z) ? 'z : point.x;
endmodule
module m_y_if (if_point point, input clk);
  always_ff @(posedge clk)
    point.y <= func(point.x, point.z);
  assign point.bus = (point.x!=point.z) ? 'z : point.y;
endmodule
module m_z_if (if_point point, input clk);
  always_ff @(posedge clk)
    point.z <= func(point.x, point.y);
  assign point.bus = (point.x!=point.y) ? 'z : point.z;
endmodule

module top_with_if (input clk);
    if_point point();
    m_x_if mx_inst (point,clk);
    m_y_if my_inst (point,clk);
    m_z_if mz_inst (point,clk);
endmodule
Run Code Online (Sandbox Code Playgroud)

运行代码:http://www.edaplayground.com/s/6/1150