Verilog语法简易教程ppt课件_第1页
Verilog语法简易教程ppt课件_第2页
Verilog语法简易教程ppt课件_第3页
Verilog语法简易教程ppt课件_第4页
Verilog语法简易教程ppt课件_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、电子设计大赛 Verilog 与 FPGA,什么是Verilog HDL?,Verilog 是一种用于数字逻辑设计的硬件描述语言。 在设计中常用于硬件电路的行为级描述就是告诉电路,你应该做什么,做什么,再做什么!,Verilog与C语言,Verilog的某些语法是与C相似的。但只是形似,神是不同的! Verilog只是Verilog而已,你可以参考C,但不能当做C!你必须了解Verilog的本质。,记住!,你编写的Verilog代码,是会生成实际硬件电路的。而电路,一般都不是串行执行的,很多时候都是并行工作的。所以在Verilog中,你一定要对电路的时序图与数据量图有深刻的认识!,不是所有的V

2、erilog代码都能够转换成实际电路的,学习语法时要分辨清楚。那些可以转换成实际电路的,我们称为“可综合”!另外,即使你使用的可综合的代码去编写,如果你描述的电路实际上无法实现,也是无法综合的!,也许在C语言中,代码越简洁越好。但是在Verilog中绝不是这样!衡量Verilog代码的唯一标准,就是在代码正确与清晰的前提下,可以生成结构尽可能简单、功能却非常强大的电路!,也许有用的Tips,多使用编译器附带RTL Viewr看看RTL级原理图,看清楚你写的代码到底生成了什么样的电路。多使用SignalTap II Logical Analyzer,看看你写的模块的时序图,看看你写的模块输出的数

3、据的值,尽量忘记C吧,C可以帮助你记住Verilog里面的关键字,但是请不要用C的思想来编写Verilog。要使用Verilog的思想来编写Verilog,多写多练吧,无论学习什么练习都是王道。当你初步掌握了Verilog之后,推荐你看看Verilog 那些事儿进行进一步的学习。什么是Verilog的思想?也许你可要在那里找到答案。,语法-符号,标识符:赋给对象的唯一名称,可以是字母、数字、下划线和符号“$”的组合,且首字符只能是字母或者下划线。区分大小写,如“if”为关键字,而“IF”不是关键字。 注释:注释有两种:1,以“/*”开头,以“*/”结束。2,以“/”开头到本行结束。 这些和C语

4、言差不多。,语法-数字量,逻辑数值:(1)0:逻辑0; (2)1:逻辑1; (3)x:未知,不定 ; (4)z:高阻态。,整数常量:基本表达格式为:长度进制 数值 如: 6b96位二进制数 5o55位八进制数 9d69位十进制数 8h1f8位十六进制数 而没有“长度进制”声明时,默认为32位十进制数。如:40,-50。,参数:参数是特殊的常量,其语法结构是: parameter para1=const1,para2=const2 paraN=constN; 如:parameter BIT=1,BYTE=8;,语法-变量定义,数据类型:数据类型用来表示数字电路硬件中的数据存储和传送元素,可以理解

5、成变量。Verilog 中总共有两大类数据类型:线网类型和寄存器类型。 数据类型的总种类很多,这里只介绍两种最常用且可综合的类型:wire与reg。有兴趣的同学可以自行学习其他类型。 wire是线网类型,可以理解成电路中的一根导线,在实际综合中一般也是生成连接线。 reg是寄存器类型,就是电路中的寄存器、触发器或选择器。,语法-变量声明,命名规则:wire与reg变量的通用命名规则: wire/reg msb:lsb Varia1,Varia2; 例如:reg3:0 Sat;/Sat为4位寄存器 wire7:0 Line; /Line为8位线网 如果没有位宽声明,则默认为1位位宽。 注意:re

6、g和wire声明的都是无符号变量,若要声明有符号变量,可以在reg和wire后加上关键字signed。如:reg signed 7:0 Sat;,语法-变量赋值,在Verilog中,变量是不能随意赋值的,必须使用赋值运算符才可以进行赋值。其中assign称为连续赋值,对应于线网类型变量wire;initial或always称为过程赋值,对应于寄存器类型变量reg。下面作具体讲解,语法-assign与wire,首先列个例子: wire a; assign a=1b1; 可以看出,语法格式就是这么简单,如下: assign 线网型变量名=赋值表达式; 需要理解的是,assign称为连续赋值的意思是

7、,等号右端赋值表达式的值会持续对被赋值变量产生连续驱动,而且只要等号右端赋值表达式的值改变,左端被赋值变量的值就会立即改变。对应到电路中去,就是导线。,语法-assign与wire,下面列举一些实际中常用的用法:(1)wire a,b;assign a = b;(2)wire 7:0 a,b;assign a=b;(3)wire 7:0 a,b;assign a3=b1;(4)wire 7:0 a,b;assign a3:0=b3:0;(5)wire a,b;wire 1:0 c;assign c=a,b;,语法-initial/always与reg,首先列举两个例子说明initial与alw

8、ays的区别,reg a,c; initial begin c=1b0; end,reg a,c; always(a) begin c=c+a; end,initial只会执行一次,即只执行一次把C赋零的行为;而always会不断执行,即每一次a的值改变时,c都会被重新赋值。,这两个例子也非常清楚的说明了initial/always 与reg如何配合使用。要注意的是,其中begin end是必须加入的,而也必须和always一起使用。具体在后面进行讲解。,语法阻塞与非阻塞,于连续赋值assign不同的是,过程赋值中的赋值操作符分为两种,分别是:“=”,称为阻塞赋值,指的在当前的赋值完成前阻塞其

9、他类型的赋值任务;“=”,称为非阻塞赋值,指的从估计右端开始并不阻碍执行其他的赋值操作。 阻塞与非阻塞赋值的区别是Verilog中较为重要的一部分,将在后面进行详尽的讲解。,语法-算数运算符,算数运算符有5种:+,-,*,/,%,用于整型数据的数学运算。随着技术的发展,上述5种算术运算符都是可以直接综合的。需要注意的是,在进行加法和乘法运算时,要注意防止数据溢出造成运算错误。,语法-逻辑运算符与关系运算符,Verilog中的逻辑运算符与关系运算符同C语言中的用法相似,可以参考。 逻辑运算符分为3种:逻辑与“逻辑不等!=。如果操作数直接的关系成立,则返回值为1;关系不成立,则返回值为0。,语法-

10、条件运算符,条件运算符为“?:”,基本表达式为:y=x?a:b;与C语言一样,x为真时返回前一个操作数a,否则返回操作数b。,语法-位运算符,Verilog用位运算符来描述硬件电路中的逻辑门,共有5种:(1):非;(2) shr15:0=shr14:1,b,c; 重复操作符为,即双重花括号,提供复制一个常量或变量的简便记法,如:32b01=6b010101;,语法-移位运算符,移位运算符只有两种:(右移),其使用格式为:s1N,N为常数。 某些情况下移位运算符的效果也可以通过拼接运算符实现,这个看个人喜好与具体电路要求。,语法-一元约简运算符,一元约简运算符是一种特殊的位运算符,它对单个操作数

11、进行运算,最后返回一位数,具体运算过程为:首先将操作数的第一位和第二位进行位运算,然后将结果与第三位进行位运算,依次类推到最后一位,输出运算结果。示例如下:out1= 一元约简运算符主要用于特殊操作中,如与约简可检测数据中是否包含位1,或约简课检测数据是否包含0。,语法-begin end,前面已经提到过beginend了。beginend在Verilog中是非常基础但是十分重要的东西。那么什么是beginend?这里可以借助C来理解:“beginend就是C语言中的花括号,只不过在Verilog中有了别的用处了,所以用beginend来表示。”,语法-触发,“”,前面讲到了在过程赋值alwa

12、ys中,必须加上。为什么?过程赋值是什么?就是如果发生了什么行为,才给你赋值。那发生的行为就要用“(行为)”来描述,我们称之为触发,完整格式为always(触发事件)begin end,语法-触发事件,触发事件有两种,这是由硬件电路决定的,在数电中已经学过:电平触发,边沿触发。,电平触发的格式为 always (a) begin end 只要a的电平一改变,内部的过程赋值就进行一次。 电平触发不能直接选择触发的电平是高还是低,如果非要选择,可以在内部加入if语句进行判断:always (a)begin if(a=1b0)begin end end,与电平触发不同,边沿触发可以直接选择触发的边沿

13、:posedge表示上升沿触发,negedge表示下降沿触发。如: always (posedge clk)begin end 需要注意的是,边沿触发不可以选用某个信号的两个沿,即不能(posedge clk or negedge clk),注意事项! 同一个always模块中只能使用一种触发方式,不可以边沿触发与电平触发混合使用。 不同的触发事件中间用“or”隔开,也可以用“,”隔开。,语法-条件语句if,Verilog中的if语句与C语言中十分相似,可以直接进行参考。需要注意的是,ifelse中,即使用不到else分支,语句中else分支也最好加上,否则电路有可能生成不稳定的电路,造成结果

14、的错误。,if(a=1b1) c=1b0; 应写成,if(a=1b1) c=1b0; else c=c;,语法-条件语句case,case与C语言中的switch比较类似,但是具体又有区别。其语法格式如下:,case(条件表达式) 分支1:语句块1; 分支2:语句块2; default:语句块n; endcase,reg 2:0 cnt; case(cnt) 3b000:q=q+1; 3b001:q=q+2; default:q=q; endcase,语法-条件语句case,当几个分支对应的操作相同时,可以将这些分支放在一起,如: reg 2:0 cnt; case(cnt) 3b000,3b

15、001,3b010:q=q+1; 3b011,3b100:q=q+2; default:q=q; endcase,另外,同else一样,default一般不要缺省。,语法-条件语句if与case的区别,最大的区别是,if生成的电路是串行,是有优先级的编码逻辑;而case生成的电路是并行的,各种判定情况的优先级相同。因此,if生成的电路延时较大,占用硬件资源少;case生成的电路延时短,但占用硬件资源多。,语法-循环语句,Verilog中也是有循环语句的,但是不推荐初学者使用。与C不同,Verilog的循环语句是依靠电路的重复生成实现的,而且并不是所有的循环语句都可以综合。 感兴趣的同学可以在深

16、入了解Verilog后自学循环语句。,语法-任务和函数,Verilog中还有两种特殊的语句:任务(task)和函数(function)。这两种语句一般用于组合电路的设计中,可以简化代码结构,但在时序电路的设计中无法使用。 感兴趣的同学可以在深入了解Verilog后自行学习。,语法-模块的概念,模块(module)是Verilog中最基本的概念,也是最常用的基本单元。一个module就是一整块电路实体,一个系统就是由许多个module组成的。 需要注意的是,在Quartus中,一个Verilog HDL文件(*.v)中只能编写一个module,而且文件名必须与module的名字相同。,语法-mo

17、dule的结构,module的基本结构如下: module 模块名 (端口列表) 端口声明 其他声明 模块条目 endmodule,端口声明有3钟:(1)input:输入端口,可以理解为输入脚;(2)output:输出端口,可以理解成输出脚;(3)inout:输入输出端口,可以理解成双向管脚。,语法-module实例:3-8译码器,module decoder3to8(din,dout); input 2:0 din; output 7:0 dout; reg 7:0 dout; always(din) begin case(din) 3b000:dout=8b0000_0001; 3b001

18、:dout=8b0000_0010; 3b111:dout=8b1000_0000; endcase end endmodule,语法*-阻塞与非阻塞的深入理解,前面说过,过程赋值有两种:阻塞赋值“=”和非阻塞赋值“=”。那么它们有什么区别呢? 说的最简单的话,阻塞式赋值左边的变量在被赋予新值前,之后用到该变量的阻塞赋值式都无法执行,而非阻塞赋值则不会。在组合逻辑和时序逻辑电路中都可以这样理解。,语法*-阻塞与非阻塞的深入理解,首先看组合逻辑中的区别,看下面两个例子,always(a,b,c,d)begin t1=a end,always(a,b,c,d)begin t1=a end,当a,b

19、,c,d都从0变为1时,左边out输出1,右边out仍为0。 因为t1的值由a,b决定,t2的值有c,d决定,在左边,由于阻塞,t1、t2被赋新值前不能给out赋值,out使用的t1,t2存储的是新的数值1;而在右边,由于 非阻塞,out赋值式立刻执行,out使用的t1,t2存储的是旧的数值0。,语法*-阻塞与非阻塞的深入理解,再来看时序逻辑中的区别,看下面两个例子,always(posedge clk) q1=d; q2=q1; q3=q2; end,always(posedge clk) q1=d; q2=q1; q3=q2; end,可以看到,实际生产的电路是不同的。在左边,由于阻塞的关

20、系,q3最后直接等于d,电路便被简化成左图了;在右边,由于非阻塞q2、q3分别对应着上一时钟沿的q1,q2,因此需要3级触发器来实现。,语法*-阻塞与非阻塞的深入理解,编码建议: (1)对组合逻辑建模采用阻塞式赋值; (2)对时序逻辑建模采用非阻塞式赋值; (3)同一个module中阻塞与非阻塞赋值放在不同的always块中。,语法*-模块调用,对于一个复杂的系统,是不可能把所有的功能都放在一个module中完成的。一般都是按照功能进行划分,分别封装成多个module,在需要用到某个module时再去调用。被成为模块调用。 下面举例说明:首先假设有一个乘法器,可以实现8位整型数乘法,其端口声明

21、为: module mult8(a0,a1,b); input 7:0 a0,a1; output 15:0 b; endmodule,语法*-模块调用,然后在另一个module中调用它: module co (c1,c2,c3,c4,result); input 7:0 c1,c2,c3,c4; output reg result; reg15:0 temp1,temp2; mult8 inst_1( .a0(c1), .a1(c2), .b(temp1) );,mult8 inst_2( .a0(c3), .a1(c4), .b(temp2) ); result=(temp1temp2)?

22、1:0; endmodule 这样就实现了模块的调用,最终实现了将输入数据相乘后比较大小的结果输出。,语法*-模块调用,根据上面例子,可以给出模块调用的语法格式: 模块名 例化后名( .端口1名(连接端口1信号名), .端口2名(连接端口2信号名), .端口3名(连接端口3信号名), ); 其中,掉用时端口的顺便可以改变,只要名字正确即可;例化后名不能为元模块名或关键字。,语法*-状态机,状态机并不是属于Verilog的范畴,但是通过Verilog实现状态机可以帮助我们简化很多设计,所以状态机一定要掌握! 状态机可分为两种:Mealy型和Moore型状态机。Mealy型状态机的输出同时依赖于当

23、前状态和输入信号,输出可以在输入发生改变之后立刻改变,而与时钟信号无关,因此Mealy型状态机具有异步输出;Moore型状态机的输出仅仅依赖于当前状态,输出是通过组合逻辑块计算得到的,本质上是当前状态的函数。,语法*-状态机,Mealy型,Mealy型,语法*-状态机,状态机设计原则: 1,给事件划分步骤,弄清楚先做什么,再做什么,做了这一步下一步应该怎么样做。 2,状态化简与状态分配。检查下是否有冗余,重复的步骤。当状态划分到最简后,给每个状态进行编码分配。 3,通过Verilog实现。这里有很多模板,后面进行讲解。 4,观察编译结果的状态流程图,检查状态机功能是否正确。,语法*-状态机,编

24、码分配原则:状态的编码形式一般有三种,普通的二进制编码,格雷码编码,One Hot码编码(One Hot码对应关系:0,0000;1,0001;2,0010;3,0100;4,1000)。二进制码占用的数据位宽比较简单,但容易产生毛刺;格雷码一定程度减少了毛刺的产生;One Hot码不会产生毛刺,可以使状态机达到较高的工作频率,但是会增加触发器的占用。具体选用什么码根据实际需求,一般普通二进制编码即可。,语法*-状态机,“一段式”状态机Verilog模板: always(posedge clk) begin if(!rst_n) begin state= out= end else begin

25、 case(state) s0:begin state= out= end,s1:begin state= out= end endcase end end 这种形式输出向量不会产生毛刺,但是不能实现异步Mealy有限状态机。,语法*-状态机,“二段式”状态机Verilog模板: /状态调转 always(posedge clk)begin if(!rst_n) state= idle; else state =next_state; end /下一状态的计算以及输出逻辑 always(state)begin case(state) s0:begin next_state = out =,en

26、d s1:begin next_state = out = end endcase end 这种形式具有最优的面积和时序性能,但输出组合逻辑,有可能产生毛刺。,语法*-状态机,飞“三段式”状态机Verilog模板: /状态调转 always (posedge clk)begin if(!rst_n) state=idle; else state=next_state; end /下一状态的计算 always(posedge clk) begin case(state) s0:next_state= s1:next_state= endcase,end /输出的逻辑处理 always(posed

27、ge clk) begin case(state) s0:out= s1:put= endcase end 这种形式的输出同样无毛刺,是一些参考书上的推荐写法。,写在Verilog的最后,下面是一些我推荐的代码风格,同学们可以参考一下,希望对同学们学习Verilog有帮助; 模块声明:module(/input a, b, /output c, d ); 在声明时就用注释将输入输出脚区别出来。,写在Verilog的最后,异步复位的always: always(posedge clk,negedge rst_n)begin if(!rst_n)begin /一堆复位的行为 end else be

28、gin end end 模块带有异步复位的功能推荐都这样写,FPGA的概述,Filed programmable gate array,现场可编程门阵列。 FPGA的引脚分为电源脚,I/O脚,特殊功能脚。能给外设使用的只有I/O脚。 FPGA的逻辑实现是通过查找表的方式实现的,就是通过RAM来实现逻辑函数。所以,FPGA内部没有真正的逻辑门。,FPGA使用注意,FPGA内部是RAM,RAM掉电丢失数据,所以与CPLD不同,FPGA普通下载的程序在掉电后是没有了的。 FPGA内部没有真正的逻辑门,所以不要在内部使用带高阻态的输出相连,编译器不会报错,但是电路功能是无法实现的。如果非要把两个输出连一起,可以使用“:?”进行二选一。 FPGA的I/O引脚电路是支持双向高阻态的。,FPGA内部硬件,1.锁相环(PLL):可以将输入的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论