深入浅出学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)ÿ…...

【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、案例分析 设有一个信号由三个正弦信号组成,其频率分别为 ,即…...
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 结论 摘要 随着自然语言处理的最新进展,大型语言模型&…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...