有没有办法在SystemVerilog中的结构中嵌入常量?

时间:2022-09-05 11:50:23

In a perfect world, I would be able to scope a localparam to the inside of a struct:

在一个完美的世界中,我可以将localparam范围扩展到结构的内部:

typedef struct {
  logic [10:0] mantissa;
  localparam exponent = -10;
} my_fixed_point_type;

But alas, this is not legal SystemVerilog. I've investigated using const ints (illegal), enums (not scoped to the struct, and requires "storage").

但唉,这不是合法的SystemVerilog。我调查过使用const int(非法),枚举(没有作用于结构,需要“存储”)。

I might consider just embedding an int into the struct, and trust the synthesis tool to notice the values are only ever initialized, and strip them away, but some synthesis tools are just as likely to ignore initialization.

我可能会考虑在结构中嵌入一个int,并相信综合工具注意到这些值只是初始化,并将它们剥离,但是一些综合工具也可能忽略初始化。

The only approach I've found so far that actually words is this abomination:

到目前为止,我发现的唯一方法实际上就是这个令人厌恶的词:

typedef struct {
  logic [10:0] mantissa;
  logic [25:0] _hidden;
} my_fixed_point_type;

`define FP_EXPONENT(var) $bits(var._hidden)

Since _hidden is never read from, I have high confidence that it will get stripped out at elaboration time, while the bit width of _hidden can be used to hide an (unsigned) integer constant. Ugly!

由于_hidden永远不会从中读取,因此我很有信心它会在精化时被剥离,而_hidden的位宽可用于隐藏(无符号)整数常量。丑陋!

Surely there must be a better way to scope a constant to a struct in a way that is preserved in synthesis, but doesn't take up any actual bits. Or, do I have to take this up with the SystemVerilog 2016 committee?

当然必须有一种更好的方法,以一种在综合中保留的方式将常量范围限定为结构,但不占用任何实际位。或者,我是否必须参加SystemVerilog 2016委员会?

3 个解决方案

#1


There are a number of things you could do, but without knowing why you are trying to do this, it is difficult to recommend a good solution. Here are a few suggestions:

您可以做很多事情,但不知道为什么要这样做,很难推荐一个好的解决方案。以下是一些建议:

You can define an initial value to a typedef

您可以为typedef定义初始值

typedef struct {
  logic [10:0] mantissa;
  int exponent = -10;
} my_fixed_point_type;

or use an anonymous enumerated type to prevent any other value ever being assigned to it

或使用匿名枚举类型来防止任何其他值被分配给它

   typedef struct {
      logic [10:0] mantissa;
      enum {value=-10} exponent = value;
    } my_fixed_point_type;

or us a continuous assignment to the variable declared with this type

或者我们对用这种类型声明的变量进行连续赋值

   typedef struct {
      logic [10:0] mantissa;
      int exponent;
    } my_fixed_point_type; 

my_fixed_point_type fpv;
assign fpv.exponent = -10;

#2


_hidden can be made signed with logic signed [25:0] _hidden;

_hidden可以用逻辑签名[25:0] _hidden签名;

It can be made a semi-constant with always_comb var._hidden = -10;
assign could also work but unlike always_comb simulators are not required to give errors with multiple drivers.

它可以用always_comb var._hidden = -10制成半常数; assign也可以工作,但与always_comb模拟器不同,不需要为多个驱动程序提供错误。

An alternative is to use use an interface instead of a struct, where you can use const or parameters (even functions).

另一种方法是使用接口而不是结构,您可以使用const或参数(甚至函数)。

I'm not sure how well a synthesizer will optimize either; you'll need to experiment. My guess is an interface with parameters will strip away the unused signals better then with a struct.

我不确定合成器的优化程度如何;你需要实验。我的猜测是一个带有参数的接口将更好地剥离未使用的信号,然后使用结构。

#3


Have you ever found a way around this? I just started to build a fixed point library as well and wanted to use a structure to hold the [full, integer and fractional] width of signals. I'm not even trying to do anything fancy, I just wanted to collect the parameters in a structure so it's easy to have access to them. Unfortunately no matter what I do the tools complain cause they think the structure content aren't constant - even if I only ever assign once.

你有没有找到解决方法?我刚开始构建一个定点库,并希望使用一个结构来保存信号的[完整,整数和小数]宽度。我甚至都没有尝试做任何花哨的事情,我只是想在结构中收集参数,因此很容易访问它们。不幸的是,无论我做什么工具都抱怨他们认为结构内容不是一成不变的 - 即使我只分配一次。

For example:

typedef struct { int w, i, q; } fxpt;
fxpt dw = '{16, 1, 15}; 
wire signed [dw.w-1:0] din;

Or even if I would accept to have different structures for each signal so it's obvious everything is constant:

或者即使我接受每个信号都有不同的结构,所以很明显一切都是恒定的:

typedef struct { int w=18, i=1, q=17; }  dw_constant;
dw_constant dw; 
wire signed [dw.w-1:0] din;

I'm now reverting back to just having parameters directly in the code, such as:

我现在回到直接在代码中使用参数,例如:

parameter integer dw[0:2] = '{16, 1, 15};
wire signed [dw[0]-1:0] din;

Note that I haven't accessed the .i and .q parameter in the code snippet so it might look a bit useless, but when doing multiplication/addition those fields are important to have.

请注意,我没有访问代码片段中的.i和.q参数,因此它可能看起来有点无用,但在进行乘法/加法时,这些字段非常重要。

#1


There are a number of things you could do, but without knowing why you are trying to do this, it is difficult to recommend a good solution. Here are a few suggestions:

您可以做很多事情,但不知道为什么要这样做,很难推荐一个好的解决方案。以下是一些建议:

You can define an initial value to a typedef

您可以为typedef定义初始值

typedef struct {
  logic [10:0] mantissa;
  int exponent = -10;
} my_fixed_point_type;

or use an anonymous enumerated type to prevent any other value ever being assigned to it

或使用匿名枚举类型来防止任何其他值被分配给它

   typedef struct {
      logic [10:0] mantissa;
      enum {value=-10} exponent = value;
    } my_fixed_point_type;

or us a continuous assignment to the variable declared with this type

或者我们对用这种类型声明的变量进行连续赋值

   typedef struct {
      logic [10:0] mantissa;
      int exponent;
    } my_fixed_point_type; 

my_fixed_point_type fpv;
assign fpv.exponent = -10;

#2


_hidden can be made signed with logic signed [25:0] _hidden;

_hidden可以用逻辑签名[25:0] _hidden签名;

It can be made a semi-constant with always_comb var._hidden = -10;
assign could also work but unlike always_comb simulators are not required to give errors with multiple drivers.

它可以用always_comb var._hidden = -10制成半常数; assign也可以工作,但与always_comb模拟器不同,不需要为多个驱动程序提供错误。

An alternative is to use use an interface instead of a struct, where you can use const or parameters (even functions).

另一种方法是使用接口而不是结构,您可以使用const或参数(甚至函数)。

I'm not sure how well a synthesizer will optimize either; you'll need to experiment. My guess is an interface with parameters will strip away the unused signals better then with a struct.

我不确定合成器的优化程度如何;你需要实验。我的猜测是一个带有参数的接口将更好地剥离未使用的信号,然后使用结构。

#3


Have you ever found a way around this? I just started to build a fixed point library as well and wanted to use a structure to hold the [full, integer and fractional] width of signals. I'm not even trying to do anything fancy, I just wanted to collect the parameters in a structure so it's easy to have access to them. Unfortunately no matter what I do the tools complain cause they think the structure content aren't constant - even if I only ever assign once.

你有没有找到解决方法?我刚开始构建一个定点库,并希望使用一个结构来保存信号的[完整,整数和小数]宽度。我甚至都没有尝试做任何花哨的事情,我只是想在结构中收集参数,因此很容易访问它们。不幸的是,无论我做什么工具都抱怨他们认为结构内容不是一成不变的 - 即使我只分配一次。

For example:

typedef struct { int w, i, q; } fxpt;
fxpt dw = '{16, 1, 15}; 
wire signed [dw.w-1:0] din;

Or even if I would accept to have different structures for each signal so it's obvious everything is constant:

或者即使我接受每个信号都有不同的结构,所以很明显一切都是恒定的:

typedef struct { int w=18, i=1, q=17; }  dw_constant;
dw_constant dw; 
wire signed [dw.w-1:0] din;

I'm now reverting back to just having parameters directly in the code, such as:

我现在回到直接在代码中使用参数,例如:

parameter integer dw[0:2] = '{16, 1, 15};
wire signed [dw[0]-1:0] din;

Note that I haven't accessed the .i and .q parameter in the code snippet so it might look a bit useless, but when doing multiplication/addition those fields are important to have.

请注意,我没有访问代码片段中的.i和.q参数,因此它可能看起来有点无用,但在进行乘法/加法时,这些字段非常重要。