Verilog HDL 语法整理 (一)

目录

导读

一、模块结构

        1、模块的端口定义

        2、模块内容

二、数据类型

1、常量

2、参量

3、变量

 1、寄存器数据类型

2、线网型数据类型

参考声明



导读

        本篇博文主要介绍Verilog HDL 语法的基本框架和数据类型、常量变量等。

        推荐PC端或者pad端食用~~


一、模块结构

        以一个简单的组合逻辑的例子进行示例说明,给出模块的模板:

//********************************** 文 件 说 明 **********************************\

//    版本:0.0
//设计日期:2021 09 15
//    作者:在路上,正出发

//功能说明:作语法示例

//相关参考:

//*********************************************************************************\



//********************************** 代 码 部 分 **********************************\

`timescale         1ns/1ps

module 	module_example  #(

//*************---------------------- 参数列表 --------------------------**********\
	
parameter         ADDER_WIDTH            =                               2'd3,
parameter         SUM_WIDTH	             =                               3'd4
//各 parameter 之间以逗号隔开 且 最后一个 parameter 后面无 逗号

)(

//*************-------------------- 输入端口列表 -----------------------***********\

input						[ADDER_WIDTH-1:0]							I_ADD1,
input						[ADDER_WIDTH-1:0]							I_ADD2,

//*************-------------------- 输出端口列表 -----------------------***********\

output				        [SUM_WIDTH-1:0]				                O_SUM_RES
//各 output 之间以逗号隔开 且 最后一个 output 后面无 逗号    
);

//*************-------------------- 内部参数定义 ----------------------************\



//*************-------------------- 内部信号定义 ----------------------************\



//*************------------------- 模块的程序设计 ---------------------************\

assign			O_SUM_RES				= 					           I_ADD1+I_ADD2;

endmodule

//*********************************************************************************\

        Verilog HDL 的程序结构位于 moduleendmodule 之间,每个Verilog 程序主要包括四个部分:IO端口定义、声明、内部参数和信号定义、功能定义。

        1、模块的端口定义

        建议在进行端口声明时直接定义其类型(输入、输出、双端口),如上例所示。这样简单明了。

        模块端口不加特殊声明 默认 wire 类型,模块端口的输出端可以定义为 reg 类型。如果直接将 always 块内的输出直接送到输出端口 那么输出必须定义为 reg 类型 ,这是语法要求,否则会报错。

        端口的 位宽默认是 1位,当需要多位时就需要指定位宽,如:output reg [11 : 0]  O_RES 。一般都是左边是高位,右边是低位,当然也可以反过来写成:output reg [0 : 11]  O_RES 为了方便设计,一般都是选择前者。

        顶层模块调用底层模块,对应端口连接时有两种方式:

1、引用端口的顺序和所声明端口的顺序严格对应。这种方法使用较少。

2、引用端口时用 英文 "." 来引用原模块的端口名,这种方法最为常用,尤其在端口数目多的时候:

	module_example #(
			.ADDER_WIDTH(ADDER_WIDTH),
			.SUM_WIDTH(SUM_WIDTH)
		) inst_module_example (
			.I_ADD1    (I_ADD1),
			.I_ADD2    (I_ADD2),
			.O_SUM_RES (O_SUM_RES)
		);

        2、模块内容

        此部分也即模块的实现部分,主要包括中间变量或模块内部信号的声明和逻辑设计。

        1、内部信号或者参数的声明:

                内部信号的声明主要就是 wire 、reg 型的声明。内部参数(非模块传输参数)可以用 localparam 进行声明。

        2、逻辑设计:

                逻辑设计包括模块调用和程序块。模块调用的方式上面有例子说明。程序块中主要是 组合逻辑和时序逻辑。最常用到的语句块就是 always 语句块。

always 语句块的总体结构:

always @ (<敏感向量表>)
    begin
        <逻辑描述>;
    end

对于 always 块实现纯组合逻辑,敏感向量表应该是 该逻辑块所有的输入信号 ,以英文 逗号 隔开。

对于 always 块实现纯同步时序逻辑,敏感向量表应该是 时钟信号的边沿。

对于 always 块实现纯异步时序逻辑,敏感向量表应该是 时钟信号的边沿 和 复位信号的边沿。

注意:某些语句只能在 always 语句块内 使用 比如 if-else

                除了always语句块,还有常用的连续赋值语句 assign ,该语句只对线网型变量赋值。线网型变量一般对应到 FPGA 内部是一段连线 ,连线的值会随着驱动源变化而不断变化。

二、数据类型

1、常量

首先介绍Verilog HDL 语法的四值系统:

逻辑1:高电平;

逻辑0:低电平;

不确定逻辑X:未知电平,一般由于赋值冲突造成;

高阻逻辑Z:高阻态,相当于电路开路;

二进制表示法:< 二进制位宽 > ' b < 二进制数 > (B 、b 均可) 例:8‘b0011_1001

        注意:可以赋值 高阻态 Z(z 或 ?) ,但不可以赋值 不定态 X (x)。当二进制位宽过大时,可以用下划线分割开,便于查看,下划线处于数字之间。

八进制表示法:< 二进制位宽 > ' o < 八进制数 > (O 、o 均可) 例:6‘o71

        注意:八进制赋值,经常出现位宽不匹配的情况,编译器会将高位截断。同样支持下划线表示法。支持高阻态。

十六进制表示法:< 二进制位宽 > ' h < 十六进制数 > (H 、h 均可) 例:8‘h39

        注意:支持下划线表示法。支持高阻态。

十进制表示法:< 二进制位宽 > ' d < 十进制数 > (D 、d 均可) 例:8‘d39

        注意:十进制数不要超过位宽的表示范围。支持高阻态,但是只有一个Z(z),如8'dz。负数的 常量表达式注意:-8'd100  而不是 8'd-100。

2、参量

        parameter Verilog HDL 语法中,常用 parameter 来定义常量。从而提高程序的可读性和代码可维护性。可以声明在模块接口部分(如文章开头的示例代码);也可以声明在模块内部。在模块接口处使用 parameter 可以实现模块的复用,在模块的例化时可以重新给定 parameter 的数值(如  模块端口的定义小节  的例子),这给模块的设计带来很大的灵活性。

        语法:parameter   <参量名>   =   <常量表达式> ;

        localparam:使用方法与 parameter 基本一致,不同的是,localparam 只能用在模块内部,不能实现参量复用。

        语法:localparam   <参量名>   =   <常量表达式> ;

        specparam:specify 语法块中,定义模块的时序模型,为了区别于module内的参数,使用关键字:specify。(使用极少,模块设计基本用不到)

        语法:specparam   <参量名>   =   <常量表达式> ;

3、变量

 1、寄存器数据类型

        Verilog HDL 语法中,凡是在 程序块 中被赋值的信号(变量)必须为寄存器类型。但是未必在实际电路中就是寄存器。如果程序块中描述的是组合逻辑则,实际电路中寄存类型变量对应硬件连线;如果描述的是时序逻辑,实际电路中寄存器类型的变量对应寄存器;对于组合时序逻辑混合的程序块,实际电路中寄存器类型的变量可能对应锁存器。

1、reg

reg型变量是寄存器类型中用的最多的,具体语法:reg    <位宽范围>   <变量名>   <变量数目范围>;

示例:reg  [15:0]  R_COUNTER [512:1]; //512个16位的reg型数据空间

           reg  [3:0]    R_1,R_2,R_3;

           reg  R_VALID;

2、integer

整数类型,位宽等于32;实际设计时除了仿真,一般不用 integer 进行设计。具体语法:integer  <变量名>;

示例:integer  K; 

3、real

实数类型,抽象级别高,一般都不建议使用该类型。

2、线网型数据类型

        模块的输入接口(input)、双端口(inout)必须为线网类型,连续赋值的对象为线网类型。实际电路中,线网类型对应硬件连线。

1、wire

wire 是线网类型中最最常用的一种类型。语法:wire   <位宽范围>   <变量名>    <变量数目范围>;

示例:wire  [15:0]  W_COUNTER  [1024:1];//1024个16位宽的 wire 型数据

           wire  [3:0]    W_1,W_2,W_3;

           wire  W_VALID;

2、tri

tri 用法和 wire 在语法上完全一致。三态门驱动的硬件连线用此定义。

3supply1/supply0

表示上拉到逻辑1/逻辑0。用的很少,亦可作常数1/0来用。

4wand/triand

线与(wand、triand)一般用于集电极开路电路中。但是FPGA内部一般无OC门,基本不用此类型。

5wor/trior

FPGA内部一般此结构,线或一般不用。

6tri1/tri0/trireg

分别表示高阻态时,可以进行上拉、下拉、保持之前逻辑。一般不用。

参考声明

【1】夏宇闻. Verilog 数字系统设计教程 第二版.

【2】狄超. FPGA之道.

【3】IEEE Standard for Verilog Hardware Description Language 1364-2005.

博文声明:整理时间有限,如有发现任何纰漏,及时私信我更正~



文末推荐

掌握了基本的Verilog语法,不去实战练习的话很难有大的突破。牛客网可以为大家提供一个免费的刷题练习的平台。非常推荐大家使用。

 链接如下:牛客网-Verilog专项https://www.nowcoder.com/link/pc_csdncpt_zls_verilog这个里面有很多代码题目练习,对于新手来说可以快速掌握Verilog编程的基本语法,对于老手来说也可以巩固自己的编程能力。不用付费免费试用哦。基本是每个即将找工作的人必备的刷题网站。快行动起来吧!

你可能感兴趣的:(Verilog,HDL,语法整理,Verilog,HDL,语法)