연산자 = 데이터를 연산하는 기호
Verilog 연산자는 실제 하드웨어 회로로 합성된다.
연산자를 쓰면 해당 기능을 수행하는 회로가 생성된다.
각 비트 위치별로 독립적으로 수행하는 연산

wire [3:0] a = 4'b1100;
wire [3:0] b = 4'b1010;
~a // 0011 (각 비트 반전)
a & b // 1000 (둘 다 1인 위치만 1)
a | b // 1110 (하나라도 1이면 1)
a ^ b // 0110 (서로 다른 위치만 1)
AND, OR, NOT 등의 연산으로, 연산 결과가 항상 0 아니면 1이다.

wire [3:0] a = 4'b1100; // 12 (0이 아님 → 참)
wire [3:0] b = 4'b0000; // 0 (→ 거짓)
wire [3:0] c = 4'b0001; // 1 (0이 아님 → 참)
!a // 0 (a는 참이므로 → 거짓)
!b // 1 (b는 거짓이므로 → 참)
a && c // 1 (둘 다 참)
a && b // 0 (b가 거짓)
a || b // 1 (a가 참)
참고로 논리 연산에서 0이면 거짓이고, 0이 아니면 참이다.
여러 비트를 하나의 비트로 압축하는 연산

wire [7:0] data = 8'b1010_1010;
// 모든 비트가 1인지 확인
wire all_ones = &data; // 0 (8'hFF일 때만 1)
// 하나라도 1인지 확인 (= 0이 아닌지)
wire not_zero = |data; // 1
// 패리티 계산 (1의 개수가 홀수면 1)
wire parity = ^data; // 0 (1이 4개 → 짝수)
수학적인 숫자의 계산

wire [7:0] a = 8'd15;
wire [7:0] b = 8'd4;
a + b // 19
a - b // 11
a * b // 60
a / b // 3 (정수 나눗셈)
a % b // 3 (15 = 4*3 + 3)
2 ** 3 // 8
wire [3:0] a = 4'd15; // 최대값
wire [3:0] b = 4'd1;
wire [3:0] sum = a + b; // 오버플로우! 결과: 0 (16의 하위 4비트)
이런 경우, a=4'b1111 이고, b=4'b0001 이므로 a+b = 5'b10000 이다.
이때 sum이 4비트이므로 MSB인 1이 잘리고 결국 sum에는 잘못된 값인 4'b0000 이 저장된다.
이를 막기위해서 비트폭을 확장해주면 된다.
wire [3:0] a = 4'd15;
wire [3:0] b = 4'd1;
wire [4:0] sum = a + b; // 5비트로 확장 → 5'b10000 = 16 ✅
이런식으로 비트폭을 확장해주면 된다.
비트를 좌 or 우로 밀어주는 연산

논리 시프트는 Shift 결과 생기는 빈자리를 단순하게 0으로 채운다.
반면, 산술 시프트는 Shift 후에 부호 확장을 수행하여 수의 부호 손실 문제를 해결한다.
a = 1100_0000 (signed: -64)
논리 우시프트 (>>):
1100_0000 >> 2 = 0011_0000
↑↑
00 채움 (부호 손실!)
산술 우시프트 (>>>):
1100_0000 >>> 2 = 1111_0000
↑↑
11 채움 (부호 유지!)
우 Shift는 2로 나누는 것이고, 좌 Shift는 2를 곱하는 것이다.
예를들어 아래와 같다.
왼쪽 시프트 n칸 = × 2^n
오른쪽 시프트 n칸 = ÷ 2^n
a << 1 → a × 2
a << 3 → a × 8
a >> 1 → a ÷ 2
a >> 3 → a ÷ 8
두 값을 비교하여 참/거짓을 반환하는 연산

wire [3:0] a = 4'd5;
wire [3:0] b = 4'd3;
a == b // 0 (5 ≠ 3)
a != b // 1 (5 ≠ 3)
a > b // 1 (5 > 3)
a <= b // 0 (5 > 3)
==은 피연산자에 x가 포함되면
불확정(x)을 반환하지만, ===은 x도 하나의 값으로보고완전 일치를 비교한다.
여러 신호를 하나로 붙이는 연산
2개 이상의 연결선을 1개로 붙이는 연산
wire [3:0] a = 4'b1010;
wire [3:0] b = 4'b0011;
{a, b} // 8'b1010_0011 (a를 상위, b를 하위에 연결)
{b, a} // 8'b0011_1010 (순서 반대)
{a[1:0], b[3:2]} // 4'b1000 (부분 연결)
위와 같이 사용될 수 있다.
데이터를 복제하는 연산
wire [1:0] a = 2'b10;
{4{a}} // 8'b1010_1010 (a를 4번 반복)
{3{1'b1}} // 3'b111 (1을 3번 반복)
{8{1'b0}} // 8'b0000_0000 (0을 8번 반복)
복제연산은 위와 같이 사용하면 된다.
