Verilog 스칼라와 벡터: 비트 선택, 부분 선택, 벡터 연산 마스터
Verilog는 단일 비트(스칼라)와 비트 그룹(벡터)을 모두 표현해야 합니다. 플립플롭은 1비트지만 16비트 레지스터는 16비트를 저장합니다.
스칼라 vs 벡터 선언
- 스칼라: 범위 지정 없음 → 1비트
- 벡터:
[MSB:LSB] 범위 지정 → 다중 비트
wire o_nor; // 1비트 스칼라 넷
wire [7:0] o_flop; // 8비트 벡터 넷
reg parity; // 1비트 스칼라 변수
reg [31:0] addr; // 32비트 벡터 변수 (주소 저장용)
MSB(최상위 비트)는 좌측, LSB(최하위 비트)는 우측에 표기. 상수 표현식만 허용되며 변수 사용 불가. 음수 인덱스도 허용.
비트 선택 (Bit-Select)
벡터의 개별 비트에 접근: vec[index]. 범위 초과나 x/z 인덱스면 x 반환.
reg [7:0] addr;
addr[0] = 1; // 비트 0에 1 할당
addr[3] = 0; // 비트 3에 0 할당
addr[8] = 1; // 불법: 8번 비트 없음
부분 선택 (Part-Select)
연속된 비트 범위 선택. 두 가지 형태:
- 상수 부분 선택:
addr[23:16] = 8'h23;
- 인덱스 부분 선택 (변수 시작 비트, 고정 폭):
[start +: width]: 시작 비트부터 상위 방향 폭만큼
[start -: width]: 시작 비트부터 하위 방향 폭만큼
module des;
reg [31:0] data;
int i;
initial begin
data = 32'hFACE_CAFE;
for (i = 0; i < 4; i++) begin
$display("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
end
end
endmodule
// 출력:
// data[8*0 +: 8] = 0xfe (data[7:0])
// data[8*1 +: 8] = 0xca (data[15:8])
// data[8*2 +: 8] = 0xce (data[23:16])
// data[8*3 +: 8] = 0xfa (data[31:24])
자주 하는 실수
module tb;
reg [15:0] data;
initial begin
$display("data[0:9] = 0x%0h", data[0:9]); // 에러: MSB:LSB 순서 위반 (LSB:MSB로 썼음)
end
endmodule
부분 선택 시 반드시 [MSB:LSB] 순서(좌측이 큰 값)를 지켜야 합니다.
요약
| 구분 | 문법 | 용도 |
| 비트 선택 | vec[idx] | 단일 비트 읽기/쓰기 |
| 상수 부분 선택 | vec[msb:lsb] | 고정 범위 비트 슬라이스 |
| 인덱스 부분 선택 (+:) | vec[start +: width] | 루프 내 동적 슬라이스 (상향) |
| 인덱스 부분 선택 (-:) | vec[start -: width] | 루프 내 동적 슬라이스 (하향) |