0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog表达式的位宽确定规则

ZYNQ 来源:ZYNQ 2024-10-22 15:41 次阅读

一般规则

很多时候,Verilog中表达式的位宽都是被隐式确定的,即使你自己设计了位宽,它也是根据规则先确定位宽后,再扩展到你的设计位宽,这常常会导致结果产生意想不到的错误。比如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a,b;
reg[1:0]c1,c2;

initialbegin
a=4'b0111;
b=4'b1111;
c1=a&b;
c2=a&&b;
end

endmodule

结果是这样的:

2d027082-8f8a-11ef-a511-92fbcf53809c.png

a & b的结果本来应该是4‘b0111 ,但是c1只有2位,所以高位被截断,导致c1为2’b11;而a && b 的结果本来是1位的1’b1,但是c2有2位,所以会在高位补0,导致c2为2’b01。

类似的情况还有很多,为了减少设计出错的可能性,有必要探究一下表达式的位宽确定规则。

Verilog语法规定了如下的确定表达式位宽的规则:

表达式的位宽由表达式中的操作数(operands)或表达式所处的上下文(context)决定。

自决定表达式(self-determined expression)就是表达式中所有操作数的位宽完全由自己决定。

上下文决定表达式(context-determined expression)就是表达式中所有操作数的位宽由整个表达式上下文环境中最大的位宽决定。

自决定表达式

这一类表达式的位宽都是根据表达式自身的位宽和运算结果来决定的。具体规则如下:

2d19e578-8f8a-11ef-a511-92fbcf53809c.png

1、无位宽常数

这种情况它的位宽等同于整数integer,在大多数编译器中,integer的默认位宽都为32位。例如modelsim环境下的测试:

`timescale1ns/1ns
moduletb_test();

initialbegin
$display("answer=%b",(1));//以2进制形式打印
end

endmodule

打印结果是32位宽的 “1”:

answer = 00000000000000000000000000000001

2、给定位宽常数

没什么好说的,位宽就是给定的这个数,比如 4‘d1的位宽就是4。例如:

//以2进制形式打印`timescale1ns/1ns
moduletb_test();

reg[3:0]a;

initialbegin
a=4'd1;
$display("answer=%b",a);//以2进制形式打印
end

endmodule

打印结果:

answer = 0001

3、运算(1)

i 和 j 做以下运算:+ - * / % & | ^ ^~ ~^ 时,位宽等于 i 和 j 中位宽较大者的位宽。很好理解,这些运算就是常见的 加减乘除取模 与或异或同或 运算。例如4bits数和5bits数相加:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;
reg[4:0]b;

initialbegin
a=4'd1;
b=5'd1;
$display("answer=%b",(a+b));
end

endmodule

打印结果是5bits:

answer = 00010

4、运算(2)

对 i 做以下运算:+ - ~ 时,位宽等于它本身。也很好理解,就是正负表达和取反,所以位宽肯定不会改变。例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;

initialbegin
a=4'b1001;
$display("answer=%b",(~a));//取反
end

endmodule

打印结果仍是4bits:

answer = 0110

5、比较

二个数的比较结果只有 是 和 不是,所以位宽只需要1位,例如:=== !== == != > >= < <=。例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a,b;

initialbegin
a=4'd5;
b=4'd3;
$display("answer=%b",(a>b));
end

endmodule

打印结果是1bit:

answer = 1

6、逻辑与、逻辑或

逻辑与&& 和 逻辑或 || 的结果也只有1bit。

`timescale1ns/1ns
moduletb_test();

reg[3:0]a,b;

initialbegin
a=4'd5;
b=4'd3;
$display("answer=%b",(a&&b));
end

endmodule

打印结果是1bit:

answer = 1

7、规约运算(Reduction)

下面这些规约运算的结果只有1位:& ~& | ~| ^ ~^ ^~ !。规约运算就是对数据本身的所有位做同样的对应的运算,例如规约与(该数的所有位相与):

`timescale1ns/1ns
moduletb_test();

reg[3:0]a,b;

initialbegin
a=4'b1101;
b=&a;//1&1&0&1
$display("answer=%b",(b));
end

endmodule

打印结果是1bit:

answer = 1

8、移位和乘方

移位和乘方运算(>> << ** >>> <<<)的结果位宽是该数本身位宽。例如移位:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;

initialbegin
a=4'b1011;
$display("answer=%b",(a>>1));
end

endmodule

打印结果是4bits:

answer = 0101

乘方运算的结果有可能会溢出,例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a,b;

initialbegin
a=4'd3;
b=4'd3;
$display("answer=%b",(a**b));
end

endmodule

打印结果是4bits:

answer = 1011

3**3的结果原本是27,即1_1011,高位被截断后,成了4bits的1011。

9、条件表达式

条件表达式(i ? j : k)的位宽等于 j 和 k 中的位宽较大者。例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;
reg[5:0]b;
regc;

initialbegin
c=1;
a=4'b1011;
$display("answer=%b",(c?a:b));
end

endmodule

打印结果是6bits:

answer = 001011

尽管c为真,所以该式的结果是a,但是位宽却等于更宽的b,所以结果的高位会补2个0,扩展到6bits。

10、拼接

第一种拼接:{i,…,j},位宽为二者之和。例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;
reg[5:0]b;

initialbegin
a=4'b1011;
b=6'b001011;
$display("answer=%b",({a,b}));
end

endmodule

打印结果是4 + 6 = 10bits:

answer = 1011001011

第二种拼接:{i{j,…,k}},位宽为二者之和与系数的乘积。例如:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;
reg[5:0]b;

initialbegin
a=4'b1011;
b=6'b001011;
$display("answer=%b",({2{a,b}}));
end

endmodule

打印结果是2*(4 + 6) = 20bits:

answer = 10110010111011001011

上下文决定表达式

上下文决定表达式其实就是各种自决定表达式的集合,所以需要视具体情况而具体分析。看一个例子:

`timescale1ns/1ns
moduletb_test();

reg[3:0]a;
reg[5:0]b;
reg[15:0]c;

initialbegin
a=4'hF;//15
b=6'hA;//10

$display("a*b=%b",a*b);//10*15

c={a**b};//15^10
$display("a**b=%b",c);

c=a**b;//15^10
$display("c=%b",c);
end

endmodule

打印结果:

a*b=010110

a**b=0000000000000001

c=1010110001100001

a*b原本是15×10=150,即1001_0110,但是结果的位宽是a、b中的较大位宽(6bits),所以被结果截断到 01_0110;

a**b原本是15^10=576,650,390,625,即1000011001000011000010101010110001100001,但是乘法的结果位宽是a的位宽(4bits),所以结果被截断到 0001;然后和 0 做拼接,相当与位宽没变,所以结果仍是0001,最后赋值给c,c的位宽为16,所以需要在高位补0,最终结果为0000000000000001

第三个和第二个的区别在于没有拼接运算符,a**b的位宽结果取决于上下文环境,即c的位宽。所以在计算时,a和b都会被先拓展到16位,然后再计算结果。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Verilog
    +关注

    关注

    28

    文章

    1340

    浏览量

    109901
  • 运算
    +关注

    关注

    0

    文章

    129

    浏览量

    25764
  • 语法
    +关注

    关注

    0

    文章

    44

    浏览量

    9756

原文标题:如何确定Verilog表达式的位宽

文章出处:【微信号:ZYNQ,微信公众号:ZYNQ】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    什么是正则表达式?正则表达式如何工作?哪些语法规则适用正则表达式

    正则表达式又称规则表达式(Regular Expression,在代码中常简写为 regex、regexp 或 RE),是一种用于匹配、查找、替换文本的强大工具。它能够以特定的模式匹配字符串,从而
    的头像 发表于 11-03 14:41 2530次阅读
    什么是正则<b class='flag-5'>表达式</b>?正则<b class='flag-5'>表达式</b>如何工作?哪些语法<b class='flag-5'>规则</b>适用正则<b class='flag-5'>表达式</b>?

    GVIM正则表达式介绍和使用示例

    20世纪50年代,一名叫Stephen Cole Kleene的美国数学家发表了规则的语言(regular language)的定义。规则表达式就是用来描述
    的头像 发表于 12-18 15:09 1084次阅读
    GVIM正则<b class='flag-5'>表达式</b>介绍和使用示例

    MATLAB符号表达式

    符号表达式是代表数字、函数、算子和变量的MATLAB字符串,或字符串数组。不要求变量有预先确定的值,符号方程式是含有等号的符号表达式。符号算术是使用已知的规则和给定符号恒等式求解这些符
    发表于 09-22 15:45

    如何创建正则的表达式

    正则表达式:用于匹配规律规则表达式,正则表达式最初是科学家对人类神经系统的工作原理的早期研究,现在在编程语言中有广泛的应用,经常用于表单校验,高级搜索等。
    发表于 10-27 15:49

    正则表达式以及实用的匹配规则概述

    地查阅正则表达式的匹配规则。不过,实际经验告诉我,多用了几次之后,常用的匹配规则也就都记住了。03 常用关系特性从CheatSheet可以直接看到正则表达式最基础的匹配
    发表于 09-16 14:23

    Verilog HDL硬件描述语言_表达式

    本章讲述在Verilog HDL中编写表达式的基础。表达式由操作数和操作符组成。表达式可以在出现数值的任何地方使用。verilog相关教程材
    发表于 04-25 16:09 19次下载

    Verilog HDL中编写表达式的基础讲述

    本章讲述在Verilog HDL中编写表达式的基础。 表达式由操作数和操作符组成。表达式可以在出现数值的任何地方使用。 4.1 操作数 操作数可以是以下类型中的一种: 1) 常数 2)
    的头像 发表于 03-05 15:20 2747次阅读

    Python正则表达式指南

    本文介绍了Python对于正则表达式的支持,包括正则表达式基础以及Python正则表达式标准库的完整介绍及使用示例。本文的内容不包括如何编写高效的正则表达式、如何优化正则
    发表于 03-26 09:13 10次下载
    Python正则<b class='flag-5'>表达式</b>指南

    C语言如何使用正则表达式

    C语言的正则表达式规则,特此跟大家分享。
    的头像 发表于 03-16 08:41 4841次阅读

    Lambda表达式详解

    C++11中的Lambda表达式用于 **定义并创建匿名的函数对象** ,以简化编程工作。下面看一下Lambda表达式的基本构成。
    的头像 发表于 02-09 11:28 1111次阅读

    运算符/表达式规则

    运算符对操作数执行操作。大多数运算符都有两个操作数。例如,在运算a+b中,+(加法)运算的操作数是a和b。每个操作数都被称为表达式表达式可以是文字值、变量、网络;函数调用的返回,或另一个操作的结果。表达式有许多影响操作执行方式
    的头像 发表于 02-09 15:37 919次阅读
    运算符/<b class='flag-5'>表达式</b><b class='flag-5'>规则</b>

    C语言的表达式

    在C语言中,表达式是由操作符和操作数组成。表达式可以由一个或者多个操作数组成,不同的操作符与操作数组成不同的表达式,因此,表达式才是C语言的基本。
    的头像 发表于 02-21 15:09 1267次阅读
    C语言的<b class='flag-5'>表达式</b>

    逻辑运算符与表达式

    逻辑运算符与逻辑表达式可以实现的编辑,比如的清零、设置、取反和取补等操作。使用逻辑运算
    的头像 发表于 02-21 15:22 1192次阅读
    <b class='flag-5'>位</b>逻辑运算符与<b class='flag-5'>表达式</b>

    Linux入门之正则表达式

    一些约定好的匹配规则,但由于规则较多,可能比较容易忘记。 本文会先整理出所有的正则表达式以及其含义,接下来会利用grep命令,详细介绍每种正则表达式的使用方式,并给出案例。
    的头像 发表于 05-12 15:31 813次阅读
    Linux入门之正则<b class='flag-5'>表达式</b>

    一文详解Verilog表达式

    表达式由操作符和操作数构成,其目的是根据操作符的意义得到一个计算结果。表达式可以在出现数值的任何地方使用。
    的头像 发表于 05-29 16:23 2701次阅读
    一文详解<b class='flag-5'>Verilog</b><b class='flag-5'>表达式</b>