【原创】SystemVerilog和Verilog中的表达式位宽

2023-05-16

Verilog和SystemVerilog作为一种“松散类型”的语言已经被很多工程师广泛的用于设计验证领域,但是这并不是说各种电路结构或者验证环境中就可以肆无忌惮的随意使用,特别是在不同位宽的信号进行计算时,结果经常出现与自己表达式预期的结果不一致,以至于怀疑自己数学是不是体育老师教的,为此,本文将示例说明表达式不同位宽信号进行运算时,结果到底应该是什么。

首先我们先看一个运算的各位数位宽一致,但是计算结果与期望不一致的示例。

【示例】本示例中,期望将运算结果向右移动一位,这样两个数的和的进位位就可以保留下来。

图片

【仿真结果】

图片

示例中,(sig1+sig2)结果应该为“1_1110_0011”,以为后的结果应该包含进位位“1”,但是实际result中并没有包含进位位。这是为什么呢?这是因为表达式中(sig1+sig2)进位操作时会产生一个中间结果,这个中间结果的位宽与sig1和sig2最宽的那一个数保持一致。示例中因为sig1和sig2都是8位宽,所以这个中间结果并没有包含进位位,因此进行移位操作的这个中间结果实际上只包含了(sig1+sig2)“和”的部分,因此移位后的结果进位位“消失”了,跟我们期望的结果不一致。为了解决这样的问题,我们需要保持中间结果中能够有效地把和的进位位保留下来,那么如何可以实现进位结果保留下来并且能够参与到移位操作中呢?我们一块看看下面几个示例。

【示例】方法一:加入宽位宽数据拓展结果

图片

【仿真结果】 

图片

示例中,对sig1和sig2进行加法操作时,增加了一个9位宽的0(可以指定任何一个大于8位的0),这样子(sig1+sig2+9’b0_0000_0000)进行加法操作时,所有的操作数都被扩展为9位进行计算,(sig1+sig2+9’b0_0000_0000)运算的结果(中间结果)中也将包含进位位,在对这个中间9位宽结果移位时,就会将其进位位一并进行移位,所以最终的结果中包含了我们期望的(sig1+sig2)的进位位。除了这个方法外,我们还可以通过类型转换实现操作数位宽的扩展,如下例。

【示例】方法二:使用静态类型转换

图片

【仿真结果】

仿真结果同上例。

示例中,通过将sig1和sig2中任意一个使用”int'”转换成32位,此时sig1和sig2进行操作时,所有的操作数都会拓展为32位后进行计算,移位操作时就会对这个32位的中间结果进行移位,此时的最终结果result中就会包含加法操作的进位位。

其实除了上述两种方法外,最稳妥的操作方式是我们在进行操作时,对于要进行操作的各种结果的位宽要有足够的估计,如下例。

【示例】方法三:扩展赋值表达式中相关操作数的位宽 

图片

【仿真结果】

图片

示例中,将result的位宽声明为9位宽,那么当sig1和sig2进行运算时,会被扩展为9位宽,此时sig1+sig2的结果也为9位,即此时两个数相加结果的进位位被保留下来,所以此时进行移位操作后输出结果包含进位位。

在Verilog和SystemVerilog中之所有会出现上述示例中的问题是因为Verilog和SystemVerilog在对表达式进行解析时,对于操作数的位宽以及表达式结果的位宽的处理方式不是很了解导致的,其实在Verilog和SystemVerilog中对于表达式的位宽是会按照一定的规则进行确定的,而这个规则的依据就是具体表达式中参与的各种运算符以及操作数位宽,并且将表达式分为了两类:self-determined和context-determined。

self-determined表达式的位宽仅由表达式中操作数的位宽决定,这样的表达式的位宽不会受到表达式上下文的影响,也就是不会受到表达式其他部分的影响;

context-determined表达式的位宽既由表达式决定,也由整个语句的其他部分表达式位宽决定;

这两种说法可能比较抽象,下表中对经常遇到的运算操作后表达式的位宽进行汇总分类如下,用以帮助大家具体运算时理解(参考IEEE1800 2012 Chapter 11),其中黄色部分为self-determined表达式常用操作符。 

图片

下面我们针对上述运算符结合示例进行说明。

【示例】

图片

【仿真结果】 

图片

示例结果分析:

1st和2nd:因为&sig1和&sig2并未出现在赋值表达式中,并且符合“& op”条件,所有操作数位宽self-determined,通过上表分析&sig1和&sig2的结果均为1位,与仿真结果一致。

3rd:因为&sig1和&sig2并未出现在赋值表达式中,&sig1和&sig2分别计算完成后的结果均为1位,并且这两个&运算的结果位于“+”左右两侧,两个1位数相加的结果仍为1位,所以仿真结果为0。

4th和5th:因为“&sig1+sig2”和“sig1+&sig2”并未出现在赋值表达式中,所以所有操作数的位宽self-determined,sig1和sig2均位于“+”运算符两侧,此时“+”操作结果位宽取决于“+”操作符操作数最大位宽,所以在4th中显示的结果与sig1的位宽相同,而5th中显示的结果与sig2位宽相同。

6th:“sig1+sig2”的结果产生的原因与4th和5th相同,“sig1+sig2”结果由sig1和sig2位宽最宽的那个数决定,所以显示结果位宽同sig2。

7th:在“result = (&sig1 + &sig2)>>1”中,因为&sig1和&sig2符合“& op”条件,所以先会计算&sig1和&sig2的结果,应该为1位,但是作为赋值表达式(赋值表达式右侧操作数位宽由context-determined决定,即由赋值表达式左右两侧位宽最宽的数决定)右侧的操作数“&sig1”和“&sig2”的位宽由赋值表达式两侧的操作数共同决定,因为表达式左侧的result位宽为10位,所以&sig1和&sig2进行“+”操作时,位宽会被扩展为10位宽,所以最终的计算结果如仿真结果所示:’h00_0000_0001。

8th和9th:与7th计算过程类似,此处不再赘述。

10th:在“result = (sig1 + sig2) >>1”中,sig1和sig2在进行计算时的位宽由赋值表达式两侧的操作数共同决定,因为表达式左侧的result位宽为10位,所以sig1和sig2进行“+”操作时,位宽会被扩展为10位宽,所以最终的计算结果如仿真结果所示:’h01_0111_11111。

11th、12th、13th和14th与上述计算过程类似,此处不再赘述。

那么,当赋值表达式左侧操作数的位宽小于右侧某个操作数的位宽时,结算结果还是上述示例那样吗?请看下例。

【示例】

图片

【仿真结果】

图片

示例中,result的位宽为7位,所以7th-14th计算结果相较于上例均发生了高位截断情况。可见,当操作数位于赋值表达式左右两侧时,赋值表达式最终结果的位宽由赋值表达式赋值表达式左侧操作数决定,但是其中的各种运算及中间结果位宽需要对赋值表达式两侧数的位宽都进行考虑,即context-determined。所以,为了获得期望的结果,在使用各种操作数进行运算时,需要注意以下几点:

Ø 操作数的符号特性,是否为有符号数,因为牵扯到数据拓宽时高位补位;

Ø 操作数的位宽,特别是在赋值表达式中位于赋值表达式两侧操作数的位宽;

Ø 操作表达式所使用的运算符(self-determined);

Ø 表达式是否位于赋值表达式中,决定了是self-determined还是context-determined。

而在实际过程中,我们的表达式往往即包含了self-determined运算又包含了context-determined,那么我们在具体运算时可以参考如下步骤:

第一步:先确定赋值表达式左右两侧的self-determined运算,并对其完成解析;

第二步:根据赋值表达式两侧最大的位宽对赋值表达式左右两侧表达式的位宽进行扩展;

第三步:左右两侧拓展后的操作数进行相关运算,但是需要注意,赋值表达式的最终结果将不会被拓展;

更多内容请关注下面公众号!

图片

本文纯属学习之用,欢迎指正文中不足,封面图片若有侵权,请及时沟通!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【原创】SystemVerilog和Verilog中的表达式位宽 的相关文章

  • SV 或 UVM 中的正则表达式

    我需要调用哪些函数才能在 Systemverilog UVM 中使用正则表达式 注意 我不是问如何使用正则表达式 只是问方法名称 首先 如果您想使用正则表达式 您需要确保您使用的是与其 DPI 代码一起编译的 UVM 库 即UVM NO D
  • [Verilog] Verilog 基本格式和语法

    主页 元存储博客 全文 3000 字 文章目录 1 声明格式 1 1 模块声明 1 2 输入输出声明 1 3 内部信号声明 1 4 内部逻辑声明
  • System Verilog 中的覆盖点

    是否可以根据参数从特定组中排除某些覆盖点 covergroup NEW string for exclusion clk option per instance 1 option comment for exclusion apples c
  • 修改后的 baugh-wooley 算法乘法 verilog 代码不能正确乘法

    以下 verilog 源代码和 或测试平台可以很好地工作商业模拟器 iverilog https www edaplayground com x 3TuQ也形式化验证工具 yosys smtbmc https gist github com
  • 如何将时钟门映射到技术库单元

    我的设计中有以下时钟门 module my clkgate clko clki ena Clock gating latch triggered on the rising clki edge input clki input ena ou
  • Verilog 中的“net”代表什么?

    我刚刚开始学习Verilog 据我了解 Verilog有net数据类型 什么是net代表 网络就是这样一种数据类型 您不使用它来存储值 它们代表物理连接 您可以将线路视为一种网络数据类型 你可以去网上看看更多here http www ee
  • 我们可以在 C 或 SystemVerilog 中使用 ifdef MACROS 中的条件吗?

    我想要那样的东西 ifdef N O gt N I define GREATER 1 else define LESSER 1 endif 但做不到 有什么解决方案或阅读吗 我很努力地想要做到这一点 但是却做不到 Verilog 不提供这样
  • 始终块中的 Veriloggenerate/genvar

    我试图让一个模块通过 ISE 12 4 中的语法检查 但它给了我一个我不明白的错误 首先是代码片段 parameter ROWBITS 4 reg ROWBITS 1 0 temp genvar c generate always pose
  • 向左旋转 verilog 大小写

    我的任务是用verilog编写一个16位ALU 当我做需要旋转操作数和进行2的补码加法和减法的部分时 我发现了困难 我知道如何用纸和铅笔解决这个问题 但我无法弄清楚如何在 Verilog 中做到这一点 例如 A表示为a15 a14 a13
  • FPGA大输入数据

    我正在尝试向 FPGA 发送 4 KB 字符串 最简单的方法是什么 是我正在使用的fpga的链接 我正在使用 Verilog 和 Quartus 您的问题的答案在很大程度上取决于将数据输入 FPGA 的内容 即使没有您需要遵守的特定协议 S
  • 开始后跟冒号和变量是什么意思?

    什么是data mux意思是这里 它只是块的名称吗 if PORT CONFIG 32 P0 1 b1 begin data mux end 这些是块名称 它们特别适用于generate块 例如 您可以定义一个generate块如 genv
  • 具有 +1 逻辑的 4 位计数器 D 触发器

    我正在尝试通过 Verilog 实现带有 1 逻辑的 D 触发器计数器 但是我收到了很多有关网络多个常量驱动程序的错误代码 有人可以帮我吗 这是到目前为止的代码 module LAB clk clear Enable Q input clk
  • 如何在Verilog中将二维数组中的所有位设置为0?

    我构建了一个 8 2bits 数组来表示 Verilog 中的一块内存 reg 1 0 m 0 7 该存储器有一个复位信号 如果复位为1 则该存储器中的所有位都应重置为0 但是我不知道如何以简洁的方式设置m的所有位 因为如果有数百个内存中有
  • Verilog 中的 If 语句和分配连线

    我试图弄清楚基于组合逻辑分配电线的基础知识 I have wire val wire x wire a wire b always begin if val 00 I want to assign x a if val 01 I want
  • 在测试台中显示信号名称/文字

    是否可以在 Verilog 中引用 显示信号的名称 文字 对于在 Verilog 测试台中创建通用信号检查功能来说 这将是一个有用的功能 我知道使用 display 时 m 将打印信号的范围 是否有显示信号名称的等效项 在 Verilog
  • VIM 高亮匹配开始/结束

    我正在尝试找到一个插件 它将突出显示与 Verilog 匹配的开始 结束语句 VIM 可以使用花括号 方括号 但不能使用它的开始 结束 我希望 VIM 突出显示正确的开始到正确的结束 在我看来 最好的选择是使用 matchit 该脚本是 v
  • 我怎样才能让我的verilog移位器更通用?

    这里我有一个移位器 但现在它最多只能工作 3 位 我一直在寻找 但不知道如何让它工作最多 8 位 module shifter a b out input 7 0 a b output 7 0 out wire 7 0 out1 out2
  • verilog 中的案例陈述

    我遇到了优先级编码器设计 并找到了一种使用 case 语句来实现它的新方法 唯一令人困惑的是 case语句是否优先考虑case 例子 case 1 b1 A 3 Y lt 4 b1000 A 2 Y lt 4 b0100 A 1 Y lt
  • Verilog 双向握手示例

    我正在完成一个项目 要求是处理器内部功能单元之间的双向握手 我知道它是什么 但是有没有任何 标准 或一个简单的例子 我唯一能想到的就是两个单元之间 当它们之间有一条数据线并且当 X 发送到 Y 时 会给出一个单独的 发送 信号 当 Y 接收
  • Verilog 数组语法

    我是 Verilog 新手 并且遇到了很多麻烦 例如 我想要一个包含八个单元的数组 每个单元都是 8 位宽 以下不起作用 reg 7 0 transitionTable 0 7 assign transitionTable 0 10 仅仅做

随机推荐