Verilog HDL

一、基础语法

1. 基础知识

(1)逻辑值

逻辑0:低电平。

逻辑1:高电平。

逻辑X:未知,可能是高电平,也可能是低电平。

逻辑Z:高阻态,外部没有激励信号,是一个悬空状态。

(2)数字进制

十进制数10的表示:

二进制:4'b1010

十进制:4‘d10

十六进制:4’ha

若不指定位宽,默认32位位宽

若不指定位宽和进制,默认32位十进制

16‘b1001_1010_1010_1001 = 16'h9AA9

(3)标识符

用于定义模块名、端口名、信号名等。

是任意一组字母、数字、$符号和_(下划线)符号的组合,第一个字符必须是字母或者下划线,区分大小写。

推荐写法:普通内部信号建议全部小写,用下划线区分词。

sum、cpu_addr、clk_50、clk_cpu

2. 数据类型

Verilog中,三大数据类型:(1)寄存器;(2)线网;(3)参数。

(1)寄存器类型

寄存器表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器存储的值。

寄存器数据类型的关键字是reg,reg类型数据的默认初始值为不定值x

reg [31:0] delay_cnt;

reg            key_reg;

reg类型的数据只能在always语句和initial语句中被赋值。

时序逻辑中,寄存器对应为触发器;组合逻辑中,寄存器对应位硬件连线。

(2)线网类型

线网数据类型表示结构实体之间的物理连线,不能存储值。

驱动线网类型变量的元件有门、连续赋值语句、assign等。

如果没有驱动元件连接到线网类型的变量上,则该变量就是高阻的,其值为z。

线网数据类型包括wire和tri,常用的为wire

wire key_flag;

(3)参数类型

常量,用parameter定义。

parameter        H_SYNC = 11'd41;

parameter        H_BACK = 11'd2;

parameter        H_DISP = 11'd480;

参数型数据常用于定义状态机的状态、数据位宽和延迟大小等。

采用标识符来代表一个常量可以提高程序的可读性和可维护性。

在模块调用时,可通过参数传递来改变被调用模块中已定义的参数。

3. 运算符

Verilog HDL_第1张图片

 Verilog HDL_第2张图片

除法只能整除

Verilog HDL_第3张图片

Verilog HDL_第4张图片

Verilog HDL_第5张图片

Verilog HDL_第6张图片

Verilog HDL_第7张图片

Verilog HDL_第8张图片

 Verilog HDL_第9张图片

二、 程序框架

1. 注释

两种注释方式:和C语言相同//和/* */

2. 关键字

Verilog HDL_第10张图片

 Verilog HDL_第11张图片

3. 程序框架

Verilog 的基本设计单元是“模块”

一个模块由两部分组成,一部分描述接口,另一部分描述逻辑功能。

module block(a, b, c, d);
    input a, b;
    output c, d;

assign c = a | b;
assign d = a & b;

endmodule

每个Verilog程序包括4个主要的部分:(1)端口定义、(2)IO说明、(3)内部信号声明、(4)功能定义。

流水灯模块

`timescale 1ns / 1ps

module led(
    output reg[3:0] led,
    input   clk,
    input   rst_n
    );
    reg [31:0] cnt;
    reg [1:0]  led_on_number;
parameter CLOCK_FREQ = 50000000;
parameter COUNTER_MAX_CNT = CLOCK_FREQ/2-1;
    
    always @(posedge clk, negedge rst_n)begin
        if(!rst_n) begin
            cnt <= 31'd0;
            led_on_number <= 2'd0;
        end
        else begin
            cnt <= cnt + 1'b1;
            if(cnt == COUNTER_MAX_CNT) begin
                cnt <= 31'd0;
                led_on_number <= led_on_number + 1'b1;
            end
        end
    end
    
    always@(led_on_number) begin
        case(led_on_number)
            0:led<=4'b0001;
            1:led<=4'b0010;
            2:led<=4'b0100;
            3:led<=4'b1000;
        endcase
    end
endmodule

功能定义部分有三种方法:

1. assign语句:描述组合逻辑

2. always语句:描述组合/时序逻辑

3. 例化实例元件

上述三种逻辑功能是并行的。

在always块中,逻辑是顺序执行的;而多个always块之间是并行的。

模块的输入端可以是wire类型,也可以是reg类型;输出端必须是wire类型。

三、进阶

1. 结构语句

initial语句:在模块中只执行一次,常用于测试文件的编写,用来仿真测试信号。 

always语句:一直在不断地重复活动,但是只有和一定的时间控制结合在一起才有作用。

Verilog HDL_第12张图片

always的时间控制可以是沿触发,也可以是电平触发。触发信号可以是单个信号,也可以是多个信号,多个信号中间要用关键字or连接。

always语句后紧跟的过程块是否运行,要看其触发条件是否满足。

Verilog HDL_第13张图片

沿触发的always语句块常常描述时序逻辑行为,如上图。 时序逻辑中,任意时刻的输出不仅仅取决于当时的输入信号,而且还取决于电路原来的状态。或者说还与以前的输入有关,因此时序逻辑必须具备记忆功能。

Verilog HDL_第14张图片

电平触发的always块常常描述组合逻辑行为,如下图。组合逻辑中,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关。

Verilog HDL_第15张图片

2. 赋值语句

Verilog HDL语句中,信号有两种赋值方式:(1)阻塞赋值;(2)非阻塞赋值。

(1)阻塞赋值

在同一个always块中,后面的赋值语句是前一句赋值语句结束后才开始。

阻塞赋值:计算RHS并更新LHS。

Verilog HDL_第16张图片

(2)非阻塞赋值

在计算非阻塞赋值的RHS以及更新LHS期间,允许其他的非阻塞赋值语句同时计算RHS和更新LHS。

非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial块和always块等过程块中。

非阻塞赋值:(1)赋值开始时,计算RHS;(2)赋值结束时,更新LHS。

Verilog HDL_第17张图片

 在描述组合逻辑的always块中用阻塞赋值,综合成组合逻辑的电路结构;在描述时序逻辑的always块中使用非阻塞赋值,综合成时序逻辑的电路结构。

在同一个always块中不要既用非阻塞赋值又用阻塞赋值。

不允许在多个always块中对同一个变量进行赋值。

3. 条件语句

Verilog HDL_第18张图片

 (1)if(a)等同于if(a==1)        if(!a) 等同于 if(a!=1)

(2)if语句对表达式的值进行判断,若为0、x、z,则按假处理;若为1,则按真处理。

(3)if和else后面的操作语句可以用begin和end包含多个语句。

(4)语序if语句的嵌套

Verilog HDL_第19张图片

case语句        (多分支选择语句)

 

 

你可能感兴趣的:(ZYNQ,fpga开发)