当前位置:文档之家› verilog任务和函数课件例程

verilog任务和函数课件例程


果合并后输出到端口“data”。
在定义任务时必须注意如下几点: (1) 在第一行“task”语句中不能列出端口名列表。 (2) 在任务定义结构中的“行为语句”部分可以有延时语句、 敏感事件控制语句等时间控制语句出现。 (3) 一个任务可以没有输入、输出和双向端口,也可以有一 个或多个输入、输出和双向端口。 (4) 一个任务可以没有返回值,也可以通过输出端口或双向 端口返回一个或多个返回值。 (5) 在一个任务中可以调用其它的任务或函数,也可以调用 该任务本身。 (6) 在任务定义结构内不允许出现过程块(initial 或 always过程块)。 (7) 在任务定义结构内可以出现“disable中止语句”,这 条语句的执行将中断正在执行的任务。当任务被中断后,程序流 程将返回到调用任务的地方继续向下执行。
内的标识符“c”都代表局部变量,而在任务定义结构外出现的
“c”则代表着模块内定义的变量c。 下面是一个具体的、实现交通灯控制的例子,在该模块中使 用任务可以使程序简洁易懂。
【例7-4】交通灯控制模块。 module traffic_lights; reg clock, red, amber, green; parameter on=1, off=0, red_tics=350, amber_tics=30,green_tics=200; //交通灯初始化 initial red=off; initial amber=off; initial green=off; //交通灯控制时序 always begin red=on; //开红灯 light( red, red_tics); //调用等green, green_tics); //等待 amber=on; //开黄灯 light( amber, amber_tics); //等待
下面我们举几个例子说明任务的调用。
【例7-3】用任务来实现一个8位加法器。 module task_example (a,b,c);
input [7:0] a,b;
output [7:0] c; reg [7:0] c; task adder; input [7:0] a,b; output [7:0] adder; reg c; integer i; //此处的变量c是任务内的局部变量 //任务内局部变量说明 //任务定义部分
2. 任务的调用
任务的调用是通过“任务调用语句”来实现的。任务调用语 句的语法如下: <任务名> ( 端口1,端口2,……,端口n ); 其中,“(端口1, 端口2,……, 端口n)”组成了一个端口名列表。 在调用任务时必须注意: (1) 任务调用语句只能出现在过程块内。 (2) 任务调用语句就像一条普通的行为语句那样得到处理。 (3) 当被调用的任务具有输入或输出端口时,任务调用语句 必须包含端口名列表,这个列表内各个端口名出现的顺序和类型 必须与任务定义结构中端口说明部分的端口顺序和类型相一致, 注意只有寄存器类的变量才能与任务的输出端口相对应。 例如,例7-2所示模块对例7-1中定义的任务“read_mem”进行 了调用。
务被调用时,模块中的变量a,b,c分别和任务中的端口a,b, adder相互对应,这样在任务执行完毕后运算结果(即adder的值)
可以通过输出端口传递给变量c 。要注意在模块和任务内都定义
了变量“c”,它们是两个不同的变量,在任务内定义的局部变量 只能在任务内部使用。所以在这种情况下,出现在任务定义结构
上是相同的。任务定义结构不能出现在任何一个过程块的内部。
【例7-1】任务的定义。 task read_mem; //任务定义结构的开头,指定任务名为“read_mem” 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 //输出端口说明 //局部变量说明 //局部变量说明
其中:关键词task和endtask将它们之间的内容标志成是一个任
务定义。其中关键词task标志着一个任务定义结构的开端,其后
的“<任务名>”是为被定义任务所取的一个名称。在“<任务名>” 后面不能出现输入输出端口列表。
“端口与类型说明”用于对任务各个端口的宽度和类型进行
说明,其中端口类型由关键词input,output和inout (分别表示: 输入、输出和双向端口)指定,该说明语句的语法与进行模块定
共同点
• 任务和函数必须在module内调用 • 在任务和函数中不能声明wire
• 所有输入/输出都是局部寄存器
• 任务/函数执行完成后才返回结果。
例如,若任务/函数中有forever语句,则永远不会返回结果
7.1 Verilog 任务
“任务(task)”类似于其它编程语言中的“过程”。任务的使用包
begin c = 0; begin // c存储着上一位数字相加时的进位 for (i = 0; i <= 7; i = i+1)
adder[i] = a[i] ^ b[i] ^ c;
end
//求一位数字相加的结果
c = (a[i] & b[i]) | (a[i] & c) | (b[i] & c);
义时的相应说明语句语法是一致的。
“局部变量说明”用来对任务内用到的局部变量进行宽度和 类型说明,这个说明语句的语法与进行模块定义时的相应说明语
句语法是一致的。
由“begin”和“end”关键词界定的一组行为语句指明了任务 被调用时需要进行的操作。在任务被调用时,这些行为语句将按
串行方式得到执行。
任务定义与“过程块”、“连续赋值语句”及“函数定义” 这三种成份以并列方式存在于行为描述模块中,它们在层次级别
任务的调用具有以下特点:
(1) 在任务内定义的局部变量都具有局部和静态的特点。也 就是说,如果同时对同一任务进行两次调用,则两个调用进程使 用的将是相同物理地址处的同一个局部变量。在这种情况下要注 意防止内存使用冲突。 (2) 在一个任务中可以直接访问上一级调用模块中的任何寄 存器,例如上例中我们可以在任务“read_mem”中对存储器变量 mem进行访问,这个mem变量是在上一级模块(调用模块) “demo_task_invo”中定义的。 (3) 由于任务内部可以包含时间控制语句,所以调用执行一 个任务所需的时间可以是非零时间单位,也就是说任务启动时刻 可以是不同于任务结束时刻的。 (4) 可以通过一个disable语句来中断任务的执行。任务被 中断后,程序流程将返回到调用任务的地方继续往下执行。
end
endtask always@(a or b) //任务定义部分结束
adder (a,b,c);
endmodule
//任务调用语句
上例所示的模块由“任务定义部分”和“always过程块”两 部分组成,其中定义的任务“adder”实现了一个8位加法器的运
算功能,它有两个输入端口a和b,有一个输出端口adder。在任
endtask
//任务定义结构的结尾
上例定义了一个名为“read_mem”的任务,该任务有一个16 位的输入端口“address”、一个32位的输出端口“data”、一个4 位的局部变量“counter”和一个8位的存储器“temp”。 当上例所定义的任务被调用时,begin和end中间的语句得到 执行,它们用来执行对存储器“mem”进行的四次读操作,将其结
【例7-2】对任务进行调用。 module demo_task_invo; reg[7:0] mem [128:0]; reg[15:0] a; reg[31:0] b; initial begin a=0; read_mem(a,b); //第一次调用 #10; a=64; read_mem(a,b); //第二次调用 end <任务“read_mem”定义部分> endmodule
括任务定义和任务调用。任务既可表示组合逻辑又可表达时
序逻辑,定义的形式如下 task <任务名>; <端口及数据类型声明语句> begin <语句1> <语句2> ..... <语句n> end endtask 任务可以没有或有一个或多个参数。值通过参数传入和传出 任务。除输入参数外(参数从任务中接收值),任务还能带 有输出参数(从任务中返回值)和输入输出参数。任务的定 义在模块说明部分中编写。
Verilog的任务及函数区别和联系
区别
• 任务(task) 通常用于调试,或对硬件进行行为描述 可以包含时序控制(#延迟,@, wait) 可以有 input,output,和inout参数 可以调用其他任务或函数 • 函数(function) 通常用于计算,或描述组合逻辑 不能包含任何延迟;函数仿真时间为0 只含有input参数并由函数名返回一个结果 可以调用其他函数,但不能调用任务
always@(code or a or b) begin case(code) 2'b00: my_and (a, b, c); /* 调用任务my_and,需注意端口列表的
顺序应与任务定义中的一致,这里的a,b,c分别对应任务定义中的 a,b,out */
2'b01: c=a|b; //或 2'b10: c=a-b; //相减 2„b11: c=a+b; //相加 default: c=2‟bx; endcase end endmodule
相关主题