task被一段封装在“task-endtask”之间的程序。task通过调用来执行,而且只有在调用时才会被执行,如果定义了task,但是在整个过程中都没有调用它,那么这个task是不会执行的。调用某个task时可能需要它处理某些数据并返回操作结果,所以task应当有接收数据的输入端和返回数据的输出端。另外,task可以彼此调用,而且task内还可以调用函数。
task语法如下:
//Verilog-2001 Task Declaration
task [automatic] task_name(
port_declaration port_name,...,
port_declaration port_name,...,
local variable declarations
procedural_statement or statement_group
endtask
/************************************************************
Task : TSK_TX_SYNCHRONIZE
Inputs : None
Outputs : None
Description : Synchronize with tx clock and handshake signals
*************************************************************/
task TSK_TX_SYNCHRONIZE;
input first_; // effectively sof
input active_; // in pkt
input last_call_; // eof
reg last_;
begin
if (trn_lnk_up_n) begin
$display("[%t] : Trn interface is MIA", $realtime);
$finish(1);
end
@(posedge trn_clk);
if ((trn_tdst_rdy_n == 1'b1) && (active_ == 1'b1)) begin
while (trn_tdst_rdy_n == 1'b1) begin
@(posedge trn_clk);
end
end
if (active_ == 1'b1) begin
// read data driven into memory
board.RP.com_usrapp.TSK_READ_DATA_128(first_, last_call_,
`TX_LOG,
trn_td,
trn_trem_n);
end
if (last_call_)
board.RP.com_usrapp.TSK_PARSE_FRAME(`TX_LOG);
end
endtask // TSK_TX_SYNCHRONIZE
/************************************************************
Task : TSK_READ_DATA_128
Inputs : None
Outputs : None
Description : Consume clocks.
*************************************************************/
task TSK_READ_DATA_128;
input first;
input last;
input txrx;
input [127:0] trn_d;
input [1:0] trn_rem;
integer _i;
reg [7:0] _byte;
reg [127:0] _msk;
reg [4:0] _rem;
reg [3:0] _strt_pos;
begin
_msk = (first && trn_rem[1]) ? 128'h0000000000000000ff00000000000000 : 128'hff000000000000000000000000000000;
_rem = first ? (last ? ((trn_rem == 2'b01) ? 12 : 16) : 8) : (last ? (trn_rem[1] ? (trn_rem[0] ? 4 : 8) : (trn_rem[0] ? 12 : 16)) : 16);
_strt_pos = (first && trn_rem[1]) ? 4'd7 : 4'd15;
for (_i = 0; _i < _rem; _i = _i + 1) begin
_byte = (trn_d & (_msk >> (_i * 8))) >> (((_strt_pos) - _i) * 8);
if (txrx) begin
board.RP.com_usrapp.frame_store_tx[board.RP.com_usrapp.frame_store_tx_idx] = _byte;
board.RP.com_usrapp.frame_store_tx_idx = board.RP.com_usrapp.frame_store_tx_idx + 1;
end else begin
board.RP.com_usrapp.frame_store_rx[board.RP.com_usrapp.frame_store_rx_idx] = _byte;
board.RP.com_usrapp.frame_store_rx_idx = board.RP.com_usrapp.frame_store_rx_idx + 1;
end
end
end
endtask // TSK_READ_DATA_128
(1)在task定义的描述语句中,可以使用出现不可综合操作符合语句(使用最为频繁 的就是延迟控制语句),这样会造成该任务不可综合。 (2)在task中可以调用其他的任务或函数,也可以调用自身。 (3)在task定义结构内不能出现 initial和 always过程块。 (4)在task定义中可以出现“disable 中止语句” ,将中断正在执行的任务 (5)在task内可以声明各种变量(reg (signed),integer,time,real,…)
task调用:
my_task(x,y,z);
/************************************************************
Task : TSK_TX_TYPE0_CONFIGURATION_READ
Inputs : Tag, PCI/PCI-Express Reg Address, First BypeEn
Outputs : Transaction Tx Interface Signaling
Description : Generates a Type 0 Configuration Read TLP
*************************************************************/
task TSK_TX_TYPE0_CONFIGURATION_READ;
input [7:0] tag_;
input [11:0] reg_addr_;
input [3:0] first_dw_be_;
begin
if (trn_lnk_up_n) begin
$display("[%t] : Trn interface is MIA", $realtime);
$finish(1);
end
TSK_TX_SYNCHRONIZE(0, 0, 0);
trn_td <= #(Tcq) {
1'b0,
2'b00,
5'b00100,
1'b0,
3'b000,
4'b0000,
1'b0,
1'b0,
2'b00,
2'b00,
10'b0000000001, // 32
COMPLETER_ID_CFG,
tag_,
4'b0000,
first_dw_be_, // 64
COMPLETER_ID_CFG,
4'b0000,
reg_addr_[11:2],
2'b00,
32'b0
};
trn_tsof_n <= #(Tcq) 0;
trn_teof_n <= #(Tcq) 0;
trn_trem_n <= #(Tcq) 2'b01;
trn_tsrc_rdy_n <= #(Tcq) 0 ;
TSK_TX_SYNCHRONIZE(1, 1, 1);
trn_tsof_n <= #(Tcq) 1;
trn_teof_n <= #(Tcq) 1;
trn_trem_n <= #(Tcq) 2'b00;
trn_tsrc_rdy_n <= #(Tcq) 1;
end
endtask // TSK_TX_TYPE0_CONFIGURATION_READ
(1)task调用语句只能出现在过程块内; (2)task调用语句和一条普通的行为描述语句的处理方法一致; (3)当被调用输入、输出或双向端口时,任务调用语句必须包含端口名列表,且信号端口顺序和类型必须和任务定义结构中的顺序和类型一致。需要说明的是,任务的输出端口必须和寄存器类型的数据变量对应。 (4)可综合任务只能实现组合逻辑,也就是说调用可综合任务的时间为“0” 。而在面向仿真的任务中可以带有时序控制,如时延,因此面向仿真的任务的调用时间不为“0” 。