본문으로 건너뛰기
code0.HDL

벡터·비트 선택·연산자

비트를 벡터로 묶고, 범위를 꺼내고, 중괄호로 이어 붙인 뒤, 비트·논리·축약 연산부터 산술·시프트·비교·우선순위까지 연산자마다 만들어지는 회로와 결과 폭을 익히고 실습에서 바이트를 재배치합니다.

이 장에서 배울 내용

  • [MSB:LSB]로 벡터를 선언하고 각 비트 위치의 값을 말할 수 있습니다
  • 범위 선택, 연결, 반복의 폭과 값을 손으로 계산할 수 있습니다
  • 더 좁거나 넓은 assign 대상이 값을 어떻게 바꾸는지, Icarus가 왜 경고하지 않는지 예측할 수 있습니다
  • 결과에 필요한 폭에 따라 비트 연산, 논리 연산, 축약 연산 가운데 하나를 고를 수 있습니다
  • 산술·시프트·비교 결과의 폭, 넘침, 부호 여부를 읽고, 우선순위가 읽는 순서와 다른 곳에 괄호를 칠 수 있습니다
이 장에서 배우는 개념
  • 벡터·비트 선택·연결·연산자
먼저 알아야 할 개념

1. 벡터는 여러 비트를 한 이름으로 묶은 신호입니다

앞 장의 포트는 모두 1비트였습니다. 여러 비트를 함께 다루는 신호가 벡터입니다. 선언에는 비트 수와 비트 번호를 함께 적습니다. 이름 앞의 대괄호에 최상위 비트 번호 MSB와 최하위 비트 번호 LSB를 씁니다.

형식

wire [MSB:LSB] 이름;
reg  [MSB:LSB] 이름;
wire [7:0] data;    // bit 7부터 bit 0까지 8비트
reg  [3:0] count;   // 4비트

대괄호를 생략하면 1비트 신호입니다. 콜론 왼쪽 번호가 최상위 비트, 오른쪽 번호가 최하위 비트입니다. 바이트는 보통 [7:0]으로 씁니다. bit 7의 값은 128, bit 0의 값은 1이고, 16진수 한 자릿수가 비트 네 개에 해당합니다. 공통 기초에서 버스라고 부른 것이 Verilog에서는 벡터이며, 포트도 input [7:0] data처럼 벡터로 선언할 수 있습니다.

2. 범위 선택은 비트를 꺼내고 중괄호는 비트를 이어 붙입니다

벡터 이름 뒤에 범위를 쓰면 그 비트만 선택되고, 결과의 폭은 선택한 비트 수와 같습니다. 중괄호 {}는 여러 값을 하나의 넓은 값으로 이어 붙이며, 먼저 쓴 항목이 최상위 쪽에 놓입니다. 이 식들은 게이트를 만들지 않습니다. 범위 선택은 전선 가운데 몇 개를 고르는 일이고, 연결은 전선을 나란히 놓는 일입니다.

2.1 범위 선택

벡터의 일부 비트만 꺼낼 때는 이름 뒤의 대괄호에 범위나 비트 번호를 씁니다.

구문결과폭
data[7:4]bit 7부터 bit 4까지. 상위 nibble4
data[0]bit 0 하나1

2.2 연결과 반복

중괄호 { }는 여러 값을 이어 붙여 더 넓은 벡터를 만듭니다. 처음 쓴 항목이 최상위 쪽에 놓입니다.

{2'b10, data, 1'b0}   // 2 + 8 + 1 = 11비트
{2{data[3:0]}}        // data[3:0]을 두 번 이어 붙인 8비트
구문이름뜻결과 폭
{a, b, c}연결a, b, c를 차례로. 먼저 쓴 항목이 최상위각 항목 폭의 합
{n{a}}반복a를 n번 되풀이a의 폭 × n

data가 8비트일 때 {2'b10, data, 1'b0}은 10, data 8비트, 0을 차례로 연결한 2 + 8 + 1 = 11비트입니다. {2{data[3:0]}}은 하위 nibble을 두 번 반복한 4 × 2 = 8비트입니다.

2.3 BitFields.v와 테스트벤치 읽기

BitFields.v는 8비트 입력 data 하나에서 출력 여섯 개를 만드는 조합 회로입니다. 출력 포트마다 assign이 하나씩 있으므로, 먼저 각 출력의 폭을 확인한 뒤 우변을 읽으세요.

BitFields.v
module bit_fields (
  input  [7:0]  data,
  output [3:0]  high,
  output        lsb,
  output [10:0] framed,
  output [7:0]  repeated,
  output [3:0]  narrow,
  output [11:0] wide
);
  // 범위는 비트를 선택하며 결과 폭은 범위의 폭과 같다.
  assign high     = data[7:4];
  assign lsb      = data[0];
  // 중괄호는 왼쪽부터 비트를 잇는다. 첫 항목이 최상위 쪽에 놓인다.
  assign framed   = {2'b10, data, 1'b0};
  assign repeated = {2{data[3:0]}};
  // 넓은 값은 상위 비트를 잃고, 좁은 값은 0으로 확장된다.
  assign narrow   = data;
  assign wide     = data;
endmodule

Tb.v는 bit_fields를 시험하는 테스트벤치입니다. 모듈·포트·assign 장에서 본 대로, 포트가 없는 모듈이 설계에 입력을 넣고 출력을 확인합니다. data에 1100_0101을 넣고, assign이 계산을 마치도록 #1만큼 기다린 뒤 세 줄을 출력합니다. 그다음 data를 8'hFF로 바꾸고 한 줄 더 출력합니다. 인스턴스와 이름 포트 연결의 전체 규칙은 인스턴스·계층·parameter 장에 있습니다.

Tb.v
module tb;
  reg  [7:0]  data;
  wire [3:0]  high;
  wire        lsb;
  wire [10:0] framed;
  wire [7:0]  repeated;
  wire [3:0]  narrow;
  wire [11:0] wide;

  bit_fields dut (
    .data(data), .high(high), .lsb(lsb), .framed(framed),
    .repeated(repeated), .narrow(narrow), .wide(wide)
  );

  initial begin
    data = 8'b1100_0101;
    // 출력하기 전에 연속 대입이 갱신될 시간 단계를 준다.
    #1;
    $display("SELECT high=%b lsb=%b", high, lsb);
    $display("CONCAT framed=%b repeated=%b", framed, repeated);
    $display("RESIZE narrow=%b wide=%b", narrow, wide);
    data = 8'hFF;
    #1;
    $display("FOLLOW high=%b framed=%b", high, framed);
    $finish;
  end
endmodule

이 개념 실습하기

다음 단계로 짧은 Verilog 문제에 이 개념을 적용해 보세요.

실행하기 전에 예측해 보세요. data = 1100_0101일 때 high, framed, repeated를 손으로 계산해 보세요.

확인 문제

data가 1100_0101일 때 data[7:4]로 선언한 high의 값은 무엇입니까?

답

확인 문제

data가 8비트일 때 {2'b10, data, 1'b0}의 폭은 몇 비트입니까?

3. 대상의 폭이 다르면 값이 경고 없이 바뀝니다

assign의 값과 대상의 폭이 다르면 Verilog는 오류 없이 폭을 맞춥니다. 대상이 더 좁으면 상위 비트를 버리고, 대상이 더 넓으면 상위를 0으로 채웁니다. Icarus는 두 경우 모두 경고를 출력하지 않으므로, 선언에 적은 폭은 주석이 아니라 회로 동작의 일부입니다.

대상동작1100_0101을 대입하면
[3:0], 더 좁음상위 비트를 버림(절단)0101
[11:0], 더 넓음상위를 0으로 채움(0 확장)0000_1100_0101

BitFields.v의 출력 narrow와 wide가 바로 이 두 경우입니다. 전체 규칙에는 signed 값에 대한 행이 하나 더 있고, 넓은 대상이 거기에 연결된 덧셈의 폭도 넓힌다는 결과가 따라옵니다. 두 내용은 리터럴·signed·식의 폭 장에 있습니다.

확인 문제

8'hC5를 4비트 wire에 대입했습니다. wire에 남는 16진수 한 자리는 무엇입니까?

실행을 누르세요. SELECT, CONCAT, RESIZE 줄을 위의 세 답과 비교합니다.

결과 확인. data = 1100_0101일 때의 모든 출력입니다.

출력계산값
highbit 7..41100
lsbbit 01
framed10, data 8비트, 0 순서로 연결10_11000101_0
repeated하위 4비트 0101을 두 번 반복01010101
narrow4비트 대상이므로 하위 4비트만 남음0101
wide12비트 대상이므로 앞에 0 네 개0000_1100_0101

그다음 마지막 FOLLOW 줄을 보세요. 테스트벤치는 data를 8'hFF로 바꾸기만 했는데 high와 framed가 새 값을 보입니다. assign은 한 번 실행되고 끝나는 문장이 아니라 연결이므로, 시뮬레이션이 진행되는 동안 출력이 입력을 계속 따라갑니다.

4. 연산자 세 가족은 결과 폭이 다릅니다

Verilog에는 모양이 비슷하지만 동작이 다른 연산자가 세 가족 있습니다. 어느 가족을 쓰는지가 결과의 폭을 정합니다.

가족연산자대상결과
비트 연산&, |, ^, ~두 벡터를 비트 위치마다피연산자와 같은 폭
논리 연산&&, ||, !값 전체. 0이 아니면 참1비트
축약 연산&a, |a, ^a벡터 하나의 모든 비트를 접음1비트

a = 4'b1010, b = 4'b0101일 때 a & b는 0000입니다. 두 값이 함께 1인 비트 위치가 없기 때문입니다. a && b는 1입니다. 두 값이 모두 0이 아니기 때문입니다. |a는 1이고 &a는 0입니다. 축약 연산자는 "어느 비트라도 1인가", "모든 비트가 1인가"를 Verilog로 쓴 것입니다.

확인 문제

|4'b0100, 곧 0100의 축약 OR은 무엇입니까?

확인 문제

a = 4'b1010, b = 4'b0101입니다. 옳은 결과 쌍은 어느 것입니까?

답

5. 산술 연산자는 가산기를 만들고, 폭을 넘으면 한 바퀴 돕니다

연산자뜻하드웨어
a + b, a - b덧셈, 뺄셈가산기. 뺄셈은 2의 보수를 더하는 가산기입니다
a * b곱셈곱셈기. 가산기보다 훨씬 큽니다
a / b, a % b몫, 나머지2의 거듭제곱 상수로 나누면 시프트와 범위 선택이라 게이트가 없습니다. 그 밖의 값이면 큰 나눗셈기가 됩니다
a ** b거듭제곱parameter의 2 ** W처럼 상수 계산에 씁니다

산술 결과에는 정해진 폭이 없습니다. 가장 넓은 피연산자와 대입 대상 모두를 고려한 폭으로 계산하고, 그 폭을 넘는 부분은 역시 경고 없이 버립니다. 그래서 12 + 5는 5비트 대상에서는 17이지만, 4비트 대상에서는 자리올림이 사라져 1만 남습니다. 부호 없는 뺄셈도 같은 방식으로 한 바퀴 돕니다. 4비트에서 5 - 12는 -7이 아니라 16 - 7 = 9입니다. 시뮬레이터의 버그가 아니라, 빌림 출력이 없는 4비트 감산기가 실제로 내는 값입니다. 자리올림이나 빌림이 필요하면 대상을 한 비트 넓게 선언하세요. 폭 규칙 전체는 리터럴·signed·식의 폭 장에 있습니다.

하드웨어 비용이 드러나는 곳은 나눗셈입니다. 여기서처럼 a가 부호 없는 값이면 a / 4와 a % 4는 배선만으로 구현됩니다. 4로 나누면 하위 두 비트가 떨어져 나가고, 나머지는 바로 그 두 비트입니다. 반면 b가 변수인 a / b는 한 클록 안에 끝나는 나눗셈기 전체를 뜻합니다. 합성 도구는 이것을 크고 느린 회로로 만들거나 아예 거부하므로, 실제 설계에서는 시프트나 여러 사이클에 걸친 나눗셈기를 씁니다. 시뮬레이션에서 0으로 나누면 오류도 0도 아닌 x가 나옵니다.

6. 시프트는 비트를 옮기고, 부호를 복사하는 것은 signed 값의 >>>뿐입니다

연산자이름비어 있는 자리에 들어오는 비트
a << n논리 왼쪽 시프트아래쪽에 0
a >> n논리 오른쪽 시프트위쪽에 0
a <<< n산술 왼쪽 시프트아래쪽에 0. <<과 같습니다
a >>> n산술 오른쪽 시프트a가 signed이면 부호 비트, 아니면 0

시프트의 폭은 왼쪽 피연산자와, 대입문에서는 그보다 넓은 대상의 문맥 폭으로 정합니다. 시프트 양은 결과 폭을 넓히지 않으며, 양 끝 밖으로 밀려난 비트는 사라집니다. 조심할 것은 >>>입니다. 피연산자가 signed로 선언되어 있을 때만 부호 비트를 복사합니다. 일반 벡터에서는 >>와 똑같아서 8'b1001_0110 >>> 2는 0010_0101입니다. 같은 비트를 담은 reg signed [7:0]일 때만 1110_0101이 나오고 값이 음수로 남습니다. -106을 4로 나누어 내림한 -27입니다.

상수만큼 시프트하면 게이트가 생기지 않습니다. 연결과 같은 배선이며, 8비트 a에서 a << 2는 {a[5:0], 2'b00}입니다. 변수만큼 시프트하는 a << n은 배럴 시프터가 됩니다. 출력 비트마다 어느 입력 비트가 도착할지 고르는 멀티플렉서를 여러 단 쌓은 회로입니다.

7. 비교 결과는 1비트이고, ==와 ===는 x에서 갈립니다

연산자묻는 것결과
<, <=, >, >=어느 값이 더 작거나 큰가1비트. 피연산자에 x나 z 비트가 있으면 x
==, !=두 값이 같은가1비트. x나 z 비트 때문에 판정할 수 없으면 x
===, !==x와 z까지 포함해 비트 패턴이 똑같은가언제나 0 또는 1

대소 비교는 피연산자 둘 다 signed일 때만 부호 있는 비교입니다. 한쪽이라도 일반 벡터이면 양쪽을 모두 부호 없는 값으로 읽습니다. 그러면 -1을 담은 signed 변수는 비트 패턴 1111_1111, 곧 255가 되어 s < 8'd1은 0이고 s < 8'sd1은 1입니다. 식 전체를 부호 없는 식으로 만드는 리터럴·signed·식의 폭 장의 규칙과 같은 규칙입니다.

==는 하드웨어가 할 수 있는 방식으로 비교합니다. 알려진 비트 가운데 하나라도 다르면 0입니다. x 비트만 불확실하면 결과는 x입니다. 실제 회로라면 그 자리에서 0과 1 어느 쪽이든 볼 수 있기 때문입니다. ===는 x와 z를 독립된 값으로 보고 패턴이 기호 하나하나까지 같은지 묻습니다. 실제 전선은 x가 되지 않으므로 ===에 해당하는 게이트는 없습니다. 설계에는 ==를 쓰고, ===는 출력이 정말 x인지, 또는 정말 x가 아닌지 확인할 때 테스트벤치에서 씁니다.

8. 조건 연산자는 두 값 가운데 하나를 고릅니다

cond ? x : y는 cond가 0이 아니면 x, 0이면 y입니다. 2:1 멀티플렉서를 식 하나로 쓴 것이며, 결과 폭은 x와 y 가운데 넓은 쪽과 그보다 넓은 대입 문맥을 함께 따릅니다. 여러 갈래로 중첩하는 방법과 case로 바꿔 쓰는 방법은 net·변수·조합 always 장에서 배웁니다.

9. 우선순위가 헷갈리면 괄호를 치세요

IEEE 1364-2005의 순서이며, 위쪽일수록 먼저 묶입니다. 같은 줄의 연산자는 우선순위가 같고 왼쪽부터 묶입니다. ?:만 오른쪽부터 묶입니다.

순위연산자
1단항 + - ! ~, 축약 & ~& | ~| ^ ~^
2**
3* / %
4이항 + -
5<< >> <<< >>>
6< <= > >=
7== != === !==
8이항 &
9이항 ^ ~^
10이항 |
11&&
12||
13?:

눈으로 읽는 순서와 표의 순서가 어긋나는 대표적인 경우가 셋 있습니다.

쓴 식Verilog가 읽는 방식보통 의도한 식
a & b == ca & (b == c). 1비트 비교 결과와 비트 AND(a & b) == c
a + b << 1(a + b) << 1. 합을 두 배로a + (b << 1)
!a == b(!a) == b. a의 1비트 NOT을 b와 비교!(a == b) 또는 a != b

비트 연산자는 비교 연산자보다 늦게 묶입니다. 대부분의 사람이 예상하는 것과 반대입니다. 괄호는 하드웨어에 아무 비용도 들지 않으니, 비트 연산자와 비교가 한 식에 함께 나오면 괄호를 치세요.

10. 실행: 연산자 가족을 한 테스트벤치에서 확인하기

Operators.v는 4비트 벡터 a = 12, b = 5를 선언하고, 8비트 패턴 1001_0110을 일반 벡터 u와 reg signed인 s에 한 번씩 넣습니다. $display 줄마다 앞에 어느 가족을 보여 주는지 이름표가 붙어 있습니다.

Operators.v
module operators;
  reg [3:0] a, b;
  reg [3:0] sum4, diff;
  reg [4:0] sum5;
  reg [7:0] pow, u, wide, grouped;
  reg signed [7:0] s;
  reg [3:0] q;
  reg [2:0] n;

  initial begin
    a = 4'd12;
    b = 4'd5;
    // 4비트 대상에는 17의 하위 4비트만 남고, 5비트 대상에는 자리올림까지 남는다.
    sum4 = a + b;
    sum5 = a + b;
    // 4비트 부호 없는 뺄셈 5 - 12의 결과는 16을 더한 9다.
    diff = b - a;
    pow = b ** 2;
    $display("ARITH sum4=%0d sum5=%0d diff=%0d pow=%0d", sum4, sum5, diff, pow);
    // 2의 거듭제곱으로 나누기는 시프트와 같고, 0으로 나누면 x가 나온다.
    $display("DIV a/b=%0d a%%b=%0d a/4=%0d a%%4=%0d a/0=%0d", a / b, a % b, a / 4, a % 4, a / 4'd0);

    // 같은 비트를 부호 없는 값과 signed 값으로 둔다. 부호 비트를 복사하는 것은 signed 쪽의 >>>뿐이다.
    u = 8'b1001_0110;
    s = 8'sb1001_0110;
    n = 3;
    $display("SHIFT u>>2=%b u>>>2=%b s>>2=%b s>>>2=%b", u >> 2, u >>> 2, s >> 2, s >>> 2);
    $display("SHIFTN n=%0d u<<n=%b u>>n=%b", n, u << n, u >> n);

    // 피연산자 하나가 부호 없는 값이면 비교 전체가 부호 없는 비교가 되어 -1을 255로 읽는다.
    s = -1;
    $display("COMPARE signed=%b mixed=%b", s < 8'sd1, s < 8'd1);

    // ==는 x 비트 때문에 같고 다름을 정할 수 없으면 x이고, ===는 x도 하나의 값으로 비교한다.
    q = 4'b10x1;
    $display("EQUAL q==10x1:%b q===10x1:%b q==0000:%b", q == 4'b10x1, q === 4'b10x1, q == 4'b0000);

    // 각 쌍은 쓴 그대로의 식, 그다음 작성자가 의도한 괄호를 친 식이다.
    $display("PREC-AND %b %b", a & b == 4'd4, (a & b) == 4'd4);
    wide = a + b << 1;
    grouped = a + (b << 1);
    $display("PREC-SHIFT %0d %0d", wide, grouped);
    $display("PREC-NOT %b %b", !a == b, !(a == b));

    // $display 인자에는 대입 대상이 없으므로 a + b는 4비트 폭 그대로 계산된다.
    $display("SELF a+b=%0d", a + b);
    $finish;
  end
endmodule

확인 문제

s는 -1을 담은 8비트 signed 변수입니다. COMPARE 줄의 혼합 비교 s < 8'd1은 무엇을 출력합니까?

답

실행을 누르고 출력을 한 줄씩 읽어 보세요.

줄볼 곳
ARITHsum4=1은 17의 자리올림을 잃었고 sum5=17은 지켰습니다. diff=9는 4비트에서 한 바퀴 돈 5 - 12입니다
DIVa/4=3과 a%4=0은 12의 상위 비트와 하위 비트입니다. a/0=x
SHIFT세 결과가 00100101입니다. signed 값의 산술 시프트인 s>>>2만 1로 채웁니다
SHIFTN변수 n = 3만큼 시프트합니다. 끝 밖으로 밀려난 비트는 사라집니다
COMPARE같은 -1이 양쪽 모두 signed이면 1보다 작고, 한쪽만 아니어도 1보다 큽니다
EQUAL==는 x 비트만 불확실하면 x, 알려진 비트가 다르면 0입니다. ===는 1입니다
PREC-AND, PREC-SHIFT, PREC-NOT각 쌍은 쓴 그대로의 식, 그다음 대부분이 의도한 괄호를 친 식입니다
SELF$display 안의 a + b는 폭을 넓혀 줄 대상이 없어 4비트로 계산되고 1을 출력합니다

하나만 바꿔 보세요. s 선언에서 signed를 지우고 다시 실행하세요. 실행하기 전에 SHIFT와 COMPARE에서 어느 값이 바뀔지 먼저 정합니다. s>>>2는 00100101이 되고, signed는 1에서 0으로 바뀝니다. 이제 -1은 양쪽 모두에서 그냥 255이기 때문입니다.

11. 하나만 바꿔 보세요

실행 패널에서 BitFields.v의 연결 순서를 {data, 2'b10, 1'b0}으로 바꾸고 다시 실행하세요. 폭은 그대로 11비트이지만 data가 맨 위로 옮겨 갑니다. 결과를 보기 전에 FOLLOW 줄에서 framed의 끝 세 비트가 무엇일지 먼저 정하세요.

확인 문제

framed = {data, 2'b10, 1'b0}일 때 framed의 하위 세 비트는 무엇입니까?

답

두 번째 변경은 테스트벤치 쪽입니다. Tb.v에서 첫 번째 #1;을 지우고 실행해 보세요. 처음 세 줄 가운데 일부에 x가 나타납니다. data가 바뀐 바로 그 순간에는 assign이 아직 다시 계산되지 않았기 때문입니다. 어느 출력이 x가 되는지는 시뮬레이터의 계산 순서에 따라 달라집니다. 설계는 올바르고, 테스트벤치가 출력을 너무 일찍 읽었습니다. 같은 실수와 그것을 고치는 #1은 net·변수·조합 always 장의 자주 하는 실수에 정리되어 있습니다.

12. 실습: 바이트의 배선을 바꾸기

점검 과제는 실습 문제 nibble-swap입니다. 8비트 입력의 두 절반을 출력에서 서로 바꿔 놓는 문제입니다. 필요한 도구는 이 장에 모두 있습니다. 범위 선택으로 두 절반에 이름을 붙이고, 중괄호 안에서 순서를 바꿔 이어 붙이세요. 이 수정은 게이트를 하나도 추가하지 않고 같은 전선 여덟 개의 경로만 바꿉니다. 채점은 공개 테스트벤치가 출력하는 세 값만이 아니라 모든 입력 값을 확인합니다.

두 번째 문제 byte-merge는 3절의 반대 상황입니다. assign은 모두 옳고 선언한 폭 하나가 틀려서, 마지막 assign이 두 값을 합치기 전에 비트가 사라집니다. 코드를 고치기 전에 선언된 폭으로 세 줄을 모두 계산해 보세요. 첫 줄은 올바르지만 나머지 두 줄은 선택된 상위 비트를 잃습니다. 두 문제 모두 바이트를 다루는 작은 모듈을 완성하는 과제입니다. 범위 선택과 연결로 비트를 재배치하고, 벡터 폭이 결과에 주는 영향을 직접 확인합니다.

13. 정리

요소뜻
wire [7:0] d;8비트 벡터. bit 7이 최상위. 대괄호가 없으면 1비트
d[7:4], d[0]범위 선택과 비트 선택. 선택한 비트 수가 폭
{a, b}, {n{a}}연결과 반복. 먼저 쓴 항목이 최상위. 폭은 항목 폭의 합 또는 a의 폭 × n
좁거나 넓은 대상상위 비트를 버리거나, 부호 없는 값이면 0으로 채움. Icarus는 어느 쪽도 경고하지 않음
&, &&, &a비트 연산, 논리 연산, 축약 연산
+ - * / %피연산자와 대상의 폭으로 계산하고 넘치면 한 바퀴 돎. 변수로 나누면 큰 나눗셈기, 0으로 나누면 x
<< >> <<< >>>왼쪽 피연산자와 대입 문맥이 폭을 정하고 시프트 양은 폭에 영향 없음. >>>는 signed 피연산자일 때만 부호 비트를 복사
< == ===1비트. 양쪽이 모두 signed가 아니면 부호 없는 비교. ==는 x가 될 수 있고 ===는 아님
우선순위비트 연산자가 비교보다 늦게 묶임. +가 <<보다 먼저

14. 확인 문제

  1. {4'hF, 1'b0, data[2:0]}의 폭과 최상위 비트 값은 무엇일까요?

    정답 보기

    폭은 4 + 1 + 3 = 8비트입니다. 처음 쓴 4'hF가 최상위 쪽에 놓이므로 최상위 비트는 1입니다.

  2. 12비트 wire에 8비트 값을 대입하면 어느 비트가 0이 될까요? 이때 컴파일 오류가 나는지도 답해 보세요.

    정답 보기

    값이 부호 없는 값이므로 상위 4비트(bit 11..8)가 0으로 채워집니다. 폭이 다른 대입은 자동으로 폭을 맞추므로 컴파일 오류가 없고 Icarus에서는 경고도 없습니다.

  3. 테스트벤치에서 #1을 지우자 일부 출력이 x가 되었습니다. 고쳐야 할 쪽은 설계와 테스트벤치 가운데 어느 쪽일까요?

    정답 보기

    테스트벤치입니다. 설계의 assign은 올바르지만, 테스트벤치가 입력을 바꾼 바로 그 순간에 출력을 읽어서 다시 계산되기 전의 값을 보았습니다.

리터럴에 쓸 수 있는 x와 z 숫자, 출력에서 본 %d의 앞 공백은 리터럴·signed·식의 폭 장에서 다룹니다.

확인 지점

실습 문제를 제출해 채점을 받습니다

채점은 서버의 비공개 테스트로 진행되며, 결과는 이 브라우저에만 기록됩니다.

참고 자료

참고한 자료의 라이선스와 고지