微信公众号获取更多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相关源码: