当前位置: 首页 > news >正文

深入浅出学Verilog--基础语法

1、简介

        Verilog的语法和C语言非常类似,相对来说还是非常好学的。和C语言一样,Verilog语句也是由一连串的令牌(Token)组成。1个令牌必须由1个或1个以上的字符(character)组成,令牌可以是:

  • 注释(Comment)
  • 空白符(White space)
  • 运算符(Operator)
  • 数字(Number)
  • 字符串(String)
  • 标识符(Identifier)
  • 关键字(Keyword)

        Verilog是区分大小写的,所以下面两个变量是不相同的:

var_a;   //小写

var_A;     //大写

         Verilog的书写格式很自由,既可以把代码写在同一行,也可以写在多行。不过一般来讲,我都建议一条代码写一行,这样的代码格式美观,阅读起来也没那么累。每一条Verilog语句的末尾都应使用 ; (即分号)作为结束。下面两种写法是等价的:

//换行写法(推荐写法)

reg a;

wire b;

//不换行写法(眼睛看得累写法)

reg a;wire b;

        除了转义字符(escaped identifiers)外的空白符和换行符都没有实际意义,在编译阶段会被编译工具忽略。

2、注释(Comment)

        子曾经曰过:我平生最讨厌两件事----写代码的时候写注释和看没注释的代码。

        写注释是一个很好的开发习惯,虽然有些麻烦,但确实可以帮助其他开发者阅读代码,也可以在自己更改代码的时候提供一些思路上的帮助。因为编译器不会对注释进行编译,所以注释可以看做是给开发者阅读的设计说明----也就是说注释可以是英文,也可以是中文。

        Verilog 2 种注释方式:

  •  // 进行单行注释,在 // 后面的单行内容均会被编译器视为注释。。例如:

reg cnt;//定义一个寄存器cnt

  •  /* 与 */ 进行跨行注释, /* 与 */ 内的内容均会被编译器视为注释(/* 与 */ 可以是多行,也可以是一行)。例如:

reg cnt;/* 定义一个寄存器cnt */。

reg cnt;

/*

定义一个

寄存器

cnt

*/

        该种注释方式不可嵌套(注释一般也没必要嵌套)。

3、空白符(White space)

        空白符是指 空格符(spaces), 制表符(tabs), 换行符(newlines), 和换页符(formfeeds)。当空白符用于独立的令牌时,编译器通常会忽略它;但当空格符和制表符在字符串中则不能被忽略,它们会起到作用。

        空白符通常被用来对齐以调整代码格式,从而使代码更具可读性。比如下面的代码看起来有点拥挤,不够美观的同时也不方便阅读:

reg[3:0]cnt;//定义一个4位宽的寄存器cnt

wire[15:0]blk;//定义一个15位宽的线网blk

        由于空白符是对编译不起作用的,所以上面的代码可以通过空白符来等价地修改为:

reg   [3  :0]  cnt;   //定义一个4位宽的寄存器cnt

wire  [15:0]  blk;   //定义一个15位宽的线网blk

        这样的代码看起来就舒服多了。

4、运算符(Operator)

        Verilog中有3种类型的运算符:

  • 一元运算符(unary):一元运算符必须放在运算数的左边。例如:

x = ~y; // ~是一元运算符,y是运算数,该句表示对y值取反后赋给x

  • 二元运算符(binary):二元运算符必须放在两个运算数的中间。例如:

z = x & y; // &是二元运算符,x、y是运算数,该句表示将x、y值相与后赋给z

  • 三元运算符(ternary) 或者叫 条件运算符(conditional):条件运算符由两个独立的运算符来分开三个运算数。例如:

x = (y > 5) ? 1 : 0; // ?和:是条件运算符,表达式(y > 5)、1和0是运算数。该句表示当 y>5 成立时将1赋给x;否则将0赋给x。

5、数字(Number)

        Verilog中的数字有两种形式:整数(integer constants)和实数(real constants)

整数

        整数除了可以使用我们最熟悉,同时也是默认使用的10进制(decimal)外,还可以使用2进制(binary)8进制(octal)16进制(hexadecimal)。例如:

16            //10进制的16

0x10        //16进制的16

10000      //2进制的16

20            //8进制的16

         整数的写法可以指明位宽,也可以不指明位宽。

指明位宽

        这种写法的一般格式为:

[size]'[base_format][number]

  • size用来指定数字的位宽,这个数只能用10进制表示,即10一定表示位宽为10进制的10,而不是位宽为16进制的16
  • 撇号(apostrophe character) ' 介于size和base_format之间
  • base_format用来指定数字的进制,可以是2进制('b or 'B)、8进制 ('o or 'O)、10进制 ('d or 'D)、和16进制('h or 'H) 
  • number即为数字本身,2进制的0和1、8进制的0~7、10进制的0~9和16进制的0~9/a/b/c/d/e/f(不区分大小写

        例如:

4'b1010  //位宽为4的2进制数字1010

5'd3        //位宽为5的10进制数字3

        

不指明位宽

        不指名位宽直接写数字时,默认为10进制,位宽取决于所用的编译器(位宽一般为32),写法有2种:

'd10   //位宽根据编译器而定,一般为32,即32'd10

10      //位宽根据编译器而定,一般为32,即32'd10

4af     //非法写法,f为16进制数字,但是这里没有表明进制

负数

        在表示位宽的数字前面加一个负号 -  来表示负数,例如:

-6'd3    //位宽为6的数字-3

        如果把负号 - 放在进制和数字之间则是非法的,例如:

6'd-3    //这是非法写法。一定要注意,因为与日常写法很相似。

         可以在base_format前添加一个s(或S)来指明这是一个有符号数,当然也可以不添加。有符号数的最高位将被视为符号位----0表示正数,1表示负数例如:

4'b1111        //无符号数,等于10进制的15

4'sb1111      //有符号数,最高位1表示负数,剩余三位111转化等于10进制的7

        负数应以二进制的补码形式表示,例如:

-8'd6        // 这定义了6的补码

4'shf        // 等价于有符号数4'b1111,最高位1表示为负数,剩余三位111的补码(取反+1)是1,所以等价于 -4'h1

-4'sd15    // 等价于有符号数-4'b1111,最高位1表示为负数,剩余三位111的补码(取反+1)是1,所以等价于 -(-4'd1),即4'd1

下划线

        当数字过多的时候,可以用下划线(underscore character) _ 来拆分数字,提高阅读效率,但是下划线不可以放在数字的最开始。下划线无实际意义,仅用于辅助阅读。例如:

16‘b1010111101010111                //数字太多,阅读起来不太方便

16‘b1010_1111_0101_0111          //用下划线拆分数字后,阅读起来方便多了

16‘b_1010_1111_0101_0111        //非法写法,下划线不能放在数字的最前面

实数

        实数的表示方法有2种:10进制表示法(decimal notation)科学计数法(scientific notation)

10进制表示法

        该方法有小数点,且小数点两边都必须存在至少一位数字。例如:

1.2                //合法写法

0.1                //合法写法

2394.26331  //合法写法

.12  //非法写法,小数点左侧不存在至少一位数字

9.    //非法写法,小数点右侧不存在至少一位数字

科学计数法

        把一个数表示成 a(1≤|a|)与10的n(n为整数)次幂相乘的形式,其中10的整数次幂用e(或E)+ 数字来表示,例如10的8次幂即为e8或E8。例如:

1.2E2     //大小为120

0.1e-0    //大小为0.1

29E-2     //大小为0.29

.2e-7      //非法写法,小数点左侧不存在至少一位数字

4.E3       //非法写法,小数点右侧不存在至少一位数字

转换

        实数到整数的转换采用四舍五入(round)的方法,而非直接截取整数部分。例如:

35.7  >>  36

1.5  >>  2

-1.5  >>  -2

6、字符串(String)

        字符串是由包含在双引号(double quotes)" " 内的多个字符组成的有限序列。字符串存储在reg变量中,每个字符都需要8 bits的空间。例如:

reg [8*12:1] stringvar;                //位宽96 bits

initial begin

        stringvar = "Hello world!";  //12个字符,共需要12*8=96 bits

end

        字符串不能跨行书写,即字符串中不能包含回车符。下面是跨行的非法写法:

reg [8*12:1] stringvar;               

initial begin

        stringvar = "Hello

world!";                                       //非法写法

end

        如果字符串的内容大于存储空间,则最高测(最左侧)的多余内容会被截掉;如果字符串的内容小于存储空间,则最高测(最左侧)的多余空间会填充0。例如:

module	tb_test;reg	[3*8 : 1]	str1;
reg	[7*8 : 1]	str2;initial beginstr1 = "Hello";    //5字符放入3个byte,左侧多余的 "He" 会被截掉$display("%s is stored as %h", str1,str1);    //打印str1str2 = "Hello";    //5字符放入7个byte,左侧多余空间会用0填充$display("%s is stored as %h", str2,str2);    //打印str2
endendmodule

        字符串是以字符的ASCII码形式存储的(H e l l o的ASCII码分别为 0x48 0x65 0x6c 0x6c 0x6f),所以上面代码的打印内容是这样的:

llo is stored as 6c6c6f                                //多余的左侧两位 He 被截断
  Hello is stored as 000048656c6c6f         //多出的左侧两位空间被填充 0

        还有一类字符被称为转义字符----以反斜杠 \ 为开头,后面跟一个或几个字符,其意思是将反斜杠 \ 后面的字符转变成为另外的意义。例如 \n 不代表字母n而作为换行字符。类似的转义字符还有:

转义字符说明
\n换行字符
\t制表字符
\\\
\""

7、标识符(Identifier)

        标识符是指用来标识某个实体如变量、信号、模块等(object)的独特符号,它可以是任意一组字母、数字、$ (美元符号)和 _(下划线)符号的组合,但标识符的第1个字符必须是字母或者下划线,且不能以数字或者美元符号开始。此外,标识符是区分大小写的。

shiftreg_a                 //合法标识符

busa_index               //合法标识符

error_condition         //合法标识符

merge_ab                 //合法标识符

_bus3                        //合法标识符

n$657                        //合法标识符

23                              //非法标识符,不能以数字开始

2var                           //非法标识符,不能以数字开始

$var                           //非法标识符,不能以美元符号开始

        标识符的长度限制取决于具体使用的编译器,但是这个限制长度至少要大于1024个字符。如果标识符超出长度,那么编译器需要发出错误警告。

        为了能够使用标识符集合以外的字符或标号,除了普通的标识符外, Verilog还定义了转义标识符(Escaped identifiers)。采用转义标识符可以在一条标识符中包含任何可打印的字符。转义标识符以反斜杠开头,以空白字符(空格字符、制表字符或换行字符)结尾。例如:

\busa+index

\-clock

\***error-condition***

\net1/\net2

\{a,b}

\a*(b+c)

        开头的反斜杠和结尾的空白字符都不会被视为转义标识符的一部分,例如 \cpu3 就等价于 cpu3 。

8、关键字(Keyword)

        关键字是 Verilog 中预留的用于定义语言结构的特殊标识符。关键字不能转义,且关键字全部为小写。下图是Verilog-2005中的所有关键字:

9、其他

        除了上述的7类语法外,Verilog中还有一些特殊的语法。

系统任务和函数

        系统任务和函数(System tasks and functions)是一类预定义好的系统子函数,用于实现特定的功能。它们不是Verilog的功能语法,一般只能用于仿真。所有的系统任务都以美元符号$作为开始,例如:

$display ("display a message");        //打印系统任务,用于仿真时打印信息

$finish;                                               //结束仿真系统任务,用于结束仿真

编译指令

        以反引号 ` 开始的编译指令(Compiler directives )为Verilog代码的编写、编译、调试等提供了极大的便利。例如:

`define wordsize 8  //定义wordsize等价于8

属性

        属性(Attributes)通俗来讲,就是Verilog开放的某些特定操作的接口。例如:

(* fsm_state *) reg [7:0] state1;        //指定这是状态机的状态编码

        如果不添加属性(* fsm_state *),那么后面定义的reg state1有可能不会被综合工具指定为状态机的状态编码。


  • 📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

相关文章:

深入浅出学Verilog--基础语法

1、简介 Verilog的语法和C语言非常类似,相对来说还是非常好学的。和C语言一样,Verilog语句也是由一连串的令牌(Token)组成。1个令牌必须由1个或1个以上的字符(character)组成,令牌可以是&#x…...

基于Spring、SpringMVC、Mybatis的超市管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SSM的超市订单管理系统,java项目。 …...

spring中的@Configuration配置类和@Component

在Spring的开发工作中,基本都会使用配置注解,尤其以Component及Configuration为主,当然在Spring中还可以使用其他的注解来标注一个类为配置类,这是广义上的配置类概念,但是这里我们只讨论Component和Configuration&…...

企业架构LNMP学习笔记29

Nginx负载均衡配置: 架构分析: 1)用户访问请求Nginx负载均衡服务器; 2)Nginx负载均衡服务器再分发请求到Web服务器。 实际配置负载均衡,只需修改作为负载均衡服务器的Nginx即可,当前架构中的…...

Ubuntu14.04离线安装gcc-5.3.0

离线安装gcc 下载gcc安装包下载相关依赖下载gmp下载mpfr下载mpc 编译、安装gcc配置环境变量 拉取的一个虚拟机使用的系统是Ubuntu14.04,gcc版本是4.8.4,由于gcc版本较低,不太支持Libtorch,于是搜寻了许多办法来解决这个问题&#…...

axios返回几种数据格式? 其中Blob返回时的size是什么意思?

axios返回几种数据格式? 其中Blob返回时的size是什么意思? 1、字符串(String):服务器可以返回纯文本或HTML内容,Axios会将其作为字符串返回。 2、JSON(JavaScript Object Notation)&#xff…...

【GO语言基础】基本数据类型

系列文章目录 【Go语言学习】ide安装与配置 【GO语言基础】前言 【GO语言基础】变量常量 【GO语言基础】数据类型 文章目录 系列文章目录数据类型数值型:整数类型:浮点数类型: 字符型-布尔型-字符串零值转义字符 常用类型转换运算符总结 数据…...

【Python】OpenCV立体相机配准与三角化代码实现

下面的介绍了使用python和OpenCV对两个相机进行标定、配准,同时实现人体关键点三角化的过程 import cv2 as cv import glob import numpy as np import matplotlib.pyplot as pltdef calibrate_camera(images_folder):images_names = glob.glob(images_folder...

通过Idea或命令将本地项目上传至git

通过Idea或命令将本地项目上传至git 一、Git创建仓库 1、登录Gitee账号,点击新建 2、填写如下相关信息,点击创建 3、在此处可以复制项目链接 二、Idea配置和解绑git,提交项目 1、idea打开项目,操作如下 2、在弹框里选择…...

python selenium 爬虫教程

Python和Selenium是很强大的爬虫工具,可以用于自动化地模拟浏览器行为,从网页中提取数据。下面是一个简单的使用Python和Selenium进行爬虫的案例。 入门: 1. 安装和配置: 首先,你需要安装Python和Selenium。可以使用…...

Linux基础知识及常见指令

Linux简介及相关概念 什么是Linux? Linux是一个免费开源的操作系统内核,最初由Linus Torvalds于1991年创建。它是各种Linux发行版(通常称为“发行版”)的核心组件,这些发行版是完整的操作系统,包括Linux内…...

分享一个基于Python和Django的产品销售收入数据分析系统源码

💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…...

UniTask保姆级教程

目录 一、UniTask的简介和安装 https://github.com/Cysharp/UniTask.gitpathsrc/UniTask/Assets/Plugins/UniTask 空载性能测试 二、基础用法详解 三、基础用法扩展 四、进阶 五、VContainer简介 六、VContainer基础实例 方便快速查找 一、UniTask的简介和安装 项目地…...

uni-app 可视化创建的项目 移动端安装调试插件vconsole

可视化创建的项目,在插件市场找不到vconsole插件了。 又不好npm install vconsole 换个思路,先创建一个cli脚手架脚手架的uni-app项目,然后再此项目上安装vconsole cli脚手架创建uni-app项目 安装插件 项目Terminal运行命令:npm…...

HOperatorSet.GenRandomRegions 有内存泄漏或缓存,释放不掉

开发环境 VS2022 win7 halcon12 halcon18 随机生成100个园 不释放 private void butTemp_Click(object sender, EventArgs e) { butTemp.Enabled false; HOperatorSet.SetSystem("clip_region", "false"); …...

一维数组笔试题及其解析

Lei宝啊 :个人主页 愿所有美好不期而遇 前言: 数组名在寻常情况下表示首元素地址,但有两种情况例外: 1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小 2.&数组名,这里的…...

微信小程序源码

1:仿豆瓣电影微信小程序 https://github.com/zce/weapp-demo 2:微信小程序移动端商城 https://github.com/liuxuanqiang/wechat-weapp-mall 3:Gank微信小程序 https://github.com/lypeer/wechat-weapp-gank 4:微信小程序高仿QQ…...

Browserslist 信息和配置使用整理

我们可以在各种前端工程看到 Browserslist 的配置身影,看似简单但实际上可能会有暗坑导致线上兼容问题,借此文来整理下 Browserslist 的信息。 Browserslist 是由 Autoprefixer 团队维护的一个开源项目,用于自动处理 CSS 和 JavaScript 文件…...

Matlab 如何选择采样频率和信号长度

Matlab 如何选择采样频率和信号长度 1、概述 在实际信号分析中经常会遇到要分辨出频率间隔为 的两个分量,在这种情形中如何选择采样频率和信号的长度呢? 2、案例分析 设有一个信号由三个正弦信号组成,其频率分别为 ,即&#xf…...

TPTU: Task Planning and Tool Usage of Large Language Model-based AI Agents

本文是LLM系列文章,针对《TPTU: Task Planning and Tool Usage of Large Language Model-based AI Agents》的翻译。 TPTU:任务规划和工具使用的LLM Agents 摘要1 引言2 方法3 评估4 相关工作5 结论 摘要 随着自然语言处理的最新进展,大型语言模型&…...

golang循环变量捕获问题​​

在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下: 问题背景 看这个代码片段: fo…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...