文章目录
前言
上文我们对Verilog语言有了一定的了解,知道了Verilog语言是一种硬件描述语言,他能够在EDA工具上综合成实际的电路,在FPGA或者单片机开发领域有着很高的地位。
我们学习一门语言,肯定需要学习它的语法结构,就像学习C语言一样,我们相应对某一事件重复操作,我们可以用for循环实现,这就是一种语法结构,弄清楚了会极大地提高我们的开发效率。Verilog语言的语法结构还是挺简单的,相信比其他语言来得容易。
下面我们看一端简单的代码来了解Verilog的端口定义基础知识:
module adder(
input [2:0] a ,
input [2:0] b ,
input cin ,output count ,
output [2:0] sum
);assign {count,sum} = a + b + cin;
endmodule
这个例子通过连续赋值语句描述了一个模块名为adder的三位加法器可以根据两个三比特数a、b和进位cin计算出和(sum)和进位(count)。
通过这个例子,一个模块由module开头,endmodule结束,紧跟着module后面的是模块名。模块名后面括号里面的是输入输出端口信号,input为输入端口,output为输出端口,中括号里面是位宽,当没有指定位宽时默认为32位宽,{}叫做位拼接运输符,中间用逗号隔开,后面我们会细讲。
标识符用于定义模块名、端口名和信号名等,上面代码里的adder就是一个标识符,也是模块名。Verilog的标识符可以是任意一组数字、字母、下划线等符号的组合,但是标识符的第一个字符必须是字母或者下划线。
标识符虽然可以任意定义,但是它是区分大小写的,比如Count和count就不是同一个标识符,这点需要注意。对于标识符的定义虽然没有限制,但是我们最好还是遵循一定的规则,以便于你以后回来对代码升级维护时一眼就能知道这个模块是干什么的。
关于标识符的规范,我这里有几个建议:
① 模块名定义最好见名知其意,定义的模块名最好和代码实现的功能相关,如sum等。
② 用下划线来隔开两个词组,看起来简单易懂,如cpu_addr就要比cpuaddr好很多。
③ 系统时钟和复位信号统一写法,系统时钟用clk,复位用rst_n。
④ 采用一些前缀或者后缀命名,如cnt_500ms、clk_50mhz等。
⑤ 参数统一大写,如TIME_SHOW。
⑥ 自定义的标识符不能与关键字同名。
逻辑电路中一般有4种逻辑值,表示4种逻辑状态:
逻辑 0:表示低电平,也就是对应电路中的接地(GND)。
逻辑 1:表示高电平,也就是对应电路中的电源(VCC)。
逻辑 X:表示未知态,有可能是高电平,也有可能是低电平。
逻辑 Z:表示高阻态,即表示一个悬空状态。
在Verilog语言中的进制格式主要有二进制、八进制、十进制和十六进制,一般我们常用的就是二进制、十进制和十六进制。
① 二进制:只有0和1两字符,满二进一,4’b0010表示4位二进制数字0010;
② 八进制:满八进一,4'o0011表示4位八进制数字0011;
③ 十进制:满十进一,4'd2表示4位十进制数字2;
④ 十六进制:满十六进1,4'ha表示4位十六进制数字a,十六进制的计数方式为0~f。
在进制换算中我们还需要注意:
① 换算为二进制后位宽的总长度 > 与数值进制符号对应的数值的实际位数时,则自动在与数值进制符号对应的数值的左边补0。如2'd10换算成二进制为4'b1010,则把2'd10补位为4'd0010。
② 换算为二进制后位宽的总长度 < 与数值进制符号对应的数值的实际位数时,自动截断与数值进制符号对应的数值左边超出的位数。
③ 数字中的下划线没有任何意义,只是为了提高可读性,如25_0000与250000相同。
在Verilog语法中,主要有三大数据类型,分别是寄存器类型,线网类型和参数类型。
寄存器是数据存储单元的抽象。寄存器数据类型的关键字是reg,通过赋值语句可以改变寄存器储存的值,但reg类型只能在always语句和initial语句中被赋值,并且它的值从一个赋值到另一个赋值过程中被保存下来。如果该过程语句描述的是时序逻辑,即always语句中带有时钟信号,则该寄存器变量对应为寄存器;如果该过程语句描述的是组合逻辑,即always语句中没有时钟信号,则该寄存器变量对应为硬件连线。寄存器类型的却省值是X,寄存器的数据类型有很多种,如reg、integer、real等,但我们常用的就是reg类型。
wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。 线网类型表示Verilog结构化元件间的物理连线,它的值由驱动元件的值确定。如果没有驱动元件连接到线网,线网的缺省值为z(高阻态)。
所谓参数其实就是一个常量,我们在状态机定义、数据大小定义时都会用到参数,由于它可以在编译时修改参数的值,因此它又常被用于一些参数可调的模块中,使用户在实例化模块时,可以根据需要配置参数。
参数类型可以分为全局参数类型和局部参数类型,所谓全局参数类型是指该参数不仅在本模块中实用,在其他模块中还可以调用该参数。而局部参数类型就只在当前模块中有效。
Verilog HDL语言的运算符范围很广,运算符按其功能可分为:①算术运算符、②关系运算符、③逻辑运算符、④条件运算符、⑤位运算符、⑥移位运算符、⑦拼接运算符。
Verilog中的算术运算符有:+、-、*、/ 、%
算术运算符就是我们常说的加减乘除,数字逻辑处理有时候也需要进行数字运算,所以需要算术运算符。在Verilog语法中常用到了算术运算有+、-、*、/和%。值得注意的是,Verilog实现乘法和除法比较浪费逻辑资源,一般能进行移位的我们用移位替代。
Verilog中的关系运算符有:> 、< 、>= 、<= 、==、!=
关系运算符主要是用来做一些条件判断的,在进行关系运算符时,如果声明的关系是假的,则返回值0,如果声明的关系是真的,则返回值1;所有关系运算符都有着相同的优先级。
Verilog中的逻辑运算符有: ! 、&& 、 ||
逻辑运算符是连接多个关系表达式用的,可实现更加复杂的判断,一般不单独使用,都需要配合具体语句来实现完整的意思。
Verilog中的条件运算符有: ?:
条件运算符一般用来构建从两个输入中选择一个作为输出的条件选择结构,功能与always中的if - else语句差不多。
Verilog中的位运算符有:~、&、|、^
位运算符是一类基本的运算符,可以把他们当成与、或、非逻辑门看待。
Verilog中的移位运算符有:<< 、>>
移位运算符包括左移运算符和右移运算符,左移运算符相当于乘法,右移运算符相当于除法。如果a = 8‘b00000011,将其左移两位得a = 8'b00001100。
Verilog中的位拼接运算符有:{}
这是C语言中所不具备的运算符,假设有两个4bit的数a = 4'b0011 和 b = 4'b1100,则将其进行位拼接为{a,b} = 8'b00111100。
在Verilog语法中,运算符也是有优先级的,下面是verilog中的运算符优先级表格:

在经过上面是基本知识点的介绍之后,我们对Verilog语法也有了一定的了解。那么我们利用Verilog进行程序设计的话也是有一定的框架的,有了这个框架,可以极大地提高我们的代码可读性和可移植性,对别人学习你的代码也是非常友好的。但这样的框架结构并不是唯一的,下面是我常用的程序框架。

我个人是习惯用这样的框架来编写程序的,首先是输入输出定义,然后是需要用到的参数,后续需要修改参数的话也是很方便的,接下来就是状态机参数定义(如果需要用到状态机),然后是需要用到的中间信号定义。接下来就是程序的主体部分了,主体部分也是先写状态机,然后写满足状态机的条件(计数器以及其他条件),最后写输出。
作为一个程序设计者,必要的程序注释还是要有的,注释不仅仅是为了给别人看,而是让自己一眼明了该程序的功能,如果你长时间没有去接触这个程序,那么有可能这个程序所实现的功能你也会忘记,就算你自己会弄明白,但也要花费一定的时间,但如果我们对程序写一些中文或者英文注释,那么我们一眼就能看出这个程序是干什么的了。
在Verilog语言中,程序的注释可分为单行注释和多行注释,如果是对单行注释,那么只需要注释符号 // 后的全都是注释的内容;如果是多行注释,就像上面框架那样,那么注释符号 /* */内的是注释内容。
Verilog语言和C语言一样,都因编写需要定义一些关键字,这些关键字是识别语法的关键。所以我们在对模块或者信号进行命名时不要与所保留的关键字一样。下面是Verilog语法中所有的关键字。

看到这么多关键字,是不是人都傻了!但是别慌,虽然有这么多关键字,但是我们刚开始实际用到的并不多,等你全部都能用上的时候,你已经是这个领域的大佬级人物了。下面我就来盘点一些我们经常用到的关键词,其实没几个。
1、module(模块开始定义),2、endmodule(模块结束定义),3、input (输入端口定义),4、output(输出端口定义),5、inout(双向端口定义),6、parameter(参数定义),7、wire(wire型信号定义),8、reg(reg型信号定义),9、always (产生reg信号语句关键字),10、assign(产生wire信号语句关键字),11、begin....end (相当于括号),12、posedge/negedge(时序电路标志),13、case(Case语句开始标志),14,endcase(Case语句结尾标志),15、default(Case语句默认分支标志),16、if ....else(if/else语句),17、for(for语句标志)。
注意保留关键字全部都是小写哦!!!!!
这篇文章总结了一些Verilog语法中最基础的一些东西,也对Verilog程序设计框架做了简单的介绍,总体来说还是比较简单的。如果大家需要用到其他的关键字,还是得去看一看Verilog语法相关的书籍,书上讲的肯定要详细一点的,我这里只是简单总结一下。
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a
可能已经问过了,但我找不到它。这里有2个常见的情况(对我来说,在编程Rails时......)用ruby编写是令人沮丧的:"astring".match(/abc(.+)abc/)[1]在这种情况下,我得到一个错误,因为字符串不匹配,因此在nil上调用[]运算符。我想找到的是比以下内容更好的替代方法:temp="astring".match(/abc(.+)abc/);temp.nil??nil:temp[1]简而言之,如果不匹配,则简单地返回nil而不会出错第二种情况是这样的:var=something.very.long.and.tedious.to.writevar=some
我正在学习Ruby的基础知识(刚刚开始),我遇到了Hash.[]method.它被引入a=["foo",1,"bar",2]=>["foo",1,"bar",2]Hash[*a]=>{"foo"=>1,"bar"=>2}稍加思索,我发现Hash[*a]等同于Hash.[](*a)或Hash.[]*一个。我的问题是为什么会这样。是什么让您将*a放在方括号内,是否有某种规则可以在何时何地使用“it”?编辑:我的措辞似乎造成了一些困惑。我不是在问数组扩展。我明白了。我的问题基本上是:如果[]是方法名称,为什么可以将参数放在括号内?这看起来几乎——但不完全是——就像说如果你有一个方法Foo.d
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功
ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new