目录
一、design code
1 Combinational logic for always
always@(*)begin
end
2 sequential logic
- sync rst
always@(posedge clk)begin
if(!rst)
else
end
- async rst
always@(posedge clk or negedge rst)begin
if(!rst)
else
end
3 例化循环语句
genvar i;
generate
for()begin:name
instance
end
endgenerate
4 function
1)不含有任何延迟、时序或时序控制逻辑
2)至少有一个输入变量
3)只有一个返回值,没有输出
4)不含有非阻塞赋值语句
5)函数可以调用其他函数,但是不能调用任务
function [N-1,0] function_id(
input A,
input B
);
//outher_declaration
//procedural statement
endfunction
- 常数函数举例
parameter MEM_DEPTH = 256 ;
reg [log2(MEM_DEPTH)-1: 0] addr_width ; //可得addr的宽度为8bit
function integer log2;
input integer depth ;
//256为9bit,我们最终数据应该是8,所以需depth=2时提前停止循环
for(log2=0; depth>1; log2=log2+1) begin
depth = depth >> 1 ;
end
endfunction
- automatic 函数
由于,一般的函数被调用时,函数的局部变量都会使用同一个存储空间,所以在两个地方同时被调用时,会产生不确定值。
automatic函数能够自动分配地址空间,且可以进行层次访问。
wire [16:0] results3 = plusd(6);
function automatic integer plusd ;
input integer data_in ;
begin
plusd = (data_in>=2)? data_in * plusd(data_in-1) : 1 ;
end
endfunction//阶乘运算
5 task
比较点 | 函数 | 任务 |
---|---|---|
输入 | 函数至少有一个输入,端口声明不能包含 inout 型 | 任务可以没有或者有多个输入,且端口声明可以为 inout 型 |
输出 | 函数没有输出 | 任务可以没有或者有多个输出 |
返回值 | 函数至少有一个返回值 | 任务没有返回值 |
仿真时刻 | 函数总在零时刻就开始执行 | 任务可以在非零时刻执行 |
时序逻辑 | 函数不能包含任何时序控制逻辑 | 任务不能出现 always 语句,但可以包含其他时序控制,如延时语句 |
调用 | 函数只能调用函数,不能调用任务 | 任务可以调用函数和任务 |
书写规范 | 函数不能单独作为一条语句出现,只能放在赋值语言的右端 | 任务可以作为一条单独的语句出现语句块中 |
仿真时间单位 | 函数与主模块公用一个时间单位 | 任务可以定义自己的仿真时间单位 |
https://www.runoob.com/w3cnote/verilog-task.html
task task_name;
//<端口名及数据类型说明>
//procedural statement
endtask
调用
task_name (port1,port2,…);
NOTES:
对于task,输入默认为wire,输出默认为reg。不需要再次说明。
- 举例说明
task and;
input [N-1:0] a;
input [N-1:0] b;
output [N-1:0] c;
#3 c = a & b;
endtask
- automatic task
task automatic test;
二、testbench code
1 process
//1 port type
//2 initialization signal
//3 stimulate signal
//4 generate clock
//5 module instance
//6 stop
2 stop
initial begin
forever begin
#100;
if ($time >= 1000) $finish ;
end
end
3 clock
一定要使用2.0,否则会出错(精度问题)
always #(period/2.0) clk = ~clk;