Verilog 태스크 이해: 함수와의 차이점, 문법, 활용법
function은 입력에 대한 처리 후 단일 값을 반환하는 반면, task는 더 범용적이며 여러 결과 값을 계산하여 output과 inout 타입 인자로 반환할 수 있습니다. 태스크는 @, posedge 등 시뮬레이션 시간을 소비하는 요소를 포함할 수 있습니다.
문법
태스크는 포트 리스트의 인자 집합이 필요하지 않을 수 있으며, 이 경우 비워둘 수 있습니다.
// 스타일 1
task [name];
input [port_list];
inout [port_list];
output [port_list];
begin
[statements]
end
endtask
// 스타일 2
task [name] (input [port_list], inout [port_list], output [port_list]);
begin
[statements]
end
endtask
// 빈 포트 리스트
task [name] ();
begin
[statements]
end
endtask
정적 태스크 (Static Task)
태스크가 정적이면, 그 멤버 변수들이 같은 태스크의 다른 동시 호출 간에 공유됩니다.
task sum (input [7:0] a, b, output [7:0] c);
begin
c = a + b;
end
endtask
// 또는
task sum;
input [7:0] a, b;
output [7:0] c;
begin
c = a + b;
end
endtask
initial begin
reg [7:0] x, y, z;
sum (x, y, z);
end
태스크 활성화 인자(x, y, z)는 태스크에서 정의된 인자(a, b, c)에 대응됩니다. a와 b가 입력이므로 x와 y의 값이 a와 b에 놓입니다. c가 output으로 선언되어 호출 시 z와 연결되므로, 합이 자동으로 c에서 z로 전달됩니다.
자동 태스크 (Automatic Task)
automatic 키워드는 태스크를 재진입 가능하게 만듭니다. 그렇지 않으면 기본적으로 정적입니다. automatic 태스크 내 모든 항목은 각 호출마다 동적으로 할당되며, 동시에 실행되는 같은 태스크의 호출 간에 공유되지 않습니다. automatic 태스크 항목은 계층적 참조로 접근할 수 없습니다.
예를 들어, 동시에 실행되는 다른 initial 블록에서 호출되는 정적 태스크 display를 생각해 봅시다. 이 경우 태스크 내 선언된 정수 변수가 태스크의 모든 호출 간에 공유되므로, 표시된 값은 호출마다 증가해야 합니다.
module tb;
initial display();
initial display();
initial display();
initial display();
// 정적 태스크
task display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
시뮬레이션 로그
xcelium> run
i=1
i=2
i=3
i=4
xmsim: *W,RNQUIE: Simulation is complete.
태스크를 automatic으로 만들면 각 호출이 시뮬레이션 메모리의 다른 공간을 할당받아 다르게 동작합니다.
module tb;
initial display();
initial display();
initial display();
initial display();
// 태스크를 automatic으로 변경
task automatic display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
시뮬레이션 로그
xcelium> run
i=1
i=1
i=1
i=1
xmsim: *W,RNQUIE: Simulation is complete.
전역 태스크 (Global Tasks)
모든 모듈 밖에 선언된 태스크를 전역 태스크라고 하며, 전역 범위를 가지므로 모든 모듈에서 호출할 수 있습니다.
// 이 태스크는 모든 모듈 밖에 있음
task display();
$display("Hello World !");
endtask
module des;
initial begin
display();
end
endmodule
시뮬레이션 로그
xcelium> run
Hello World !
xmsim: *W,RNQUIE: Simulation is complete.
태스크가 모듈 des 내에 선언되었다면, 모듈 인스턴스 이름을 참조하여 호출해야 합니다.
module tb;
des u0();
initial begin
u0.display(); // 태스크가 'tb' 모듈에서 보이지 않음
end
endmodule
module des;
initial begin
display(); // 태스크 정의가 모듈 로컬
end
task display();
$display("Hello World");
endtask
endmodule
시뮬레이션 로그
xcelium> run
Hello World
Hello World
xmsim: *W,RNQUIE: Simulation is complete.
function과 task의 차이점
Verilog 함수와 태스크는 비슷한 목적을 가지지만 몇 가지 주목할 만한 차이가 있습니다.
| 함수 (Function) |
태스크 (Task) |
| 시간 제어 문장/지연을 가질 수 없음, 따라서 같은 시뮬레이션 시간 단위에서 실행됨 |
시간 제어 문장/지연을 포함할 수 있으며, 나중에 완료될 수 있음 |
| 위 규칙 때문에 태스크를 활성화할 수 없음 |
다른 태스크와 함수를 활성화할 수 있음 |
| 최소 하나의 입력 인자가 필요, output 또는 inout 인자 불가 |
어떤 타입이든 0개 이상의 인자를 가질 수 있음 |
| 단일 값만 반환 가능 |
값을 반환할 수 없지만, output 인자로 같은 효과 달성 가능 |
함수가 task를 호출하거나 시간 소비 문장을 포함하려 하면 컴파일러가 에러를 보고합니다.
module tb;
reg signal;
initial wait_for_1(signal);
function wait_for_1(reg signal);
#10;
endfunction
endmodule
시뮬레이션 로그
#10; | xmvlog: *E,BADFCN (testbench.sv,7|4): illegal time/event control statement within a function or final block or analog initial block [10.3.4(IEEE)].
태스크 비활성화 (Disable Task)
태스크는 disable 키워드로 비활성화할 수 있습니다.
module tb;
initial display();
initial begin
// 50 타임 유닛 후, 태스크 'display' 안의 특정 이름 블록 T_DISPLAY 비활성화
#50 disable display.T_DISPLAY;
end
task display();
begin : T_DISPLAY
$display("[%0t] T_Task started", $time);
#100;
$display("[%0t] T_Task ended", $time);
end
begin : S_DISPLAY
#10;
$display("[%0t] S_Task started", $time);
#20;
$display("[%0t] S_Task ended", $time);
end
endtask
endmodule
첫 번째 initial 블록에서 display 태스크가 시작되면 T_DISPLAY가 시작되고, 시간이 50 유닛에 도달하면 비활성화됩니다. 즉시 다음 블록 S_DISPLAY가 시작되어 80 유닛에 완료됩니다.
시뮬레이션 로그
xcelium> run
[0] T_Task started
[60] S_Task started
[80] S_Task ended
xmsim: *W,RNQUIE: Simulation is complete.