Verilog 数据类型和数组简介

news2024/12/29 4:13:45

在这篇文章将讨论 verilog 中最常用的数据类型,包括对数据表示,线网类型、变量类型,向量类型和数组的讨论。

尽管 verilog 被认为是一种弱类型语言(loosely typed),但设计者仍必须在 Verilog 设计中为每个端口或信号声明一个数据类型,被指定的类型用于定义数据的特征。例如,设计者可以使数据完全解释为逻辑值的类型,或者也可以将数据解释为数值的类型。

在大多数情况下,挡在verilog 中将数据赋值给信号时,数据都会被隐式地转换为正确的类型。因此,通常不需要在 verilog 中显式地执行类型转换。

1、Verilog 中的数值表示

编写 verilog 时,经常需要在代码中表示数据值。为此可以将此数据表示为2进制,8进制,10进制或者16进制值。

与其他编程语言不同,verilog中还需要定义数据的位宽。这是因为verilog 本质上是在描述硬件电路。

下面的代码片段显示了在 verilog 中表示数字数据的一般语法。

<bits>'<representation><value>
  • <bits> :指定数据的位宽

  • <representation> :指定数据用何种进制来描述。可以是2进制(b或B)、8进制(o或O)、10进制(d或D)、16进制(h或H)

  • <value> :指定数据的具体数值

下面的代码片段展示了使用不同方法来描述10进制值数字 8 。

4'b1000;    //10进制数字8的位宽4的2进制表示
4'o10;      //10进制数字8的位宽4的8进制表示
4'd8;       //10进制数字8的位宽4的10进制表示
4'h8;       //10进制数字8的位宽4的16进制表示

2、Verilog 中的基本数据类型

从广义上讲,verilog 中的基本数据类型可以分为两大类--线网类型(net)和变量类型(variable )。这两个不同的类别可以被用来建模数字电路的不同元素。

net类型用来对数字电路中的连接建模。它们无法自行存储数值,必须由数据驱动。

variable类型用来对寄存器或触发器建模。它们可以存储数据,有点类似于其他编程语言(例如 C)中的变量。

无论开发者使用的确切类型是什么,都可以将4个有效值赋给数据中的各个位。这4个不同的值如下表所示。

0

逻辑 0 或 "假"

1

逻辑 1 或 "真"

z

高阻

x

未知

同样可以用相同的语法在 verilog 中声明变量,而不用管确切的类型。下面的代码片段展示了这种一般语法。

<type_name> <size> <variable_name> = <value>;

<type_name> 用来声明变量类型。

下面的 verilog 代码声明了一个名为example的integer (整型)变量并为其赋值 100。

integer example = 100;

2.1、Verilog 中的net类型

verilog 中的net数据类型可以用来描述设计中不同组件之间的物理连接。因此,net类型本身不能用于存储数据或驱动数据。

在上面的电路中,net类型将多路复用器的输出连接到触发器的输入。

通常使用连续赋值(continuous assignment)语句来将数据驱动到线型(wire)上。为此,必须使用 assign 关键字,如下面的代码片段所示。

assign a = 1'b0;  //给a赋值为0

2.1.1、wire类型

verilog 中最常用的net类型就是wire类型。使用wire类型来声明设计中基本的点对点连接信号。顾名思义,它们大致相当于传统电路中的电线(wire英文原意)。

下面的 verilog 代码展示了如何将连wire类型与 assign 关键字一起使用。

wire a;          //声明一个1位宽wire类型信号a

assign a = c;    //使用assign关键字来赋值
assign b = d;    //使用assign关键字来赋值

2.1.2、wand & wor类型

除了最常用的net数据类型wire类型外,还有几种其他的net类型。

wand 和 wor 类型用于将基本逻辑门插入到电路中。wand 相当于插入一个与门,wor 类型则相当于插入一个或门(顾名思义)。

当使用 wand 和 wor 类型时,必须对信号进行多次赋值,这样做是因为每次赋值都代表底层逻辑门的一个输入。

下面的 verilog 代码展示了如何将 wand 和 wor 类型与 assign 关键字一起使用。

wor a;                  //声明wor类型
wand b;                 //声明wand类型
wire c, d, e, f;        //逻辑门的输入

//创建一个输入为c、d的或门
assign a = c;
assign a = d;
 
//创建一个输入为e、f的与门
assign b = e;
assign b = f;

因为与门跟或门都可以轻松使用assign的组合逻辑实现,因此,并不推荐实践中使用 wor 和 wand 类型。

2.1.3、tri, triand & trior 类型

除了 wire、wand 和 wor 状态,还可以使用等效的 tri、triand 或 trior 类型。

使用这些类型的方式与 wire、wand 和 wor 类型完全相同。事实上,这些类型的功能是完全一样的。但是,设计者可以使用它们来更清楚地表达设计意图。

下面的代码片段显示了一个基本示例,其中 tri 类型被驱动为高阻。

tri a;              //声明一个tri类型信号
assign a = 1'bz;    //将其驱动为高阻

由于wire类型也可以取三态值,所以在实践中很少使用tri类型。trior 和 triand 类型也是如此,它们也可以使用wire类型轻松实现。

2.1.4、supply0 & supply1 类型

supply0 和 supply1 类型可以用来连接到一个2进制常量0或1上(即高电平与低电平)。这相当于直接连接到电路中的地ground或者电源VCC。

下面的代码片段展示了如何使用这些类型来创建连接到高电平或低电平的信号。

supply0 a;    //声明信号a连接到低电平
supply1 b;    //声明信号b连接到高电平

然而,在实践中很少需要将信号连接到高电平或低电平。哪怕真的需要这样做,使用wire类型也能很容易完成。因此,supply0 和 supply1 类型在实践中也很少使用。

2.2、Verilog 中的变量(Variable )类型

与net类型不同,在 verilog 中使用variable(变量)类型来存储数据。将一个值赋给一个变量类型后,它会一直保持这个值直到它被再次赋值。

variable类型通常比net类型更容易理解,因为它与C语言中的变量很类似。

在上面的电路中,将使用variable类型对触发器的输出进行建模,因为它可以有效存储一位数据。

variable类型必须在过程代码块中使用,例如always块,如下面的代码片段所示,它实现了一个D触发器。

//D触发器
always @(posedge clock)
  q <= d;
end

2.2.1、Verilog 中的触发器(Reg)类型

verilog中最常用的variable类型是reg类型。当需要在设计中存储一个值时,可以使用这种类型。

虽然reg 类型常被用来建模触发器,但在某些情况下,reg 类型也可用于在 verilog 中对组合逻辑进行建模。

下面的 verilog 代码片段展示了如何使用 reg 类型来实现一个基本的D触发器。

reg q;        //声明一个reg变量q

//D触发器
always @(posedge clock)
  q <= d;
end

2.2.2、数值变量(Numeric Variable)类型

到目前为止,所讨论到的类型都是与单个数据位一起使用的。设计者当然也可以在 verilog 中以数值方式来表示数据。

在verilog中,有两种常用的数值类型--integer(整数型)和real(实数型)。

①、integer类型

verilog 中最常用的数值数据类型是integer类型。但是,integer类型通常用于模块中的内部信号而不是端口。

默认情况下,integer是一个 32 位补码,这意味着其可以被用来表示 verilog 设计中的任何整数(当然是范围内)。

在使用integer类型时,需要为integer变量直接分配数值而不是2进制值。

因为 reg 类型也可以被直接赋予数值,因此通常将 reg 类型用作 verilog 中的常量或循环变量。

综合工具会自动缩减 reg 类型类型中未使用到的位。例如,如果声明一个值为 255 的整数常量,综合工具会将其缩减为 8 位(即8'b1111_1111)。

下面的代码片段展示了如何在 verilog 对integer类型进行声明和赋值。

integer a = 255;    //声明一个值为255的integer类型变量a

②、real 类型

real类型被用来存储非整数,即也有小数部分的数字。real类型通常在 verilog 中用64位浮点数来实现。因此,它不能被综合为实际电路,所以通常在testbench等测试脚本中使用。

real类型可以使用十进制或科学记数法来赋值。

下面的代码片段展示了如何声明一个real类型并为其赋值。

real a; //声明一个real变量a
a = 2.5; //十进制方式赋值
a = 1e-3; //科学记数法方法赋值

2.3、Verilog 中的向量(Vector )类型

除了Numeric类型之外,目前看到的其他类型均由单个位组成。然而,在数字电路中却经常使用数据总线来传输数据。

在 verilog 中可以使用Vector(向量)类型来创建数据总线,这意味着允许声明多于一位的信号。

下面的代码片段展示了在 verilog 中声明vector类型的一般语法。

//声明向量类型的一般语法
<type> <size> <variable_name>;

定义vector的大小时,必须指定最高有效位和最低有效位(MSB 和 LSB)。因此,<size> 要采用 [MSB:LSB] 的形式。

例如,如果要声明一个 4 位little endian(小字节序)类型vector,将使用结构 [3:0]。反之,如果要使用big endian(大字节序)类型vector,则使用结构 [0:3]。在实际应用中小字节序更为常见。

正如在本文前面所述,设计者可以使用2进制、8进制、10进制或16进制格式表示数据。当给vector赋值时,可以使用其中任何一种方式。

下面的 verilog 代码展示了如何声明一个 4 位宽的 reg 类型,并使用不同的方式将 1010b 赋值给变量。

reg [3:0] a;    //声明一个位宽为4的reg变量a

a = 4'b1010;    //2进制方法赋值
a = 4'o12;      //8进制方法赋值
a = 4'd10;      //10进制方法赋值
a = 4'ha;       //16进制方法赋值

2.4、Verilog 中的有符号(Signed)和无符号数据(Unsigned)

在Verilog-2001标准发布之前,所有net类型和variable类型都只能用于存储无符号(Unsigned)数据类型。同样,integer类型总是被解释为有符号值(Signed)

Verilog-2001 标准引入了signed 和 unsigned关键字。这改变了变量存储数据的方式。

在 verilog 中将类型声明为signed时,它会被解释为补码。这意味着可以为这些信号分配负数值。默认情况下,integer类型是有符号的,而 reg 和 wire 类型都是无符号的。如果希望修改此默认行为,只需要使用这些关键字(signed 和 unsigned)。

下面的 verilog 代码展示如何使用 reg、wire 和integer类型声明有符号和无符号数据。统一起见,声明的所有变量都是 32 位宽的。

//声明无符号reg变量a、有符号reg变量b
reg [31:0] a;
reg signed [31:0] b;

//声明无符号wire变量a、有符号wire变量b
wire [31:0] a;
wire signed [31:0] b;

//声明无符号integer变量a、有符号integer变量b
integer unsigned a;
integer b;

3、Verilog 中的数组(Arrays

设计者可以在 verilog 中创建和使用Arrays(数组)类型。为了在 verilog 中声明一个数组,只需在变量名后添加一个额外的字段来声明数组中的元素个数。该声明采用与之前讨论过的向量大小字段相同的格式。

下面的代码片段展示了在 verilog 中声明数组类型的一般语法。<elements> 被用来声明数组的大小。

<type> <size> <variable_name> <elements>;

假设要创建一个 3 位 reg 类型的数组,该数组中总共有 8 个元素。下面的 verilog 代码展示了如何创建这个数组。

//共有8个元素的数组example,每个元素的位宽为3位
reg [2:0] example [7:0];

可以使用带有数组下标的方括号来访问数组中的单个元素。例如,下面的 verilog 代码显示了如何将 5h 的值分配给示例数组中的最后一个元素(下标为7,即从0开始的第8个元素)。

//将5赋值给数组example中的最后一个元素
example[7] = 3'h5;   

多维数组

在Verilog-1995标准中,只能创建一维数组。而 verilog 2001 标准则可以创建多于一维的数组。为此,只需添加另一个字段来定义需要的元素数量。

下面的代码片段展示了在 verilog 中创建2维数组时使用的一般语法。

<type> <size> <variable_name> <elements> <elements>;

假设现在要创建一个变量,它可以存储 2 个元素,这2个元素都有 8 个 4 位 reg 类型元素。

为此,只需在声明的末尾添加一个额外的字段。下面的代码片段展示了如何做到这一点。

reg [3:0] example2d [7:0][1:0];

设计者还使用与赋值维数组相同的方法来赋值多维数组,但现在需要使用一对方括号来定义数组的两个维度中的元素。

假设要将 0xa 的值赋给两个维度中的最后一个元素,下面的 verilog 代码展示了如何将数据分配给数组中的这个元素。

example2d [7][1] = 4'ha;
example2d [7][0] = 4'ha;

  • 📣您有任何问题,都可以在评论区和我交流📃

  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net

  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/374398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

处理器管理

处理器状态处理器管理是操作系统中重要组成部分&#xff0c;负责管理、调度和分配计算机系统的重要资源——处理器&#xff0c;并控制程序执行由于处理器管理是操作系统最核心的部分&#xff0c;无论是应用程序还是系统程序&#xff0c;最终都要在处理器上执行以实现其功能&…

5.OCR文本识别CRNN算法

文章目录1.基础介绍2.CRNN模型结构2.1 特征提取2.2 双向循环神经网络层2.3 转录层(Transcription Layers)参考资料欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; title: 2.OCR文本识别Convolution Recurrent Neural Network toc: true ca…

记一次冲突的产生与解决

冲突的概念 git在使用中&#xff0c;如果遵循了它的使用的步骤&#xff0c;比如&#xff0c;在上班之前先去拉取&#xff0c;下班的时候&#xff0c;先提交&#xff0c;如果遵循这个步骤&#xff0c;一般在用的时候没有错误会产生的&#xff0c;但是&#xff0c;因为在开发的时…

Unity 之 实现读取代码写进Word文档功能实现 -- 软著脚本生成工具

Unity 之 实现读取代码写进Word文档功能前言一&#xff0c;实现步骤1.1 逻辑梳理1.2 用到工具二&#xff0c;实现读写文件2.1 读取目录相关2.2 读写文件三&#xff0c;编辑器拓展3.1 编辑器拓展介绍3.2 实现界面可视化四&#xff0c;源码分享4.1 工具目录4.2 完整代码前言 之所…

【SPSS】两独立样本T检验分析详细操作教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

消除“马路黑洞”,计讯物联智能井盖综合管理系统平台有绝招

窨井盖作为市政公用设施的重要组成部分&#xff0c;一旦出现松动、损坏等问题时,不仅会影响市容市貌&#xff0c;还会给道路上的车辆、行人带来安全隐患&#xff0c;对社会安定与安全造成极大负面影响。 痛点分析 01 由于地下管线错综复杂、窨井盖分布广泛&#xff0c;加之信…

Linux 进程:父子进程

目录一、了解子进程二、创建子进程1.创建子进程2.区分父子进程三、理解子进程四、创建子进程的意义进程就是运行中的应用程序&#xff0c;如果一个程序较为庞大&#xff0c;我们可以给这个程序创建多个进程&#xff0c;每个进程负责一部分代码的运行。 A进程如果创建了B进程&am…

【华为OD机试模拟题】用 C++ 实现 - GPU 调度(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明GPU 调度题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。

动态规划:完全背包基础、518.零钱兑换II、377.组合总和IV

leetcode 518.零钱兑换IIleetcode 377.组合总和IV完全背包基础有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里…

CleanMyMac4.20最新版新增功能及电脑清理垃圾使用教程

CleanMyMac4.20作为知名的Mac清理工具&#xff0c;仅需一键即可快速而安全地清理系统垃圾&#xff0c;释放磁盘空间&#xff0c;因此一直深受Mac用户的喜爱。在不断更新的版本中&#xff0c;CleanMyMac已经不仅仅满足于只做简单的Mac清理工具&#xff0c;而是为Mac用户提供更多…

借助Intune无感知开启Bitlocker

希望使用 Intune 部署 BitLocker&#xff0c;但不知道从哪里开始&#xff1f;这是人们最开始使用 Intune 时最常见的问题之一。在本博客中&#xff0c;你将了解有关使用 Intune 管理 BitLocker 的所有信息&#xff0c;包括建议的设置、BitLocker CSP 在客户端上的工作方式&…

彻底搞懂React-hook链表构建原理

写在前面的小结 每一个 hook 函数都有对应的 hook 对象保存状态信息useContext是唯一一个不需要添加到 hook 链表的 hook 函数只有 useEffect、useLayoutEffect 以及 useImperativeHandle 这三个 hook 具有副作用&#xff0c;在 render 阶段需要给函数组件 fiber 添加对应的副…

Spring Boot系列04--静态资源处理

目录1. 静态资源映射规则2. 欢迎页1. 静态资源映射规则 在项目中双击shift或ctrlN搜索WebMvcAutoConfiguration.class文件&#xff0c;文件中的addResourceHandlers方法如下&#xff1a; public void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.reso…

运维排查篇 | Redis占用内存过高怎么办

我们知道&#xff0c;Redis是一个key-value数据库&#xff0c;它的数据是运行在内存中的其读写效率比将数据存储到磁盘上的数据库要快很多虽然性能强大&#xff0c;但是如果我们不了解Redis的内存回收策略&#xff0c;就有可能导致Redis消耗内存过高甚至导致内存溢出&#xff0…

[优化]上下游交互策略

书接上文&#xff1a;https://blog.csdn.net/weixin_43303530/article/details/127227147?spm1001.2014.3001.5502&#xff0c;为满足产品提的在24小时内能重试尽量去重试&#xff0c;不计较重试的次数的要求&#xff0c;在第三方电子卡系统无法提升接口并发数量的情况下&…

电脑C盘空间不足?这样做就行了!

一般来说&#xff0c;电脑C盘都是系统盘&#xff0c;它的稳定关系到系统能否正常运行&#xff0c;但是很多朋友的C盘却总是红色的&#xff0c;这也就意味着C盘储存空间不足了&#xff0c;那么我们就需要进行以下操作&#xff0c;来让C盘重新拥有储存空间。方案一&#xff1a;运…

BLE Mesh蓝牙协议学习记录

BLE Mesh蓝牙协议学习 文章目录BLE Mesh蓝牙协议学习前言概述一、蓝牙技术整体框架二、经典蓝牙和低功耗蓝牙mesh协议架构图承载层&#xff08;Bearer Layer&#xff09;网络层&#xff08;Network Layer&#xff09;底层传输层&#xff08;Lower Transport Layer&#xff09;上…

JAVA连接数据库——JDBC的简单使用

JDBC即Java数据库连接.用来实现Java程序对数据库增删查改。 为了对接Java程序和数据库&#xff0c;java.sql提供了很多api包含在java.sql和javax.sql里面 结构: DriverManager接口: 每一个数据库的驱动程序都必须去到DriverManager注册&#xff0c;生成一个Connection Conn…

电商平台的促销活动如何抵御大流量的ddos攻击

每一次活动大促带来的迅猛流量&#xff0c;对技术人而言都是一次严峻考验。如果在活动期间遭受黑产恶意 DDoS 攻击&#xff0c;无疑是雪上加霜。电商的特性是业务常态下通常不会遭受大流量 DDoS 攻击&#xff0c;且对延迟敏感&#xff0c;因此只需要在活动期间按需使用 DDoS 防…

【第五章 AOP概述,底层原理,AOP术语,切入点表达式,AOP操作(基于注解方式,基于xml配置文件)】

第五章 AOP概述&#xff0c;底层原理&#xff0c;AOP术语&#xff0c;切入点表达式&#xff0c;AOP操作&#xff08;基于注解方式&#xff0c;基于xml配置文件&#xff09; 1.AOP概述&#xff1a; &#xff08;1&#xff09;什么是AOP&#xff1a; ①面向切面编程&#xff08;…