데이터를 비트 단위로 조작하는 것
wire [31:0] data = 32'hDEADBEEF;
// 고정 범위 선택
wire [7:0] byte0 = data[7:0]; // EF
wire [7:0] byte1 = data[15:8]; // BE
wire [7:0] byte2 = data[23:16]; // AD
wire [7:0] byte3 = data[31:24]; // DE
// 단일 비트 선택
wire lsb = data[0]; // 1 (최하위 비트)
wire msb = data[31]; // 1 (최상위 비트)
위와 같이 벡터에서 원하는 비트의 데이터만 추출할 수 있다.
wire [31:0] data;
reg [1:0] sel
// 방법 1: +: 연산자 (권장)
wire [7:0] byte_sel = data[sel*8 +: 8]; // sel 위치부터 8비트
// 방법 2: -: 연산자
wire [7:0] byte_sel2 = data[sel*8+7 -: 8]; // sel*8+7부터 아래로 8비트
위와 같이 +: 와 -:를 이용하여 가변적인 인덱스로 슬라이싱할 수 있다.
data[base +: width]
Concatenation 연산 ({}) 을 활용하여 비트를 연결할 수(합칠 수) 있다
wire [7:0] a = 8'hDE;
wire [7:0] b = 8'hAD;
wire [7:0] c = 8'hBE;
wire [7:0] d = 8'hEF;
// 연결: 왼쪽이 MSB, 오른쪽이 LSB
wire [31:0] combined = {a, b, c, d}; // 32'hDEADBEEF
// 다양한 크기 연결
wire [15:0] half = {a, b}; // 16'hDEAD
wire [11:0] mixed = {a[3:0], d}; // 12'hEEF
이런식으로 Concatenation 연산 ({}) 을 활용하여 비트를 연결할 수(합칠 수) 있다.
// 필드 결합 (패킷 헤더 등)
wire [3:0] version = 4'h4;
wire [3:0] ihl = 4'h5;
wire [7:0] tos = 8'h00;
wire [15:0] ip_header_start = {version, ihl, tos}; // 16'h4500
위와 같이 필드 결합에 사용될 수 있다.
Verilog에서는 비트 패턴 복제도 가능하다.
문법은 {횟수{패턴}} 이다.
wire bit1 = 1'b1;
wire [3:0] nibble = 4'hA;
// 복제 문법: {횟수{패턴}}
wire [7:0] rep8 = {8{bit1}}; // 8'b11111111 = 8'hFF
wire [15:0] rep4 = {4{nibble}}; // 16'hAAAA
wire [11:0] rep3 = {3{nibble}}; // 12'hAAA
// 복제 + 연결 조합
wire [7:0] pattern = {4{2'b10}}; // 8'b10101010 = 8'hAA
양수 (MSB=0): 0으로 확장
8'b0xxx_xxxx → 16'b0000_0000_0xxx_xxxx
음수 (MSB=1): 1로 확장
8'b1xxx_xxxx → 16'b1111_1111_1xxx_xxxx
위와 같이 부호 확장을 활용하면, 수의 부호와 크기를 유지하며 더 큰 비트수로 나타낼 수 있게된다.
wire [7:0] small = 8'hF6; // -10 (signed)
wire [15:0] extended;
// 방법 1: 복제 연산자 사용
assign extended = {{8{small[7]}}, small};
// ↑ MSB를 8번 복제
// 방법 2: signed 타입 활용
wire signed [7:0] small_s = 8'hF6;
wire signed [15:0] extended_s = small_s; // 자동 부호 확장
// 방법 3: $signed 함수
wire [15:0] extended2 = $signed(small);
부호 확장은 위와 같이 3개의 방식으로 구현할 수 있다.
// 32비트 명령어에서 필드 추출 (RISC-V 예시)
wire [31:0] instruction;
wire [6:0] opcode = instruction[6:0];
wire [4:0] rd = instruction[11:7];
wire [4:0] rs1 = instruction[19:15];
wire [4:0] rs2 = instruction[24:20];
wire [6:0] funct7 = instruction[31:25];
// 필드 삽입 (명령어 생성)
wire [31:0] add_instr = {funct7, rs2, rs1, 3'b000, rd, opcode};
wire [7:0] data = 8'b1010_1100;
// 특정 비트만 추출
wire [7:0] lower4 = data & 8'b0000_1111; // 8'b0000_1100
// 특정 비트만 설정
wire [7:0] set_bit3 = data | 8'b0000_1000; // bit3 = 1
// 특정 비트만 클리어
wire [7:0] clr_bit2 = data & ~8'b0000_0100; // bit2 = 0
// 특정 비트 토글
wire [7:0] toggle = data ^ 8'b0000_1111; // 하위 4비트 반전(1과의 xor은 NOT과 동일)