【Verilog】表达式位宽与符号判断机制
缘起于p1课下alu算数位移设计。查了好多资料,最后发现还是主要在翻译官方文档。浪费了超多时间啊,感觉还是没搞透,还是先以应用为导向放一放,且用且归纳
1.表达式位宽 expression bit length
身为硬件描述语言,Verilog表达式运算过程中必然要严肃考虑位宽问题
表达式的位宽由式中操作数和语境决定
表达式按位宽确定方式分为两类:
- self-determined expression
位宽仅有表达式自身确定,不会受语境影响也不影响语境中其他表达式(在复合表达式中某些位置上的子表达式,如i>>j中的表达式j、i?j:k中的表达式i)。 - context-determined expression
位宽由表达式本身和其所属表达式(父子表达式)共同决定(如阻塞赋值操作的RHS位宽由其自身和LHS被赋值变量的位宽决定)。
下表中i,j,k表示"单操作数表达式",L(i)表示表达式i的位宽

截自verilog-std-1364-2005
注意:RHS中context-determined表达式位宽受左值LHS影响,这点和符号性判断不同
这点尚未弄清存疑,且看示例
例0:缩减运算符相关(包含了优先级内容)
module trial(
output C,
output D,
output E,
output F,
output [7:0] Da,
output [7:0] Ea
);
wire [7:0] A = 8'b1011_1100;
wire B = 1;
assign C = ^A; // expect:1 ; got:1
assign D = ^A && B; // expect:1 ; got:1
assign E = ^A & B; // expect:0 ; got:1 ---> 缩减运算符优先级低了
assign F = ^(A & B); // expect:0 ; got:0
assign Da = ^A && B;
assign Ea = ^A & B;
endmodule

例1:所谓中间值位宽
reg [15:0] a,b,ans;
assign ans = (a + b) >> 1; //结果本意是将结果右移一位保留溢出的高位
根据i >> j规则,j为self-determined表达式不影响总表达式位宽,i为(a + b)位宽和左值ans均为16,因而总表达式位宽为16。a + b运算结束值即为16位,溢出被丢弃,所以达不成原本的目的。
修改为ans = (a + b + 0) >> 1;强行将位宽改为0(Integer)的32位,便可达成目的。
例2:三元运算符表达式位宽
reg [3:0] a,b,c;
reg [4:0] d;
initial begin
a = 9; b = 8; c = 1;
$display("%b", c ? (a&b) : d);
end
根据i ? j : k规则,i为self-determined表达式不影响总表达式位宽,max{L(j),L(k)}为d的5位,因而总表达式位宽为5,输出01000。
例3:综合由语境决定位宽
reg [3:0] a;
reg [5:0] b;
reg [15:0] c;
initial begin
a = 4'hf; b = 6'ha;
$display("%h", a*b); // a*b 位宽为6
c = a ** b; // a ** b 位宽是L(a)为4,受左值c的影响位宽最终为16。 c获得值16'hac61
$display("%h", c);
c = {a ** b}; // a ** b 位宽是L(a)为4,在{}内每一项均为self-determined表达式,最终位宽为4。 c获得值4'h1再扩展成16'h1
$display("%h", c);
end
最终输出
16
ac61
1
2.表达式符号性 expression signedness
Verilog计算表达式前,需要确定表达式的符号性,规则如下:
- 仅取决于RHS操作数,与LHS无关(与位宽确定有别,如
assign a = b ? c : d;中LHS符号性与a自身无关) - 十进制数视为signed
- 进制表示数视为unsigned,除非使用进制前加s特殊标明(
4'd3无符号,4'sd3有符号) - 位选择(不论是否选全)、位拼接(不论操作数)结果视为unsigned

- 比较表达式结果视为unsigned
- 实数强转整形表达式结果视为signed
- self-determined expression:符号性取决于其中操作数
- context-determined expression:
- 若存在操作数为real,则结果视为real
- 若存在操作数为unsigned,则结果视为unsigned
- 若所有操作数为signed,则结果视为signed
- 若存在操作数为real,则结果视为real
- 变量本身是unsigned(不过存了01串罢了,不要因为
reg [3:0]a = 2'sb11就认为变量a是signed),除非声明时附加关键字signed


确定整个表达式的符号性后,便会向内层表达式传递符号性,直至各操作数。
$signed(exp)函数计算传入的exp并返回与其值和位宽均相同的数据,将其符号性改为signed。可以看作屏蔽了外部表达式的符号性传递。
例:含三元运算符的表达式
testbench中使ALUop恒为
3'd5,A=4'b1101input [3:0] A,
input [3:0] B,
input [2:0] ALUOp,
output [3:0] C
assgin C = (ALUOp == 3'd5) ? A >>> B : 4'sd0;
分析:
在三元运算符(ALUop == 3'd5)属于self-determined表达式,不会影响符号性判断。因而看后半部分。4'sd0为符号数;A >>> B表达式中B为self-determined表达式(操作数),所以符号性仅看A。A无符号,因而总表达式RHS无符号。
传递符号性后,A无符号数经算数位移值为4'b0110,再赋给C。
assgin C = (ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0;
分析:
$signed()使$signed(A)表达式有符号,则$signed(A) >>> B表达式有符号,则总表达式RHS有符号。
传递符号性后,$signed(A)(A相当于被$signed()隔绝,仍无符号)被视为有符号数,算数位移后值为4'b1110
assgin C = (ALUOp == 3'd4) ? A + B :
(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0 ;
分析:
嵌套式三元运算符的结构。A + B表达式无符号(其中中A、B无符号),因而总表达式RHS无符号。
传递符号性:(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0无符号;$signed(A) >>> B无符号;$signed(A)无符号(A被$signed()保护),算数位移后值为4'b0110
assgin C = (ALUOp == 3'd4) ? A + B :
(ALUOp == 3'd5) ? $signed($signed(A) >>> B) : 4'sd0 ;
分析:
同上,总表达式RHS无符号。
传递符号性:(ALUOp == 3'd5) ? $signed(A) >>> B : 4'sd0无符号;$signed($signed(A) >>> B)无符号。$signed(A) >>> B被保护,因而$signed(A)仍视为有符号,算数位移后值为4'b1110。
【Verilog】表达式位宽与符号判断机制的更多相关文章
- verilog parameter 位宽问题
前言 一直以为parameter 的位宽是无限的,其实不然. 流程: 仿真一下就知道啦: 用处: 精准控制位宽理论上会占用更少的内存,其他好像并没有什么卵用,注意不要越界,我这里系统默认32bit位宽 ...
- ZYNQ Block Design中总线位宽的截取与合并操作
前言 在某些需求下,数据的位宽后级模块可能不需要原始位宽宽度,需要截位,而某些需求下,需要进行多个数据的合并操作. 在verilog下,截位操作可如下所示: wire [7:0] w_in; wire ...
- system verilog中的类型转换(type casting)、位宽转换(size casting)和符号转换(sign casting)
类型转换 verilog中,任何类型的任何数值都用来给任何类型赋值.verilog使用赋值语句自动将一种类型的数值转换为另一种类型. 例如,当一个wire类型赋值给一个reg类型的变量时,wire类型 ...
- Verilog中变量位宽注意
Verilog中,变量定义方式可以为:reg[位宽-1:0] 数据名:reg[位宽:1] 数据名.其他变量也类似. 以reg变量cnt为例,当cnt位宽为4时,可定义为reg[3:0] cnt,或者定 ...
- Verilog定义计算位宽的函数clogb2
在很多情况下要计算输入输出的位宽,比如你写一个8*8的ram,那么地址需要三位去表示,那么这个函数的方便就体现出来了,你需要使用函数定义就好了,如果对于多文件可以包含定义的文件: 如果你的DEPTH是 ...
- Chisel3 - 运算符和位宽推断
https://mp.weixin.qq.com/s/rI-CJM6GyI6EUHPZ3uYiFg 如同Verilog中的众多运算符,Chisel也针对自身的数据类型,提供了很多运算符. Ch ...
- FPGA位宽的转换和定义
数字表达式的定义<位宽><进制><数字>,这是一种全面的描述方式 例如:如果我要定义一个变量counter = 5000 0000 ,10进制数:那么他的位宽应该是 ...
- MySQL----数据的显示位宽
问题:在MySQL表中的列可以定义它显示的位宽.那么定义了位宽会不会影响数据的取值范围呢? 测试: 1.定义一个用于测试的表 create table t(x int,y int(2),z int(2 ...
- 外设位宽为8、16、32时,CPU与外设之间地址线的连接方法
有不少人问到:flash连接CPU时,根据不同的数据宽度,比如16位的NOR FLASH (A0-A19),处理器的地址线要(A1-A20)左移偏1位.为什么要偏1位? (全文有点晦涩,建议收藏本文对 ...
- FPGA设计千兆以太网MAC(3)——数据缓存及位宽转换模块设计与验证
本文设计思想采用明德扬至简设计法.上一篇博文中定制了自定义MAC IP的结构,在用户侧需要位宽转换及数据缓存.本文以TX方向为例,设计并验证发送缓存模块.这里定义该模块可缓存4个最大长度数据包,用户根 ...
随机推荐
- Qt编写嵌入式linux输入法/支持自定义词语和繁体/支持wayland和watson/纯QWidget/界面精美可换肤
一.功能特点 纯QWidget编写,原创输入法机制,没有任何第三方动态库的依赖. 支持各种Qt版本,包括Qt4.Qt5.Qt6及后续版本. 支持各种编译器,包括mingw.msvc.gcc.clang ...
- Qt音视频开发09-ffmpeg内核音视频同步
一.前言 用ffmpeg来做音视频同步,个人认为这个是ffmpeg基础处理中最难的一个,无数人就卡在这里,怎么也不准,本人也是尝试过网上各种demo,基本上都是渣渣,要么仅仅支持极其少量的视频文件比如 ...
- [转]基于图像的三维模型重建4——增量SFM
内容 几种BA的形式 同时优化相机和三维点 优化相机 只优化三维点 单目相机 增量运动恢复结构(Incremental SFM) 运动恢复结构的几个问题 几种BA的形式 数学模型 n个三维点和m个相机 ...
- 网络编程入门如此简单(四):一文搞懂localhost和127.0.0.1
本文由萤火架构分享,原题"localhost和127.0.0.1的区别是什么?",原文链接"juejin.cn/post/7321049446443417638" ...
- Windows应用开发-常用工具集推荐
.NET/WPF开发 Visual Studio 最新版本是VS2022,官网下载:Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 VsColorOutput 控制台 ...
- 《C++并发编程实战》读书笔记(4):原子变量
1.标准原子类型 标准原子类型的定义位于头文件<atomic>内.原子操作的关键用途是取代需要互斥的同步方式,但假设原子操作本身也在内部使用了互斥,就很可能无法达到期望的性能提升.有三种方 ...
- c# Progress<T>
c# Progress<T> 用于显示进度........主要是利用IProgress<T> 的Report(T)方法: private void BtnDownload_Cl ...
- Redis组件的特性,实现一个分布式限流
分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...
- Educational Codeforces Round 168 (Rated for Div. 2)
题目链接:Educational Codeforces Round 168 (Rated for Div. 2) 总结:题目较简单,但是发挥很一般.A,B题一直读假题,卡了半个小时:C题用char存i ...
- drools 规则引擎和 solon-flow 哪个好? 规则引擎 solon-flow 简明教程
前言 做电子政务的项目时,经常会有大量的业务逻辑变更,但其实里面的业务改动,其实就是一些业务逻辑变动. 而程序员编写的代码也没有任何技术含量,跟着式样书逐字逐句的翻译就行.大量的 if/else 判断 ...