Verilog는 4-Value Logic System을 지원하며, 이는 디지털 회로의 신호 값을 표현하는 다양한 상태를 포함합니다.
0: false, ground, low, VSS, negative assertion (부정적인 신호 또는 낮은 전압)1: true, high, Power, VDD, VCC, positive assertion (긍정적인 신호 또는 높은 전압)x: bus 충돌(unknown state) 또는 미초기화된 상태. 이 값은 여러 신호가 동시에 충돌할 때 나타날 수 있습니다.z: High Impedance (Hi-Z) 상태를 나타냅니다. 이는 세트되지 않거나 연결되지 않은 상태로, 일반적으로 Tri-state 버퍼에서 사용됩니다.wire, tri, supply1, supply0, wand, wor, triand 등 여러 가지 타입이 있으며, 주로 연결된 신호를 표현할 때 사용됩니다.Register는 추상적인 저장 요소입니다. reg, integer, real, time 등 다양한 데이터 타입이 포함될 수 있습니다.
순차 회로에서 값을 저장하는 데 사용됩니다. 예를 들어 플립플롭(FF)나 레지스터는 상태를 유지해야 할 때 사용됩니다.
중요: FF나 letch는 단순히 하드웨어에서 상태를 저장하는 요소에 해당합니다. 이를 구체적으로 표현하는 것이 reg, integer, real 등이죠.
parameter WIDTH = 8;와 같이 상수 값을 정의할 수 있습니다.#() 또는 defparam으로 오버라이드(값을 변경)할 수 있습니다.wire나 reg와 같은 기본 타입이 있습니다.reg 타입에만 가능합니다. 이는 프로시저적 할당 방식으로 값이 변경되는 경우에 사용됩니다.wire 타입입니다. 이는 기본적으로 물리적인 신호를 나타내는 데 사용됩니다.Vectors는 여러 비트로 구성된 신호를 나타냅니다. 예를 들어, reg [7:0] data;는 8비트 레지스터를 의미합니다.
비트 벡터는 [msb:lsb]로 표현되며, 크기 조정을 할 때 주의해야 합니다.
크기 조정(Truncation & Padding)
0으로 채워집니다.4'b1001, 8'd255와 같은 literal 값을 사용합니다. [size]'[base][value]4'b1001 = 4비트 바이너리 10014'd9 = 10진수 95'o11 = 8진수 11MSB(최상위 비트)가 x나 z일 경우, 자동으로 확장이 될 수 있습니다.wire 타입으로 설정됩니다.supply1, supply0: 전원 공급용 신호tri: 트라이 상태 (Hi-Z 상태) 신호wand, wor: AND/OR 결과로서의 연산 신호wire로 선언된 신호는 여러 드라이버가 있을 경우 x 값이 될 수 있습니다.real, time, realtime 등 다양한 데이터 타입을 사용할 수 있습니다.reg 또는 net type으로 선언할 수 있습니다. (값을 외부로 내보내는 신호)parameter WIDTH=8;과 같이 특정 값들을 설정하고, 이를 #()를 통해 오버라이드할 수 있습니다.reg [7:0] data[0:99];는 100개의 8비트 배열을 정의하는 방식입니다.arithmetic
bitwise
logical: operand reduction by a single bit operation
*reduction
unary reduction operators : 결과 1, 0, x
shift
relational
== : logical equality operator
===: case equality operator
conditional
triset, mux 구현할 때 사용
?:
concatenation
replication
알겠습니다! 이번에는 Verilog에서 사용되는 다양한 연산자(Operators)에 대해 자세히 설명하겠습니다. 각 연산자의 종류와 특징을 설명하고, 어떻게 사용되는지 구체적인 예시를 추가하여 정리해 드리겠습니다.
산술 연산자는 수학적 계산을 수행하는 데 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
+ | 덧셈 | a + b |
- | 뺄셈 | a - b |
* | 곱셈 | a * b |
/ | 나눗셈 | a / b |
% | 나머지 | a % b |
** | 거듭제곱 | a ** b |
reg [3:0] a, b, sum;
a = 4'b0011; // 3
b = 4'b0101; // 5
sum = a + b; // 8 (4'b1000)
비트 단위 연산자는 각 비트에 대해 연산을 수행합니다. 이러한 연산자는 wire 타입과 같이 net type에 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
& | 비트 AND | a & b |
| ` | ` | 비트 OR |
^ | 비트 XOR | a ^ b |
~ | 비트 NOT (단일 피연산자) | ~a |
~& | NOR (비트 AND 후 부정) | ~(a & b) |
| `~ | ` | NAND (비트 OR 후 부정) |
^~ | XNOR (비트 XOR 후 부정) | ~(a ^ b) |
reg [3:0] a, b, result;
a = 4'b1101; // 13
b = 4'b1011; // 11
result = a & b; // 4'b1001 (AND 연산)
result = a | b; // 4'b1111 (OR 연산)
result = a ^ b; // 4'b0110 (XOR 연산)
논리 연산자는 boolean 값을 처리하는 데 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
&& | 논리 AND (단락 평가) | a && b |
| ` | ` | |
! | 논리 NOT | !a |
reg a, b, result;
a = 1'b1; // true
b = 1'b0; // false
result = a && b; // 1'b0 (AND 연산)
result = a || b; // 1'b1 (OR 연산)
축소 연산자는 벡터의 모든 비트를 하나의 값으로 축소하는 데 사용됩니다. 주로 wire 타입에 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
& | AND 축소 | &a (모든 비트가 AND 연산됨) |
| ` | ` | OR 축소 |
^ | XOR 축소 | ^a (모든 비트가 XOR 연산됨) |
~& | NOR 축소 | ~&a (모든 비트가 NOR 연산됨) |
| `~ | ` | NAND 축소 |
reg [3:0] a;
a = 4'b1011; // 4비트 벡터
wire and_result;
assign and_result = &a; // AND 축소 -> 1'b0
조건부 연산자는 if-else 구문처럼 작동하지만, 한 줄로 간단하게 표현할 수 있습니다.
if else 문 대신에 사용도 가능하다.
| 연산자 | 설명 | 예시 |
|---|---|---|
? : | 조건부 연산자 (if-else) | a ? b : c (a가 참이면 b, 아니면 c) |
reg [3:0] a, b, c, result;
a = 4'b1100;
b = 4'b1010;
c = 4'b0110;
result = (a == 4'b1100) ? b : c; // 4'b1010 (a가 참이면 b)
연결 연산자는 여러 비트나 벡터를 합치는 데 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
{} | 벡터 연결 | {a, b} (a와 b를 연결) |
reg [3:0] a, b, result;
a = 4'b1100;
b = 4'b1010;
result = {a, b}; // 8비트 벡터: 4'b11001010
복제 연산자는 하나의 값을 여러 번 반복하여 벡터로 만드는 데 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
{} | 값 복제 | {n{a}} (a를 n번 반복) |
reg [3:0] a, result;
a = 4'b1010;
result = {3{a}}; // 12비트 벡터: 4'b101010101010
좋아요! 추가적으로 Shift 연산자, 관계 연산자, 논리/케이스 동등 연산자에 대해 설명하겠습니다.
Shift 연산자는 비트를 왼쪽 또는 오른쪽으로 이동하는 데 사용됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
<< | 논리 왼쪽 시프트 (Logical Left Shift) | a << b |
>> | 논리 오른쪽 시프트 (Logical Right Shift) | a >> b |
<<< | 산술 왼쪽 시프트 (Arithmetic Left Shift) | a <<< b |
>>> | 산술 오른쪽 시프트 (Arithmetic Right Shift) | a >>> b |
<<, >>): 비어 있는 자리를 0으로 채운다.<<<, >>>): 오른쪽 시프트 시 부호 비트를 유지한다.reg [7:0] a, b;
a = 8'b00001111; // 15
b = a << 2; // 8'b00111100 (왼쪽으로 2비트 이동, 60)
b = a >> 2; // 8'b00000011 (오른쪽으로 2비트 이동, 3)
reg signed [7:0] c;
c = -8'sd4; // 8'b11111100 (-4)
c = c >>> 1; // 8'b11111110 (-2) (MSB 유지)
관계 연산자는 두 값 간의 크기 비교를 수행합니다. 결과는 1(true) 또는 0(false)이 됩니다.
| 연산자 | 설명 | 예시 |
|---|---|---|
> | 크다 (greater than) | a > b |
< | 작다 (less than) | a < b |
>= | 크거나 같다 (greater than or equal to) | a >= b |
<= | 작거나 같다 (less than or equal to) | a <= b |
reg [3:0] a, b;
a = 4'b1010; // 10
b = 4'b0101; // 5
if (a > b) // 10 > 5 → 참 (1)
$display("a가 b보다 크다");
==, !=)== : 두 값이 같으면 1을 반환 (논리적 동등)!= : 두 값이 다르면 1을 반환 (논리적 비동등) reg [3:0] a, b;
a = 4'b1010; // 10
b = 4'b1010; // 10
if (a == b) // 참 (1)
$display("a와 b는 같다");
⚠ 주의: x 또는 z가 포함된 값을 비교하면 결과가 X가 될 수도 있음.
===, !==)=== : 두 값이 모든 비트가 완전히 같아야 1을 반환 (비교할 때 x와 z도 고려)!== : 두 값이 하나라도 다르면 1을 반환 (비교할 때 x와 z도 고려)==) vs. 케이스 동등(===) 비교| 비교 연산자 | 비교 결과 |
|---|---|
4'b10xx == 4'b1010 | X (논리 비교는 x 고려 안함) |
4'b10xx === 4'b1010 | 0 (x도 엄격하게 비교) |
4'b1010 !== 4'b1010 | 0 (완전히 같음) |
4'b10xx !== 4'b1010 | 1 (x 때문에 다름) |
reg [3:0] a, b;
a = 4'b10xx;
b = 4'b1010;
if (a == b) // 결과: X (논리 비교)
$display("a와 b는 같다");
if (a === b) // 결과: 0 (모든 비트 다 비교)
$display("a와 b는 완전히 같다");
else
$display("a와 b는 다르다");
외우기 힘드니 괄호를 사용하자