Verilog 快速上手笔记 – 你好,FPGA 您所在的位置:网站首页 verilog的assign什么意思 Verilog 快速上手笔记 – 你好,FPGA

Verilog 快速上手笔记 – 你好,FPGA

2023-04-08 14:49| 来源: 网络整理| 查看: 265

本文为自己整理的Verilog快速上手笔记,笔记借鉴了夏宇闻老师的 《Verilog数字系统设计教程》,以及自己对verilog的一些理解,也借鉴了网络上的一些关于verilog的资料整理而来

因为笔记比较简单,而verilog本身又比较庞大,加上自己能力也有局限,所以仅供没有verilog基础的人快速了解之用, 如需深入系统的学习verilog 还是建议大家看完整的verilog书籍来系统学习最佳

另外 虽然verilog在很多语法上和c语言非常类似 ,但是一定要记住 verilog是一门硬件描述语言,请把它和软件编程语言区分开,因为你所写的每一个逻辑都会最终对应成实实在在的硬件资源的

资料写的虽然浅显,但是也是花了好些日子整理的,大家有什么疑问直接 在网站下方留言即可,看到会回复 后续有精力会整理具体的verilog 小模块例子

资料整理在网站hellofpga.com下,如转载请注明出处

模块的结构

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

1 module and_block( 2 input A , 3 input B , 4 output Y 5 ); 6 7 assign Y = A & B; 8 9 endmodule

上面描述了一个与门的完整模块,我们着重关注下代码的结构

模块由 module 开始 ,由endmodule 结束 module 后跟着的是模块名,这里是and_block(这里名称可以根据设计的功能自行更改) 模块声明的括号中的是 端口信号,其中input代表输入信号,output代表输出信号,inout代表双向输入输出口,每一个信号以”,”来划分, 最后一个信号 不加任何标点 模块的逻辑功能部分(模块的功能,即输入如何影响输出,这里是Y = A & B) 模块声明结束后 必须要在右括号后增加分号“;”

上述代码的功能很简单,实际的功能就是 输出y的结果 等于 输入a和b的相与,其功能就相当于下图的与门功能

其实模块的声明有多种方式 同样拿上面的代码来举例 申明可以是下面两种形式

1 module and_block( 2 input A , 3 input B , 4 output Y 5 ); 1 module and_block(A,B,Y); 2 input A ; 3 input B ; 4 output Y ;

上面两种方式都是可以的,区别就是在申明的时候定义端口类型, 还是先申明有哪些信号后,再在后面描述端口的类型

注意,上述的A ,B 和 Y信号都是1位的, 大部分使用场合输入输出信号都不止1位的时候,那定义接口类型的时候就要按下述方法来定义了

input [信号位宽-1:0]端口名; 输入口 output [信号位宽-1:0]端口名; 输出口 inout [信号位宽-1:0]端口名; 输入/输出口 举个例子 input [2-1:0]A; 就是定义了一个2个bit位宽的 输入信号A 备注(没有说明reg 或者 wire类型的时候, input output 默认定义的A都是 wire类型的)

数据类型 常量

1.数字类型

在Verilog HDL 中,整形常量有以下四种表示方式

二进制 b或B 十进制 d或D 十六进制 h或H 八进制 o或者O

数字的表示方式一般由 形式进行描述 举几个例子

8’d128 8代表8bit 位宽(后边跟一个符号 ‘ ),d代表十进制 ,128代表十进制的128的意思

8‘b00000001 同样代表 8bit的 二进制的 00000001(其值等同于 8’d1 即8bit十进制的1)

但是 8’d500 这个就是错误的,因为500对应的 二进制是 111110100 一共是9位,已经超过8位位宽了,8bit的范围只能是0-255 ,这里要特别注意,否则写程序的时候容易溢出

2. x和z 值

在数字电路中,除了0和1以外,还有另外两种情况,那就是 不定值 和高阻态, 其中x 代表不定值, z代表高阻态,对于没有进行初始化的信号,一般处于不确定值 x(仿真的时候经常会出现),高阻态表示该信号没有被其他信号驱动(可以简单理解为悬空状态)

x和z 在二进制中代表1位,在八进制中代3位x或者z,在十六进制中代表4位x或者z

3. 下划线 _

下划线只是用来提高代码的可读性的,当一串数字比较长的时候 我们就可以用下划线来进行分割

比方说25’d50_000_000 这里其实等同于25’d50000000只是代码可读性更强了

4. 参数parameter

可以理解为C语言中定义的常量,parameter 参数名=数值

如 parameter a=25;

数据类型 变量

变量 (即程序运行过程中其值可以改变的量)常用的变量的数据类型有 reg ,wire

wire型

wire 可以理解为物理连线,即只要输入有变化,输出马上无条件地反映,不能保存数据,而且必须收到驱动器(如门或者连续赋值语句assgin)的驱动。

wire [n-1:0]数据名; n-1代表数据的位宽是n位 ,数据名代表数据的名称 举个例子 wire [8-1:0]a ; 定义了一个8位的wire型数据,并且命名为a 如果只定义1位的wire型 就不需要定义位宽 比方说 wire b; 就代表定义了1位的wire型

reg型

reg代表寄存器,寄存器只有才在触发的条件下才能改变值,没有输入的时候可以保存原来的值(即寄存器可以在下一次触发之前锁存当前的数据)

reg和wire的区别是 :reg可以保持最后一次的赋值,而wire数据需要持续的驱动 wire 通常需要assign 语句进行连接, 而reg 一般需要在 initial 和always 块中进行赋值 (在“always”块内被赋值的每一个信号都必须定义成reg型)

reg的定义同wire型相似 reg[n-1:0]数据名; n-1代表数据的位宽是n位 ,数据名代表数据的名称 举个例子 reg [8-1:0]a ; 定义了一个8位的reg型数据,并且命名为a 如果只定义1位的reg型 就不需要定义位宽 比方说 reg b; 就代表定义了1位的reg

memory型

verilog 通过对reg型变量建立数组来对存储器建模,从而描述ram或者rom存储器。数组中的每一个单元通过一个数组索引进行寻址。在Verilog语言中没有多维数组存在。(memory型数据是通过扩展reg型数据的地址范围来生成的)

reg [n-1:0] 存储器名[m-1:0]; 其中reg[n-1:0]定义了存储器中存储单元的位宽为n,而[m-1:0]则定义了又多少个这样的存储单元 备注 reg[n-1:0]a; 代表一个n位的寄存器 reg a[n-1:0]a;代表n个1位的存储器 不要弄混了 运算符及表达式:

1) 算术运算符(+,-,×,/,%)

用法和C语言比较类似,但是值得注意的是,在进行算数运算操作时,如果某一个操作数有不确定的值x,则整个结果也为不定值x 另外,Verilog直接实现乘除比较浪费组合逻辑资源,实际项目中会用FPGA的DSP资源来代替乘除法,或者用2的指数次幂的乘除法直接用移位的方式来替代

2) 位运算符(~,|,^,&,^~) 和C语言比较类似

~ //取反 对一个操作数进行按位取反 & //按位与 将两个操作数的对应位进行与运算 | //按位或 将两个操作数的相应位进行或运算 ^ //按位异或(XOR) 将两个操作数的相应位进行异或运算 ^~ //按位同或(异或非) 将两个操作数的相应位进行异或运算再进行非运算

3) 逻辑运算符(&&,||,!) 和C语言比较类似

&& 逻辑与 参与运算的两个数都为真时, 结果才为真 || 逻辑或 参与运算的两个数其中任意一个为真,结果就为真 ! 逻辑非 对参数进行取反,与~不同的是~是一位一位取反,而!是对整个数据取反,如果 这个数取反前不为零,取反后就是零,如果这个数取反前是零,取反后就是1

4) 关系运算符(>,=, 右移运算符 数据高位补0

7) 拼接运算符({ })

可以把两个或多个信号的某些位拼接起来作为一个新的信号 {a[2:1],b[5:3]} 即相当于把a的2到1位,b的5到3位拼接起来了 结果等同于{a[2],a[1],b[5],b[4],b[3]}

8) 条件运算符(?:)

条件运算符可根据条件语句的真假 来将不同的信号进行输出 要使用条件运算符,需要在 ? 运算符之前写一个逻辑表达式,然后判断它是真还是假。根据表达式的真假将两个值中的某一个赋值给输出 输出 = 条件 ? 真的情况 : 假的情况 ; 如 a = (c > b) ? c : b; //如果c大于b,则a等于c;否则a等于b

9) 赋值运算符(=,



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有