Skip to content

Verilog HDL基础语法(上)

🕒 Published at:

写在前面的

本博客是对于自己接触基于Verilog硬件开发学习的基础语法学习笔记!接触Verilog之前一定要有《数字电子技术》的基础!

Verilog HDL是一门硬件描述性语言,可以类似于软件开发一样去做硬件开发。符合“顶层设计”,与传统的搭电路是不一样的,学习过C之类的会更容易。

对于基础概念和简介在此跳过了!!Verilog大小写敏感!

关于寄存器、锁存器、触发器可以参考 锁存器与寄存器的区别

Verilog的注释

和C一样,// 为单行注释,/* */为多行注释

module初探

module模块由module和endmodule包裹

verilog
module <模块名>(<端口列表>)
<端口说明>
<内部信号说明>
<功能定义>
endmodule
  • 端口:相当于硬件的pin 模块通过端口与外部通信
  • 端口说明:input和output(输入or输出)

输入输出

verilog
module block(a,b,c,d);
    // 端口说明
    input a,b;
    output c,d;

    // 不指明内部信号说明,默认为wire

    // 功能定义
    assign c=a | b;
    assign d=a & b;
endmodule

Verilog基础

术语

  1. 空白符:空格、tabs、换行
  2. 标识符:对象的名字
  3. 关键字:比如module之类的
  4. LSB:最低有效位
  5. MSB:最高有效位

Verilog的四值逻辑系统

逻辑值含义
0低位,逻辑假
1高位,逻辑真
x或X不定态
z或Z高阻态

常量及其表示

常量分为整数型和实数型

  1. 整数的大小可以定义也可不。表示为:

    verilog
    <size>'<base><value>
    • size:位数大小,由十进制数表示。缺省为32位
    • base:数基,2(b),8(o),10(d),16(h)进制。缺省为10进制
    • value:基内的有效数字

    注意:规定了位数大小,如果值超过位数会舍掉超过的高位!

  2. 实数常量可以用十进制数或科学计数法表示

    实例解释
    12未规定大小的十进制数
    'h83a未规定大小的十六进制数
    8'b1100 0001八位二进制数
    16'hff01十六位十六进制数
    32'bz01xZ扩展至32位
    3'b1010 11013位数字,3'b101
    6.3十进制数
    32e-40.0032的科学计数法表示
    4.1E34100的科学计数法表示
  3. 注意的一些点

    整数:

    • size缺省即32位
    • 数基缺省即10进制
    • 数基和数字中字母无大小写之分
    • value大于指定大小时,截去高位2'b1101 => 2'b01

    实数:

    • 可以用十进制或者科学计数法表示
    • 表示方法,略,见上面表格的例子

字符串(仅用在测试中)

大多用于显示信息的命令中,由一对双引号包裹!

  • 不能跨行
  • 可以使用格式符,比如:%b
  • 可以使用转义符,比如:\t

标识符

  • 对象名字
  • 必须以( a-z, A-Z )或( _ )开头,后面可以是字母、数字、( $ )或( _ )
  • 最长1023个字符
  • 区分大小写

所有的Verilog的关键字都是小写字母!

数据类型

  1. 线网类型(net type):表示Verilog结构化元件间的物理连线。缺省为z。

    需要被持续驱动,门或者模块都可以!net驱动器值变化时,新值被传送到net上。

    net类型功能
    wire, tri标准内部连接线(缺省)
    supply1, supply0电源和地
    wor, trior多驱动源线或
    wand, triand多驱动源线与
    trireg能保存电荷的net
    tri1, tri0无驱动时上拉/下拉

    可综合的线网数据类型:wire、wor、wand、tri、supply1、supply0。缺省默认为1位wire!!!

    使用语法:

    verilog
    <net类型> [msb:lsb] net1, net2, ..., netN
  2. 寄存器类型(register type):表示一个抽象的数据存储单元,只能在always和initial等过程语句中被赋值,并且它的值从一个赋值到另一个赋值被保存下来。缺省为x。

    寄存器类型功能
    reg最常用,无符号型
    integer32位有符号整型,算术操作产生二进制补码形式。通常不用于由硬件实现的数据处理
    real双精度的带符号的浮点变量,用法上同
    time64位无符号整数变量,用于仿真时间保存与处理
    realtime上同,但可以用于实数仿真时间保存与处理

    reg使用语法:

    verilog
    reg [msb:lsb] reg1, reg2, ..., regN              // [msb:lsb]缺省即1位

    integer使用语法:

    verilog
    integer A, B, C;
  3. 参数

    参数是一个常量,建议常量使用大写字母,变量使用小写字母

    定义语法:

    verilog
    parameter <list_of_assignment>;          // 多个使用逗号隔开
    
    examples:
    parameter WIDTH = 8'h20;
    
    parameter WORD_WIDTH = 8;
    wire[WORD_WIDTH:0] int1;
    
    parameter WORD_WIDTH = 32, ADDR_WIDTH = 8;

    参数的定义是 局部的,只在 当前模块 有效。和 `define有区别 !

  4. 位选择

    位选择从向量中抽取特定的位,整数不能作为位向量访问。

  5. 常见信号类型

    • 寄存器类型:reg(在always等过程快中被赋值的信号,往往代表触发器,但是不一定)时序逻辑电路中常常被综合为D触发器,纯组合逻辑电路中被组合为连线
    • 连线类型:wire:用assign关键字给指定连续/持续赋值所描述的组合逻辑信号或者连线。

Verilog中reg与wire不同点举例 参考PPT

图片

verilog
// 用寄存器类型变量生成组合逻辑
module rw1(a, b, out1, out2);
    input a, b;
    output out1, out2;
    reg out1;
    wire out2;

    assign out2 = a;
    always @(b) out1 = ~b;
endmodule

图片

verilog
// 用寄存器生成触发器
module rw2(clk, d, out1, out2);
    input clk, b;
    output out1, out2;
    reg out1;
    wire out2;

    assign out2 = d & ~out1;
    always @(posedge clk)
        out1 <= d;
endmodule

Verilog的运算符

不面向纯的编程小白,在此就不细解释了,和其他语言大都一样。

算术及逻辑运算符功能
+
-
*
/整除
%取模
&&逻辑与
丨丨逻辑或
!逻辑非

注意:

  1. 将负数赋值给reg或其他无符号变量,使用2的补码算术
  2. 如果一位操作数是x或z,则结果为x
  3. 模运算使用第一个操作数的符号
  4. integer和reg算术有差异,一个有符号,一个没有
按位操作运算符功能
~一元非
&二元与
二元或
^二元异或
~^, ^~二元异或非
关系运算符功能
>大于
<小于
>=不小于
<=不大于
相等操作符功能
==逻辑等
!=逻辑不等
===相同(case等)
!==不相同(case不等)

注意:

  • 对于有值不确定的位,确定的位相等,结果为x
  • ===左右值(包含x,z)相同为一,不可被综合!

条件操作符

verilog
<LHS>=<condition>?<true_expression>:<false_expression>;

与其他语言一样,缺少参数会出现错误!

移位操作符功能
<<左移
>>右移

第二位操作数为无符号数!

连接操作

将小表达式合并成大表达式!

verilog
{expr1, expr2, expr3, ..., exprN}

// 实例
wire [9:0] d;
wire [9:0] a;
assign d[9:5] = {a[0], a[1], a[2], a[3], a[4]};  // 以反转的顺序把a的低五位赋值给d的高五位

assign d = {d[4:0], d[9:5]};  // 高五位与低五位交换

!!不允许连接非定长常数!!

verilog
reg [16:0] a;
reg [31:0] d;
...
d = {a,5};           // 不允许连接非定长常数
d = {a, 16'h0005}    // 左边32位,右边33位,位宽不匹配,一样会报错

复制操作

verilog
{repetition_number{expr1, expr2, ..., exprN}}

复制指定重复次数来执行操作

verilog
// 实例
wire [7:0] d;
wire [11:0] a;
...
assign d = {2{4'b1011}};          // d => 8'b1011 1011

/* 符号扩展 */
{3{1'b1}}   // 结果为3'b111
{3{Ack}}    // 和{Ack, Ack, Ack}相同