1、第 17章 Verilog中的高级结构学习内容: 任务和函数的定义和调用 怎样使用命名块 怎样禁止命名块和任务 有限状态机( FSM)及建模Verilog的任务及函数结构化设计是将任务分解为较小的,更易管理的单元,并将可重用代码进行封装。这通过将设计分成模块,或任务和函数实现。 任务( task) 通常用于调试,或对硬件进行行为描述 可以包含时序控制( #延迟, , wait) 可以有 input, output,和 inout参数 可以调用其他任务或函数 函数 (function) 通常用于计算,或描述组合逻辑 不能包含任何延迟;函数仿真时间为 0 只含有 input参数并由函数名返回一个结
2、果 可以调用其他函数,但不能调用任务Verilog的任务及函数 任务和函数必须在 module内调用 在任务和函数中不能声明 wire 所有输入 /输出都是 局部 寄存器 任务 /函数执行完成后才返回结果。例如,若任务 /函数中有 forever语句,则永远不会返回结果任务下面的任务中含有时序控制和一个输入,并引用了一个 module变量,但没有输出、输入输出和内部变量,也不显示任何结果。时序控制中使用的信号(例如 ck)一定不能作为任务的输入,因为输入值只向该任务传送一次。module top;reg clk, a, b;DUT u1 (out, a, b, clk);always #5 c
3、lk = !clk;task neg_clocks;input 31:0 number_of_edges;repeat( number_of_edges) ( negedge clk);endtaskinitial beginclk = 0; a = 1; b = 1;neg_clocks(3); / 任务调用a = 0; neg_clocks (5);b = 0;endendmodule任务 任务可以有 input,output 和 inout参数。 传送到任务的参数和与任务 I/O说明顺序相同。尽管传送到任务的参数名称与任务内部 I/O说明的名字可以相同,但在实际中这通常不是一个好的方法。
4、参数名的唯一性可以使任务具有好的模块性。 可以在任务内使用时序控制。 在 Verilog中任务定义一个新范围( scope) 要禁止任务,使用关键字 disable 。 主要特点:从代码中多处调用任务时要小心。 因为任务的局部变量的只有一个拷贝,并行调用任务可能导致错误的结果。在任务中使用时序控制时这种情况时常发生。在任务或函数中引用调用模块的变量时要小心。 如果想使任务或函数能从另一个模块调用,则所有在任务或函数内部用到的变量都必须列在端口列表中。任务下面的任务中有输入,输出,时序控制和一个内部变量,并且引用了一个 module变量。但没有双向端口,也没有显示。任务调用时的参数按任务定义的顺
5、序列出。 module mult (clk, a, b, out, en_mult);input clk, en_mult;input 3: 0 a, b;output 7: 0 out;reg 7: 0 out;always ( posedge clk)multme (a, b, out); / 任务调用task multme; / 任务定义input 3: 0 xme, tome;output 7: 0 result;wait (en_mult)result = xme * tome;endtaskendmodule函数( function)函数中不能有时序控制,但调用它的过程可以有时序控
6、制。函数名 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) elsef_or_and = 0;endfunctionendmodu
7、le函数主要特性: 函数定义中不能包含任何时序控制语句。 函数至少有一个输入,不能包含任何输出或双向端口。 函数只返回一个数据,其缺省为 reg类型。 传送到函数的参数顺序和函数输入参数的说明顺序相同。 函数在模块( module)内部定义。 函数不能调用任务,但任务可以调用函数。 函数在 Verilog中定义了一个新的范围( scope)。 虽然函数只返回单个值,但返回的值可以直接给信号连接赋值。这在需要有多个输出时非常有效。o1, o2, o3, o4 = f_ or_ and (a, b, c, d, e);函数要返回一个向量值(多于一位),在函数定义时在函数名前说明范围。函数中需要多条
8、语句时用 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;beginzero_count = 0;for (I = 0; I 8; I = I + 1)if (! in_bus I )zero_count = zero_count + 1;endendfunctionendmodule函数函数返回值可以声明为其它 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; / 结果可能为负endfunctionalways (a or b)if (subtr( a, b) 0)neg = 1;elseneg = 0;endmodule