logic [7:0] image [0:3][0:3];Структура:
logic [7:0]- кожен елемент 8 біт (піксель, 0-255)[0:3]- перший вимір: 4 рядки (rows)[0:3]- другий вимір: 4 стовпці (columns)- Unpacked dimensions - кожен елемент зберігається окремо в пам'яті
Звернення:
image[row][col] // row = 0..3, col = 0..3for (row = 0; row < 4; row++) begin
for (col = 0; col < 4; col++) begin
image[row][col] = row * col;
end
endРезультат:
image[0][0] = 0×0 = 0 image[0][1] = 0×1 = 0 ...
image[1][0] = 1×0 = 0 image[1][1] = 1×1 = 1 ...
image[2][0] = 2×0 = 0 image[2][1] = 2×1 = 2 ...
image[3][0] = 3×0 = 0 image[3][1] = 3×1 = 3 ...
Візуалізація:
Col 0 Col 1 Col 2 Col 3
+------+------+------+------+
Row 0 | 0 | 0 | 0 | 0 |
Row 1 | 0 | 1 | 2 | 3 |
Row 2 | 0 | 2 | 4 | 6 |
Row 3 | 0 | 3 | 6 | 9 |
+------+------+------+------+
💡 Цікавий факт: Це таблиця множення! Стовпець 3 = рядок 3 = [0, 3, 6, 9]
for (row = 0; row < 4; row++) begin
$write("Рядок %0d: [", row);
for (col = 0; col < 4; col++) begin
$write("%3d", image[row][col]);
if (col < 3) $write(", ");
end
$display("]");
endВивід:
Рядок 0: [ 0, 0, 0, 0]
Рядок 1: [ 0, 1, 2, 3]
Рядок 2: [ 0, 2, 4, 6]
Рядок 3: [ 0, 3, 6, 9]
for (col = 0; col < 4; col++) begin
$write("Стовпець %0d: [", col);
for (row = 0; row < 4; row++) begin
$write("%3d", image[row][col]);
if (row < 3) $write(", ");
end
$display("]");
endВивід:
Стовпець 0: [ 0, 0, 0, 0]
Стовпець 1: [ 0, 1, 2, 3]
Стовпець 2: [ 0, 2, 4, 6]
Стовпець 3: [ 0, 3, 6, 9]
Відмінність:
- Рядок: фіксуємо
row, змінюємоcol→image[row][0..3] - Стовпець: фіксуємо
col, змінюємоrow→image[0..3][col]
function int row_sum(int row_index);
int total;
total = 0;
for (int c = 0; c < 4; c++) begin
total += image[row_index][c];
end
return total;
endfunctionВикористання:
// Після розкоментування:
for (row = 0; row < 4; row++) begin
$display("Сума рядка %0d = %0d", row, row_sum(row));
endОчікувані результати:
row_sum(0) = 0 + 0 + 0 + 0 = 0
row_sum(1) = 0 + 1 + 2 + 3 = 6
row_sum(2) = 0 + 2 + 4 + 6 = 12
row_sum(3) = 0 + 3 + 6 + 9 = 18
Альтернатива (inline обчислення):
// Без функції, прямо в initial блоці:
for (row = 0; row < 4; row++) begin
sum = 0;
for (col = 0; col < 4; col++) begin
sum += image[row][col];
end
$display("Сума рядка %0d = %0d", row, sum);
endlogic [7:0] image [0:3][0:3];
↑ ↑ ↑ ↑
│ │ │ └─ стовпці (unpacked dimension)
│ │ └──────── рядки (unpacked dimension)
│ └────────────────── розмір елемента (packed part)
└───────────────────────────── тип елементаPacked vs Unpacked частини:
- Packed:
[7:0]- це один 8-бітний вектор на елемент - Unpacked:
[0:3][0:3]- це розміри масиву (4×4 = 16 елементів)
Поелементно:
image[0][0] = 8'd100;
image[0][1] = 8'd200;
// ... і так даліЧерез цикли:
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
image[i][j] = i * j;Через агрегатну ініціалізацію (тільки в комерційних симуляторах):
// ✅ Працює в Questa, VCS, Xcelium:
image = '{
'{8'd0, 8'd0, 8'd0, 8'd0}, // рядок 0
'{8'd0, 8'd1, 8'd2, 8'd3}, // рядок 1
'{8'd0, 8'd2, 8'd4, 8'd6}, // рядок 2
'{8'd0, 8'd3, 8'd6, 8'd9} // рядок 3
};// ❌ Compilation error!
image = 128'h0000_0123_0246_0369;
// ❌ НЕ підтримується в Icarus Verilog:
image = '{'{0,0,0,0}, '{0,1,2,3}, ...};// До окремого елемента:
pixel = image[2][3]; // ✅ OK
// До цілого рядка (це теж масив):
logic [7:0] row_copy [0:3];
row_copy = image[2]; // ✅ OK (в деяких симуляторах)
// До біта в елементі:
bit_value = image[2][3][5]; // ✅ OK (біт 5 елемента [2][3])
// Part-select в елементі:
nibble = image[2][3][7:4]; // ✅ OK (старші 4 біти)// Part-select по масиву:
slice = image[3:2]; // ❌ ERROR
// Звернення як до плоского масиву:
element = image[10]; // ❌ ERROR (потрібно [row][col])
// Побітові операції на масиві:
inverted = ~image; // ❌ ERROR- Тестбенчі: зберігання тестових даних
- Матриці: обробка зображень, матриці трансформацій
- Таблиці пошуку (LUT): ROM, конфігураційні таблиці
- Буфери: FIFO, черги даних
- Багатовимірні дані: RGB зображення
[height][width][3]
- Синтез апаратури - unpacked arrays НЕ синтезуються!
- Порти модулів - не можна передати як один порт
- Побітові операції - немає операцій на рівні масиву
// ✅ Можна:
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
image[i][j] = image[i][j] + 1; // Поелементна операція
// ✅ Можна передавати в функції:
function void print_matrix(logic [7:0] mat [0:3][0:3]);
// ...
endfunction
// ❌ НЕ можна:
image = image + 1; // ERROR! Немає операцій на масиві
image = ~image; // ERROR!
result = image & mask; // ERROR!PACKED ARRAY:
logic [3:0][7:0] packed_data;
Пам'ять: [XXXXXXXX|XXXXXXXX|XXXXXXXX|XXXXXXXX]
↑----- 32 біти безперервно ------↑
packed_data = 32'hFACE_CAFE; ✅ OK
UNPACKED ARRAY:
logic [7:0] unpacked_data [0:3];
Пам'ять: [XXXXXXXX] ... [XXXXXXXX] ... [XXXXXXXX] ... [XXXXXXXX]
↑element 0 ↑element 1 ↑element 2 ↑element 3
Окремі елементи, не обов'язково поруч!
unpacked_data = 32'h...; ❌ ERROR
| Характеристика | Packed Array | Unpacked Array |
|---|---|---|
| Оголошення | logic [3:0][7:0] data |
logic [7:0] data [0:3] |
| Зберігання | Безперервний вектор | Окремі елементи |
| Пряме присвоєння | ✅ data = 32'hXXXX |
❌ Тільки поелементно |
| Побітові операції | ✅ ~data, data & mask |
❌ НЕ підтримується |
| Part-select | ✅ data[3:2] |
❌ НЕ підтримується |
| Flat indexing | ✅ data[15:0] (в деяких) |
❌ НЕ підтримується |
| Порт модуля | ✅ Можна передати | ❌ Не можна як один порт |
| Синтез | ✅ Синтезується | ❌ НЕ синтезується |
| Використання | RTL код, апаратура | Тестбенчі, моделі |
| Швидкість симуляції | Швидше | Повільніше |
| Гнучкість | Обмежена | Більша |
Потрібен синтез в апаратуру?
├─ Так → PACKED ARRAY
│ • Регістри
│ • Порти модулів
│ • Шини даних
│ • FIFO, RAM
│
└─ Ні → UNPACKED ARRAY
• Тестбенчі
• Моделі пам'яті
• Таблиці даних
• Матриці для обробки
// Unpacked: зручно для обробки зображень у тестбенчах
logic [7:0] rgb_image [0:31][0:31][0:2];
// ↑ ↑ ↑ ↑
// 8-біт height width RGB channels
// Заповнення червоним кольором:
for (int y = 0; y < 32; y++)
for (int x = 0; x < 32; x++) begin
rgb_image[y][x][0] = 8'd255; // R = 255
rgb_image[y][x][1] = 8'd0; // G = 0
rgb_image[y][x][2] = 8'd0; // B = 0
end// Unpacked: таблиця sin(x) для тестування
logic [15:0] sin_lut [0:359]; // 360 значень (градуси)
initial begin
// Заповнення таблиці
for (int angle = 0; angle < 360; angle++) begin
// Імітація sin(angle) * 32767
sin_lut[angle] = $rtoi($sin(angle * 3.14159 / 180.0) * 32767);
end
end
// Використання:
logic [15:0] sin_45 = sin_lut[45];// Unpacked: FIFO буфер у тестбенчі
logic [31:0] fifo_buffer [0:15]; // 16 елементів по 32 біти
int write_ptr = 0;
int read_ptr = 0;
// Запис:
task fifo_write(logic [31:0] data);
fifo_buffer[write_ptr] = data;
write_ptr = (write_ptr + 1) % 16;
endtask
// Читання:
task fifo_read(output logic [31:0] data);
data = fifo_buffer[read_ptr];
read_ptr = (read_ptr + 1) % 16;
endtasklogic [7:0] arr [0:3];
arr = 32'hFACECAFE; // ❌ ERROR!✅ Рішення:
arr[0] = 8'hFA;
arr[1] = 8'hCE;
arr[2] = 8'hCA;
arr[3] = 8'hFE;logic [7:0] arr [0:3];
arr = ~arr; // ❌ ERROR!✅ Рішення:
for (int i = 0; i < 4; i++)
arr[i] = ~arr[i]; // Поелементна інверсіяlogic [7:0] arr [0:3];
logic [15:0] slice = arr[3:2]; // ❌ ERROR!✅ Рішення:
logic [15:0] slice;
slice = {arr[3], arr[2]}; // Конкатенаціяlogic [7:0] data [0:3];
module receiver(input logic [7:0] in [0:3]); // ❌ НЕ синтезується!
// ...
endmodule✅ Рішення (використати packed):
logic [3:0][7:0] data; // Packed array
module receiver(input logic [3:0][7:0] in); // ✅ Синтезується
// ...
endmodule- Unpacked array = окремі елементи в пам'яті
- НЕ синтезується - тільки для тестбенчів!
- Немає побітових операцій на рівні масиву
- Ініціалізація: тільки поелементно або через цикли (в Icarus Verilog)
- Звернення: завжди через всі індекси
arr[i][j] - Використання: тестові дані, моделі, буфери
✅ ВИКОРИСТОВУЙТЕ unpacked array для:
• Тестбенчів (верифікація)
• Зберігання тестових даних
• Матриць і таблиць
• Моделей пам'яті
• Обробки даних у симуляції
❌ НЕ використовуйте unpacked array для:
• RTL дизайну
• Портів модулів
• Синтезу в апаратуру
• Побітових операцій
• Передачі як одне ціле
| Потрібно... | Використовуйте |
|---|---|
| Синтез апаратури | Packed |
| Тестбенч | Unpacked |
| Порт модуля | Packed |
| Матриця даних | Unpacked |
| Побітові операції | Packed |
| Багатовимірні дані | Unpacked |
| Шина даних | Packed |
| Таблиця пошуку | Unpacked |
Пам'ятайте: Unpacked arrays - це інструмент для верифікації та моделювання, не для апаратури! Для RTL коду завжди використовуйте packed arrays. 🧪