一、基础语法
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. 运算符
除法只能整除
二、 程序框架
1. 注释
两种注释方式:和C语言相同//和/* */
2. 关键字
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类型。