베릴로그에서 코드를 짜는데는 세 가지 방법이 있다.
Gate Level의 작성, Behaviral level의 작성, Dataflow level의 작성.
사실 엄밀한 분류인것같진 않은데... (검색해보면 좀 다양하게나옴)
디지털시스템을 처음 가르쳐주신 교수님이 이렇게 구분해서 과제해오라 시키셨다.
이 글은 full adder를 각각 gate level, behavioral level, dataflow level로 작성하여 각각의 특성을 보고자 한다.
일단 Gate Level부터 알아보자.
module full_adder (
input a, b, c_in,
output sum, c_out
);
wire s1, c1, s2;
xor g1(s1, a, b);
and g2(c1, a, b);
xor g3(sum, s1, c_in);
and g4(s2, s1, c_in);
or g5(c_out, s2, c1);
endmodule
위의 코드가 Gate Level로 작성된 full adder이다. 모두가 알다시피 full adder는 다음과 같이 생겼는데, 각각의 wire와 gate를 열심히 이어서 만들어주면 된다.
gatelevel modeling의 코드를 좀 더 뜯어보자.
코드는 다음과 같이 작성하면 된다.
'사용하는 모듈' '모듈이름' ('output', 'input1', 'input2', ... 'input n') ;
위에서는 다음과 같이 작성한것이다.
and g2(c1, a, b);
and는 입력이 한개, 출력이 두 개인 게이트이며 베릴로그는 and, or, xor, nand, nor, xnor등을 제공한다.
behavioral modeling이 제일 많이 쓰인다. 회로의 기능이 복잡해지면 일일히 게이트단계로 그려낼 수 없다. 우리가 C-like문법으로 디지털 회로의 기능을 description해주면 컴파일러가 열심히 일해서 회로를 짜잔~ 뽑아줄것이다. 그것이 베릴로그와 같은 HDL(Hardware Description Language)의 의의인것이다.
module full_adder (
input a, b, c_in,
output sum, c_out
);
reg sum, c_out;
always @(a, b, c_in) begin
{c_out, sum} = a + b + c_in;
end
endmodule
코드가 베릴로그 초짜가 이해하기엔 좀 거시기하다. 이 글에서 스타일을 이해하려하기보다 그냥 adder는 gate level로 짜고 다음 글에 있을 mux나 decoder 코드를 보고 이해해보는 것이 좋다.
behavioral modeling의 가장 큰 특징은 always문을 사용하는 것 같다.
always문은 지정된 이벤트(변화)가 감지될 때 마다, begin - end 구문으로 묶인 사이의 행동을 하도록 한다. always문은 다음과 같이 사용한다.
awlays @('event') begin
'변수' = '할당식';
end
위의 코드의 경우 a, b, c_in이 변화할 때 마다, a+b+c_in의 2bit 값을 각각 c_out과 sum에 할당한다.
always문에서 할당될 왼쪽의 변수들은 꼭 reg로 선언되어야 한다. 이 reg와 wire의 선택이 굉장히 많이 헷갈리는데... always문 안에 들어갈거면 reg를 써보자.
사실 이 dataflow level이 정확히 어디 쓰여야하는지 아직 잘 모르겠다. 이름이 왜 dataflow인지도 모르겠다. 그렇지만 교수님이 그걸로 구현해오라고 하면 하는게 학부생인거다.
module full_adder(
input a, b, c_in,
output s, c_out
);
assign s = a^b^c_in;
assign c_out = (a&b)|((a^b)&c_in);
endmodule
약간... gatelevel과 뭐가 다른지 모르겠다. 그렇지만 분명 생긴게 다르다. dataflow level은 저 assign문을 사용한다. assign문은 다음과 같이 쓴다.
assign '변수' = '할당식';
할당식은 ^로 xor, &로 and, |로 or을 표현하여 각 변수를 사용한 논리연산을 해 줄 수 있고, 4'b0000;과 같은 값이 들어갈수도 있다. 할당받는 변수는 wire로 선언되어있어야 한다. (input, output으로 선언된 wire들은 추가적인 reg 선언이 없다면 wire이다.)
베릴로그로 프로젝트를 해본지 세달쯤 지나니까 사실 좀 가물가물하다. 근데 대충 맞을거다. 틀린거나 모르겠는거 있으면 댓글로 얘기해주세요...