当前位置: 首页 > 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 结论 摘要 随着自然语言处理的最新进展,大型语言模型&…...

【Spring IoC容器的加载过程】

加载配置文件 Spring IoC容器的配置通常以XML形式存储,并通过ResourceLoader和XmlBeanDefinitionReader类来加载。ResourceLoader主要负责加载Bean配置文件,而XmlBeanDefinitionReader则负责解析这些文件,将Bean定义封装为BeanDefinition对象…...

C++多文件类的声明与实现

...

16 “count(*)“ 和 “count(1)“ 和 “count(field1)“ 的差异

前言 经常会有面试题看到这样的问题 “ select count(*) ”, “ select count(field1) ”, “ select count(1) ” 的效率差异啥的 然后 我们这里 就来探索一下 这个问题 我们这里从比较复杂的 select count(field1) 开始看, 因为 较为复杂的处理过程 会留一下一些关键的调试…...

【云原生进阶之PaaS中间件】第一章Redis-1.4过期策略

1 设置带过期时间的 key # 时间复杂度:O(1),最常用方式 expire key seconds# 字符串独有方式 setex(String key, int seconds, String value)除了string独有设置过期时间的方法,其他类型都需依靠expire方法设置时间&a…...

windows弹出交互式服务检测一键取消bat脚本

现象 脚本命令 新建一个bat文件,将下面的脚本拷贝进去,保存,双击即可 禁用服务:重启电脑的时候不会启动 停止服务:立即停止服务,马上生效的 sc config UI0Detect start disabled net stop UI0Detect...

接口使用的最佳时机

1. 引言 接口在系统设计中,以及代码重构优化中,是一个不可或缺的工具,能够帮助我们写出可扩展,可维护性更强的程序。 在本文,我们将介绍什么是接口,在此基础上,通过一个例子来介绍接口的优点。…...

freertos之任务运行时间统计实验

这里写目录标题 任务时间统计函数时间统计API函数使用流程实验 任务时间统计函数 void vTaskGetRunTimeStats(char * pcWriteBuffer); 时间统计API函数使用流程 实验 1.首先现在FreeRTOSConfig.h文件里将configGENERATE_RUN_TIME_STATS 和configUSE_STATS_FORMATTING_FUNCTIO…...

Js中一些数组常用API总结

前言 Js中数组是一个重要的数据结构,它相比于字符串有更多的方法,在一些算法题中我们经常需要将字符串转化为数组,使用数组里面的API进行操作。本篇文章总结了一些数组中常用的API,我们把它们分成两类,一类是会改变原…...

LlamaIndex:将个人数据添加到LLM

推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 LlamaIndex是基于大型语言模型(LLM)的应用程序的数据框架。像 GPT-4 这样的 LLM 是在大量公共数据集上预先训练的,允许开箱即用的令人难以置信的自然语言处理能力。但是,…...

Mojo 摸脚语言,似乎已经可以安装

文章原地址:https://i.scwy.net/it/2023/090821-mojo/ Mojo 吹得很凶,面向AI编程,甩Python几十条街,融资上亿.... 但无缘一试,在Win和Ubuntu上试都不能通过。 由 LLVM 和 Swift 编程语言的联合创始人 Chris Lattner…...