system verilog 进程与通信

1.task 与 functions

(1.1)task

        任务可以包含参数声明、输入参数、输出参数、输入参数、寄存器、事件和零或多个行为语句。任务可以是static(静态的)也可以是automatic(动态的) 。静态任务为所有任务调用共享相同的存储空间,动态任务为每个任务调用分配唯一的堆叠存储空间。

SV允许:

  • 在静态任务中声明动态变量,也可以在动态任务中声明静态变量;
  • 声明端口的更多功能;
  • 在任务结束前使用return返回;   (返回值是什么???)
  • 通过引用、值、名称和位置传递参数值;
  • 存在默认的参数值;
  • 默认的参数方向是input;
  • 默认的参数类型是logic

看下面例子:

(1)在方法名的括号内部声明参数,并标明输入输出方向

module sv_task;
  int x;
  
  //task to add two integer numbers. 
  task sum(input int a,b,output int c);
    c = a+b;    
  endtask
  
  initial begin
    sum(10,5,x);
    $display("\tValue of x = %0d",x);
  end  
endmodule

 (2)在方法体内部声明参数和方向

module sv_task;
  int x;
 
  //task to add two integer numbers.
  task sum;
    input int a,b;
    output int c;
    c = a+b;  
  endtask
 
  initial begin
    sum(10,5,x);
    $display("\tValue of x = %0d",x);
  end
endmodule

(1.2)function

函数可以包含范围声明、返回类型声明、参数声明、输入参数声明、寄存器声明和事件声明.和任务一样,函数分为静态的和动态的。

  • 没有范围或返回类型声明的函数返回一个1bit的值;
  • 任何表达式都可以用作函数参数;
  • 函数不能包含任何时间控制的语句,也不能调用任务;
  • 函数只能返回一个值

SV允许:

  • 在静态函数中声明动态变量,也可以在动态函数中声明静态变量;
  • 声明端口的更多功能;
  • 在函数结束前使用return返回;
  • 通过引用、值、名称和位置传递参数值;
  • 存在默认的参数值;
  • 默认的参数方向是input;
  • 默认的参数类型是logic;
  • SV中的Task和Function不需要,必须加一个begin..end来指明body,但是需要加入标识符。

                     task    muliple_line;

                               ......body...

                     endtask :multiple_line

看下面例子:

 (1)在函数名的括号内部声明参数

module sv_function;
  int x;
  //function to add two integer numbers.
  function int sum(input int a,b);
    sum = a+b;  
  endfunction
 
  initial begin
    x=sum(10,5);
    $display("\tValue of x = %0d",x);
  end
endmodule

 (2)在函数体内部声明参数

module sv_function;
  int x;
 
  //function to add two integer numbers.
  function int sum;
    input int a,b;
    sum = a+b;  
  endfunction
  initial begin
    x=sum(10,5);
    $display("\tValue of x = %0d",x);
  end
endmodule

(3)带return关键字的函数

module sv_function;
  int x;
 
  //function to add two integer numbers.
  function int sum;
    input int a,b;
    return a+b;  
  endfunction
 
  initial begin
    x=sum(10,5);
    $display("\tValue of x = %0d",x);
  end
endmodule

(4) Void 函数,无返回值

module sv_function;
int x;
  
  //void function to display current simulation time 
  function void current_time;
    $display("\tCurrent simulation time is %0d",$time);    
  endfunction
  
  initial begin
    #10;
    current_time();
    #20;
    current_time();
  end
endmodule

 (5)丢弃函数的返回值,用关键字void

module sv_function;
  int x;
   //function to add two integer numbers. 
  function int sum;
    input int a,b;
    return a+b;    
  endfunction
  
  initial begin
    $display("Calling function with void");
    void'(sum(10,5));//丢弃返回值
  end
 endmodule

 (6)函数作为表达式的一部分

module sv_function;
  int x;
  //function to add two integer numbers. 
  function int sum;
    input int a,b;
  return a+b;    
  endfunction
  initial begin
    x = 10 + sum(10,5);
    $display("\tValue of x = %0d",x);
  end
endmodule

(1.3) function 和task 的区别

        区别有传参种类、ref类型、传参缺省值、传参方向

        a:函数与任务的主要区别是任务可以带时序,函数不能。

 函数和任务的传参可以在名字后的小括号里,也可以在函数和任务体内。传参是默认顺序,也可以使用.in(addr)这种形参方式。

       函数和任务的参数缺省值为方向为input,类型为logic。建议不缺省。一旦指定一个参数的方向,那它就成为后面参数的缺省方向。

       参数方向可以为input、output、inout(函数开始时复制,结束时输出)、ref(传递引用,传递句柄或指针),如果传参为const ref,这函数内部不会改变此参数。ref只能用在automatic的子程序。

       传参默认值时,调用此函数时,可以缺少传参。否则,不能缺少传参。

       void’( func1()); 忽略func1函数的返回值,仿真器不会告警。

       module和program,package的函数和任务默认是静态的,可以使用automatic改为动态的。而在class中的函数和任务默认是动态automatic的。可以在静态函数中,指定变量或者形参为自动的;也可以在自动函数中,将形参和变相声明称静态的。

2.fork .. join   /    begin  ..  end

        fork join 中的语句是并行执行的,维并行语句块。语句之间并行执行,同时开始;

        begin end是串行执行既顺序执行语句。

2.1 fork join  用来标识并行执行的语句,用它的标识的块称为 并行块;

示例:

fork
 
    语句1;
 
    语句2;
 
   ....
 
    语句n;
 
join

特点:

  • 块内语句同时执行的,程序流程控制进入该模块时刻,块内语句即开始同时并行执行;
  • 当耗时最长的语句执行完成后,程序才跳出该并行模块;

2.2 begin end  用来标识顺序执行的语句,用它标识的块称作顺序块;

示例

begin
 
    语句1;
 
    语句2;
 
   ....
 
    语句n;
 
end

特点:

  • 块内语句顺序执行的,即只有上面一条语句执行完后下面的语句才能执行;
  • 最后一条语句执行完,程序才跳出该语句块

2.3 fork join  / fork join_any  /  fork join_none

在这里插入图片描述

 这三个兄弟虽然长的比较像,但是其实性格是不一样的!他们的主要性格区别是他们对待称为“线程”的小朋友的态度上。“线程”小朋友是轻量级的“进程”,是程序调度的基本单位。假如某一时段同时来了好几个线程小朋友去他们家吃饭,三兄弟性格可以表现的非常明显。其中fork-join的性格是最温和耐心的,他会静静等待所有线程小朋友全部吃完饭才去做别的事情。而fork-join_any性格是最健忘和丢三落四的,当他看到其中某个线程小朋友吃完后会直接忘了别的小朋友还在吃,以为都完成了,直接去做自己的事情。至于fork-join_none则是脾气最暴躁的,他不会等待任何一个线程小朋友吃饭,会直接去搞自己的事情.

.

.贴代码

.

.

.

3.mailbox

前言:mailboxe是一种通信机制,允许进程之间交换消息。希望与另一个进程通信的进程将消息发送到mailboxe,mailboxe将消息临时存储在系统定义的内存对象中,以便将消息传递给所需的进程。

Mailboxes赋值:new()
放数据:put()
非阻塞放数据:try_put()
获取数据:get()或peek()
非阻塞获取数据:try_get()或try_peek()
获取Mailboxes中的数据数:num()

....

.

.

.

.lizi 

.

4.semaphore  旗语

作用

信号是通过初始化一定数量的许可证,通过限制获得许可证的线程数量来阻塞未获取许可证达的线程,达到限制对特定资源访问的线程数量。

接口函数

new(): Creat a semaphore with a specified number kerys;

get(): OBtian one or more keys from the busket;

put(): Return one or more kyes into the bucker;

try_get(): Try to obtian one or maor keys without blocking;

使用举例

单许可证,两线程竞争:

 sem = new(1)

process 1:
  sem.get(1);
  ....
  sem.put(1);


process 1:
  sem.get(1);
  ....
  sem.put(1);

多许可证,多线程竞争

sem = new(5)

process 1:
  sem.get(2);
  ....
  sem.put(2);


process 1:
  sem.get(2);
  ....
  sem.put(2);


process 2:
  sem.get(2);
  ....
  sem.put(2);

5.events

6.interface

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值