※수업 시간에 배운 내용을 주관적으로 정리한 것으로, 순서나 내용이 다를 수 있습니다...!!
이번에는 Vivado를 활용하여 원하는 논리 게이트 동작을 구현할 것이다.
가장 첫번째로 and 게이트를 구현해보려고 한다.
and 논리 연산자는 비교하는 두개의 값이 참일 때에만 참의 값을 내보내고, 그 외에는 모두 거짓값을 내보내는 특징을 지닌다. 즉, 하나라도 거짓이면 거짓을 내보내는 동작을 실행한다.
진리표로 표현하자면 아래와 같다.
X | Y | 결과 |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
and 게이트 동작을 위한 코드는 아래와 같다.
module and_gate(
input a, b,
output reg q
);
always @(a, b)begin
case({a, b})
2'b00: q = 0;
2'b01: q = 0;
2'b10: q = 0;
2'b11: q = 1;
endcase
end
endmodule
Verilog HDL은 모듈(module)을 기본 단위로 구성된다. Verilog HDL 모듈은 크게 머리부, 선언부, 몸체부 세 부분으로 구성되며, 머리부는 키워드 module로 시작하여 세미콜론(;)으로 끝난다. 그리고 항상 뒤에는 endmodule을 붙혀 마무리한다.
and 게이트의 입력을 담당할 입력하는 두개의 변수는 a, b로 설정하였고, 출력 동작을 위한 출력 레지스터는 q로 설정하였다.
여기서 출력 레지스터 q의 앞에 reg라는 것을 확인할 수 있는데, reg란 데이터를 저장하기 위한 변수로, 다음 값이 할당되기 전 까지는 현재의 값을 유지하는 특성을 지닌다.
reg와는 별개로 wire라는 변수 타입이 존재하는데, wire는 reg와는 달리 데이터를 저장할 수 없으며, 쉽게 생각해서 단어 그대로의 뜻인 물리적인 연결선의 동작을 수행한다.
코드를 살펴보면 always라는 것을 확인할 수 있다.
always는 항상 특정 조건이 참일 때 블록 내의 코드를 실행하는 역할을 한다. @(a, b)는 입력 a와 b가 변경될 때마다 always 블록 내의 코드가 실행되어야 함을 나타내며, 이는 a나 b 중 하나라도 변경될 때마다 always 블록 내의 코드가 실행됨을 의미한다.
always 블록 내에서는 입력 a와 b를 조합하여 case 문을 통해 모든 가능한 입력 조합에 대해 출력 레지스터 q의 값을 설정한다. case 문은 입력 {a, b}의 값에 따라 다른 동작을 수행하며, 이 경우에는 모든 입력 조합에 대해 정의되어 있다.
위의 코드에서는 입력 a와 b가 모두 1일 때만 출력 q가 1이 되는 and 게이트의 동작을 구현하고 있으며, 그 외의 입력 조합에 대해서는 출력 q가 0이 된다.
아래의 그림은 위의 코드를 바탕으로 실행 된 and gate의 출력 파형이다. 첫번째에는 a와 b의 값에 0을 대입하여 q의 결과가 0으로 나온 상황이고, 그 뒤에는 차례대로 a = 1. b = 0 그리고 a = 0, b = 1을 대입한 결과이다. 모두 다 q의 출력이 0으로 나온 것을 확인할 수 있다. 마지막에는 a 와 b의 값에 1을 대입하여 q의 출력값이 1이 나온 것을 확인할 수 있다.
다음은 반가산기(Half_adder)를 구현해보려고 한다.
반가산기란, 두개의 변수를 통해 합과 캐리를 산출하기 위한 조합논리회로를 의미한다.
반가산기의 진리표는 아래와 같다.
X | Y | SUM | CARRY |
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
반가산기의 동작을 구현할 코드에서 '.'를 확인할 수 있는데, 코드 내에서 '.'이 붙으면 게이트 간에 연결을 의미하는 것이다. 즉, '.a(a)' 라 하면 a의 포트에 a라는 선을 연결한다는 의미로 생각하면 된다.
추가로 논리 연산자를 선언할 때 입력 변수가 두개라고 가정한다면, (출력, 입력, 입력) 순서로 선언하면 된다.
아래와 같은 코드를 예로 들면, xor의 출력은 s, 입력은 a,b 이므로, xor(s, a, b)가 되는 것이다.
반가산기 동작을 구현할 코드는 아래와 같다.
module and_gate(
output reg q,
input a, b
);
always @(a, b)begin
case({a, b})
2'b00: q = 0;
2'b01: q = 0;
2'b10: q = 0;
2'b11: q = 1;
endcase
end
endmodule
module half_adder(
input a, b,
output s, c);
and carry(c, a, b); // Output(c), Input(a), Input(b)
xor(s, a, b); // Output(s), Input(a), Input(b)
endmodule
코드를 동작시키면 아래와 같은 파형이 출력되는 것을 확인할 수 있다.
코드의 출력 파형은 위에 나와있는 반가산기의 진리표와 동일한 것을 확인할 수 있다.
'Language > Verilog' 카테고리의 다른 글
Vivado : Edge Detector, Shift Register(SISO, SIPO, PISO, PIPO) (2) | 2024.07.16 |
---|---|
Vivado : 동기식 카운터 (0) | 2024.07.12 |
Vivado : Decoder, Encoder (2) | 2024.06.25 |
Vivado : 4bit 가산기 (0) | 2024.06.16 |
Vivado : 전가산기(Full-adder) 구현 (0) | 2024.06.13 |