第五讲 任务、函数和编译预处理
函数与编译预处理
函数与编译预处理一、函数的定义1、无参函数的定义形式类型标识符函数名()第一行:函数首部{声明部分语句 { }包含的:函数体}例1:void fun( ){printf(“Hello!\n”);}2、有参函数的定义形式类型标识符函数名(形式参数列表){声明部分语句}例2:int max(int x, int y){ int z;z = x > y ? x : y;return (z);}注:“类型标识符”是指函数值的类型。
若省略,默认为int。
二、函数的调用无参函数:函数名()有参函数:函数名(实际参数列表)例3:在main函数中调用fun和max函数void main( ){int m,n,t;scanf(“%d,%d”,&m,&n);t=max(m,n); /*调用max函数*/fun(); /*调用fun函数*/printf(“max number is %d\n”,t);}注:1、C语言程序由函数构成,其中有且仅有一个main函数,各函数书写的先后顺序任意。
2、函数的定义是相互独立的,不能在一个函数的内部定义另一个函数,即函数的定义不能嵌套。
3、程序从main函数开始执行,其他函数被调用时执行,调用完后回到主调函数,最后在main函数中结束整个程序。
三、函数的声明在主调函数中一般要对被调函数进行声明。
声明的作用是告知编译器被调函数的函数名、函数类型、参数个数和参数类型,方便进行语法检查。
声明的形式:类型标识符函数名(形式参数列表);即:函数首部加分号例如:void fun( );int max(int x, int y);其中参数名称可省略,如:int max(int , int );Turbo C在以下两种情况中,可省略函数声明:1、被调函数定义在主调函数前。
2、被调函数类型为int、char。
四、参数的传递1、形参是变量,但函数被调用时才被分配内存,调用完毕,所占内存将被释放。
第五讲 任务、函数和编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
第二种解答
module sort4(clk,reset,ra,rb,rc,rd,a); output [7:0] ra,rb,rc,rd; input [7:0] a; input clk,reset; reg [7:0] ra,rb,rc,rd; reg [7:0] va,vb,vc,vd; always @ (posedge clk) begin if(!reset) begin va<=0; vb<=0; vc<=0; vd<=0; end else va<=a; end ... .....
verilog2008--TJU. ASIC Center---Arnold Shi
目 录
1 2 3 4
任务(task) 任务(task) 函数(function) 函数(function) 系统任务和系统函数 编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
verilog2008--TJU. ASIC Center---Arnold Shi
任务调用举例(用全局变量传递数据) 任务调用举例(用全局变量传递数据)
module Global_Var; reg [0:7] RamQ[0:63]; integer Index; reg CheckBit; task GetParity; input Address; output ParityBit; ParityBit = ^ RamQ [Address]; endtask initial for(Index=0; Index<=63; Index=Index+1) begin GetParity(Index,CheckBit); $display("Parity bit of memory word %d is %b.", Index, CheckBit); end endmodule
C++学习资料-函数和编译预处理
int maxi(int a,int b) { return a>b?a:b;}
19:01
5.2 形参与实参的结合方式
值传递:实参将它的值传递给形参变量
int max(int x,int y)
a: 20
{x=100;return(x>y?x:y);}
3*f(2)
}
递归调用包括两个过程: 2*f(1)
递推和回代过程.
1
1*2*3*4*5 1*2*3*4 1*2*3 1*2
递推过程 回代过程
19:01
5.3 递归调用的较复杂例子
河内塔问题:A(n)C(借助B )
A柱
B柱
C柱
设A柱上有n个盘子,盘子大小不等,大盘子在下,小盘 子在上,要求将A柱上盘子移到C柱上,每次只能移动 一个盘子,在移动过程中可以借助于任一柱子,但必须 保证三根柱子上的盘子都是大盘子在下,小盘子在上. 要求编一个程序打印出移动盘子的步骤.
40 20
20 40
19:01
5.3 函数的嵌套调用
在函数体内定义另一个函数是不允许的, 每个C++函数都具有平等的地位.但在函 数调用时可以嵌套调用:
A函数{ B函数;
}
B函数{ C函数;
}
C函数{ 函数体;
}
19:01
5.3 函数的递归调用
在函数的嵌套调用中:
函数调用其本身: 称为直接递归
A函数{ A函数;
#include "iostream.h"
int maxi(int a,int b) { return a>b?a:b;}
C++学习课件PPT5 函数和编译预处理
#include “iostream.h” int i=100;
全局变量i
void main(void)
局部变量i
{ int i=50,j=20; int max(int i,int j);
局部变量i
cout<<max(i,j)<<‘\t’;
cout<<max(::i,j); }
引用全局变量
int max(int i,int j)
14:07
5.2 例
#include "iostream.h"
int maxi(int a,int b) 注意这里的
{ return a>b?a:b;} 实参表达式
void main()
计算顺序
{
int a,b;
a=20; b=40;
cout<< maxi(b+a,b=b+1); 问题:maxi函数输出值?
14:07
动态变量与静态变量例
例 #include “iostream.h”
int t(void) {static int i=100;
i+=5; return i; } void main(void) {cout<<“i=“<<t()<<‘\t’; cout<<“i=“<<t()<<‘\t’; }
14:07
河内塔问题:
第一步已完成: A(n-1)B(借助C)
A柱
B柱
C柱
第二步:将A柱剩下的一个最大的盘子移到C 柱
AC
14:07
原状态: A柱
河内塔问题:
第五讲 任务、函数和编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
任务的调用
一个任务由任务调用语句调用。任务调用语句给出传入任 务的参数值和接收结果的变量值,一个任务调用能够修改 被其他任务调用读取的局部变量的值. 任务调用语句是过程性语句,可以在always 语句或 initial 语句中使用。形式如下: task_id [(expr1, expr2 ,...,exprN )] ; 任务调用语句中参数列表必须与任务定义中的输入、输出 和输入输出参数说明的顺序匹配。参数要按值传递,不能 按地址传递。 因为任务调用语句是过程性语句,所以任务调用中的输出 和输入输出参数必须是寄存器类型的
verilog2008--TJU. ASIC Center---Arnold Shi
任务使用举例2
任务的输入和输出在任务开 始处声明。这些输入和输 出的顺序决定了它们在任 务调用中的顺序 task Rotate_Left; inout [1:16] In_Arr; input [0:3] Start_Bit, Stop_Bit, Rotate_By; reg Fill_Value; integer Mac1, Mac3; begin
TJIC
第五讲 任务、函数和编译预处理
天津大学电子科学与技术系 史再峰 shizaifeng@
verilog2009--TJU. ASIC Center---Arnoldsk)
函数(function) 系统任务和系统函数
2
3 4
编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
end
交通灯例子(续)
//定义交通灯开启时间的任务 task light; output color; input [31:0] tics; begin repeat(tics) @(posedge clock); //等待tics个时钟的上升沿
中国铁道出版社C++_5_函数和编译预处理
C++程序设计----第三章 函数与编译处理
图3.1是一个程序中函数调用的示意图。
main()
func1()
func2()
func3()
func4()
func5()
图3.1
3- 7
C++程序设计----第三章 函数与编译处理
例3.1 在主函数中调用其他函数。 #include <iostream.h> //*****ex3_1.cpp***** int calc_sum(int n) //定义calc_sum()函数 { int k,s; s=0; for (k=1;k<=n;k++) s=s+k; return s; } void print_word() //定义print_word()函数 { cout<<"Hello,C++!"<<endl; //输出一行文字 } void main() { int n; cin>>n; if (n>1) cout<<"the sum is:"<< calc_sum(n)<<endl; //调用calc_sum()函数 print_word(); //调用rint_word()函数 3- 8 }
3- 14
C++程序设计----第三章 函数与编译处理
3.2.2 函数的声明
void A(){…….......................}//函数A定义在B之前 函数的声明与函数定义的规律 void B(){A;….......................}//函数B中调用函数A 如果函数的定义在调用之前就不要函数的声明。 void B();//函数的声明,因为B函数定义在A函数之后 如果函数的定义在调用之后,那么必须在调用的 A(){B;……………………….}//函数A中调用函数B 前面必须进行函数的声明。 B(){………………………….}//函数B的定义 函数的声明可以放在任何位置,关键是一定要放
实验五 函数与编译预处理
《C语言程序设计》实验报告实验五函数与编译预处理学号201002314 姓名李光一、实验目的1、掌握函数定义及调用的方法,正确理解函数调用时实参和形参的对应关系2、掌握并正确使用数组作为函数参数;3、掌握函数的嵌套调用和递归调用的方法;4、理解变量的作用域和生存期;5、掌握宏定义、文件包含的方法。
二、实验内容1、分析下面的程序并上机运行程序,要求写出3组以上程序的运行结果。
#include <stdio.h> /*程序需要使用C语言提供的标准函数库*/int fun(int k) /*此函数用于计算阶乘*/{int result=1,i;for(i=1;i<=k;i++) /*循环k次*/{result=result*i;}return result;}void main() /*主函数*/{int n;printf("Input n please(1<=n<=10)");scanf("%d",&n); /*输入一个数*/printf("%d!=%d\n",n,fun(n)); /*输出结果*/}『运行结果:』2、编写程序,输出2~n之间的所有素数,n由键盘输入。
要求判断素数的过程要写在函数中,由主函数调用实现,并写出2组以上程序运行结果。
程序代码:#include<stdio.h>#include<math.h>void fun(int n){int a,b;for (a=2;a<=n;a++){for (b=2;b<=a-1;b++){if (a%b==0)break;if (b==a-1){printf ("%3d ",a);}}}}void main(){ int t;printf("input t=");scanf("%d",&t);fun(t);printf("\n");} 『运行结果:』3、编程实现输入8个学生某门功课的成绩,用函数求出平均分,并在主函数中输出平均分以及高于平均分的同学的成绩。
第五章 编译预处理综述
宏定义
宏提供了一种文本替换机制,可分为两类: 不带参数的宏和带参数的宏。
3 2 、带参数的宏定义是指在宏名后面跟有形参表,在替换时,仅用 、预处理命令 1、不带参数的宏定义命令是将一个标识符定义为一个字符序列。 #undef和预处理运算符#注意见书 、 ## P69 (1)~(6) 例如,已知半径,求圆的周长和面积。 #include<iostream.h> 实参替换宏体中与形参表中相同的标识符,宏体中其余部分不变。 #undef 其定义格式: 与#define 命令相对应,是取消宏定义的命令。 字符串化运算符 #:若将 #放在替换文本中的某个形参之前,宏替 // 宏定义 #define PI 3.14159 其定义格式: 格式如下: #define <标识符 > [< 字符序列>] 换时对应的参数将被转化成一个字符串。 void main() < 区别两种定义符号常量的方法: #undef #define <宏名 宏名 > >(<参数表 >) <宏体 > 替换文本 宏名 { const修饰符和#define预处理命令。 调用带参数的宏: 宏定义的生存期是以定义时起,到被取消时为止。 字符连接运算符 ## :用于将两个字符序列连接起来,形成一个 执行时,预处理程序将把源程序中出现在宏定义之后的所有宏名 double r,l,s; 例如,#define SQ(x) x*x 如果始终没有被取消,则到该文件结束为止。 宏名 [ 空格 ]( 实参表 ) 新的字符序列。 cout<<“Input radius:”; 逐一替换成相应的替换文本。这样的替换过程称为宏替换。 语句 s=SQ(a+b); cin>>r; 将被替换为:s=a+b*a+b; // 宏替换为 :l=2*3.14159*r; l=2*PI*r; 带参宏与函数的差异:见书 P71~72 (1)~(4) 若是,#define SQ(x) (x)*(x) // 宏替换为: s=3.14159*r*r; s=PI*r*r; 事实上带参宏的优越性已被内联函数所替代。 则上述语句将被替换为: cout<<“L=”<<l<<‘\n’<<“S=”<<s<<endl; s=(a+b)*(a+b); }
函数和编译预处理.doc
函数和编译预处理函数和编译预处理(第五章)一、单项选择题1.关于函数,以下正确的描述是(B)A,函数的定义可以嵌套,但函数的调用不可以嵌套B,函数的定义不可以嵌套,但函数的调用可以嵌套C,函数的定义可以嵌套,函数的调用也可以嵌套D,函数的定义和函数的调用都不M以嵌套2.关键字inline用于定义内联函数,定义时,是将该关键字(D )A.取代定义函数的类型标识符B.取代被定义的函数名C.加在类型标识符之后D.加在类型标识符之前3.以下不正确的描述为(B )A.在函数之外定义的变量称为外部变量,外部变量是全局变量。
B.在函数之内说明的外部变量是局部变量,仅在本函数中有效。
C.在函数之外说明的静态变量也是全局变量,其作用域是文件作用域。
D.文件作用的域范围是一个程序文件,但必须符合“定义在前,使用在后”的规则。
4.以下正确的描述为(C )A,每个C++程序必须在开头用预处理命令^include <iostream. h>B,预处理命令必须位于C++源程序的首部C.在C++中,预处理命令都以#开头D.C++语言的预处理命令只能实现宏定义和条件编译的功能5.在下面的函数原型说明中,存在着语法错误的是(D )A.void BC(int a, int) ;B. void BD(int , int);C. void BE(int , int=5) ;D. int BF(int x ; int y);6.下列哪个不是重载函数在调用时选择的依据(C )A.形参类型B.形参个数C.函数返回值类型D.函数名7.在一个源程序文件中有以下函数定义,其中(D )是重载函数。
A.ABCB. BCDC. ACDD.全部A) int sum (float x, int y) B) float sum (float x, int y, char z) (. . . )C) float sum (float x, float y) D) int sum(int x, int y, char z) (. . . )8.有一个函数原型abc(float x, float y);该函数的返回值类型为(C )A.voidB. doubleC. intD. float9.在程序中,函数声明语句正确位置是(D )A.随便任何位置B.不包含在另一函数中的任何位置。
第5章 C语言的编译预处理
6
C语言教学 幻灯片版 第五 章 编译预处理 语言教学
5.2 文件包含
功能: 功能:一个源文件可将另一个源文件的内容全部包 含进来 一般形式: 文件名” 一般形式: #include “文件名” 文件名 文件名> 或 #include <文件名 文件名 处理过程:预编译时,用被包含文件的内容取代该预 处理过程:预编译时 用被包含文件的内容取代该预 <> 直接按标准目录搜索 处理命令,再对“包含”后的文件作一 处理命令,再对“包含”,再搜索标准目 先在当前目录搜索, 当前目录搜索 “” 先在当前目录搜索 个 录 源文件编译 可指定路径
• 作用:对源程序编译之前做一些处理 生成扩展 源程序 作用:对源程序编译之前做一些处理,生成扩展 生成扩展C源程序 • 种类: 种类:
– 宏定义 – 文件包含 – 条件编译 #define #include #if--#else--#endif等 等
• 格式: 格式:
– – – “#”开头 开头 占单独书写行 语句尾不加分号
C语言教学 幻灯片版 第五 章 编译预处理 语言教学
第五章 编译预处理
5.1 宏定义 5.2 文件包含 5.3 条件编译
1
C语言教学 幻灯片版 第五 章 编译预处理 语言教学
概 述
“编译预处理”是C语言编译系统的 一个组成 编译预处理” 编译预处理 语言编译系统的 部分。 是在编译前 编译前由编译系统中的预处理程 部分 。 是在 编译前 由编译系统中的预处理程 序对源程序的预处理命令进行加工。 序对源程序的预处理命令进行加工。
C语言教学 幻灯片版 第五 章 编译预处理 语言教学
5.3 条件编译
条件编译举例: 条件编译举例:
函数和编译预处理第5章
引言
随着模拟对象的复杂性增加,程序将会变得越来 越复杂和冗长。在编写一个较大的程序时,为了 便于管理,可以采用一些较好的编程策略,常用 的方法是按功能或操作将程序分割成一些具有特 定功能的、相对独立的且便于管理和阅读的小模 块。本章主要介绍这种分割工具之一:函数,包 括函数的定义、函数的调用、参数的传递方法、 内联函数、函数的重载、变量的作用域等,另外 简要介绍编译预处理以及程序多文件组织的编译 和连接方法。
函数调用的使用方式
对于有返回值的函数,可以用两种方式调 用:一种方式是函数调用出现在表达式中, 其值(也称为函数值)参与表达式的运算; 另一种方式是用一个语句来实现调用,即 在调用格式后加上一个分号,构成函数调 用语句,在这种情况下,函数返回值不起 任何的作用。 对于没有返回值的函数,函数调用只能通 过函数调用语句实现。
函数的定义和调用
函数概述 函数定义 函数调用
5.1
函数概述
5.1.1
C++中的函数就是具有特定功能的模块。函数是构 成C++程序的基本单位,C++程序的运行都是由主 函数(main())开始,然后通过一系列函数调用来 实现各种功能。 从用户角度看,函数包括用户自定义函数和系统 库函数。 从函数的形式来看,函数可以分为无参函数、有 参函数、无返回值函数和有返回值函数等 。 除了main()函数以外,一个函数既可以被其它函 数调用,也可以调用其它函数。 图5-l反映了函数的层次组织结构以及相互之间的 调用关系 。
函数原型说明的一般格式
《类型》 <函数名>(<形参表>); 或 《类型》 <函数名>(<形参类型说明表>); 函数原型说明的形参和返回值的类型必须 与对应的函数定义一致,对于第一种格式, 原型说明中形参表的形参名可以和定义时 的形参名不一致,又由于形参在原型说明 中并不起任何作用,因此可以省略形参名 (即第二种格式)。
函数与编译预处理
例6.3 用递归方法计算n!。
long fact(int n) { if(n==0||n==1) return 1; else return n*fact(n-1); } main() { int n; long m; scanf("%d",&n); m=fact(n); printf("%d!=%ld\n",n,m); }
程序举例
1.以下程序的输出结果是 #define M(x,y,z) x*y+z main() {int a=1,b=2,c=3; printf(“%d\n”,M(a+b,b+c,c+a)); }
计算过程: 1+2*2+3+3+1=12
4+4*4+4/2+2*2+2=28
有以下程序执行后输出结果是 #define f(x) x*x main() {int i; i=f(4+4)/f(2+2); printf(“%d\n”,i); }
2.带参数的宏定义
带参数的宏定义的一般形式为: #define 宏名(形参表) 字符串 对带参数的宏,在调用时,不仅要宏展开,而且要用实参去代换形参。 带参数宏调用的一般形式为:宏名(实参表); #define MAX(x,y) x>y?x:y main() { int a,b,m; scanf("%d%d",&a,&b); m=MAX(a,b); printf("max=%d\n",m);
全局变量和局部变量的使用特点 变量存储类别
05-编译预处理课件
主要内容:宏定义文件包含条件编译C 的源程序预处理 编译 目标程序 (*.C) _______________ (*.OBJ)编译系统中有: 预处理程序 编译程序 宏定义 #define 文件包含 #include 条件编译 #if( )C 语言中的预处理命令分类:预处理是在编译之前对程序中的特殊命令进行的处理工作。
以#开头的是C 语言的编译预处理命令。
•宏定义宏定义的一般格式:#define 宏名字符串功能:在预处理时 ,将程序中宏定义之后出现的所有的宏名,用宏替换字符串代替。
这个过程也称为宏展开,即将宏名替换成字符串的过程。
例如:#define PI 3.1415926说明•宏定义通常放在程序开头,以#开头,不加分号;•宏名一般习惯用大写字母表示。
•一个宏名只能被定义一次。
•宏定义的作用域:从定义开始到程序结尾。
•在进行宏定义时,可以引用已定义的其他宏名。
•对在字符串常量及用户标识符中,与宏名相同部分不作替换。
•当宏定义在一行写不下,换行时需在行尾加换行字符"\"。
#include<stdio.h> #define R 3.0#define PI 3.1415926 #define L 2*PI*R #define S PI*R*R int main() {printf("L =%.2f\n S =%.2f\n", L , S ); return 0; }例10 使用宏定义求圆的周长和面积。
使用宏定义的优点: •可提高源程序的可维护性; •可提高源程序的可移植性; •减少源程序中重复书写字符串的工作量。
#include <stdio.h>#define N 2#define M N+1#define NUM (M+1)*M/2 int main(){int i,n=0;for(i=1;i<=NUM;i++){n++;printf(“%d”,n); }return 0;} (N+1+1)*N+1/2=8例11 求下列语句的循环次数下列语句的循环次数?C语言中还可以定义一种像函数一样的带参数的宏,不仅能进行字符串代替,而且还能进行参数代换。
函数和编译预处理.doc
函数和编译预处理.doc函数和编译预处理函数和编译预处理(第五章)一、单项选择题1.关于函数,以下正确的描述是(B)A,函数的定义可以嵌套,但函数的调用不可以嵌套B,函数的定义不可以嵌套,但函数的调用可以嵌套C,函数的定义可以嵌套,函数的调用也可以嵌套D,函数的定义和函数的调用都不M以嵌套2.关键字inline用于定义内联函数,定义时,是将该关键字(D )A.取代定义函数的类型标识符B.取代被定义的函数名C.加在类型标识符之后D.加在类型标识符之前3.以下不正确的描述为(B )A.在函数之外定义的变量称为外部变量,外部变量是全局变量。
B.在函数之内说明的外部变量是局部变量,仅在本函数中有效。
C.在函数之外说明的静态变量也是全局变量,其作用域是文件作用域。
D.文件作用的域范围是一个程序文件,但必须符合“定义在前,使用在后”的规则。
4.以下正确的描述为(C )A,每个C++程序必须在开头用预处理命令^includeB,预处理命令必须位于C++源程序的首部C.在C++中,预处理命令都以#开头D.C++语言的预处理命令只能实现宏定义和条件编译的功能5.在下面的函数原型说明中,存在着语法错误的是(D )A.void BC(int a, int) ;B. void BD(int , int);C. void BE(int , int=5) ;D. int BF(int x ; int y);6.下列哪个不是重载函数在调用时选择的依据(C )A.形参类型B.形参个数C.函数返回值类型D.函数名7.在一个源程序文件中有以下函数定义,其中(D )是重载函数。
A.ABCB. BCDC. ACDD.全部A) int sum (float x, int y) B) float sum (float x, int y, char z) (. . . )C) float sum (float x, float y) D) int sum(int x, int y, char z) (. . . )8.有一个函数原型abc(float x, float y);该函数的返回值类型为(C )A.voidB. doubleC. intD. float9.在程序中,函数声明语句正确位置是(D )A.随便任何位置B.不包含在另一函数中的任何位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
endmodule
这个例子描述了一个简单 的交通灯的时序控制,并 且该交通灯有它自己的时 钟产生器。
verilog2008--TJU. ASIC Center---Arnold Shi
练习. 在Verilog HDLBits。 函数返回一个长度为 MAXBITS的向量。函数有 一个输入Din.K,是局部整 型变量。
verilog2008--TJU. ASIC Center---Arnold Shi
隐式地声明一个寄存器变量
函数定义在函数内部隐式 地声明一个寄存器变量, 该寄存器变量与函数同名 并且取值范围相同。函数 通过在函数定义中显式地 对该寄存器赋值来返回函 数值。对这一寄存器的赋 值必须出现在函数定义中。 在该函数中, Parity是函 数的名称。因为没有指定 长度,函数返回1位二进 制数
任务
一个任务就像一个过程,它可以从描述的不同位臵执行共 同的代码段。 共同的代码段用任务定义编写成任务,这样它就能够从设 计描述的不同位臵通过任务调用被调用。 任务可以包含时序控制,即时延控制,并且任务也能调用 其它任务和函数。
verilog2008--TJU. ASIC Center---Arnold Shi
任务的定义
任务可以没有或有一个或多个参数。值通过参数传入和传 出任务。除输入参数外(参数从任务中接收值),任务还 能带有输出参数(从任务中返回值)和输入输出参数。任 务的定义在模块说明部分中编写。 tasktask_id任务名; [declarations]端口及数据类型声明语句 procedural_statement endtask
verilog2008--TJU. ASIC Center---Arnold Shi
练习题解答
module sort4 (ra,rb,rc,rd,a,b,c,d); output [7:0] ra,rb,rc,rd; input [7:0] a,b,c,d; reg [7:0] ra,rb,rc,rd; reg [7:0] va,vb,vc,vd; task change; //make comparing inout[7:0] x,y; reg[7:0] tmp; if(x>y) begin tmp=x; x=y; y=tmp; end endtask always @ (a or b or c or d) begin {va,vb,vc,vd}={a,b,c,d}; change(va,vb); change(vb,vc); change(vc,vd); change(va,vb); change(vb,vc); change(va,vb); {ra,rb,rc,rd}={va,vb,vc,vd}; end endmodule
verilog2008--TJU. ASIC Center---Arnold Shi
任务定义举例
moduleHas_Task; parameterMAXBITS = 8; task Reverse_Bits; input [MAXBITS-1:0]Din; output [MAXBITS-1:0]Dout; integer K; begin for (K=0;K<MAXBITS;K=K+1) Dout [MAXBITS-K] = Din[K]; end endtask ... endmodule
交通灯例子(续)
//定义交通灯开启时间的任务 task light; output color; input [31:0] tics; begin repeat(tics) @(posedge clock); //等待tics个时钟的上升沿
color=off;//关灯 end endtask
//产生时钟脉冲的always块
verilog2008--TJU. ASIC Center---Arnold Shi
任务调用举例(用全局变量传递数据)
module Global_Var; reg [0:7] RamQ[0:63]; integer Index; reg CheckBit; task GetParity; input Address; output ParityBit; ParityBit = ^ RamQ [Address]; endtask initial for(Index=0; Index<=63; Index=Index+1) begin GetParity(Index,CheckBit); $display("Parity bit of memory word %d is %b.", Index, CheckBit); end endmodule
verilog2008--TJU. ASIC Center---Arnold Shi
任务的调用
一个任务由任务调用语句调用。任务调用语句给出传入任 务的参数值和接收结果的变量值,一个任务调用能够修改 被其他任务调用读取的局部变量的值. 任务调用语句是过程性语句,可以在always 语句或 initial 语句中使用。形式如下: task_id [(expr1, expr2 ,...,exprN )] ; 任务调用语句中参数列表必须与任务定义中的输入、输出 和输入输出参数说明的顺序匹配。参数要按值传递,不能 按地址传递。 因为任务调用语句是过程性语句,所以任务调用中的输出 和输入输出参数必须是寄存器类型的
for (Mac3=1; Mac3<=Rotate_By; Mac3=Mac3+1) begin Fill_Value = In_Arr[Stop_Bit]; for (Mac1=Stop_Bit; Mac1>=Start_Bit+1; Mac1 = Mac1-1) In_Arr [Mac1] = In_Arr[Mac1-1]; In_Arr [Start_Bit] = Fill_Value; end end endtask
always @ (posedge clk) begin if(!reset) begin va<=0; vb<=0; vc<=0; vd<=0; end else va<=a; end ... .....
verilog2008--TJU. ASIC Center---Arnold Shi
目 录
1
red=on; //开红灯
light(red,red_tics);//调用等待任务 green=on; //开绿灯 light(green,green_tics);//等待 amber=on; //开黄灯
light(amber,amber_tics); //等待
end
verilog2008--TJU. ASIC Center---Arnold Shi
#2 ClockQ=0; end endtask initial GenarateWaveform (NoClock); endmodule 任务GenerateWaveform对ClockQ的 赋值不出现在NoClock上,只有对 ClockQ的最终赋值0在任务返回后 出现在NoClock上。为避免这一情 形出现,最好将ClockQ声明为全 局寄存器类型,即在任务之外声 明它。
verilog2008--TJU. ASIC Center---Arnold Shi
任务使用举例2
任务的输入和输出在任务开 始处声明。这些输入和输 出的顺序决定了它们在任 务调用中的顺序 task Rotate_Left; inout [1:16] In_Arr; input [0:3] Start_Bit, Stop_Bit, Rotate_By; reg Fill_Value; integer Mac1, Mac3; begin
TJIC
第五讲 任务、函数和编译预处理
天津大学电子科学与技术系 史再峰 shizaifeng@
verilog2009--TJU. ASIC Center---Arnold Shi
目录
1
任务(task)
函数(function) 系统任务和系统函数
2
3 4
编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
任务(task)
函数(function) 系统任务和系统函数
2
3 4
编译预处理
verilog2008--TJU. ASIC Center---Arnold Shi
function说明语句
函数可以在模块不同位臵执行共同代码。函数与任务的不同之处是函 数只能返回一个值,它不能包含任何时延或时序控制(必须立即执 行),并且它不能调用其它的任务。此外,函数必须带有至少一个输 入,在函数中允许没有输出或输入输出说明。函数可以调用其它的函 数。 函数的目的是返回一个用于表达式的值。 定义函数的语法: function <返回值的类型或范围> (函数名); <端口说明语句> <变量类型说明语句> begin <语句> ........ end endfunction 请注意<返回值的类型或范围>这一项是可选项,如缺省则返回值为一 位寄存器类型数据。
verilog2008--TJU. ASIC Center---Arnold Shi
函数实例
module Function_Example ..... parameter MAXBITS=8; function [MAXBITS-1:0] Reverse_Bits; input [MAXBITS-1:0] Din; integer K; begin for(K=0; K<MAXBITS; K=K+1) Reverse_Bits [MAXBITS-K] = Din[K]; end endfunction ... endmodule