1.一个完整版实例

上一次Verilog学习笔记中,我通过几个小例子,较为直观的对Verilog编程有了一些了解。这次笔记,我开始着重的系统学习Verilog编程语法基础。在我系统学习语法之前,我先用一个实例,引入这次笔记。

上图被测试器件被测试器件DUT 是一个二选一多路器。测试装置(test testbench or fixture)提供测试激励及验证机制。TestBench 使用行为级描述,DUT采用门级描述。下面将给出 采用门级描述。下面将给出TestBench的描述、DUT的描述及如何进行混合仿真。

1)书写Verilog程序

上图依旧是我们曾经提到的经典二选一电路,现在我对其进行Verilog编程(以后文章中程序均为笔者在Sublime Text3中书写):

2)书写该程序的TestBench

书写TestBench时候应注意,此验证性程序是没有端口的,这是因为TestBench是最顶层模块,不会被其他模块实例化,所以不需要端口。同时硬件描述程序中,即MUX2_1.V程序在TestBench中需要进行实例化,应注意模块名字要与引用模块(即MUX2_1)相同;实例的名字可以任意,但是要符合标记命名规则;端口列表与引用模块次序相同(即out ,a,b,sel)。

在书写TestBench时候常用initial和always这两个过程语句,二者区别为:initial:只能执行一次;always:循环执行。值得注意的是所有过程在时间0执行一次,过程之间是并行执行的(FPGA的特点)

激励描述:

(本图同数字电路中真值表)

• 例子中,a, b, sel说明为reg类数据。reg类数据是寄存器类数据信号,在重新赋值前一直保持当前数据。例子中,a, b, sel说明为reg类数据。reg类数据是寄存器类数据信号,在重新赋值前一直保持当前数据。

• #5 用于指示等待5个时间单位。

• $ stop是结束仿真的系统任务,也可以写成$finish。

3)TestBench 响应的产生

Verilog 提供了一些系统任务和系统函数,包括:

• $time 系统函数,给出当前仿真时间;

• $monitor 系统任务,若参数列表中的参数值发生变化,则在时间单位末显示参数值。

格式:$monitor ([“format_specifiers”,] <arguments>);

例如:$monitor($time, o, in1, in2);

$monitor($time, “%b %h%d %o”, sig1, sig2, sig3,sig4);

说明:

a)$time 是一个系统函数,返回当前返回仿真时间。时间用64位整数表示。

b)$monitor 在时间单位末,若参数列表中的参数值发生变化则显示所列参数的值。由$time引起的变化不会显示。

c)$monitor系统任务支持不同的数基。缺省数基是十进制。支持的数基还有二进制、八进制、十进制。
4)完整的TestBench

2.模块的结构

Verilog的基本设计单元是“模块”(block) 。一个模块是由两部分组成的,一部分描述接口,另一部分描述逻辑功能,即定义输入是如何影响输出的。

Verilog 模块的结构由在module和endmodule 关键词之间的四个主要部分组成:

1)模块端口的定义

模块的端口声明了模块的输入输出口。其格式如下:

module 模块名(口1,口2,口3,口4, ………);

模块名(标识符)的命名规则:

• 标识符是用户在描述时给 标识符是用户在描述时给Verilog对象起的名字;

• 标识符必须以字母 标识符必须以字母(a-z, A-Z) 或( _ ) 开头,后面可以是字母、数字、( $ )或( _ )。

• 最长可以是1023个字符个字符。

• 标识符区分大小写,标识符区分大小写,sel 和SEL是不同的标识符。

• 模块、端口和实例的名字都是标识符。

• 标识符要区别与关键字,这个命名规则和C语言大同小异。

2)编程命名规范

a)匈牙利命名:

开头字母用变量类型的缩写,其余部分用变量的英文或英文的缩写,要求单词第一个字母大写。

int iMyAge; “i”是int类型的缩写; char cMyName[10]; “c”是char类型的缩写; float fManHeight; “f”是float类型的缩写;

b)驼峰式命名法:

又叫小驼峰式命名法。第一个单词首字母小写,后面其他单词首字母大写。

int myAge;
char myName[10];
float manHeight;

c)帕斯卡命名法:

又叫大驼峰式命名法。每个单词的第一个字母都大写。

int MyAge;
char MyName[10];
float ManHeight;

个人比较喜欢驼峰命名法和下划线结合来用。

3)模块内容

模块的内容包括I/O说明、内部信号声明、功能定义。

I/O说明的格式:

输入口:input[信号位宽-1:0] 端口名1;

input[信号位宽-1:0] 端口名2;

input[信号位宽-1:0] 端口名i; //(共有i个输入口)

输出口:output[信号位宽-1:0] 端口名1;

output[信号位宽-1:0] 端口名2;

output[信号位宽-1:0] 端口名j; //(共有j个输出口)

输入/输出口:inout[信号位宽-1:0] 端口名1;

inout[信号位宽-1:0] 端口名2;

inout[信号位宽-1:0] 端口名k; //(共有k个双向总线端口)

注:I/O说明也可以写在端口声明语句里。其格式如下:

module module_name(input port1,input port2,… output port1,output port2… );

4)内部信号说明

在模块内用到的和与端口有关的wire 和 reg 变量的声明。

如: reg [width-1 :0] R变量1,R变量2 …;

wire [width-1 : 0] W变量1,W变量2 …;

5)功能定义

模块中最重要的部分是逻辑功能定义部分。有三种方法可在模块中产生逻辑。

a)用 assign 语句(数据流描述):assign a = b & c ;

b)用实例元件(结构化描述):and2 and_inst ( q, a, b);

c)用 “always” 块(行为描述):

always @ (posedge clk or
posedge clr)//敏感性列表

begin

if (clr) q<= 0;
else if (en) q<= d;

end //begin……end相当于C语言中的()

说明:上述三条语句是并行的,他们产生独立的逻辑电路;而在always块中:begin和end之间是顺序执行的。

3.数据类型及常量和变量

1)常量

在程序运行过程中,其值不能被改变的量称为常量。

I.数字:

(1)整数

在Verilog HDL中,整型常量即整常数有以下四种进制表示形式:

a)二进制整数(b或B)

b) 十进制整数(d或D)

c) 十六进制整数(h或H)

d) 八进制整数(o或O)

数字表达方式有以下三种:

a) <位宽><进制><数字>这是一种全面的描述方式。

b) <进制><数字>在这种描述方式中,数字的位宽采用缺省位宽(这由具体的机器系统决定,但至少32位)。

c) <数字>在这种描述方式中,采用缺省进制十进制。

(2)X,Z,0,1的含义

在数字电路中,x代表不定值,z代表高阻值。一个x可以用来定义十六进制数的4位二进制数的状态,八进制数的3位,二进制数的1位。z的表示方式同x类似。z还有一种表达方式是可以写作“?”。

(3)负数

一个数字可以被定义为负数,只需在位宽表达式前加一个减号,减号必须写在数字定义表达式的最前面。注意减号不可以放在位宽和进制之间也不可以放在进制和具体的数之间。

-8'd5 //这个表达式代表5的补数(用八位二进制数表示)

8‘d-5 //非法格式

(4)下画线(underscore_)

下划线可以用来分隔开数的表达以提高程序可读性。但不可以用在位宽和进制处,只能用在具体的数字之间。

16'b1010_1011_1111_1010 //合法格式

8'b_0011_1010 //非法格式

当常量不说明位数时,默认值是32位,每个字母用8位的ASCII值表示。

(5)基数符号及其合法的表示值

举例:

(6)实型数及其表示

Verilog中的实数可以用十进制与科学计数法两种格式来表示,如果采用十进制格式,小数点两边必须都有数字,否则为非法的表示形式。

实例:

排版太困难了,原谅我用图片了

II. 参数型(parameter)

a)用参数声明一个可变常量,常用于定义延时及宽度变量。

b)参数定义的语法:parameter <list_of_assignment>;

c)可一次定义多个参数,用逗号隔开。

d)在使用文字(literal)的地方都可以使用参数。

e)参数的定义是局部的,只在当前模块中有效。

f)参数定义可使用以前定义的整数和实数参数。

2)变量

变量即在程序运行过程中其值可以改变的量。常用的网络数据类型包括wire型和tri型。wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。

a)wire型

wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。Verilog程序模块中输入输出信号类型缺省时自动定义为wire型。其格式如下:

wire [n-1:0] 数据名1,数据名2,……数据名i; //共有i条总线,每条总线内有n条线路,或

wire [n:1] 数据名1,数据名2,……数据名i;

b)reg型

寄存器是数据储存单元的抽象。寄存器数据类型的关键字是

reg。 reg类型数据的默认初始值为不定值x。reg型数据常用来表示用于“always”模块内的指定信号,常代表触发器。在“always”块内被赋值的每一个信号都必须定义成reg型。

reg型数据的格式如下:

reg [n-1:0] 数据名1,数据名2,… 数据名i;

reg [n:1] 数据名1,数据名2,… 数据名i;

c)memory型

Verilog HDL通过对reg型变量建立数组来对存储器建模,可以描述RAM型存储器,ROM存储器和reg文件。数组中的每一个单元通过一个数组索引进行寻址。在Verilog语言中没有多维数组存在。 memory型数据是通过扩展reg型数据的地址范围来生成的。其格式如下:

reg [n-1:0] 存储器名[m-1:0];

reg [n-1:0] 存储器名[m:1];

3)如何选择正确的数据类型

a)输入口(input)可以由寄存器或网络连接驱动,但它本身只能驱动网络连接。

b)输出口 (output)可以由寄存器或网络连接驱动,但它本身只能驱动网络连接。

c)输入/输出口(inout)只可以由网络连接驱动,它本身也只能驱动网络连接。

d)如果信号变量是在过程块 (initial块或always块)中被赋值的,必须把它声明为寄存器类型变量。

文末说明

本文作者:小强子

知乎ID:Power小强

一个细腻不油腻,嗜好多能力小的普通人,专注于分享电子电气相关知识的打杂硕士生

b 计数器位选信号 verilog_Verilog HDL菜鸟学习笔记———三、Verilog常用语法之一...相关推荐

  1. 菜鸟学习笔记:Java基础篇6(数组、字符串)

    菜鸟学习笔记:Java常用类(数组.字符串) 数组 概述 数组的定义 二维数组 数组查找和排序 查找 排序 数组运用--字符串 不可变字符序列(String) 可变字符序列(StringBuilder ...

  2. 菜鸟学习笔记:Java提升篇9(网络1——网络基础、Java网络编程)

    菜鸟学习笔记:Java提升篇9(网络1--网络基础.Java网络编程) 网络基础 什么是计算机网络 OS七层模型 Java网络编程 InetAddress InetSocketAddress URL类 ...

  3. 菜鸟学习笔记:Java提升篇8(线程2——线程的基本信息、线程安全、死锁、生产者消费者模式、任务调度)

    菜鸟学习笔记:Java提升篇8(线程2--线程的基本信息.线程安全.死锁.生产者消费者模式.任务调度) 线程的基本信息 线程同步 线程安全 死锁 生产者消费者模式 任务调度(了解) 线程的基本信息 J ...

  4. 菜鸟学习笔记:Java提升篇6(IO流2——数据类型处理流、打印流、随机流)

    菜鸟学习笔记:Java IO流2--其他流 字节数组输入输出流 数据类型处理流 基本数据类型 引用类型 打印流 System.in.System.out.System.err 随机流RandomAcc ...

  5. 菜鸟学习笔记:Java提升篇5(IO流1——IO流的概念、字节流、字符流、缓冲流、转换流)

    菜鸟学习笔记:Java IO流1--IO流的概念.字节流.字符流.缓冲流.转换流 IO流的原理及概念 节点流 字节流 文件读取 文件写出 文件拷贝 文件夹拷贝 字符流 文件读取 文件写出 处理流 缓冲 ...

  6. 菜鸟学习笔记:Java提升篇3(容器3——泛型、排序)

    菜鸟学习笔记:Java容器3--泛型.排序 泛型 泛型类 泛型接口 泛型方法 泛型继承 通配符"?" 泛型知识点补充 容器排序 Comparable接口与compareTo方法 C ...

  7. 菜鸟学习笔记:Java提升篇1(容器1——List)

    菜鸟学习笔记:Java容器1--List容器 容器基本概念 List容器 ArrayList 初始化 add方法 remove方法 LinkList 链表 双向链表 初始化 add方法 remove方 ...

  8. 菜鸟学习笔记:Java基础篇7(包装类、时间相关类、文件类、异常处理类)

    菜鸟学习笔记:Java其他常用类 基本数据类型包装类 时间处理和文件处理相关类 Date时间类 SimpleDateFormat Calendar日历类 文件类 异常机制 异常的概念 Java异常处理 ...

  9. 菜鸟学习笔记:Java基础篇2(变量、运算符、流程控制语句、方法)

    菜鸟学习笔记:Java基础篇2 变量 基本概念 变量作用域 final关键字 运算符 算术运算符 比较运算符 逻辑运算符 位运算符 赋值运算符 条件运算符 运算符优先级 Java三种流程控制语句 顺序 ...

最新文章

  1. 推荐系统技术演进趋势:召回-排序-重排
  2. J.U.C系列(二)CyclicBarrier的使用
  3. 【Python】4000字归纳总结 Pandas+Sklearn 带你做数据预处理
  4. C语言重要知识点回顾
  5. 使用代理时服务变量的变化
  6. cloudflare 利用API将域名批量解析到cloudflare
  7. C++中include头文件使用与的区别
  8. educoder MongoDB 文档的高级查询操作
  9. 1. SVN (1)
  10. c语言电话订餐管理系统
  11. 嵌入式开发培训怎么样?嵌入式开发培训多少钱
  12. autocad 二次开发 拆分图纸_谈谈AUTOCAD.NET二次开发的一些经验(一)
  13. 干货!量子技术入门、进阶、行业专家观点、最新资讯!1000篇好文帮你揭开量子技术神秘面纱!...
  14. 廊坊金彩教育:如何进行选品
  15. 基于Canvas+React的高性能Table表格
  16. 谷歌搜索结果在新标签页中打开
  17. Arduino 光敏电阻
  18. PDApp.log占用C盘几十G空间,原因及解决方案
  19. 泡沫经济中的移动开发者
  20. 顶级程序员的成长之路2

热门文章

  1. HttpDns 原理是什么
  2. 谷歌开源MobileNets:在移动设备上高效运行的计算机视觉模型
  3. Android使用Retrofit2.0和RxJava2.0处理网络请求
  4. 使VM的虚拟机内存超越物理内存的方法
  5. leetcode 304. Range Sum Query 2D - Immutable |304. 二维区域和检索 - 矩阵不可变(二维前缀和问题)
  6. 【JavaScript】JS的变量、数组、计算器案例、函数、类、常用对象的方法
  7. linux系列之: 你知道查看文件空间的两种方法吗?
  8. 使用Tomcat Native提升Tomcat IO效率
  9. JDK10的新特性:本地变量类型var
  10. 循环首次适应算法_面向6G的极化编码链路自适应技术