ZYNQ学习笔记(四)---Verilog HDL基础知识

OK,我们到目前为止已经了解了芯片的架构、资源和使用这款芯片的开发流程,从今天开始就可以进入实践开发阶段了,本节我会先对近日所学的Verilog HDL语言知识进行总结。

目录

1.Verilog HDL基础

        1.1 Verilog HDL基本结构

        1.2数据类型及变量、常量

        1.3 运算符

        1.4 语句


1.Verilog HDL基础

1.1 Verilog HDL基本结构

        对于Verilog HDL的结构要求,我列出了以下几点供大家参考:

  1. Verilog HDL程序是由模块构成的。每个模块嵌套在module和 endmodule声明语句中。
  2. 每个Verilog HDL源文件只有一个顶层模块,其他为子模块可以每个模块写一个文件
  3. 每个模块要进行端口定义,并说明输入输出的端口,然后对模块的功能进行行为逻辑描述。
  4. 模块中的时序逻辑部分要在always块的内部,在always块中只能对寄存器变量进行赋值。
  5. 模块中对端口或其他wire型变量的赋值,必须在always块的外部用assign语句进行赋值,通常是将always内部的寄存器的值送出。
  6. 代码书写格式自由,一行可以写几个语句,一条语句也可分多行写。
  7. 除了endmodule语句、begin_end语句和fork_join语句之外,每个语句和数据定义的最后必须有分号。
  8. 代码注释可以采用//...或者/* ... */。

下图为一个简单例子。 

图1.1

1.2 数据类型及变量、常量

1.2.1 数据类型 

Verilog中有两种常用的数据类型,分别是线网类型变量类型,这两种类型都属于四态数据类型,有着4种可能的逻辑值(0、1、X、Z)。相信学过数字逻辑的同学对这四种状态肯定都比较熟悉。

图1.2.1 

对于线网类型,重点是常用的wire型变量;对于变量类型,重点是reg型变量

我们也可以说成是wire型信号和reg型信号。(我理解是,他们是在电路之间传递的,就像传递信号一样。在VHDL中似乎也有这种说法,但是VHDL的语法更加复杂。)

对于wire型信号和reg型信号的定义如下:

图1.2.2 

图1.2.3 

 ok我们现在对verilog中的数据类型和变量都有了基本的认识,那么对于常量呢?

Verilog HDL中符号常量的定义如下:

如果用关键词parameter来定义一个标识符,代表一个常量,这个常量就被称为符号常量。

值得注意的是,对于已经定义好的符号常量,我们可以在后续调用模块时再对其进行重定义

下面给出了一个符号常量定义及其重定义的例子。

图1.2.4 

 重定义的例子如下:

图1.2.5 

  我们再adder中将常量time_delay的值定义为5,time_count为10,可以看到,后续调用模块时采用了#(4,8)把常量的值重新定义。

 存储器型变量,实际上是一个寄存器数组,是由reg型衍生而来的,定义方式如下:

图1.2.6 

1.2.2 数的表达

在verilog中数的表达,大致有以下3种方式,我觉得从编程者角度来说,应当常采用完整的表达方式,这样也可以提高程序的可读性。

 图1.2.6

1.3 运算符

(1.)算术运算符

图1.3.1 

        需要注意的是,算术运算时,如果某一个操作数为X,则结果也是X。

(2.)逻辑运算符

图1.3.2

         常用于条件语句,同样的,若有一个输入为X,则结果也为X。

(3.)按位运算符

图1.3.3 

        这里注意以下按位同或,之前也没用过。

(4.)关系运算符

 

图1.3.4

        常用于条件判断,同样的,若某一操作数为X,则返回值也是X。 

(5.)等式运算符

 

图1.3.5

         这里需要注意下 === 和 !== 的用法,常用于case表达式的判别。(具体怎么用,我还没遇到过。)

(6.)缩减运算符

 

图1.3.6

       缩减运算是对单个操作数进行的运算,结果是1位的二进制数。

        查阅了一些资料,对于缩减运算符的运算过程大致如下:

第一步先将操作数的第1位和第2位进行与、或、非运算,第二步将运算结果与第3位进行与、或、非运算,以此类推直至最后一位。

(7.)移位运算符

图1.3.7

(8.)条件运算符

图1.3.8

这里需要注意的是,条件运算符?不能对寄存器变量(reg)进行赋值。

(9.)拼接运算符 

 

 图1.3.9

 

  图1.3.10

(10.)运算符优先级

图1.3.11 

1.4 语句

1.4.1 赋值语句

赋值语句分为两类连续赋值语句过程赋值语句,介绍如下:

 图1.4.1

这里需要注意的是,对wire型变量赋值要使用连续赋值语句assign;而对reg型变量赋值就直接使用过程赋值语句 = 和 <= 即可。(过程块:由always或者initial引导的语句块)

1.4.2 结构说明语句

(1.)always语句

 图 1.4.2

值得说明的是,always也可以引导组合逻辑,不一定都是时序逻辑。

这里还需要注意的是,在always块中被赋值的只能是reg型变量。

注意格式:always@(敏感信号表达式)begin(语句块)end

(2.)initial语句

用于对寄存器变量赋予初值,可在其中使用条件语句进行赋值。

格式:initial begin(语句块)end

 

图1.4.3 

 1.4.3 阻塞赋值与非阻塞赋值

 图1.4.4

这是一个比较重要的概念,我的理解是这样,阻塞就是相当于时钟信号到达之后,赋值顺序进行,有先后次序;而非阻塞就是时钟信号到达之后,并行执行所有赋值语句,同一时间完成赋值。 

 1.4.4 条件语句

常用的条件语句分为两大类:if-else语句和case语句。

需要注意的是,条件语句用于always或initial过程块的内部

(1)if-else语句

Verilog HDL中的if-else语句和C语言中的基本是一样的,都是判定所给条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。

if-else语句有3种形式:

图1.4.5 

 注:

  • 如果语句有多条组成,必须包含再begin和end之内;
  • 3种形式的if语句后面都有表达式,一般为逻辑表达式或者关系表达式。当表达式的逻辑值为1,按真处理,若为0、X、Z其他三种逻辑值,则都按照假处理;
  • else语句不能单独使用,它是if语句的一部分。

(2)case 语句

case语句是一种多分支选择语句,if只有两个分支可以选择,但是case可以直接处理多分支语句,这样可以使得程序看起来更加简洁。

在verilog中有三种类型的分支语句,分别是case,casez,casex。

 图1.4.6

 图1.4.7

图1.4.8 casex的例子

这里需要注意的是, casex和casez是不同于C语言中的用法,我们两者选一就行,就比如casex,如果分支表达式某些位的值为X或者Z,那么比较时则可以不考虑对这些位的比较,比如上面这个例子。

1.4.5 循环语句

在Verilog中存在着多种循环语句,用来控制执行语句的执行次数。

但在FPGA设计中,循环语句有时不一定能被综合,就比如循环次数未知的循环语句。

循环语句多用于在仿真代码生成仿真激励信号。

(1.)forever语句:连续执行的语句

格式:forever begin(语句块)end

常用于仿真代码中。

(2.)repeat语句:连续执行N次的语句

格式:repeat(表达式)begin (语句块)end

其中,表达式用于指定循环次数,可以是一个整数、变量或者数值表达式。如果是变量或者表达式,其数值只会在第一次循环时得到计算,从而得到确切的循环次数。

也常用于仿真中。

(3.)while语句:执行语句,直至条件不满足时跳出循环

格式:while (表达式)  begin语句块end

表达式通常是一个逻辑表达式或者关系表达式。

在每次执行循环体之前,都需要对这个表达式判断是否成立。

(4.)for语句

 有时我们在使用while语句时,循环次数并不是确定的,而for语句则可以很轻松的确定出循环次数。如果要让系统能够综合,那么循环的次数一定是固定的。

格式:for(循环变量赋初值;循环执行条件;循环变量增值)begin (语句块)end

例如:for(i=1;i<=8;i=i+1)begin...end

本节内容完,欢迎大家指正讨论!

下一节,我们介绍vivado的使用和led点灯实验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值