Verilog中的高级结构:任务及函数(下)

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

4.函数(function)主要特性

  • 函数定义中不能包含任何时序控制语句。
  • 函数至少有一个输入,不能包含任何输出或双向端口。
  • 函数只返回一个数据,其缺省为reg类型。
  • 传送到函数的参数顺序和函数输入参数的说明顺序相同。
  • 函数在模块(module)内部定义。
  • 函数不能调用任务,但任务可以调用函数。
  • 函数在Verilog中定义了一个新的范围(scope)。
  • 虽然函数只返回单个值,但返回的值可以直接给信号连接赋值。这在需要有多个输出时非常有效。如:
{o1, o2, o3, o4} = f_ or_ and (a, b, c, d, e);
  • 函数中不能有时序控制,但调用它的过程可以有时序控制。
  • 函数名f_or_and在函数中作为register使用
module orand (a, b, c, d, e, out);
  input [7: 0] a, b, c, d, e;
  output [7: 0] out;
  reg [7: 0] out;
  always @( a or b or c or d or e)
    out = f_or_and (a, b, c, d, e); // 函数调用
  function [7:0] f_or_and;
    input [7:0] a, b, c, d, e;
    if  (e = = 1)
      f_or_and = (a | b) & (c | d);
    else
      f_or_and = 0;
  endfunction
endmodule
  • 函数要返回一个向量值(多于一位),在函数定义时在函数名前说明范围。函数中需要多条语句时用begin和end。
  • 不管在函数内对函数名进行多少次赋值,值只返回一次。下例中,函数还在内部声明了一个整数。
module foo;
  input [7: 0] loo;
  output [7: 0] goo;
// 可以持续赋值中调用函数
  wire [7: 0] goo = zero_count ( loo );
  function [3: 0] zero_count;
    input [7: 0] in_ bus;
    integer i;
    begin
      zero_count = 0;
      for (i = 0; i < 8; i = i + 1)
        if (! in_bus[i])
          zero_count = zero_count + 1;
    end
  endfunction
endmodule

函数返回值可以声明为其它register类型:integer, real, 或time。在任何表达式中都可调用函数。

module checksub (neg, a, b);
  output neg;
  reg neg;
  input a, b;
 function  integer  subtr;
  input [7: 0] in_a, in_b;
  subtr = in_a - in_b; // 结果可能为负
  endfunction
  always @ (a or b)
    if (subtr( a, b) < 0)
      neg = 1;
    else
      neg = 0;
endmodule
  • 函数中可以对返回值的个别位进行赋值。
  • 函数值的位数、函数端口甚至函数功能都可以参数化。
. . .
parameter MAX_BITS = 8;
reg [MAX_BITS: 1]  D;
function  [MAX_BITS: 1]  reverse_bits;
        input [MAX_BITS-1: 0] data;
        integer K;
        for (K = 0; K < MAX_BITS; K = K + 1)
            reverse_ bits [MAX_BITS - (K+ 1)] = data [K];
endfunction
always @ (posedge clk)
        D = reverse_bits (D) ;
. . .

5.命名块(named block)

在关键词begin或fork后加上 :<块名称> 对块进行命名

module named_ blk;
 . . .
    begin : seq_blk
. . .
    end
. . .
    fork : par_blk
. . .
    join
. . .
endmodule
  • 在命名块中可以声明局部变量
  • 可以使用关键词disable禁止一个命名块
  • 命名块定义了一个新的范围
  • 命名块会降低仿真速度

6.禁止命名块和任务

module do_arith (out, a, b, c, d, e, clk, en_mult);
        input clk, en_mult;
        input [7: 0] a, b, c, d, e;
        output [15: 0] out;
        reg [15: 0] out;
        always @( posedge clk)
                begin : arith_block // *** 命名块 ***
                        reg [3: 0] tmp1, tmp2; // *** 局部变量 ***
                        {tmp1, tmp2} = f_or_and (a, b, c, d, e); // 函数调用
                        if (en_mult)  multme (tmp1, tmp2, out); // 任务调用
                end
        always @( negedge en_mult) begin // 中止运算
                disable  multme ; // *** 禁止任务 ***
                disable  arith_block; // *** 禁止命名块 ***
        end
// 下面[定义任务和函数
        ……
endmodule
  • disable语句终结一个命名块或任务的所有活动。也就是说,在一个命名块或任务中的所有语句执行完之前就返回。

语法:
  disable <块名称>

 或

  disable <任务名称>

  • 当命名块或任务被禁止时,所有因他们调度的事件将从事件队列中清除
  • disable是典型的不可综合语句。
  • 在前面的例子中,只禁止命名块也可以达到同样的目的:所有由命名块、任务及其中的函数调度的事件都被取消。

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

  • 18
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值