RTL을 작성하다보면 bit width를 계산하는 일이 종종있다. 특히, input/output port 선언에 있어서 정확한 bit는 각종 design check 과정에 있어서 경고를 줄일 수 있는 좋은 디자인이다.
간단하게, 십의 자리 단위의 정수라면 2진수로 바꾸기도 쉽지만 숫자가 커질 수록 계산이 복잡해진다. 최근에는 계산기로 그냥 입력해서 2진수의 자릿수를 확인하는 방법이 있지만 parameter로 선언된 bit width를 찾아가면서 상수값을로 설정 할 수 없을 뿐더러, parameter overriding 이 된다면 진짜 그야말로 완전 잘못 설계하는 RTL이 된다.
이때, 이런 일을 방지하기 위해서 유연함을 끼워주는 경우가 있는데 이때 사용하는 것이 clog2이다.
clog2는 간단하게 설명하면 log2의 동작과 유사해서 2의 지수값을 찾아내는 것이지만, clog2는 거기에 한자리수를 더 많게 반환하는 것이 특징이다.
예를 들어 10진수 5를 생각해보면 2진수로 변환하면 b101이 된다. 따라서, 5는 3bit으로 표현이 가능하다. 이를 보통 log2로 계산을 하면 대략 2.3 정도가 나오는데, 직관적으로 생각하면 여기서 올림을 해야, 우리가 원하는 3bit이 나오게 된다.
clog2는 바로 그러한 기능을 한다. 따라서 clog2로 5를 확인하면 3이 나오는데, 여기서 clog2를 사용하는 세가지 방법을 소개한다.
첫째, System task 사용
가장 쉽고 정확한 방법인데, 이는 바로 system task $clog2를 사용하는 것이다.
$clog2(5)
parameter BIT_WIDTH = 10
$clog2(BIT_WIDTH)
위 코드와 같이 $clog2는 별도의 function이나 task의 작성이 필요없으면서도 우리가 원하는 결과를 만들어 낼 수 있다.
또한 위의 system task는 compile 단계에서 처리되기 때문에 compile을 거치면서 상수로 변환되게 되어, 이후에 진행될 elaboration에서는 상수로 적용이 된다. 즉, 합성이 가능하다.
둘째, function을 통한 제작
위의 system task를 사용하지 않고, function을 이용해 직접적인 제작도 가능하다. 위의 경우가 사실 너무 간편해서 굳이 이렇게 만들 필요가 있을까? 싶지만, 응용을 통해 다른 RTL code를 만들 수 있으니 소개하려고 한다.
function integer clog2;
input integer value;
integer i;
begin
clog2 = 0;
for (i = value - 1; i > 0; i = i >> 1) begin
clog2 = clog2 + 1;
end
end
endfunction
function은 몇가지 특징이 있는데,
- 시간의 지연이 없이 즉시 실행
- 단일 결과 반환
- 합성가능
- combi logic의 모델링에 주로 사용
- 합성도구가 쉽게 해석 가능
따라서, 위 동작에서 value에 5가 들어왔다고 생각하고 RTL을 의미있게 풀어보면 아래와 같이 된다.
function integer clog2;
input inteeger value; // value에 5가 입력
integer i;
begin
clog2 = 0;
for (i = value - 1; i > 0; i = i >> 1) begin
clog2 = clog2 + 1;
// i = 5 - 1 = 4
// clog2 = 1
// i = 4 >> 1 = 2
// clog2 = 2
// i = 2 >> 1 = 1
// clog2 = 3
// i = 1 >> 1 = 0
// break
end
end
endfunction
RTL에서의 for문이 어떻게 동작하는지는 익히 알 것이라 생각하고, 위와 같이 value 값을 가정해서 계산을 해보면 clog2에는 최종적으로 3의 값이 할당된다.
얼핏보면 clog2가 multi-drive 되는 것으로 보이지만, blocking 구문으로 기술되고 있으며, function의 procedure에서 동일한 변수에 대한 할당은 코드의 제일 마지막에 할당된 것이 주어지게 되므로, clog2에는 3이 할당되는 것이다.
따라서, 위와 같이 function을 사용한다면 system task를 사용하지 않고 코드를 작성 할 수 있으나, 필자는 그냥 제공되는 기능을 사용하는 것이 훨씬 더 간편하다고 이야기하고 싶다.
사실 task를 이용한 방법을 하나 더 기술하고 싶었는데, 큰 틀은 function과 다르지 않고 task에 대한 기술만 바뀌는 것 뿐이었다. (output integer가 별도로 기술되는 형태이다)
task는 합성이 될 수도 있고, 안 될 수도 있는. 어떻게 작성했는지에 따라서 결과가 달라 질 수 있는 요소가 있었다. 때문에 simulation을 통해서만 결과를 보려는 사람이 아니라 ASIC이나 FPGA까지 보는 사람이라면 합성 가능한 RTL code를 소개해주는 편이 좋다고 생각했다.
'Design > Verilog HDL' 카테고리의 다른 글
[Verilog HDL] Basic digital filter - 1 : FIR (0) | 2025.02.09 |
---|