Task - Verilog's task
Previous articles recorded the use of functions such as function function: Function -- Verilog function . This time, record the function of using the task task task.
a thing for it
IIC save module needs to be used in the design, so there needs to be a corresponding master module in testbench, and a model that can read and write.
If Verilog is also used for comprehensive writing, it is somewhat trivial and requires strict control logic. Therefore, it is hoped that a function can actually carry out the read-write control timing operation of IIC.
The previous function only had function function, and the operation of the function was combinatorial logic, which could not meet the requirements of the temporal logic required this time, so the task function was selected.
Talk is cheap
The files of the entire IIC master model are as follows:
/** * Filename : iic_master_model.v * Date : Friday, May 21, 2021 4:50 PM * * Version : V 0.1 * Author : ljacki@163.com * Modification history * : Friday, May 21, 2021 4:50 PM Create the demo * : Friday, May 28, 2021 2:37 PM Add the task of write pkg. */ `timescale 1ns / 100ps `define DEBUG_INFO 1'b0 `define DELAY 2 module iic_master_model ( // system input clk, input rst_n, input req, input rd_valid_i, input [7:0] rd_data_i, output reg start, output reg stop, output reg [7:0] dvice_id, output reg wr_en_o, output reg [7:0] wr_data_o, output reg rd_en_o, output reg [7:0] rd_addr_o ); parameter DEVICE_ID = 7'h70; parameter PKG_LEN = 8'h10; // Declarations reg [7:0] dout; // initial initial begin start = 1'b0; stop = 1'b0; // The stop signal needs to be reset, otherwise req in the master will not assert dvice_id = 8'b0; wr_en_o = 1'b0; wr_data_o = 8'b0; rd_en_o = 1'b0; rd_addr_o = 8'h0; dout = 8'h0; if ( `DEBUG_INFO ) begin $display("\nINFO: IIC MASTER MODEL INSTANTIATED (%m)"); end end task m_start; input wr_rd; //1'b0: write, 1'b1:read; begin // @(posedge clk); #`DELAY start = 1'b1; dvice_id = {DEVICE_ID, wr_rd}; @(posedge clk); #`DELAY start = 1'b0; dvice_id = 8'h0; // if ( wr_rd == 1'b0 ) begin // $display("status: %t master START WRITE,\tDEVICE ID : %X", $time, DEVICE_ID); // end else begin // $display("status: %t master START READ, \tDEVICE ID : %X", $time, DEVICE_ID); // end end endtask task m_wr_data; input [7:0] wr_addr; input [7:0] wr_data; input stop_flag; begin while(~req) @(posedge clk); #`DELAY wr_en_o = 1'b1; wr_data_o = wr_addr; @(posedge clk); #`DELAY wr_en_o = 1'b0; wr_data_o = 8'b0; if ( stop_flag) begin while(~req) @(posedge clk); #`DELAY stop = 1'b1; wr_en_o = 1'b1; wr_data_o = wr_data; @(posedge clk); #`DELAY stop = 1'b0; wr_en_o = 1'b0; wr_data_o = 8'b0; end else begin while(~req) @(posedge clk); #`DELAY stop = 1'b0; wr_en_o = 1'b1; wr_data_o = wr_data; @(posedge clk); #`DELAY stop = 1'b0; wr_en_o = 1'b0; wr_data_o = 8'b0; end if ( `DEBUG_INFO) begin $display("status: %t master WRITE ADDR:%X,\tDATA:%X\n", $time, wr_addr, wr_data); end end endtask task m_write; input [7:0] waddr; input [7:0] wdata; begin m_start(1'b0); m_wr_data(waddr, wdata, 1'b1); repeat(50) @(posedge clk); if ( `DEBUG_INFO) begin $display("status: %t master WRITE ADDR:%X,\tDATA:%X\n", $time, waddr, wdata); end end endtask task m_write_pkg; // input [7:0] len; input [8*PKG_LEN-1:0] addr; input [8*PKG_LEN-1:0] data; begin m_start(1'b0); m_wr_data(addr[(PKG_LEN-0)*8-1:(PKG_LEN-1)*8], data[(PKG_LEN-0)*8-1:(PKG_LEN-1)*8], 1'b0); m_wr_data(addr[(PKG_LEN-1)*8-1:(PKG_LEN-2)*8], data[(PKG_LEN-1)*8-1:(PKG_LEN-2)*8], 1'b0); m_wr_data(addr[(PKG_LEN-2)*8-1:(PKG_LEN-3)*8], data[(PKG_LEN-2)*8-1:(PKG_LEN-3)*8], 1'b0); m_wr_data(addr[(PKG_LEN-3)*8-1:(PKG_LEN-4)*8], data[(PKG_LEN-3)*8-1:(PKG_LEN-4)*8], 1'b1); repeat(50) @(posedge clk); end endtask task m_read; input [7:0] rd_addr; output [7:0] rd_dout; begin @(posedge clk); #`DELAY m_start(1'b0); while(~req) @(posedge clk); #`DELAY rd_en_o = 1'b1; rd_addr_o = rd_addr; @(posedge clk); #`DELAY rd_en_o = 1'b0; rd_addr_o = 8'h0; while(~req) @(posedge clk); #`DELAY m_start(1'b1); while(~rd_valid_i) @(posedge clk); #`DELAY rd_dout = rd_data_i; repeat(50) @(posedge clk); if ( `DEBUG_INFO ) begin $display("status: %t master READ ADDR:%X,\tDATA:%X\n", $time, rd_addr, rd_dout); end end endtask task m_cmp; input [7:0] addr; input [7:0] dexp; // the expected data begin m_read(addr, dout); if ( dexp != dout ) begin $display("\t\t\tData compare error. Received %h, expected %h at time %t", dout, dexp, $time); end end endtask endmodule // the end of iic_master_model
Statement: the above timing needs to be used with iic master; According to the article, it is only used to explain the use of task tasks.
task introduction
A task is a program encapsulated between task and endtask.
It is executed by calling, and only when called. If a task is defined, but it is not called in the whole process, the task will not be executed.
Calling a task may require it to process some data and return the operation results, so the task in Verilog has input and output.
definition
task is defined as follows:
task<Task name>; // <= task task_id; <Port and data type declaration statement> // <= [declaration] <Statement 1> // <= procedural_statement <Statement 2> // <= procedural_statement ..... // <= <sentence n> // <= procedural_statement endtask // <= endtask // <= endtask
Among them, the keyword task and endtask mark the content between them as a task definition;
- Task marks the beginning of a task definition structure;
- task_id is the task name;
- Optional declaration is a port declaration statement and a variable declaration statement. The task receives the input value and returns the output value through the port declared here;
- procedural_statement is a process statement used to complete the task operation. If there is more than one process statement, it should be placed in the statement block;
- endtask defines the structure end flag for the task.
task can start other tasks, and other tasks can start other tasks. There is no limit to the tasks that can be started. Control can return only after all tasks are completed. task can have no or multiple input-output type variables.
The Works of Liezi
The columns of a task are:
task find_max; //The task definition structure starts with find_max input [15:0] x,y; //Enter port description output [15:0] tmp; //Output port description if(x>y) //Give the description statement of the task definition tmp = x; else tmp = y; endtask
matters needing attention
Precautions for writing task are as follows:
- The port name cannot be listed in the task statement in the first line;
- The number of input, output and two-way ports of the task is not limited, or even there can be no input, output and two-way ports;
- In the task, you can call other tasks or functions, or call yourself;
- The disable abort statement can appear in the task definition to interrupt the executing task, but it cannot be integrated. When the task is interrupted, the program flow will return to the place where the task is called and continue to execute downward.
Call of task
The syntax of the task call statement is as follows:
task_id(Port 1, Port 2, port n);
Among them, task_id is the name of the task to be called. Port 1, port 2 and port n are parameter lists. The parameter list gives the data of the incoming task (entering the input of the task) and the variables that receive the returned results (receiving the returned results from the output of the task).
When calling task, you should pay attention to the following points:
- Task call statements can only appear in procedure blocks;
- The processing method of task call statement is consistent with that of an ordinary behavior description statement;
- When the input and output users are called, the task call statement must contain a list of port names, and the order and type of signal ports must be consistent with the order and type in the task definition structure;
- The output port of the task must correspond to the data variable of register type.
- The integrable task can only realize combinatorial logic, that is, the time to call the integrable task is 0. Simulation oriented tasks can have timing control, such as multiple clock cycles or delay, and the call time of a task oriented to Fanzhen is not 0.
The above IIC master model can add test excitation to IIC bus and read bus data through simple read-write tasks:
/** * Read all the registers */ for (cnt = 8'h0; cnt <= 8'h57; cnt = cnt + 1'b1) begin m0.m_read(cnt, rd_dout); end /** * Write all the registers once */ for (cnt = 8'h0; cnt <= 8'h57; cnt = cnt + 1'b1) begin m0.m_write(cnt, cnt); end /** * Compare register values */ for (cnt = 8'h0; cnt <= 8'h57; cnt = cnt + 1'b1) begin m0.m_cmp(cnt, cnt); end /** * For continuous writing, the parameter needs to be modified: PKG_LEN; * PKG_LEN: Number of registers written continuously; * addr: Continuous write register address splicing, MSB 8-bit priority write; * data: Continuous write register value splicing, MSB 8-bit priority write; * Need to modify m manually_ write_ The main content of PKG; */ m0.m_write_pkg( addr, data ); // Short reset, register value reset; // sys_rst_n = 1'b0; // #500 // sys_rst_n = 1'b1; // $display("\nstatus: %t reset again", $time); // // for (cnt = 8'h0; cnt <= 8'h57; cnt = cnt + 1'b1) begin // m0.m_read(cnt, rd_dout); // end
For CPU read-write timing and bus interface timing such as UART/SP/IIC/PC/USB, the early verification method provided some tasks for bus interaction, but now it has a proprietary name: BFM (Bus Function Model).
Differences between tasks and functions
Tasks and functions are two common execution call objects. The difference between them is:
Difference item | Mission characteristics | Function characteristics |
---|---|---|
1 | Tasks can have input, output and inout, and the number is unlimited | The function has only input parameters and at least one input |
2 | Tasks can include timing control (such as delay, etc.) | Function cannot contain any delay, simulation time 0 |
3 | Tasks can be interrupted with disable | Function does not allow disable, wait statement |
4 | Tasks can pass values through I/O ports | The function name is the name of the output variable and returns the value through the function |
5 | Tasks can call other tasks and functions | Functions can only call other functions, not tasks |
6 | Tasks can dinginess their own simulation time units | The function can only share one simulation time unit with the main module |
7 | The task can support multiple purposes and can calculate multiple result values. The result values can only be output through the called task output port or bus port | The function responds to the value of the input signal by a return value |
8 | A wire type variable cannot be present in a function |
Reference articles
On the usage of task in FPGA verilog
Verilog key analysis (3) (task & function) : static task and dynamic task are described in this article.
2021-6-26.