Menu

Verilog 비트와이즈와 Reduction 연산자

Verilog의 비트 레벨 연산자 - 비트와이즈 AND/OR/XOR, 그 inversion 형태, 그리고 전체 vector를 단일 비트로 줄이는 reduction 연산자.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

같은 기호의 두 역할

&, |, ^, 그리고 그것들의 inverted 형제들은 두 가지 형태로 나타납니다.

  • 이항 형태(피연산자 둘): a & b - 너비가 같은 vector 간의 비트와이즈 연산.
  • 단항 형태(피연산자 하나): &a - a의 모든 비트에 걸친 reduction으로 단일 비트.

컴파일러는 피연산자 개수로 둘을 구분합니다. 사람들이 쓰는 명명 관례는 이항을 "비트와이즈 연산자", 단항을 "reduction 연산자"라고 부르는 것입니다.

비트와이즈: 한 번에 한 비트

풀세트.

연산자이름N번째 위치의 출력 비트
a & bANDa[N] AND b[N]
a | bORa[N] OR b[N]
a ^ bXORa[N] XOR b[N]
a ~& bNANDNOT (a[N] AND b[N])
a ~| bNORNOT (a[N] OR b[N])
a ~^ bXNORNOT (a[N] XOR b[N])
~aNOTNOT a[N]

~&, ~|, ~^는 tilde가 먼저, 연산자가 뒤에 옵니다. 단일 토큰이며 사이에 공백이 없습니다.

두 피연산자의 너비가 다르면 좁은 쪽이 왼쪽에서 zero-extension 되어 너비를 맞춥니다. sign-extension을 원한다면 $signed()로 부호 있는 피연산자를 명시적으로 사용하세요.

Reduction: 많은 비트에서 하나로

같은 연산자의 단항 형태는 vector를 단일 비트로 줄입니다.

각각의 의미.

  • &datadata모든 비트 가 1이면 1, 아니면 0을 반환. "전부 1인가?" 검사에 유용.
  • |datadata어떤 비트라도 1이면 1, 아니면 0을 반환. "non-zero인가?" 검사에 유용.
  • ^dataparity 를 반환 - 모든 비트의 XOR. 1의 개수가 홀수면 1, 짝수면 0.
  • ~&data, ~|data, ~^data는 위의 inverse.

실제 코드 어디서나 보이게 됩니다.

wire empty       = ~|fifo_count;       // count가 0이면 empty
wire all_ones    = &mask;              // 모든 비트가 set
wire parity_bit  = ^data;              // 바이트의 parity
wire any_request = |request_vector;    // 무언가 요청 중인가?

reduction 형태는 간결하고, 명백한 게이트 트리로 synthesize됩니다: &는 다중 입력 AND 게이트, |는 다중 입력 OR, ^는 XOR 트리(하드웨어에서 parity generator이기도)로 줄어듭니다.

흔한 패턴

비트 set/clear

wire [7:0] data;
wire [7:0] mask = 8'b0000_1000;

wire [7:0] set     = data | mask;     // 비트 3을 1로 강제
wire [7:0] cleared = data & ~mask;    // 비트 3을 0으로 강제
wire [7:0] toggled = data ^ mask;     // 비트 3 토글
wire [7:0] tested  = data & mask;     // 비트 3이 0이었으면 0, 아니면 non-zero

C에서 쓰는 비트 조작 idiom과 같습니다. 단일 게이트 연산으로 synthesize됩니다.

값이 모두 1인지 검사

wire is_max = &counter;       // counter의 모든 비트가 1이면 1

게이트 하나의 reduction AND. counter == 8'hFF라고 적는 것과 비교해(역시 동작하고; synthesizer가 보통 동일한 하드웨어를 만듦) 더 간결합니다.

parity bit 생성

활성 신호 감지

wire any_pending = |request_vector;

request_vector가 넓다면(가령 64개 요청자), reduction OR이 priority encoder나 arbiter로 공급할 단일 신호로 줄여 줍니다.

Shift 연산자

비트 레벨 연산자에 있는 김에 shift도 봅시다.

  • a << Na를 왼쪽으로 N비트 위치 shift하고 오른쪽을 0으로 채웁니다.
  • a >> Na를 오른쪽으로 N비트 위치 shift하고 왼쪽을 0으로 채웁니다.
  • a <<< N은 arithmetic left shift(부호 없는 경우 <<와 같음).
  • a >>> N은 arithmetic right shift - a가 부호 있으면 부호 비트로 채웁니다.

상수만큼의 shift는 하드웨어에서 무료입니다(그냥 재배선). 런타임 변수만큼의 shift는 barrel shifter를 만들고, 더 크지만 여전히 저렴합니다.

다음에 볼 내용

단일 값을 반환하는 모든 연산자를 봤습니다. 다음 문서 - Concatenation and Replication - 은 조각들로부터 더 넓은 vector를 만드는 {}{N{...}} 문법을 다루며, 너비가 다른 모듈 간 인터페이스에서 끊임없이 쓰게 됩니다.

자주 묻는 질문

Verilog의 비트와이즈 연산자란?

비트와이즈 연산자는 너비가 같은 두 vector를 위치별로 결합합니다. a & ba의 비트 0을 b의 비트 0과 AND하고, 비트 1을 비트 1과, 이런 식으로 입력과 같은 너비의 vector를 만듭니다. 풀세트는 &(AND), |(OR), ^(XOR), ~(NOT), 그리고 inversion 형태 ~&, ~|, ~^(NAND, NOR, XNOR)입니다.

Verilog의 reduction 연산자란?

reduction 연산자는 비트와이즈 연산자의 단항 형태로, 전체 vector를 단일 비트로 줄입니다. &datadata의 모든 비트가 1일 때만 1을 반환합니다. |data는 어떤 비트라도 1이면 1을 반환합니다. ^data는 모든 비트의 XOR - parity를 반환합니다. reduction 형태는 왼쪽에 피연산자가 없고 오른쪽에만 있습니다.

Verilog에서 &와 &&의 차이는?

&는 비트와이즈 AND - 비트를 위치별로 짝짓고 결과는 피연산자와 같은 너비입니다. &&는 logical AND - 각 피연산자를 boolean(0 vs non-zero)으로 다루고 1비트 결과를 반환합니다. 4'b1100 & 4'b00114'b0000이고, 4'b1100 && 4'b00111입니다.

Verilog에서 parity는 어떻게 계산하나요?

reduction XOR 연산자를 사용합니다: parity = ^data. data의 모든 비트를 함께 XOR합니다. 8비트 vector라면 data[7] ^ data[6] ^ ... ^ data[0]이 됩니다. 결과는 1 비트의 개수가 홀수면 1, 짝수면 0입니다. ~^로 invert하면 even parity가 됩니다.

Verilog에서 ~는 무엇을 하나요?

~는 비트와이즈 NOT입니다 - 피연산자의 모든 비트를 반전합니다. ~4'b11004'b0011입니다. !(logical NOT)와 혼동하지 마세요. !는 피연산자를 1비트 boolean으로 줄이고 그것을 반전합니다. !4'b11001'b0입니다(피연산자가 non-zero이고, 그 진리값을 NOT하면 0).

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기