System verilog 如何将msb:lsb范围定义为参数?

System verilog 如何将msb:lsb范围定义为参数?,system-verilog,System Verilog,在硬件中定义了大量包含位字段的寄存器后,我想“命名”这些寄存器,并使用它们的名称而不是msb:lsb格式在SystemVerilog中访问位字段。所以,我做了一个新的包,在里面声明了常量参数,并且尝试了那些描述范围的参数。大概是这样的: package VmeAddressMap; parameter SYS_INTCONFIG = 32'h00000044; parameter RSYS_INTCONFIGRORA = 31:16; parameter RSYS_INTCON

在硬件中定义了大量包含位字段的寄存器后,我想“命名”这些寄存器,并使用它们的名称而不是msb:lsb格式在SystemVerilog中访问位字段。所以,我做了一个新的包,在里面声明了常量参数,并且尝试了那些描述范围的参数。大概是这样的:

package VmeAddressMap;
   parameter SYS_INTCONFIG = 32'h00000044;
   parameter RSYS_INTCONFIGRORA = 31:16;
   parameter RSYS_INTCONFIGENABLE = 15:0;
endpackage // VmeAddressMap
很明显,这是行不通的。因此,我提供了一个“混合”解决方案,即简单常数保留在包中,对于范围,我制作了另一个文件,其中包含宏:

包文件:

package VmeAddressMap;
   parameter SYS_INTCONFIG = 32'h00000044;
endpackage // VmeAddressMap
宏文件:

`define RSYS_INTCONFIGRORA 31:16
`define RSYS_INTCONFIGENABLE 15:0
此解决方案允许我执行以下操作(读取是通过VME总线读取数据的任务):

这行得通,我想干什么就干什么。但是我不喜欢它。特别是将宏与SystemVerilog风格的描述混合在一起


有没有办法直接在包中完成相同的任务?

您可以对MSB使用一个参数,对LSB使用另一个参数

parameter RSYS_INTCONFIGRORA_MSB = 31;
parameter RSYS_INTCONFIGRORA_LSB = 16;

LastVmeReadData_b32[RSYS_INTCONFIGRORA_MSB:RSYS_INTCONFIGRORA_LSB]
这有点笨拙,因此如果所有内容都是16位宽的,您可以定义LSB:

parameter RSYS_INTCONFIGRORA = 16;

LastVmeReadData_b32[RSYS_INTCONFIGRORA +: 16]
或者,您可以使用结构:

typedef struct packed {
  logic [15:0] RSYS_INTCONFIGRORA;
  logic [15:0] RSYS_INTCONFIGENABLE;
} some_register_t;
如果设计的某些部分需要与整个寄存器对象交互,而其他部分只需要与位字段交互,则可以进一步与该结构进行
联合

这些寄存器结构可以构建成更大的寄存器映射结构


如果您使用的是
UVM
,那么您应该建立寄存器的
RAL
模块

您可以为MSB使用一个参数,为LSB使用另一个参数

parameter RSYS_INTCONFIGRORA_MSB = 31;
parameter RSYS_INTCONFIGRORA_LSB = 16;

LastVmeReadData_b32[RSYS_INTCONFIGRORA_MSB:RSYS_INTCONFIGRORA_LSB]
这有点笨拙,因此如果所有内容都是16位宽的,您可以定义LSB:

parameter RSYS_INTCONFIGRORA = 16;

LastVmeReadData_b32[RSYS_INTCONFIGRORA +: 16]
或者,您可以使用结构:

typedef struct packed {
  logic [15:0] RSYS_INTCONFIGRORA;
  logic [15:0] RSYS_INTCONFIGENABLE;
} some_register_t;
如果设计的某些部分需要与整个寄存器对象交互,而其他部分只需要与位字段交互,则可以进一步与该结构进行
联合

这些寄存器结构可以构建成更大的寄存器映射结构


如果您使用的是
UVM
,那么您应该建立寄存器的
RAL
模块,这正是UVM寄存器抽象层为您所做的。您可以定义字段,为其提供名称、位宽度和其他属性。这些字段被分组到寄存器中,寄存器被分组到带有地址和偏移量的块中

现在我已经告诉你了,这里有一个简单的解决方案,它使用
let
construct实现了你想要的

package VmeAddressMap;
   parameter SYS_INTCONFIG = 32'h00000044;
   let RSYS_INTCONFIGRORA(field) = field[31:16];
   let RSYS_INTCONFIGENABLE(field) = field[15:0];
endpackage // VmeAddressMap
但是现在你必须把范围放在变量前面

`CHECK_EQUAL(RSYS_INTCONFIGRORA(LastVmeReadData_b32), 15,
           "IRQ setup invalid");

这正是UVM寄存器抽象层为您所做的。您可以定义字段,为其提供名称、位宽度和其他属性。这些字段被分组到寄存器中,寄存器被分组到带有地址和偏移量的块中

现在我已经告诉你了,这里有一个简单的解决方案,它使用
let
construct实现了你想要的

package VmeAddressMap;
   parameter SYS_INTCONFIG = 32'h00000044;
   let RSYS_INTCONFIGRORA(field) = field[31:16];
   let RSYS_INTCONFIGENABLE(field) = field[15:0];
endpackage // VmeAddressMap
但是现在你必须把范围放在变量前面

`CHECK_EQUAL(RSYS_INTCONFIGRORA(LastVmeReadData_b32), 15,
           "IRQ setup invalid");