这里是尼德兰的喵·芯片设计相关文章,欢迎您的访问!
如果文章对您有所帮助,期待您的点赞收藏!
让我们一起为成为芯片前端全栈工程师而努力!
一个参数的标准定义呢应该是这样的:
parameter type range name = value;
也就是说一个标准的参数呢是有以下四个属性的:type类型,range位宽/区间,name名字和value数值。实际操作中呢,除了名字和数值其他两个是可以省略的,比如下面这些参数定义方法都是可以编译的:
parameter P0 = 5;
parameter P1 = 3'd5;
parameter P2 = -5;
parameter P3 = 1.5;
parameter P4 = P0 + P1;
parameter signed [15:0] P5 = -7;
parameter unsigned [15:0] P6 = -7;
parameter [15:0] P7 = -7;
parameter [15:0] P8 = 2'd1;
parameter real P9 = 3e7;
parameter realtime P10 = 10;
parameter unsigned [63:0]P11 = $signed(-2);
parameter signed[31:0]P12 = $unsigned(-2);
parameter P13 = $unsigned(-2);
parameter [31:0]P14 = -2;
顺便我将这些参数的打印结果也放一下:
P0 = 'b101 = 'd5 = 'f5.000000
P1 = 'b101 = 'd5 = 'f5.000000
P2 = 'b11111111111111111111111111111011 = 'd-5 = 'f-5.000000
P3 = 'b1 = 'd1 = 'f1.500000
P4 = 'b1010 = 'd10 = 'f10.000000
P5 = 'b1111111111111001 = 'd-7 = 'f-7.000000
P6 = 'b1111111111111001 = 'd65529 = 'f65529.000000
P7 = 'b1111111111111001 = 'd65529 = 'f65529.000000
P8 = 'b1 = 'd1 = 'f1.000000
P9 = 'b1110010011100001110000000 = 'd30000000 = 'f30000000.000000
P10 = 'b1010 = 'd10 = 'f10.000000
P11 = 'b1111111111111111111111111111111111111111111111111111111111111110 = 'd18446744073709551614 = 'f18446744073709551616.000000
P12 = 'b11111111111111111111111111111110 = 'd-2 = 'f-2.000000
P13 = 'b11111111111111111111111111111110 = 'd4294967294 = 'f4294967294.000000
P14 = 'b11111111111111111111111111111110 = 'd4294967294 = 'f4294967294.000000
那么我们就来分析分析这些参数定义方式的四个属性分别是什么。判定参数的属性时,遵循两个大的基本原则(就是说特殊情况除外的那种原则上说):
1.如果有显性声明,则以显性声明为准;
2.如果没有声明type和range,则以value的type和range为准;
一个与大规则2相违背的小规则:
1.如果参数有指定range,但没有type,则它的符号默认为unsigned,并且range和符号都不会被后面的声明所覆盖;
规则其实并不乱,咱们一起来看一下 。
parameter P0 = 5;
打印:
P0 = 'b101 = 'd5 = 'f5.000000
这是我们最常用的写法了,此时P0的属性由后面的5来决定。而5本身是int型数据,因此P0的属性为:type = signed,range = [31:0],value = 5。
parameter P1 = 3'd5;
打印:
P1 = 'b101 = 'd5 = 'f5.000000
与P0很接近,只不过此时3'd5指明了数据类型为unsigned,数据位宽为3bit,因此P1的属性为:type = unsigned,range = [2:0],value = 5。其实这种情况下signed和unsigned并不太区分,甚至我感觉很多时候是和编译器和lint检查软件有关系。
那么我们改一下,
parameter P2 = -5;
parameter [15:0] P7 = -7;
打印:
P2 = 'b11111111111111111111111111111011 = 'd-5 = 'f-5.000000
P7 = 'b1111111111111001 = 'd65529 = 'f65529.000000
这两个放一起看,一个等于-5一个等于-7,value的属性其实是一样的,但是看打印结果也能看出来P2是有符号数而P7是无符号数,为什么呢?注意小规则1:
1.如果参数有指定range,但没有type,则它的符号默认为unsigned,并且range和符号都不会被后面的声明所覆盖;
显然P7就符合这种情况,因此P7是无符号数,P2是有符号数。
parameter P3 = 1.5;
打印:
P3 = 'b1 = 'd1 = 'f1.500000
设计代码中很少有这种参数,所以我觉得吧看看结果就好了( • ̀ω•́ )✧能编译,能不能综合我就不知道了,感兴趣的自行探究下吧。
parameter P4 = P0 + P2;
打印:
P4 = 'b1010 = 'd10 = 'f10.000000
parameter中是可以包含运算的,像这种就是运算得出结果后在遵循之前的规则,因此P4的属性为:type = unsigned,range = [31:0],value = 10。
parameter signed [15:0] P5 = -7;
parameter unsigned [15:0] P6 = -7;
打印:
P5 = 'b1111111111111001 = 'd-7 = 'f-7.000000
P6 = 'b1111111111111001 = 'd65529 = 'f65529.000000
P5和P6很好的说明了,显性定义的type是不会被后面的value所覆盖的,P5的属性:type = signed,range = [15:0],value = -7,P6的属性:type = unsigned,range = [15:0],value = 65529。
parameter [15:0] P8 = 2'd1;
打印:
P8 = 'b1 = 'd1 = 'f1.000000
这个地方不要被打印蒙蔽哈,因为我用的是%0b/d/f的方式所以打印时会截掉没有的位宽。
parameter real P9 = 3e7;
parameter realtime P10 = 10;
打印:
P9 = 'b1110010011100001110000000 = 'd30000000 = 'f30000000.000000
P10 = 'b1010 = 'd10 = 'f10.000000
这种real、realtime型在设计中也很少写,不建议过多关注。real数据类型支持的语法显然在参数定义时也是可以支持的。
parameter unsigned [63:0]P11 = $signed(-2);
parameter signed[31:0]P12 = $unsigned(-2);
parameter P13 = $unsigned(-2);
parameter [31:0]P14 = -2;
打印:
P11 = 'b1111111111111111111111111111111111111111111111111111111111111110 = 'd18446744073709551614 = 'f18446744073709551616.000000
P12 = 'b11111111111111111111111111111110 = 'd-2 = 'f-2.000000
P13 = 'b11111111111111111111111111111110 = 'd4294967294 = 'f4294967294.000000
P14 = 'b11111111111111111111111111111110 = 'd4294967294 = 'f4294967294.000000
这四个对比着看,很有意思。P11和P12都能看出,显性声明优先级最高。P13没有显性声明听value的规则,value是无符号数那P13也是无符号数。P14只有range没有type,那type就固定为unsigned,不听value的了。
OK所有关于参数的细节就说完了,在进行lint检查时有时参数会造成一些这也不对那也不对的干扰,那么如果你很确认自己的设计没有风险的话,可以在rule.tcl中将check_static_value关闭,那么spyglass就不会对parameter的lint违规进行检查了。