目录
数据类型
-
wire
- 定义:连接物理硬件间的连线,由硬件输出端持续性改变值
-
reg
- 定义:存储单元,只有改变操作才能改变存储的值
-
integer
- 定义:整数类型寄存器,通常用于for循环等辅助操作
-
real
- 定义:实数类型寄存器,辅助操作
-
time
- 定义:时间寄存器,常用于仿真等
-
向量
- 定义:一个带有长度的量
- 顺序域赋值:
- a[31-:8]=a[31:8];
- a[0+:7]=a[0:7];
- 拼接操作:
- a[1:0]=b[8:7]+1'b1
- assign a[2:0]={b[1:0],c[8:7]};
- assign a={32{1'b0}};赋值32个0
-
数组
- 定义:多个向量
-
存储器
- 定义:类似寄存器数组,用来描述ROM和RAM的行为
-
parameter
- 定义:常用来表示常数,可通过实例化改变值
-
字符串
- 定义:8bit表示一个字符,所以存储容量要大一些:如果存储容量超过字符串长度,左边补0;反之,截去字符串多余的长度。
编译指令
`timescale
- 语法:`timescale timeunit/time precision
- timeunit 时间单位
- time precision 时间精度
- 特点:
- 作用域直到新的`timescale出现
- 模拟器会选取最小的时间单位和精度,其他时延对应换算
- 并行模块的时延设置互不影响
连续赋值
- 定义:实时将数据赋值给对应值
- 模板:
- assign LHS=RHS
- LHS(left hand side)只能为wire型
- RHS(right hand side)可以为reg,函数调用等
- wire a=b
- 声明时调用只能有一次连续赋值
- assign LHS=RHS
时延
- 普通时延:
wire a,b;
assign #10 c=a&b;
- 隐式时延:
wire a,b;
wire #10 c=a&b;
- 声明时延:
wire a,b;
wire #10 c;
assign c=a&b;
- 惯性时延:如上例,在时延范围内a,b被赋予新值,则c会使用最新的值运算,所以可能漏掉一些结果,要注意时延时间。
#10范围内,a由0变1再变0,b始终为1,c始终为0
没有时延的正常结果是c=1,但因为有了时延,a=1没被捕捉到,所以c始终为0
过程结构
-
特点
- 模块间并行
- 模块内顺序执行(除非阻塞性赋值)
-
initial
- 只运行1次
- 不可综合
- 用作初始化
-
always
- 运行多次
- 可综合
- 用作时钟或信号检测
过程赋值
-
过程性赋值:
- 通常在always,initial中赋值,必须等时钟等触发才能更新值。
-
连续性赋值:
- 实时更新值,不需要触发。
-
阻塞性赋值:
-
- 定义:必须执行完当前指令才能执行下一条指令
- 表示:a=b
-
非阻塞性赋值:
- 定义:可以并行,所以赋值为之前旧值而不是新值
- 表示:a<=b
- 功能:可以用来解决赋值的竞争冒险
always @(posedge clk) begin
a=b;//a的值变成b
end
always @(posedge clk) begin
b=a;//b的值还是b,没有达到交换效果
end
//并且两个阻塞性赋值必须有先后,这里不知谁先谁后,产生矛盾
always @(posedge clk) begin
a<=b;//a的值变成b的旧值
end
always @(posedge clk) begin
b<=a;//b的值变成a的旧值
end
时序控制
-
时延控制
- 外控:先延时再利用最新值计算结果
- general control:assign #10 a=b;
- single control: #10; assign a=b;
- 内嵌控制:计算并保存当前结果,延时一段时间再赋值
- 表达式:assign a=#10 b
- 区别:
- 右侧为常量赋值效果一致
- 右侧为变量时:外控会先延时再使用最新值赋值,内嵌控制会先使用当前值计算并保存结果,延时后再赋值,所以更可能出现“习惯时延”
- 外控:先延时再利用最新值计算结果
-
事件激发控制:
- 一般事件控制:一个寄存器或wire的值发生变化
- always @(posedge clk)
- 命名事件控制:自己命名事件作为控制信号
- 一般事件控制:一个寄存器或wire的值发生变化
event start_receiving ;
always @( posedge clk_samp) begin
-> start_receiving ; //采样时钟上升沿作为时间触发时刻
end
always @(start_receiving) begin
data_buf = {data_if[0], data_if[1]} ; //触发时刻,对多维数据整合
end
-
- 敏感列表控制:
- 逐个列:module(a or b) // module(a,b);
- 表示模块内全部输入值都触发:always(*)
- 敏感触发:@(posedge clk);
- 敏感列表控制:
- 电平敏感控制:利用电平高低进行控制
条件语句
if语句
- 通常表示
if() begin truestatement end
else if() begin truestatement end
else if() begin truestatement end
else if() begin truestatement end
else begin defaultstatement end
- 例子:4选1多路选择器
module mux4to1(
input [1:0] sel,
input [1:0] p1,
input [1:0] p2,
input [1:0] p3,
input [1:0] p4,
output [1:0] sel_out
);
reg [1:0] sel_t;
always @(*) begin
if(sel==2'b00) begin
sel_t=p1;
end else if(sel==2'b01) begin
sel_t=p2;
end else if(sel==2'b10) begin
sel_t=p3;
end else begin
sel_t=p4;
end
end
assign sel_out=sel_t;
endmodule
case语句
- 通常表示
case(op)
condition1:begin end
condition2:begin end
default:begin end
endcase
- casex,casez:在casex中利用x代替未知数字,casez用?代替未知数字,通常用于仿真
仿真激励
-
信号申明
- 端口取名和各文件最好一致
- 输入必须为reg,输出必须为wire
-
复位
- 定义:0为复位,1不复位
- 表示:
initial begin
reset=0;
#8 reset=1;
end
-
时钟
- 表示:
real CYCLE_200MHZ=5;
always begin
CLK=0;#(CYCLE_200MHZ/2);
CLK=1;#(CYCLE_200MHZ/2);
end
-
激励
- 定义:根据模块需要设计对应的输入数据
-
信号链接
- 方式:
- 链接文件名 自取名(.a(a),.b(b),.c(c));
- 链接文件名 自取名(a,b,c);a,b,c按端口顺序排列依次例化
- 方式:
-
自校验
- 定义:根据激励提供对应反应
-
停止仿真
always @(*) begin
#100;
if($time>=10000) $finish;
end