HW/SystemVerilog

[SystemVerilog] Data tpye and Module design

Hangu2 2024. 5. 25. 16:20

학습 주제 및 목표

  • 기본 및 사용자 정의 데이터 타입 : SystemVerilog에서 제공하는 다양한 데이터 타입을 이해하고 사용할 수 있다.
  • Vector, Array, Structure : 복잡한 데이터 구조를 정의하고 사용 할 수 있다.
  • Define module and Instantiation : 모듈을 정의하고 인스턴스화하여 기본 회로를 설계할 수 있다.
  • Interface 와 package: 인터페이스와 패키지를 사용하여 모듈 간의 연결을 효율적으로 할 수 있다.

### 3주차: 데이터 타입 및 모듈 설계

#### 학습 주제 및 목표
- **기본 및 사용자 정의 데이터 타입**: SystemVerilog에서 제공하는 다양한 데이터 타입을 이해하고 사용할 수 있다.
- **벡터, 배열, 구조체**: 복잡한 데이터 구조를 정의하고 사용할 수 있다.
- **모듈 정의 및 인스턴스화**: 모듈을 정의하고 인스턴스화하여 기본 회로를 설계할 수 있다.
- **인터페이스와 패키지**: 인터페이스와 패키지를 사용하여 모듈 간의 연결을 효율적으로 할 수 있다.

### 강의 내용

#### 1. 데이터 타입

SystemVerilog는 다양한 데이터 타입을 제공하여 더 유연한 설계를 가능하게 합니다.

**기본 데이터 타입:**
- **bit**: 0 또는 1 값을 가질 수 있는 데이터 타입.
- **logic**: 4가지 상태 (0, 1, x, z)를 가질 수 있는 데이터 타입.
- **reg**: 레지스터 타입, 기본 Verilog 타입.
- **int**: 32비트 정수 타입.
- **shortint**: 16비트 정수 타입.
- **longint**: 64비트 정수 타입.
- **integer**: 일반 정수 타입.
- **byte**: 8비트 정수 타입.

**예제 코드:**
```systemverilog
module data_types_example;
  bit a;
  logic b;
  reg c;
  int d;
  byte e;

  initial begin
    // 값 할당
    a = 1;
    b = '0;
    c = 1'bx;
    d = -12345;
    e = 8'hFF;

    // 값 출력
    $display("a = %b, b = %b, c = %b, d = %d, e = %h", a, b, c, d, e);
  end
endmodule
```

**결과:**
```
a = 1, b = 0, c = x, d = -12345, e = ff
```

**사용자 정의 데이터 타입:**
- **enum**: 열거형 타입으로, 특정 값의 집합을 정의할 수 있습니다.
- **struct**: 구조체 타입으로, 여러 변수를 묶어서 사용할 수 있습니다.
- **union**: 공용체 타입으로, 여러 변수를 하나의 메모리 공간에 할당할 수 있습니다.

**예제 코드:**
```systemverilog
module user_defined_types_example;
  typedef enum {RED, GREEN, BLUE} color_t;
  color_t my_color;

  typedef struct {
    int id;
    string name;
  } person_t;
  person_t person;

  typedef union {
    int i;
    byte b[4];
  } data_t;
  data_t data;

  initial begin
    // 값 할당
    my_color = RED;
    person = '{id: 1, name: "Alice"};
    data.i = 32'hAABBCCDD;

    // 값 출력
    $display("my_color = %0d", my_color);
    $display("person.id = %0d, person.name = %s", person.id, person.name);
    $display("data.i = %h, data.b = %h %h %h %h", data.i, data.b[3], data.b[2], data.b[1], data.b[0]);
  end
endmodule
```

**결과:**
```
my_color = 0
person.id = 1, person.name = Alice
data.i = aabbccdd, data.b = aa bb cc dd
```

---

#### 2. 벡터, 배열, 구조체

**벡터:**
- 벡터는 비트의 집합으로, 여러 비트를 하나의 데이터 타입으로 처리할 수 있습니다.

**예제 코드:**
```systemverilog
module vector_example;
  logic [3:0] vec;

  initial begin
    vec = 4'b1010;
    $display("vec = %b", vec);
  end
endmodule
```

**결과:**
```
vec = 1010
```

**배열:**
- 정적 배열, 동적 배열, 연관 배열 등을 사용할 수 있습니다.

**예제 코드:**
```systemverilog
module array_example;
  int arr [0:3]; // 정적 배열

  initial begin
    // 배열 값 할당
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;

    // 배열 값 출력
    foreach (arr[i]) begin
      $display("arr[%0d] = %0d", i, arr[i]);
    end
  end
endmodule
```

**결과:**
```
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
```
### SystemVerilog 배열 종류

SystemVerilog에서는 다양한 종류의 배열을 지원하여 복잡한 데이터 구조를 다룰 수 있습니다. 배열의 종류는 크게 정적 배열, 동적 배열, 연관 배열로 나눌 수 있습니다.

---

#### 1. 정적 배열 (Static Array)

정적 배열은 크기가 고정된 배열로, 배열의 크기가 컴파일 타임에 결정됩니다. 정적 배열은 미리 선언된 크기를 가지며, 컴파일 타임에 메모리가 할당됩니다.

**예제 코드:**
```systemverilog
module static_array_example;
  int arr[4]; // 4개의 요소를 가지는 정적 배열

  initial begin
    // 배열 값 할당
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;

    // 배열 값 출력
    foreach (arr[i]) begin
      $display("arr[%0d] = %0d", i, arr[i]);
    end
  end
endmodule
```

**결과:**
```
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
```

---

#### 2. 동적 배열 (Dynamic Array)

동적 배열은 크기가 런타임에 결정될 수 있는 배열로, 필요에 따라 크기를 조정할 수 있습니다. 동적 배열은 `new` 키워드를 사용하여 크기를 지정하거나 변경할 수 있습니다.

**예제 코드:**
```systemverilog
module dynamic_array_example;
  int arr[]; // 동적 배열 선언

  initial begin
    // 배열 크기 지정 및 값 할당
    arr = new[4];
    arr[0] = 10;
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;

    // 배열 값 출력
    foreach (arr[i]) begin
      $display("arr[%0d] = %0d", i, arr[i]);
    end

    // 배열 크기 변경
    arr = new[2];
    arr[0] = 50;
    arr[1] = 60;

    // 배열 값 출력
    foreach (arr[i]) begin
      $display("arr[%0d] = %0d", i, arr[i]);
    end
  end
endmodule
```

**결과:**
```
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[0] = 50
arr[1] = 60
```

---

#### 3. 연관 배열 (Associative Array)

연관 배열은 인덱스가 정수가 아닌 데이터 타입(예: 문자열, 정수 외의 다른 데이터 타입)일 수 있는 배열입니다. 연관 배열은 동적으로 메모리가 할당되며, 인덱스를 사용하여 데이터를 저장하고 검색합니다.

**예제 코드:**
```systemverilog
module associative_array_example;
  int arr[string]; // 연관 배열 선언

  initial begin
    // 배열 값 할당
    arr["first"] = 10;
    arr["second"] = 20;
    arr["third"] = 30;

    // 배열 값 출력
    foreach (arr[i]) begin
      $display("arr[%s] = %0d", i, arr[i]);
    end
  end
endmodule
```

**결과:**
```
arr[first] = 10
arr[second] = 20
arr[third] = 30
```

**연관 배열 메서드:**
- **num()**: 배열에 저장된 요소의 개수를 반환합니다.
- **first()**: 배열에서 첫 번째 인덱스를 반환합니다.
- **last()**: 배열에서 마지막 인덱스를 반환합니다.
- **next()**: 배열에서 주어진 인덱스 다음의 인덱스를 반환합니다.
- **prev()**: 배열에서 주어진 인덱스 이전의 인덱스를 반환합니다.
- **delete()**: 배열에서 특정 인덱스를 삭제합니다.

**예제 코드:**
```systemverilog
module associative_array_methods_example;
  int arr[string]; // 연관 배열 선언
  string idx;

  initial begin
    // 배열 값 할당
    arr["first"] = 10;
    arr["second"] = 20;
    arr["third"] = 30;

    // 배열 크기 출력
    $display("Array size: %0d", arr.num());

    // 첫 번째 인덱스 출력
    idx = arr.first();
    $display("First index: %s", idx);

    // 다음 인덱스 출력
    idx = arr.next(idx);
    $display("Next index: %s", idx);

    // 마지막 인덱스 출력
    idx = arr.last();
    $display("Last index: %s", idx);

    // 특정 인덱스 삭제
    arr.delete("second");

    // 배열 크기 출력
    $display("Array size after deletion: %0d", arr.num());
  end
endmodule
```

**결과:**
```
Array size: 3
First index: first
Next index: second
Last index: third
Array size after deletion: 2
```

---

### 요약

- **정적 배열**: 크기가 고정된 배열로, 컴파일 타임에 크기가 결정됩니다.
- **동적 배열**: 크기가 런타임에 결정되며, 필요에 따라 크기를 조정할 수 있습니다.
- **연관 배열**: 인덱스가 정수가 아닌 데이터 타입을 가질 수 있으며, 동적으로 메모리가 할당됩니다.


**구조체:**
- 구조체는 여러 데이터를 묶어서 사용할 수 있는 데이터 타입입니다.

**예제 코드:**
```systemverilog
module struct_example;
  typedef struct {
    int id;
    string name;
  } person_t;
  person_t person;

  initial begin
    // 구조체 값 할당
    person.id = 1;
    person.name = "Alice";

    // 구조체 값 출력
    $display("person.id = %0d, person.name = %s", person.id, person.name);
  end
endmodule
```

**결과:**
```
person.id = 1, person.name = Alice
```

---

#### 3. 모듈 정의 및 인스턴스화

**모듈:**
- 모듈은 설계의 기본 단위입니다. 입력, 출력, 내부 신호 등을 포함하며, 다른 모듈을 인스턴스화할 수 있습니다.

**예제 코드:**
```systemverilog
module simple_module(input logic a, b, output logic c);
  assign c = a & b;
endmodule

module top_module;
  logic a, b, c;

  // 모듈 인스턴스화
  simple_module u1 (.a(a), .b(b), .c(c));

  initial begin
    a = 1;
    b = 0;
    #10;
    $display("c = %b", c);
  end
endmodule
```

**결과:**
```
c = 0
```

---

#### 4. 인터페이스와 패키지

**인터페이스:**
- 인터페이스는 모듈 간의 신호 연결을 정의하고 관리할 수 있는 방법입니다.

**예제 코드:**
```systemverilog
interface simple_if;
  logic a, b, c;
endinterface

module simple_module(input simple_if intf);
  assign intf.c = intf.a & intf.b;
endmodule

module top_module;
  simple_if intf();

  // 모듈 인스턴스화
  simple_module u1 (.intf(intf));

  initial begin
    intf.a = 1;
    intf.b = 0;
    #10;
    $display("c = %b", intf.c);
  end
endmodule
```

**결과:**
```
c = 0
```

**패키지:**
- 패키지는 여러 모듈에서 공통으로 사용할 수 있는 상수, 타입, 함수 등을 정의하는 데 사용됩니다.

**예제 코드:**
```systemverilog
package my_pkg;
  typedef enum {RED, GREEN, BLUE} color_t;
  function void print_color(color_t color);
    $display("Color: %0d", color);
  endfunction
endpackage

module top_module;
  import my_pkg::*;

  initial begin
    color_t my_color = RED;
    print_color(my_color);
  end
endmodule
```

**결과:**
```
Color: 0
```

---

### 실습 및 과제

- **실습 1**: 간단한 모듈을 설계하고 시뮬레이션.
- **실습 2**: 인터페이스를 사용하여 모듈 간의 신호 연결 실습.
- **실습 3**: 사용자 정의 데이터 타입을 활용한 설계 연습.
- **실습 4**: 패키지를 사용하여 공통 상수와 타입을 정의하고 사용하는 예제 작성.

이 강의를 통해 SystemVerilog의 데이터 타입과 모듈 설계에 대한 기초를 탄탄히 다질 수 있으며, 실습을 통해 실제 설계에 적용할 수 있는 능력을 키울 수 있습니다. 궁금한 점이 있으면 언제든지 물어보세요!