Verilog语法基础 您所在的位置:网站首页 rtl的含义 Verilog语法基础

Verilog语法基础

2023-06-11 02:54| 来源: 网络整理| 查看: 265

Verilog语法基础 1 前言1.1 不可综合1.2 可综合 2 I/O说明、参数定义2.1 I/O说明2.2 参数定义 3 变量信号3.1 信号位宽3.2 wire/reg的区别 4 数字进制4.1 基数表示法(数字表示方式)4.2 二进制是基础4.3 不定态(X)4.4 高阻态(Z) 5 条件语句5.1 条件运算符5.2 if-else 条件分支语句5.3 case 分支控制语句 6 阻塞赋值和非阻塞赋值6.1 定义6.2不同场景应用 7 运算符7.1 算数运算符7.1.1 加法运算符7.1.2 减法运算符7.1.3 乘法运算符7.1.4 除法和求余运算符(一般不用) 7.2 逻辑运算符7.2.1 逻辑与7.2.2 逻辑或7.2.3 逻辑非7.2.4 如何运算 7.3 按位逻辑运算符7.3.1 按位与7.3.2 按位或7.3.3 按位非7.3.4 双目按位异或7.3.5 与逻辑运算符对比 7.4 关系运算符7.5 移位运算符7.5.1 左移运算符(通过左移乘法运算)7.5.2 右移运算符(通过右移除法运算) 7.6 拼接运算符 8 功能描述8.1 组合逻辑8.1.1 assign 语句8.1.2 always 语句 8.2 时序逻辑8.2.1 always 语句8.2.2 同步/异步 9 Testbench中的系统函数9.1 timescale9.2 '#+数字'9.3 initial9.4 $display 用于输出、打印信息9.5 $write 用于输出、打印信息9.6 $strobe 用于输出、打印信息9.7 $monitor 用于持续监测变量9.8 $ stop 用于暂停仿真,$ finish 用于结束仿真9.9 $ time、$random9.10 $ readmemb、$readmemh9.11 Testbench中与 RTL 区别9.11.1 wire和reg 区别9.11.2 begin区别9.11.3 always语句直接赋值9.11.4 时钟信号采用阻塞赋值9.11.4 区别的代码实例 10 写一段完整 RTL和 Testbench(全加器)10.1 RTL,全加器是在半加器的基础上写的10.2 仿真文件

1 前言 1.1 不可综合

Verilog 是描述硬件电路的,其建立在硬件电路的基础之上。而有些语法结构只是以仿真测试为目的,是不能与实际硬件电路对应起来的。也就是说在使用这些语法时,将一个语言描述的程序映射成实际硬件电路中的结构是不能实现的,也称为不可综合语法。不可综合或不推荐使用的代码都在测试平台Testbench使用。(下文详细叙述测试平台使用)

1.2 可综合

RTL推荐使用的代码。综合就是把编写的 RTL 代码转换成对应的实际电路。比如编写代码 assign a=b&c;EDA 综合工具就会去元件库里调用一个二输入与门,将输入端分别接上 b 和 c,输出端接上 a。“综合”要做的事情有:编译 RTL 代码,从库里选择用到的门器件,把这些器件按照“逻辑”搭建成“门”电路。

2 I/O说明、参数定义 2.1 I/O说明

在定义端口列表的时候我们知道输入用 input,输出用 output,双向端口inout。

2.2 参数定义

参数是一种常量,通常出现在 module 内部,常被用于定义状态机的状态、数据位宽和计数器计数个数大小等,和C语言,Python等语言中全局变量功能一样,方便修改。parameter 是出现在模块内部的局部定义,只作用于声明的那个文件,可以被灵活改变,这是 parameter 的一个重要特征。例如:

parameter IDLE = 3'b001; parameter CNT_1S_WIDTH = 4'd15 Parameter CNT_MAX = 25'd24_999_999 3 变量信号

Verilog 语言中主要的两种变量类型

线网型:wire表示电路间的物理连接;寄存器型:reg是Verilog 中一个抽象的数据存储单元。 3.1 信号位宽

基本语法: wire/reg [msb: lsb] wire1/reg1, wire2/reg2, . . .,wireN/regN; 1)如果没有定义范围,缺省值为 1 位; 2)msb 和 lsb 定义了范围,表示了位宽。例如[7:0]是 8 位位宽,也就是可以表示成 8’b0 至 8’b 1111_1111; 3)msb 和 lsb 必须为常数 4)没有定义信号数据类型时,缺省为 wire 类型 5)注意数组类型按照降序方式,如[7:0] ,不要写成[0:7]。

定义说明wire a位宽为 1 的 wire 型信号 awire [7:0]表示该 wire 型信号的位宽为8位wire [3:0] SatSat 为 4 位线型信号wire Cnt1 位线型信号wire [31:0] Kisp, Pisp, LispKisp, Pisp, Lisp 都是 32 位的线型信号reg [3:0] SatSat 为 4 位寄存器型信号reg Cnt1 位寄存器reg [31:0] Kisp, Pisp, LispKisp, Pisp, Lisp 都是 32 位的寄存器信号 3.2 wire/reg的区别

在设计逻辑的时候要明确定义每个信号是 wire 还是 reg 属性。 1)凡是在 always 或 initial 语句中被赋值的变量(赋值号左边的变量),不论表达的是组合逻辑还是时序逻辑,都一定是 reg 型变量; 2)凡是在 assign 语句中被赋值的变量,一定是 wire 型变量。

4 数字进制 4.1 基数表示法(数字表示方式)

[换算为二进制后位宽的总长度][’][数值进制符号][与数值进制符号对应的数值]

符号进制h十六进制o八进制b二进制d十进制

例子:

数字表示含义8’hab表示 8bit 的十六进制数,换算成二进制是 1010_10118’d171表示 8bit 的十进制数,换算成二进制是 1010_10118’o253表示 8bit 的八进制数,换算成二进制是 1010_10118’b1010_1011表示 8bit 的二进制数,二进制就是 1010_101132’h12等同于 32’h00000012,即数值未写完整时,高位补 0 4.2 二进制是基础

1和0表示高低电平 。 例如要传输送+1,-1,0,+2,线 c 表示正负,其中 0 表示正数,1 表示负数。用线 a 和线 b 表示数值。在 FPGA 设计中,不清楚小数、有符号数的计算方法的最根本原因是不清楚这些数据所对应的二进制值,只要理解了对应的二进制值,很多问题都可以解决。~~(源码、补码、反小数表示,在数字电路和计算机组成原理书中的开篇几张都有介绍,这是计算机基础不过多介绍)在这里插入图片描述

4.3 不定态(X)

前文中讲过数字电路只有高电平和低电平,分别表示 1 和 0。但代码中经常能看到 x 和 z,如 1’ bx,1’bz。那么这个 x 和 z 是什么电平呢?答案是并没有实际的电平来对应两者。x 和 z 更多地是用来表示设计者的意图或者用于仿真目的,旨在告诉仿真器和综合器如何解释这段代码。 X 态,称之为不定态,其常用于判断条件,从而告诉综合工具设计者不关心它的电平是多少,是 0 还是 1 都可以。 例如: din==4’b10x0 等价于 din == 4’b1000||din ==4’b1010

4.4 高阻态(Z)

Z 态,一般称之为高阻态,表示设计者不驱动这个信号(既不给 0 也不给 1),通常用于三态门接口当中。 在这里插入图片描述 1)当 CPU 和 FPGA 都不驱动该总线时,A 点保持为高电平。 2)当 FPGA 不驱动该总线 当CPU 驱动该总线时,A 点的值就由 CPU 决定。 当 CPU 不驱动该总线,FPGA 驱动该总线时,A 点的值就由 FPGA 决定。 但 FPGA 和 CPU 不能同时驱动该总线,否则 A 的电平就不确定了,通常 FPGA 和 CPU何时驱动总线是按事先协商的协议进行工作。 在这里插入图片描述 三态门是一个硬件,上图是它的典型结构。三态门有四个接口,如上图所示的写使能 wr_en、写 数据 wr_data、读数据 rd_data 以及与外面器件相连的三态信号 data,需要注意的是写使能信号。 1)当该信号有效时三态门会将 wr_data 的值赋给三态线 data,此时 data 的值由 wr_data 决定; 2)当 wr_data 为 0 时 data 值为 0; 3)当 wr_data 为 1 时 data 值为 1; 4)而当写使能信号无效时,则不论 wr_data 值是多少都不会对外面的 data 值有影响,也就是不驱动;

5 条件语句 5.1 条件运算符

相当于C语言的三元运算符 1)a = 6, b = 7,条件表达式(a > b) ? a : b 的结果为 7 2)a > b ? a : c > d ? c : d 相当于 a > b ? a : (c > d ? c : d) 虽然后面要讲到的 if-else 也可以实现这种功能,但是 if-else 只能在 always 块中使用,不能在 assign 中使用,如果我们想在 assign 中使用就需要用到条件运算符。

1 module mux2_1 2 ( 3 input wire in1, //输入端 1 4 input wire in2, //输入端 2 5 input wire sel, //选择端 6 7 output wire out //结果输出 8 ); 9 10 //out:组合逻辑输出选择结果 11 //此处使用的是条件运算符(三元运算符),当括号里面的条件成立时 12 //执行"?”后面的结果;如果括号里面的条件不成立时,执行“:”后面的结果 13 assign out = (sel == 1'b1) ? in1 : in2; 14 15 endmodule 5.2 if-else 条件分支语句

用法和C语言类似

1 module mux2_1 //模块的开头以“module”开始,然后是模块名“mux2_1” 2 ( 3 input wire in1, //输入端 1,信号名后就是端口列表“();”(端口列表里 4 //面列举了该模块对外输入、输出信号的方式、类型、 5 //位宽、名字),该写法采用了 Verilog-2001 标准,这 6 //样更直观且实例化时也更方便,之前的 Verilog-1995 7 //标准是将模块对外输入、输出信号的方式、类型、位 8 //宽都放到外面 9 10 input wire in2, //输入端 2,当数据只有一位宽时位宽表示可以省略 11 //且输入只能是 wire 型变量 12 13 input wire sel, //选择端,每行信号以“,”结束,最后一个后面不加“,” 14 15 output reg out //结果输出,输出可以是 wire 型变量也可以是 reg 型变 16 //量如果输出在 always 块中被赋值(即在“$random} % 2; 21 22 //in2:产生输入随机数,模拟加数 2 的输入情况 23 always #10 in2 $random} % 2; 27 28 //------------------------------------------------------------ 29 initial begin 30 $timeformat(-9, 0, "ns", 6); 31 $monitor("@time %t:in1=%b in2=%b cin=%b sum=%b cout=%b", 32 $time,in1,in2,cin,sum,cout); 33 end 34 //------------------------------------------------------------ 35 36 //---------------full_adder_inst------------------ 37 full_adder full_adder_inst( 38 .in1 (in1 ), //input in1 39 .in2 (in2 ), //input in2 40 .cin (cin ), //input cin 41 42 .sum (sum ), //output sum 43 .cout (cout ) //output cout 44 ); 45 46 endmodule


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

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