EE/Verilog HDL

[verilog HDL] Syntax 6. Task & Function

아이스얼그레이 2022. 2. 28. 14:26

verilog의 task와 function syntax에 관한 포스팅입니다. 겨울방학 때 verilog 스터디를 끝내고 싶었는데, 3월까지 지연이 됐네요. 3월 16일 전까지 마무리하는 게 목표입니다.

 

verilog에는 function과 task가 있습니다. function은 C나 python에서 쓰는 function과 유사하지만, task는 다른 언어와 equivalent한 개념이 없습니다. 그래서 task는 따로 공부해줘야 합니다.

 

function과 task를 사용하는 이유는 2가지 입니다.

 

첫 번째는 긴 module에서 반복적인 작업을 task & function으로 대체할 수 있습니다.

두 번쨰는 RTL source code의 가독성을 높여줍니다.

 

우선 fucntion과 task의 차이점을 알아보겠습니다.

 

Functions Tasks
timing과 관련이 없다.(항상 0 simulation time에 실행된다.) timing과 관련이 있다.(0 simulation time이 아닐때도 실행된다.)
function내에서 다른 function을 호출할 수 있지만, task는 호출할 수 없다. function, task 모두 호출할 수 있다.
dalay, timing control statement를 포함할 수 없다. dalay, timing control statement를 포함할 수도 있다.
적어도 하나의 input을 가져야한다. 여러 개의 input을 가질 수 도있다. input, output을 하나도 가지지 않을 수도 있고, 여러 개 가질 수도 있다.
항상 single value를 return한다. output이나 inout을 가질 수 없다.(function name이 wire형으로 반환된다.) value를 return하지는 않지만, output, inout을 통해 여러 값을 전달할 수 있다.

 

위 표에서 나타난 차이점을 보면 알겠지만, task가 function보다 좀더 큰 범주에 속합니다.

 

Note

- task와 function 둘 다 module 내에서 정의되어야 한다.

- task와 fucntion은 initial statement와 always statement를 포함할 수 없다.

 

이제 Task를 자세히 알아보겠습니다.

 

Task

task의 선언에 관한 docs가 있지만, 가독성이 떨어지고 보기싫어서 예시를 통해 알아보겠습니다.

module operation;
    parameter delay = 10;
    reg [15:0] A, B;
    reg [15:0] AB_AND, AB_OR, AB_XOR;

    always @(A or B)
    begin
        bitwise_oper(AB_AND, AB_OR, AB_XOR, A, B);
    end

    task bitwise_oper;
        output [15:0] ab_and, ab_or, ab_xor;
        input [15:0] a, b;

        begin
            #delay ab_and = a & b;
            ab_or = a | b;
            ab_xor = a ^ b;
        end
    endtask
endmodule

 

위 코드를 보면 module 하단부에 task가 선언된 것을 볼 수 있습니다. module ~ endmodule과 같이, task 또한 task ~ endtask를 써서 선언합니다.

 

task name에서 input, output을 선언하지않고 task 내에서 input, output을 선언했습니다.

 

task의 특이한 점은 hard 코딩이 가능하다는 점입니다. 즉 task 내에 input을 선언하지 않아도, module 내의 변수를 바꿀 수 있습니다. 하지만 제가 배우는 교수님은 이러한 코딩 스타일을 권하지 않는다고 합니다. task단에서 무슨 일이 일어나는지도 모르는데 변수가 바뀌고, 디버깅이 어렵기 때문입니다. 

 

Task - Automatic task

automatic task란 두 task를 동시에 operate할 수 있는 task입니다. 동시에 operate할 수 없는 task는 static task라 합니다.

 

다음과 같이 task 선언시 automatic이라는 키워드를 붙여서 선언합니다.

task automatic bitwise_xor;
...
...
...
endtask


always @(posedge clk)
	bitwise_xor(ef_xor, e, f);
    
always @(posedge clk)
	bitwise_xor(cd_xor, c, d);
    
// automatic task로 선언했으므로 두 개의 task가 동시에 실행됩니다.

 

이번에는 function을 자세히 알아보겠습니다.

 

Function

이번에도 function의 선언에 관한 docs 대신 예시를 통해 알아보겠습니다.

module parity;
...
reg [31:0] addr;
reg parity;

always @(addr)
begin
   	parity = calc_parity(addr);
end

// function 선언
function calc_parity;
input [31:0] address;

begin
	calc_parity = ^address;
end
endfunction

endmodule

 

위의 예시 code에서 calc_parity라는 function을 선언하였습니다. 위 표에서 function은 항상 single value를 return 한다고 했는데, output이 선언되어있지 않습니다. 왜 그런걸까요?

 

그런 바로 function을 선언하면 function name이 명시적으로 wire로 선언되기 때문입니다. 그래서 function statement 안에서 calc_parity 이라는 함수명에 ^address를 대입해준 것 입니다.