【发布时间】:2020-12-31 15:44:48
【问题描述】:
我想填写正确的信号声明和 modport 声明,以便我的接口和期望代码示例用例在 Vivado 中编译。我正在使用 .sv 文件扩展名在 SystemVerilog 中工作。我想“if 语句”不同的信号声明的原因是我的接口的实例化和使用更加优雅。我不希望用户必须键入许多 [0] 来指定一维的单个元素数组中的单个元素,其中一维宽度为 1,第二维宽度为 1。
请耐心等待,我必须在工作中删除此代码应用程序的所有元素。我已将其定制为一个非常简单的示例。
如果第 1 维或数组为 1 且数组的第 2 维为 1,我不希望有人需要选择第 0 和第 0 个元素。
例如,我希望用户能够执行以下操作,但无法编译。这是我的基本问题。如何实现能够像以下 sn-p 一样优雅的代码?:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 1 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data = 8'h20 ;
错误是:
[Synth 8-6038] cannot resolve hierarchical name for the item 'data' [".../File.sv":21]
相反,我发现用户必须为总共 1 个元素的特定信号执行此操作(以下内容没有错误):
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 1 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus[0][0].data = 8'h20 ;
我觉得这样的事情应该可以通过以下代码实现:
interface MyInterface #(int DATA_W, ADDR_W, A1D, A2D) () ;
typedef struct packed
{ logic valid
; logic [ADDR_W-1:0] addr
; logic [DATA_W-1:0] data
; } SimpleStruct;
if ( A1D == 1 ) begin
SimpleStruct bus;
logic ready;
end
else begin
if ( A2D == 1 ) begin
SimpleStruct [A1D-1:0] bus;
logic [A1D-1:0] ready;
end
else begin
SimpleStruct [A1D-1:0][A2D-1:0] bus;
logic [A1D-1:0][A2D-1:0] ready;
end
end
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
endinterface
这没有编译,因为 bus 和 ready 没有被“声明”......所以我改成了一个不太优雅的(我尝试在 generate 中猜测,但这没有帮助):
interface MyInterface #(int DATA_W, ADDR_W, A1D, A2D) () ;
typedef struct packed
{ logic valid
; logic [ADDR_W-1:0] addr
; logic [DATA_W-1:0] data
; } SimpleStruct;
if ( A1D == 1 ) begin
SimpleStruct bus;
logic ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
else begin
if ( A2D == 1 ) begin
SimpleStruct [A1D-1:0] bus;
logic [A1D-1:0] ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
else begin
SimpleStruct [A1D-1:0][A2D-1:0] bus;
logic [A1D-1:0][A2D-1:0] ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
end
endinterface
同样的愿望也适用于用户想要使用长度 > 1 的单维数组的情况。例如: 恕我直言:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 3 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data[0] = 8'h20 ;
assign my_signal.bus.data[1] = 8'h21 ;
assign my_signal.bus.data[2] = 8'h22 ;
我认为上面的代码比下面的代码看起来更好。我尝试或选择使用接口的全部意义在于代码的可重用性和优雅性。我不希望用户不断与“我想要一个元素,但会得到部分模棱两可的错误,很难找出解决方案”:
恕我直言,不可取:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 3 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data[0][0] = 8'h20 ;
assign my_signal.bus.data[1][0] = 8'h21 ;
assign my_signal.bus.data[2][0] = 8'h22 ;
我的愿望是让用户编写他们需要的代码来完成他们想要的元素的复杂性。单个元素的用途最多,元素的一维数组有一些用途,元素的二维数组的用途很少。由于我希望定义一个接口,因此我必须允许所有用途。我不希望仅仅因为我希望界面支持 2D 而需要不优雅的代码,并且用户只需要一个元素来实现他们的特定实例化和代码。
【问题讨论】:
-
你想做的事情在 SV 中是不可能的。另请记住,每个生成块(并且您的“if”语句是生成块)都会将分层路径添加到“总线”变量的名称中,在您的情况下,它会变成类似于
my_signal.genblk1.bus.data的名称。其中 'genblk' 是自动生成的(因为您没有为 'begin' 提供名称),并且在生成块中的每个begin...end对中都会有所不同。 -
感谢您的回复,我完全同意 gen 声明行李。我不会使用生成语句。