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

时间:2014-01-24 00:17:43

标签: 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

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

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

1 个答案:

答案 0 :(得分:12)

interface是首选。

struct内的所有信号都遵循相同的端口方向时,struct可以使用 ; inputoutputinout wire。当驾驶方向变得混杂时使用结构变得具有挑战性。混合方向是允许使用ref关键字,但许多综合工具尚未不支持ref关键字。无法使用inout,因为logic被视为变量,IEEE Std 1800-2012§6.5网络和变量。但是,inout wire可用于将struct转换为网络。 stuct的组件不能在always-block中分配,而是需要assign语句;就像常规wire

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

仅传递显式方向数据类型时使用sturct。使用interface传递共享信号。

Senario示例:

想象一下,有一组信号xyz,其中module m_x驱动x并读取y& ; zmodule m_b驱动y并读取x& z,模块m_z驱动z并读取{{ 1}}&安培; x。每个信号只有一个驱动程序,y可以用来保证这一点。

如果我们尝试添加双向三态always_ff,则不能使用结构。 bus解析了wire / logic clobber时发生冲突的驱动程序并保持调度程序正常运行。

示例代码:

使用reg使用 struct (不允许三态):

ref

使用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 使用 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 (具有三态):

interface

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