任务和函数
一、任务
task <任务名>
端口和类型声明
局部变量声明
begin
语句;
end
endtask
例子:
task read_memory;
input [15:0] address; //输入端口说明
output [31:0] data; //输出端口说明,即返回值
reg [3:0] counter; //变量类型说明
reg [7:0] temp [1:4]; //变量类型说明
begin
for(counter=1;counter<=4;counter=counter+1)
temp[counter] = mem[address + counter-1];
data = {temp[1],temp[2],temp[3],temp[4]};
end
endtask
例子:交通灯
代码实现:
module traffic_lights_tb(red,yellow,green);
output red,yellow,green;
reg [1:0]order;
reg red,yellow,green;
reg clk;
parameter tic_time_R=1,tic_time_Y=2,tic_time_G=3;
//产生时钟脉冲
initial clk=0;
always
begin
#10 clk=1;
#10 clk=0;
end
//任务:开启交通灯
task light;
output red;
output yellow;
output green;
input [1:0]order;
begin
red=0;
yellow=0;
green=0;
case(order)
2'b01:red=1;
2'b10:green=1;
2'b11:yellow=1;
default:
begin
red=0;
yellow=0;
green=0;
end
endcase
end
endtask
//任务调用,交通灯初始化
initial
begin
order=2'b00;
light(red,yellow,green,order);
end
//任务调用,交通灯控制时序
always
begin
order=2'b01;
light(red,yellow,green,order);//开红灯
repeat(tic_time_R) @(posedge clk);//重复tic_time次上升沿所经过的时间
order=2'b10;
light(red,yellow,green,order);//开绿灯
repeat(tic_time_G) @(posedge clk);//重复tic_time次上升沿所经过的时间
order=2'b11;
light(red,yellow,green,order);//开黄灯
repeat(tic_time_Y) @(posedge clk);//重复tic_time次上升沿所经过的时间
end
endmodule
仿真结果:
二、函数
function <返回值类型或位宽><函数名>;
<输入参量与类型声明>
<局部变量声明>
begin
语句1;
end
endfunction
例子:阶乘函数
module tryfact_tb;
function [31:0]factorial;//函数相当于一个返回数
input[3:0]operand;
reg[3:0]index;
begin
factorial=1;
for (index=1;index<=operand;index=index+1)
factorial=index*factorial;
end
endfunction
reg [31:0]result;
reg [3:0]n;
initial
begin
result=1;
for (n=1;n<9;n=n+1)
begin
result=factorial(n);
$display("n=%d result=%d",n,result);
end
end
endmodule
三、任务和函数的区别
四、测试向量(一般用initial定义)
(1)测试向量例子:质数打印
功能描述:产生位宽为4的质数序列{1 3 5 7 11 13}, 重复两次,样值间隔4个仿真时间单位
'timescale 1ns/1ps
module sequence_tb;
reg [3:0]out;
initial begin
repeat (2)
begin
#4 out=1;
#4 out=3;
#4 out=5;
#4 out=7;
#4 out=11;
#4 out=13;
end
end
endmodule
仿真波形:
(2)时钟测试向量例子:
module clk(clk);
output clk;
parameter clk_period=20;
reg clk;
initial clk=0;
always #(clk_period/2) clk=~clk;
endmodule
(3)自定义占空比时钟信号:
module Duty_Cycle(clk);
output clk;
reg clk;
parameter high_time=5, low_time=20;
always
begin
clk=1;
#high_time;
clk=0;
#low_time;
end
endmodule
(4)具有相位偏移的时钟信号
(组成:标准时钟加延迟,用途:一般用在将采样时钟信号移到眼图中央)
module shift_Duty_Cycle(clk_a,clk_b);
output clk_a,clk_b;
reg clk_a;
wire clk_b;
parameter high_time=5, low_time=20,shift_time=5;
always
begin
clk_a=1;
#high_time;
clk_a=0;
#low_time;
end
assign #shift_time clk_b=clk_a;
endmodule
(5)产生固定数目的时钟信号
module fix_num_clk(clk);
output clk;
reg clk;
parameter clk_num=5,clk_period=10;
initial begin
clk=0;
repeat(clk_num)
#clk_period/2 clk=~clk;
end
endcase
(6)总线信号测试向量
四、基本门级元件和模块的延时建模
上升延时:信号由0、x、z状态变化到1状态收到的门延时时间
下降延时:信号由1、x、z状态变化到0状态收到的门延时时间
截止延时:信号由0、1、x状态变化到z状态收到的门延时时间
到不定态的延时:信号由0、1、z状态变化到x状态收到的门延时时间
notif1 #(10,20,30) U1(out,in,clk); //上升延时:10,下降延时:20,截止延时:30
//不定态延时:三者中的最小,10