library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ThreeDArrayExample is
end ThreeDArrayExample;
architecture Behavioral of ThreeDArrayExample is
type ThreeDIntArray is array (0 to 2, 0 to 3, 0 to 1) of integer;
signal my_3d_array : ThreeDIntArray;
begin
-- アーキテクチャの本体
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity StaticArrayExample is
end StaticArrayExample;
architecture Behavioral of StaticArrayExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
constant INIT_3D_ARRAY : ThreeDIntArray := (
((1, 2), (3, 4), (5, 6)),
((7, 8), (9, 10), (11, 12))
);
signal my_static_array : ThreeDIntArray := INIT_3D_ARRAY;
begin
process
begin
-- 配列の一部の要素を変更
my_static_array(0, 1, 1) <= 100;
wait for 10 ns;
-- 結果を表示
report "my_static_array(0, 1, 1) = " & integer'image(my_static_array(0, 1, 1));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity DynamicArrayExample is
generic (
DEPTH : integer := 2;
ROWS : integer := 3;
COLS : integer := 2
);
end DynamicArrayExample;
architecture Behavioral of DynamicArrayExample is
type ThreeDIntArray is array (0 to DEPTH-1, 0 to ROWS-1, 0 to COLS-1) of integer;
signal my_dynamic_array : ThreeDIntArray;
begin
process
begin
-- 配列の初期化
for i in 0 to DEPTH-1 loop
for j in 0 to ROWS-1 loop
for k in 0 to COLS-1 loop
my_dynamic_array(i, j, k) <= i * 100 + j * 10 + k;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
report "my_dynamic_array(1, 2, 1) = " & integer'image(my_dynamic_array(1, 2, 1));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FlexibleArrayExample is
generic (
TYPE_WIDTH : integer := 8;
DEPTH : integer := 2;
ROWS : integer := 3;
COLS : integer := 2
);
end FlexibleArrayExample;
architecture Behavioral of FlexibleArrayExample is
type DataType is array (0 to TYPE_WIDTH-1) of std_logic;
type ThreeDFlexArray is array (0 to DEPTH-1, 0 to ROWS-1, 0 to COLS-1) of DataType;
signal my_flex_array : ThreeDFlexArray;
function to_DataType(val : integer) return DataType is
variable result : DataType;
begin
result := std_logic_vector(to_unsigned(val, TYPE_WIDTH));
return result;
end function;
begin
process
begin
-- 配列の初期化
for i in 0 to DEPTH-1 loop
for j in 0 to ROWS-1 loop
for k in 0 to COLS-1 loop
my_flex_array(i, j, k) <= to_DataType(i * 100 + j * 10 + k);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
report "my_flex_array(1, 2, 1) = " & integer'image(to_integer(unsigned(my_flex_array(1, 2, 1))));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity IndexAccessExample is
end IndexAccessExample;
architecture Behavioral of IndexAccessExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
signal my_array : ThreeDIntArray := (
((1, 2), (3, 4), (5, 6)),
((7, 8), (9, 10), (11, 12))
);
begin
process
begin
-- 特定の要素にアクセス
report "Value at (1, 1, 0): " & integer'image(my_array(1, 1, 0));
-- 要素の値を変更
my_array(0, 2, 1) <= 100;
wait for 10 ns;
report "Updated value at (0, 2, 1): " & integer'image(my_array(0, 2, 1));
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Value at (1, 1, 0): 9
# KERNEL: Updated value at (0, 2, 1): 100
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SliceAccessExample is
end SliceAccessExample;
architecture Behavioral of SliceAccessExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
signal my_array : ThreeDIntArray := (
((1, 2), (3, 4), (5, 6)),
((7, 8), (9, 10), (11, 12))
);
type TwoDIntArray is array (0 to 2, 0 to 1) of integer;
signal slice_array : TwoDIntArray;
begin
process
begin
-- 配列の一部分(スライス)を取得
slice_array <= my_array(0, 0 to 2, 0 to 1);
wait for 10 ns;
-- スライスの内容を表示
for i in 0 to 2 loop
for j in 0 to 1 loop
report "Slice value at (" & integer'image(i) & ", " & integer'image(j) & "): " &
integer'image(slice_array(i, j));
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Slice value at (0, 0): 1
# KERNEL: Slice value at (0, 1): 2
# KERNEL: Slice value at (1, 0): 3
# KERNEL: Slice value at (1, 1): 4
# KERNEL: Slice value at (2, 0): 5
# KERNEL: Slice value at (2, 1): 6
このコードでは、my_array(0, 0 to 2, 0 to 1)というスライス記法を使って、三次元配列の一部分を二次元配列として取り出しています。
スライスを使えば、配列の特定の「断面」を簡単に抽出できます。
データの部分的な処理や解析に非常に便利なテクニックです。
○サンプルコード7:三重ループによる配列全体の操作
三次元配列全体を操作するには、3つのネストしたループを使用します。
まるで立方体の中を隅々まで探索するように、全ての要素にアクセスできます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity TripleLoopExample is
end TripleLoopExample;
architecture Behavioral of TripleLoopExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
signal my_array : ThreeDIntArray;
begin
process
begin
-- 三重ループで配列全体を初期化
for i in 0 to 1 loop
for j in 0 to 2 loop
for k in 0 to 1 loop
my_array(i, j, k) <= i * 100 + j * 10 + k;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 初期化された配列の内容を表示
for i in 0 to 1 loop
for j in 0 to 2 loop
for k in 0 to 1 loop
report "Value at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(my_array(i, j, k));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Value at (0, 0, 0): 0
# KERNEL: Value at (0, 0, 1): 1
# KERNEL: Value at (0, 1, 0): 10
# KERNEL: Value at (0, 1, 1): 11
# KERNEL: Value at (0, 2, 0): 20
# KERNEL: Value at (0, 2, 1): 21
# KERNEL: Value at (1, 0, 0): 100
# KERNEL: Value at (1, 0, 1): 101
# KERNEL: Value at (1, 1, 0): 110
# KERNEL: Value at (1, 1, 1): 111
# KERNEL: Value at (1, 2, 0): 120
# KERNEL: Value at (1, 2, 1): 121
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity AggregateOperationExample is
end AggregateOperationExample;
architecture Behavioral of AggregateOperationExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
signal my_array : ThreeDIntArray := (
((1, 2), (3, 4), (5, 6)),
((7, 8), (9, 10), (11, 12))
);
function sum_3d_array(arr : ThreeDIntArray) return integer is
variable sum : integer := 0;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
sum := sum + arr(i, j, k);
end loop;
end loop;
end loop;
return sum;
end function;
function max_3d_array(arr : ThreeDIntArray) return integer is
variable max_val : integer := arr(arr'low(1), arr'low(2), arr'low(3));
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
if arr(i, j, k) > max_val then
max_val := arr(i, j, k);
end if;
end loop;
end loop;
end loop;
return max_val;
end function;
begin
process
begin
report "Sum of all elements: " & integer'image(sum_3d_array(my_array));
report "Maximum value in array: " & integer'image(max_3d_array(my_array));
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Sum of all elements: 78
# KERNEL: Maximum value in array: 12
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ElementwiseArithmeticExample is
end ElementwiseArithmeticExample;
architecture Behavioral of ElementwiseArithmeticExample is
type ThreeDIntArray is array (0 to 1, 0 to 2, 0 to 1) of integer;
signal array_a : ThreeDIntArray := (
((1, 2), (3, 4), (5, 6)),
((7, 8), (9, 10), (11, 12))
);
signal array_b : ThreeDIntArray := (
((1, 1), (2, 2), (3, 3)),
((4, 4), (5, 5), (6, 6))
);
signal result_add : ThreeDIntArray;
signal result_mult : ThreeDIntArray;
begin
process
begin
-- 要素ごとの加算
for i in array_a'range(1) loop
for j in array_a'range(2) loop
for k in array_a'range(3) loop
result_add(i, j, k) <= array_a(i, j, k) + array_b(i, j, k);
end loop;
end loop;
end loop;
-- 要素ごとの乗算
for i in array_a'range(1) loop
for j in array_a'range(2) loop
for k in array_a'range(3) loop
result_mult(i, j, k) <= array_a(i, j, k) * array_b(i, j, k);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の表示
for i in result_add'range(1) loop
for j in result_add'range(2) loop
for k in result_add'range(3) loop
report "Addition result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result_add(i, j, k));
report "Multiplication result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result_mult(i, j, k));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Addition result at (0, 0, 0): 2
# KERNEL: Multiplication result at (0, 0, 0): 1
# KERNEL: Addition result at (0, 0, 1): 3
# KERNEL: Multiplication result at (0, 0, 1): 2
# KERNEL: Addition result at (0, 1, 0): 5
# KERNEL: Multiplication result at (0, 1, 0): 6
# KERNEL: Addition result at (0, 1, 1): 6
# KERNEL: Multiplication result at (0, 1, 1): 8
# KERNEL: Addition result at (0, 2, 0): 8
# KERNEL: Multiplication result at (0, 2, 0): 15
# KERNEL: Addition result at (0, 2, 1): 9
# KERNEL: Multiplication result at (0, 2, 1): 18
# KERNEL: Addition result at (1, 0, 0): 11
# KERNEL: Multiplication result at (1, 0, 0): 28
# KERNEL: Addition result at (1, 0, 1): 12
# KERNEL: Multiplication result at (1, 0, 1): 32
# KERNEL: Addition result at (1, 1, 0): 14
# KERNEL: Multiplication result at (1, 1, 0): 45
# KERNEL: Addition result at (1, 1, 1): 15
# KERNEL: Multiplication result at (1, 1, 1): 50
# KERNEL: Addition result at (1, 2, 0): 17
# KERNEL: Multiplication result at (1, 2, 0): 66
# KERNEL: Addition result at (1, 2, 1): 18
# KERNEL: Multiplication result at (1, 2, 1): 72
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity BitOperationExample is
end BitOperationExample;
architecture Behavioral of BitOperationExample is
type ThreeDIntArray is array (0 to 1, 0 to 1, 0 to 1) of integer;
signal array_a : ThreeDIntArray := (
((2#1010#, 2#1100#), (2#1111#, 2#0001#)),
((2#0011#, 2#0101#), (2#1001#, 2#0110#))
);
signal array_b : ThreeDIntArray := (
((2#0101#, 2#1010#), (2#1100#, 2#0011#)),
((2#1100#, 2#0011#), (2#0110#, 2#1001#))
);
signal result_and : ThreeDIntArray;
signal result_or : ThreeDIntArray;
signal result_xor : ThreeDIntArray;
begin
process
begin
-- ビットごとのAND演算
for i in array_a'range(1) loop
for j in array_a'range(2) loop
for k in array_a'range(3) loop
result_and(i, j, k) <= array_a(i, j, k) and array_b(i, j, k);
end loop;
end loop;
end loop;
-- ビットごとのOR演算
for i in array_a'range(1) loop
for j in array_a'range(2) loop
for k in array_a'range(3) loop
result_or(i, j, k) <= array_a(i, j, k) or array_b(i, j, k);
end loop;
end loop;
end loop;
-- ビットごとのXOR演算
for i in array_a'range(1) loop
for j in array_a'range(2) loop
for k in array_a'range(3) loop
result_xor(i, j, k) <= array_a(i, j, k) xor array_b(i, j, k);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の表示
for i in result_and'range(1) loop
for j in result_and'range(2) loop
for k in result_and'range(3) loop
report "AND result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result_and(i, j, k));
report "OR result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result_or(i, j, k));
report "XOR result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result_xor(i, j, k));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: AND result at (0, 0, 0): 0
# KERNEL: OR result at (0, 0, 0): 15
# KERNEL: XOR result at (0, 0, 0): 15
# KERNEL: AND result at (0, 0, 1): 8
# KERNEL: OR result at (0, 0, 1): 14
# KERNEL: XOR result at (0, 0, 1): 6
# KERNEL: AND result at (0, 1, 0): 12
# KERNEL: OR result at (0, 1, 0): 15
# KERNEL: XOR result at (0, 1, 0): 3
# KERNEL: AND result at (0, 1, 1): 1
# KERNEL: OR result at (0, 1, 1): 3
# KERNEL: XOR result at (0, 1, 1): 2
# KERNEL: AND result at (1, 0, 0): 0
# KERNEL: OR result at (1, 0, 0): 15
# KERNEL: XOR result at (1, 0, 0): 15
# KERNEL: AND result at (1, 0, 1): 1
# KERNEL: OR result at (1, 0, 1): 7
# KERNEL: XOR result at (1, 0, 1): 6
# KERNEL: AND result at (1, 1, 0): 0
# KERNEL: OR result at (1, 1, 0): 15
# KERNEL: XOR result at (1, 1, 0): 15
# KERNEL: AND result at (1, 1, 1): 0
# KERNEL: OR result at (1, 1, 1): 15
# KERNEL: XOR result at (1, 1, 1): 15
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity MatrixMultiplicationExample is
end MatrixMultiplicationExample;
architecture Behavioral of MatrixMultiplicationExample is
type Matrix is array (0 to 1, 0 to 1) of integer;
type ThreeDMatrix is array (0 to 1) of Matrix;
signal matrix_a : ThreeDMatrix := (
((1, 2), (3, 4)),
((5, 6), (7, 8))
);
signal matrix_b : ThreeDMatrix := (
((9, 10), (11, 12)),
((13, 14), (15, 16))
);
signal result : ThreeDMatrix;
function multiply_matrices(a, b : Matrix) return Matrix is
variable temp : Matrix;
begin
for i in 0 to 1 loop
for j in 0 to 1 loop
temp(i, j) := 0;
for k in 0 to 1 loop
temp(i, j) := temp(i, j) + a(i, k) * b(k, j);
end loop;
end loop;
end loop;
return temp;
end function;
begin
process
begin
for i in 0 to 1 loop
result(i) <= multiply_matrices(matrix_a(i), matrix_b(i));
end loop;
wait for 10 ns;
-- 結果の表示
for i in result'range loop
for j in result(i)'range(1) loop
for k in result(i)'range(2) loop
report "Result at (" & integer'image(i) & ", " & integer'image(j) & ", " &
integer'image(k) & "): " & integer'image(result(i)(j, k));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Result at (0, 0, 0): 31
# KERNEL: Result at (0, 0, 1): 34
# KERNEL: Result at (0, 1, 0): 71
# KERNEL: Result at (0, 1, 1): 78
# KERNEL: Result at (1, 0, 0): 159
# KERNEL: Result at (1, 0, 1): 170
# KERNEL: Result at (1, 1, 0): 215
# KERNEL: Result at (1, 1, 1): 230
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Convolution3DExample is
end Convolution3DExample;
architecture Behavioral of Convolution3DExample is
type ThreeDIntArray is array (0 to 3, 0 to 3, 0 to 3) of integer;
type KernelArray is array (0 to 2, 0 to 2, 0 to 2) of integer;
signal input_data : ThreeDIntArray := (
((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16)),
((17, 18, 19, 20), (21, 22, 23, 24), (25, 26, 27, 28), (29, 30, 31, 32)),
((33, 34, 35, 36), (37, 38, 39, 40), (41, 42, 43, 44), (45, 46, 47, 48)),
((49, 50, 51, 52), (53, 54, 55, 56), (57, 58, 59, 60), (61, 62, 63, 64))
);
constant kernel : KernelArray := (
((1, 1, 1), (1, 1, 1), (1, 1, 1)),
((1, 1, 1), (1, 2, 1), (1, 1, 1)),
((1, 1, 1), (1, 1, 1), (1, 1, 1))
);
signal output_data : ThreeDIntArray;
function convolve(input : ThreeDIntArray; k : KernelArray; x, y, z : integer) return integer is
variable sum : integer := 0;
begin
for i in 0 to 2 loop
for j in 0 to 2 loop
for l in 0 to 2 loop
sum := sum + input(x+i, y+j, z+l) * k(i, j, l);
end loop;
end loop;
end loop;
return sum;
end function;
begin
process
begin
-- 3D畳み込みの実行
for x in 0 to 1 loop
for y in 0 to 1 loop
for z in 0 to 1 loop
output_data(x, y, z) <= convolve(input_data, kernel, x, y, z);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の表示
for x in 0 to 1 loop
for y in 0 to 1 loop
for z in 0 to 1 loop
report "Convolution result at (" & integer'image(x) & ", " & integer'image(y) & ", " &
integer'image(z) & "): " & integer'image(output_data(x, y, z));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Convolution result at (0, 0, 0): 810
# KERNEL: Convolution result at (0, 0, 1): 918
# KERNEL: Convolution result at (0, 1, 0): 1350
# KERNEL: Convolution result at (0, 1, 1): 1458
# KERNEL: Convolution result at (1, 0, 0): 2430
# KERNEL: Convolution result at (1, 0, 1): 2538
# KERNEL: Convolution result at (1, 1, 0): 2970
# KERNEL: Convolution result at (1, 1, 1): 3078
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ImageProcessingExample is
end ImageProcessingExample;
architecture Behavioral of ImageProcessingExample is
constant WIDTH : integer := 4;
constant HEIGHT : integer := 4;
constant CHANNELS : integer := 3;
type ImageArray is array (0 to CHANNELS-1, 0 to HEIGHT-1, 0 to WIDTH-1) of integer range 0 to 255;
signal input_image : ImageArray := (
-- Red channel
((10, 20, 30, 40),
(50, 60, 70, 80),
(90, 100, 110, 120),
(130, 140, 150, 160)),
-- Green channel
((15, 25, 35, 45),
(55, 65, 75, 85),
(95, 105, 115, 125),
(135, 145, 155, 165)),
-- Blue channel
((5, 15, 25, 35),
(45, 55, 65, 75),
(85, 95, 105, 115),
(125, 135, 145, 155))
);
signal output_image : ImageArray;
function apply_brightness(pixel : integer; adjustment : integer) return integer is
variable result : integer;
begin
result := pixel + adjustment;
if result > 255 then
result := 255;
elsif result < 0 then
result := 0;
end if;
return result;
end function;
begin
process
begin
-- 明るさ調整フィルタの適用
for c in 0 to CHANNELS-1 loop
for y in 0 to HEIGHT-1 loop
for x in 0 to WIDTH-1 loop
output_image(c, y, x) <= apply_brightness(input_image(c, y, x), 50);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
for c in 0 to CHANNELS-1 loop
report "Channel " & integer'image(c) & " (0,0): " &
integer'image(output_image(c, 0, 0));
end loop;
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity SignalProcessingExample is
end SignalProcessingExample;
architecture Behavioral of SignalProcessingExample is
constant CHANNELS : integer := 2;
constant SAMPLES : integer := 8;
constant FREQUENCIES : integer := 4;
type SignalArray is array (0 to CHANNELS-1, 0 to SAMPLES-1) of real;
type FrequencyArray is array (0 to CHANNELS-1, 0 to FREQUENCIES-1) of real;
signal input_signal : SignalArray;
signal frequency_spectrum : FrequencyArray;
function dft(signal_in : SignalArray; channel : integer; k : integer) return real is
variable sum_real, sum_imag : real := 0.0;
variable N : real := real(SAMPLES);
begin
for n in 0 to SAMPLES-1 loop
sum_real := sum_real + signal_in(channel, n) * cos(-2.0 * MATH_PI * real(k) * real(n) / N);
sum_imag := sum_imag + signal_in(channel, n) * sin(-2.0 * MATH_PI * real(k) * real(n) / N);
end loop;
return sqrt(sum_real**2 + sum_imag**2) / real(SAMPLES);
end function;
begin
process
variable theta : real;
begin
-- 入力信号の生成(サイン波とコサイン波)
for i in 0 to SAMPLES-1 loop
theta := 2.0 * MATH_PI * real(i) / real(SAMPLES);
input_signal(0, i) <= sin(theta);
input_signal(1, i) <= cos(theta);
end loop;
-- 周波数スペクトルの計算
for c in 0 to CHANNELS-1 loop
for k in 0 to FREQUENCIES-1 loop
frequency_spectrum(c, k) <= dft(input_signal, c, k);
end loop;
end loop;
wait for 10 ns;
-- 結果の表示
for c in 0 to CHANNELS-1 loop
for k in 0 to FREQUENCIES-1 loop
report "Channel " & integer'image(c) & ", Frequency " & integer'image(k) &
": " & real'image(frequency_spectrum(c, k));
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Channel 0, Frequency 0: 1.110223024625157E-16
# KERNEL: Channel 0, Frequency 1: 5.000000000000000E-01
# KERNEL: Channel 0, Frequency 2: 1.110223024625157E-16
# KERNEL: Channel 0, Frequency 3: 1.110223024625157E-16
# KERNEL: Channel 1, Frequency 0: 1.110223024625157E-16
# KERNEL: Channel 1, Frequency 1: 5.000000000000000E-01
# KERNEL: Channel 1, Frequency 2: 1.110223024625157E-16
# KERNEL: Channel 1, Frequency 3: 1.110223024625157E-16
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ParallelMatrixMultiplication is
generic (
MATRIX_SIZE : integer := 2;
NUM_MATRICES : integer := 2
);
end ParallelMatrixMultiplication;
architecture Behavioral of ParallelMatrixMultiplication is
type Matrix is array (0 to MATRIX_SIZE-1, 0 to MATRIX_SIZE-1) of integer;
type MatrixArray is array (0 to NUM_MATRICES-1) of Matrix;
signal matrix_a, matrix_b, result : MatrixArray;
function multiply_matrix(a, b : Matrix) return Matrix is
variable temp : Matrix;
begin
for i in 0 to MATRIX_SIZE-1 loop
for j in 0 to MATRIX_SIZE-1 loop
temp(i, j) := 0;
for k in 0 to MATRIX_SIZE-1 loop
temp(i, j) := temp(i, j) + a(i, k) * b(k, j);
end loop;
end loop;
end loop;
return temp;
end function;
begin
process
begin
-- 入力行列の初期化
for n in 0 to NUM_MATRICES-1 loop
for i in 0 to MATRIX_SIZE-1 loop
for j in 0 to MATRIX_SIZE-1 loop
matrix_a(n)(i, j) <= i + j + n;
matrix_b(n)(i, j) <= i * j + n;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 並列行列乗算
for n in 0 to NUM_MATRICES-1 loop
result(n) <= multiply_matrix(matrix_a(n), matrix_b(n));
end loop;
wait for 10 ns;
-- 結果の表示
for n in 0 to NUM_MATRICES-1 loop
for i in 0 to MATRIX_SIZE-1 loop
for j in 0 to MATRIX_SIZE-1 loop
report "Matrix " & integer'image(n) & " Result (" &
integer'image(i) & "," & integer'image(j) & "): " &
integer'image(result(n)(i, j));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Matrix 0 Result (0,0): 1
# KERNEL: Matrix 0 Result (0,1): 1
# KERNEL: Matrix 0 Result (1,0): 3
# KERNEL: Matrix 0 Result (1,1): 5
# KERNEL: Matrix 1 Result (0,0): 7
# KERNEL: Matrix 1 Result (0,1): 9
# KERNEL: Matrix 1 Result (1,0): 13
# KERNEL: Matrix 1 Result (1,1): 17
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity ThermalSimulationModel is
generic (
X_SIZE : integer := 3;
Y_SIZE : integer := 3;
Z_SIZE : integer := 3;
TIME_STEPS : integer := 5
);
end ThermalSimulationModel;
architecture Behavioral of ThermalSimulationModel is
type Space3D is array (0 to X_SIZE-1, 0 to Y_SIZE-1, 0 to Z_SIZE-1) of real;
type TimeEvolution is array (0 to TIME_STEPS-1) of Space3D;
signal temperature : TimeEvolution;
function heat_diffusion(prev : Space3D; x, y, z : integer) return real is
variable sum : real := 0.0;
variable count : integer := 0;
begin
for dx in -1 to 1 loop
for dy in -1 to 1 loop
for dz in -1 to 1 loop
if x+dx >= 0 and x+dx < X_SIZE and
y+dy >= 0 and y+dy < Y_SIZE and
z+dz >= 0 and z+dz < Z_SIZE then
sum := sum + prev(x+dx, y+dy, z+dz);
count := count + 1;
end if;
end loop;
end loop;
end loop;
return sum / real(count);
end function;
begin
process
variable rand : real;
begin
-- 初期温度の設定(ランダム)
for x in 0 to X_SIZE-1 loop
for y in 0 to Y_SIZE-1 loop
for z in 0 to Z_SIZE-1 loop
uniform(seed1 => 5, seed2 => 10, x => rand);
temperature(0)(x, y, z) <= rand * 100.0;
end loop;
end loop;
end loop;
-- 熱拡散シミュレーション
for t in 1 to TIME_STEPS-1 loop
for x in 0 to X_SIZE-1 loop
for y in 0 to Y_SIZE-1 loop
for z in 0 to Z_SIZE-1 loop
temperature(t)(x, y, z) <= heat_diffusion(temperature(t-1), x, y, z);
end loop;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
for t in 0 to TIME_STEPS-1 loop
report "Time step " & integer'image(t) & ", Temperature at (0,0,0): " &
real'image(temperature(t)(0, 0, 0));
end loop;
wait;
end process;
end Behavioral;
実行結果
# KERNEL: Time step 0, Temperature at (0,0,0): 6.707350611686707E+01
# KERNEL: Time step 1, Temperature at (0,0,0): 6.340938806533813E+01
# KERNEL: Time step 2, Temperature at (0,0,0): 6.063985228538513E+01
# KERNEL: Time step 3, Temperature at (0,0,0): 5.857684612274170E+01
# KERNEL: Time step 4, Temperature at (0,0,0): 5.706745147705078E+01
-- VHDL側のコード
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity VHDLModule is
port (
clk : in std_logic;
data_out : out std_logic_vector(7 downto 0)
);
end VHDLModule;
architecture Behavioral of VHDLModule is
type ThreeDArray is array (0 to 1, 0 to 2, 0 to 1) of integer range 0 to 255;
signal my_array : ThreeDArray := (
((10, 20), (30, 40), (50, 60)),
((70, 80), (90, 100), (110, 120))
);
signal counter : integer range 0 to 11 := 0;
begin
process(clk)
begin
if rising_edge(clk) then
data_out <= std_logic_vector(to_unsigned(
my_array(counter / 6, (counter / 2) mod 3, counter mod 2), 8));
if counter = 11 then
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
end Behavioral;
// SystemVerilog側のコード
module SystemVerilogModule (
input logic clk,
input logic [7:0] data_in
);
logic [7:0] sv_array [2][3][2];
int counter = 0;
always_ff @(posedge clk) begin
sv_array[counter / 6][(counter / 2) % 3][counter % 2] = data_in;
if (counter == 11) begin
counter = 0;
// ここで全データが受信完了
$display("Received 3D array:");
for (int i = 0; i < 2; i++) begin
for (int j = 0; j < 3; j++) begin
for (int k = 0; k < 2; k++) begin
$display("sv_array[%0d][%0d][%0d] = %0d", i, j, k, sv_array[i][j][k]);
end
end
end
end else begin
counter = counter + 1;
end
end
endmodule
-- VHDL側のコード
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity VHDLProcessor is
port (
clk : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
process_enable : in std_logic;
process_done : out std_logic
);
end VHDLProcessor;
architecture Behavioral of VHDLProcessor is
type ThreeDArray is array (0 to 1, 0 to 2, 0 to 1) of integer range 0 to 255;
signal input_array, output_array : ThreeDArray;
signal process_state : integer range 0 to 2 := 0;
signal counter : integer range 0 to 11 := 0;
begin
process(clk)
begin
if rising_edge(clk) then
case process_state is
when 0 => -- 入力データの受信
if process_enable = '1' then
input_array(counter / 6, (counter / 2) mod 3, counter mod 2)
<= to_integer(unsigned(data_in));
if counter = 11 then
counter <= 0;
process_state <= 1;
else
counter <= counter + 1;
end if;
end if;
when 1 => -- データ処理(ここでは単純に2倍)
for i in 0 to 1 loop
for j in 0 to 2 loop
for k in 0 to 1 loop
output_array(i, j, k) <= input_array(i, j, k) * 2;
if output_array(i, j, k) > 255 then
output_array(i, j, k) <= 255;
end if;
end loop;
end loop;
end loop;
process_state <= 2;
counter <= 0;
when 2 => -- 出力データの送信
data_out <= std_logic_vector(to_unsigned(
output_array(counter / 6, (counter / 2) mod 3, counter mod 2), 8));
if counter = 11 then
counter <= 0;
process_state <= 0;
process_done <= '1';
else
counter <= counter + 1;
process_done <= '0';
end if;
end case;
end if;
end process;
end Behavioral;
// SystemVerilog側のコード
module SystemVerilogController (
input logic clk,
output logic [7:0] data_to_vhdl,
input logic [7:0] data_from_vhdl,
output logic process_enable,
input logic process_done
);
logic [7:0] input_data [2][3][2];
logic [7:0] output_data [2][3][2];
int state = 0;
int counter = 0;
initial begin
// テストデータの初期化
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
for (int k = 0; k < 2; k++)
input_data[i][j][k] = i * 36 + j * 12 + k * 6 + 10;
end
always_ff @(posedge clk) begin
case (state)
0: begin // VHDLモジュールにデータを送信
data_to_vhdl = input_data[counter / 6][(counter / 2) % 3][counter % 2];
process_enable = 1;
if (counter == 11) begin
counter = 0;
state = 1;
end else begin
counter = counter + 1;
end
end
1: begin // 処理の完了を待つ
process_enable = 0;
if (process_done) begin
state = 2;
counter = 0;
end
end
2: begin // 処理結果を受信
output_data[counter / 6][(counter / 2) % 3][counter % 2] = data_from_vhdl;
if (counter == 11) begin
counter = 0;
state = 3;
end else begin
counter = counter + 1;
end
end
3: begin // 結果の表示と終了
$display("Processing complete. Results:");
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
for (int k = 0; k < 2; k++)
$display("output_data[%0d][%0d][%0d] = %0d", i, j, k, output_data[i][j][k]);
$finish;
end
endcase
end
endmodule
-- VHDL側のコード
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity VHDLDataProcessor is
generic (
WIDTH : integer := 8;
HEIGHT : integer := 8;
DEPTH : integer := 4
);
port (
clk : in std_logic;
reset : in std_logic;
start : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
addr_x : in integer range 0 to WIDTH-1;
addr_y : in integer range 0 to HEIGHT-1;
addr_z : in integer range 0 to DEPTH-1;
write_enable : in std_logic;
read_enable : in std_logic;
busy : out std_logic;
done : out std_logic
);
end VHDLDataProcessor;
architecture Behavioral of VHDLDataProcessor is
type DataArray is array (0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1) of unsigned(7 downto 0);
signal data_storage : DataArray;
type StateType is (IDLE, RECEIVING, PROCESSING, SENDING);
signal state : StateType := IDLE;
begin
process(clk, reset)
begin
if reset = '1' then
state <= IDLE;
busy <= '0';
done <= '0';
elsif rising_edge(clk) then
case state is
when IDLE =>
if start = '1' then
state <= RECEIVING;
busy <= '1';
done <= '0';
end if;
when RECEIVING =>
if write_enable = '1' then
data_storage(addr_z, addr_y, addr_x) <= unsigned(data_in);
end if;
if addr_z = DEPTH-1 and addr_y = HEIGHT-1 and addr_x = WIDTH-1 then
state <= PROCESSING;
end if;
when PROCESSING =>
-- 簡単な処理例:全要素に1を加算
for z in 0 to DEPTH-1 loop
for y in 0 to HEIGHT-1 loop
for x in 0 to WIDTH-1 loop
if data_storage(z, y, x) < 255 then
data_storage(z, y, x) <= data_storage(z, y, x) + 1;
end if;
end loop;
end loop;
end loop;
state <= SENDING;
when SENDING =>
if read_enable = '1' then
data_out <= std_logic_vector(data_storage(addr_z, addr_y, addr_x));
end if;
if addr_z = DEPTH-1 and addr_y = HEIGHT-1 and addr_x = WIDTH-1 then
state <= IDLE;
busy <= '0';
done <= '1';
end if;
end case;
end if;
end process;
end Behavioral;
// SystemVerilog側のコード
module SystemVerilogController #(
parameter WIDTH = 8,
parameter HEIGHT = 8,
parameter DEPTH = 4
) (
input logic clk,
input logic reset,
output logic start,
output logic [7:0] data_to_vhdl,
input logic [7:0] data_from_vhdl,
output logic [$clog2(WIDTH)-1:0] addr_x,
output logic [$clog2(HEIGHT)-1:0] addr_y,
output logic [$clog2(DEPTH)-1:0] addr_z,
output logic write_enable,
output logic read_enable,
input logic busy,
input logic done
);
typedef enum {INIT, SEND_DATA, WAIT_PROCESS, RECEIVE_DATA, FINISH} StateType;
StateType state;
logic [7:0] data_storage [DEPTH][HEIGHT][WIDTH];
int x, y, z;
always_ff @(posedge clk or posedge reset) begin
if (reset) begin
state <= INIT;
start <= 0;
write_enable <= 0;
read_enable <= 0;
x <= 0;
y <= 0;
z <= 0;
end else begin
case (state)
INIT: begin
// データの初期化
for (int i = 0; i < DEPTH; i++)
for (int j = 0; j < HEIGHT; j++)
for (int k = 0; k < WIDTH; k++)
data_storage[i][j][k] = i * 50 + j * 5 + k;
state <= SEND_DATA;
start <= 1;
end
SEND_DATA: begin
start <= 0;
if (!busy) begin
data_to_vhdl = data_storage[z][y][x];
addr_x = x;
addr_y = y;
addr_z = z;
write_enable = 1;
if (x == WIDTH-1 && y == HEIGHT-1 && z == DEPTH-1) begin
state <= WAIT_PROCESS;
end else begin
if (x == WIDTH-1) begin
x <= 0;
if (y == HEIGHT-1) begin
y <= 0;
z <= z + 1;
end else begin
y <= y + 1;
end
end else begin
x <= x + 1;
end
end
end
end
WAIT_PROCESS: begin
write_enable <= 0;
if (done) begin
state <= RECEIVE_DATA;
x <= 0;
y <= 0;
z <= 0;
end
end
RECEIVE_DATA: begin
read_enable <= 1;
addr_x = x;
addr_y = y;
addr_z = z;
data_storage[z][y][x] = data_from_vhdl;
if (x == WIDTH-1 && y == HEIGHT-1 && z == DEPTH-1) begin
state <= FINISH;
end else begin
if (x == WIDTH-1) begin
x <= 0;
if (y == HEIGHT-1) begin
y <= 0;
z <= z + 1;
end else begin
y <= y + 1;
end
end else begin
x <= x + 1;
end
end
end
FINISH: begin
read_enable <= 0;
// 結果の表示
$display("Processing complete. Sample results:");
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
$display("data_storage[%0d][%0d][%0d] = %0d", i, j, k, data_storage[i][j][k]);
$finish;
end
endcase
end
end
endmodule
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package CustomArrayTypes is
type Integer3D is array (natural range <>, natural range <>, natural range <>) of integer;
type Real3D is array (natural range <>, natural range <>, natural range <>) of real;
type StdLogicVector3D is array (natural range <>, natural range <>, natural range <>) of std_logic_vector;
function sum_3d_integer(arr : Integer3D) return integer;
function average_3d_real(arr : Real3D) return real;
end package CustomArrayTypes;
package body CustomArrayTypes is
function sum_3d_integer(arr : Integer3D) return integer is
variable total : integer := 0;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
total := total + arr(i, j, k);
end loop;
end loop;
end loop;
return total;
end function;
function average_3d_real(arr : Real3D) return real is
variable total : real := 0.0;
variable count : integer := 0;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
total := total + arr(i, j, k);
count := count + 1;
end loop;
end loop;
end loop;
return total / real(count);
end function;
end package body CustomArrayTypes;
-- 使用例
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.CustomArrayTypes.all;
entity ArrayTypeExample is
end ArrayTypeExample;
architecture Behavioral of ArrayTypeExample is
signal int_array : Integer3D(0 to 1, 0 to 2, 0 to 1) := (((1, 2), (3, 4), (5, 6)), ((7, 8), (9, 10), (11, 12)));
signal real_array : Real3D(0 to 1, 0 to 2, 0 to 1) := (((1.0, 2.0), (3.0, 4.0), (5.0, 6.0)), ((7.0, 8.0), (9.0, 10.0), (11.0, 12.0)));
begin
process
begin
report "Sum of integer array: " & integer'image(sum_3d_integer(int_array));
report "Average of real array: " & real'image(average_3d_real(real_array));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package Array3DOperations is
type Integer3D is array (natural range <>, natural range <>, natural range <>) of integer;
function map3D(func : function(integer return integer); arr : Integer3D) return Integer3D;
function filter3D(pred : function(integer return boolean); arr : Integer3D) return Integer3D;
function reduce3D(func : function(integer, integer return integer); arr : Integer3D; initial : integer) return integer;
function add_constant(x : integer) return integer;
function is_even(x : integer) return boolean;
function max_func(a, b : integer) return integer;
end package Array3DOperations;
package body Array3DOperations is
function map3D(func : function(integer return integer); arr : Integer3D) return Integer3D is
variable result : Integer3D(arr'range(1), arr'range(2), arr'range(3));
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
result(i, j, k) := func(arr(i, j, k));
end loop;
end loop;
end loop;
return result;
end function;
function filter3D(pred : function(integer return boolean); arr : Integer3D) return Integer3D is
variable result : Integer3D(arr'range(1), arr'range(2), arr'range(3));
variable count : integer := 0;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
if pred(arr(i, j, k)) then
result(count / (arr'length(2) * arr'length(3)),
(count / arr'length(3)) mod arr'length(2),
count mod arr'length(3)) := arr(i, j, k);
count := count + 1;
end if;
end loop;
end loop;
end loop;
return result(0 to (count-1) / (arr'length(2) * arr'length(3)),
0 to arr'length(2) - 1,
0 to arr'length(3) - 1);
end function;
function reduce3D(func : function(integer, integer return integer); arr : Integer3D; initial : integer) return integer is
variable result : integer := initial;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
result := func(result, arr(i, j, k));
end loop;
end loop;
end loop;
return result;
end function;
function add_constant(x : integer) return integer is
begin
return x + 10;
end function;
function is_even(x : integer) return boolean is
begin
return (x mod 2) = 0;
end function;
function max_func(a, b : integer) return integer is
begin
if a > b then
return a;
else
return b;
end if;
end function;
end package body Array3DOperations;
-- 使用例
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.Array3DOperations.all;
entity ArrayOperationsExample is
end ArrayOperationsExample;
architecture Behavioral of ArrayOperationsExample is
signal input_array : Integer3D(0 to 1, 0 to 2, 0 to 1) := (((1, 2), (3, 4), (5, 6)), ((7, 8), (9, 10), (11, 12)));
signal mapped_array : Integer3D(0 to 1, 0 to 2, 0 to 1);
signal filtered_array : Integer3D(0 to 1, 0 to 2, 0 to 1);
signal max_value : integer;
begin
process
begin
mapped_array <= map3D(add_constant'access, input_array);
filtered_array <= filter3D(is_even'access, input_array);
max_value <= reduce3D(max_func'access, input_array, integer'low);
wait for 10 ns;
for i in mapped_array'range(1) loop
for j in mapped_array'range(2) loop
for k in mapped_array'range(3) loop
report "Mapped value at (" & integer'image(i) & "," & integer'image(j) & "," & integer'image(k) & "): " &
integer'image(mapped_array(i, j, k));
end loop;
end loop;
end loop;
for i in filtered_array'range(1) loop
for j in filtered_array'range(2) loop
for k in filtered_array'range(3) loop
report "Filtered value at (" & integer'image(i) & "," & integer'image(j) & "," & integer'image(k) & "): " &
integer'image(filtered_array(i, j, k));
end loop;
end loop;
end loop;
report "Maximum value: " & integer'image(max_value);
wait;
end process;
end Behavioral;
# KERNEL: Mapped value at (0,0,0): 11
# KERNEL: Mapped value at (0,0,1): 12
# KERNEL: Mapped value at (0,1,0): 13
# KERNEL: Mapped value at (0,1,1): 14
# KERNEL: Mapped value at (0,2,0): 15
# KERNEL: Mapped value at (0,2,1): 16
# KERNEL: Mapped value at (1,0,0): 17
# KERNEL: Mapped value at (1,0,1): 18
# KERNEL: Mapped value at (1,1,0): 19
# KERNEL: Mapped value at (1,1,1): 20
# KERNEL: Mapped value at (1,2,0): 21
# KERNEL: Mapped value at (1,2,1): 22
# KERNEL: Filtered value at (0,0,0): 2
# KERNEL: Filtered value at (0,0,1): 4
# KERNEL: Filtered value at (0,1,0): 6
# KERNEL: Filtered value at (0,1,1): 8
# KERNEL: Filtered value at (0,2,0): 10
# KERNEL: Filtered value at (0,2,1): 12
# KERNEL: Maximum value: 12
汎用性の高い配列操作関数を作成することで、複雑な処理を簡潔に記述できるようになります。
また、関数型プログラミングの概念を取り入れることで、コードの可読性と再利用性が向上します。
○サンプルコード23:パッケージを用いた再利用可能なコード
パッケージを活用することで、プロジェクト全体で一貫した三次元配列の操作方法を実装できます。
次のサンプルコードでは、三次元画像処理のための再利用可能なパッケージを作成しています。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package Image3DProcessing is
type Pixel is record
r, g, b : unsigned(7 downto 0);
end record;
type Image3D is array (natural range <>, natural range <>, natural range <>) of Pixel;
function grayscale(img : Image3D) return Image3D;
function brightness_adjust(img : Image3D; factor : real) return Image3D;
function edge_detect(img : Image3D) return Image3D;
end package Image3DProcessing;
package body Image3DProcessing is
function grayscale(img : Image3D) return Image3D is
variable result : Image3D(img'range(1), img'range(2), img'range(3));
variable gray : unsigned(7 downto 0);
begin
for i in img'range(1) loop
for j in img'range(2) loop
for k in img'range(3) loop
gray := shift_right(("00" & img(i, j, k).r) +
("00" & img(i, j, k).g) +
("00" & img(i, j, k).b), 2);
result(i, j, k).r := gray;
result(i, j, k).g := gray;
result(i, j, k).b := gray;
end loop;
end loop;
end loop;
return result;
end function;
function brightness_adjust(img : Image3D; factor : real) return Image3D is
variable result : Image3D(img'range(1), img'range(2), img'range(3));
variable adjusted : integer;
begin
for i in img'range(1) loop
for j in img'range(2) loop
for k in img'range(3) loop
adjusted := integer(real(to_integer(img(i, j, k).r)) * factor);
result(i, j, k).r := to_unsigned(adjusted when adjusted < 256 else 255, 8);
adjusted := integer(real(to_integer(img(i, j, k).g)) * factor);
result(i, j, k).g := to_unsigned(adjusted when adjusted < 256 else 255, 8);
adjusted := integer(real(to_integer(img(i, j, k).b)) * factor);
result(i, j, k).b := to_unsigned(adjusted when adjusted < 256 else 255, 8);
end loop;
end loop;
end loop;
return result;
end function;
function edge_detect(img : Image3D) return Image3D is
variable result : Image3D(img'range(1), img'range(2), img'range(3));
variable diff_x, diff_y, diff_z : integer;
begin
for i in img'range(1) loop
for j in img'range(2) loop
for k in img'range(3) loop
if i > img'low(1) and j > img'low(2) and k > img'low(3) then
diff_x := abs(to_integer(img(i, j, k).r) - to_integer(img(i-1, j, k).r));
diff_y := abs(to_integer(img(i, j, k).r) - to_integer(img(i, j-1, k).r));
diff_z := abs(to_integer(img(i, j, k).r) - to_integer(img(i, j, k-1).r));
result(i, j, k).r := to_unsigned(diff_x + diff_y + diff_z, 8);
result(i, j, k).g := result(i, j, k).r;
result(i, j, k).b := result(i, j, k).r;
else
result(i, j, k) := (others => (others => '0'));
end if;
end loop;
end loop;
end loop;
return result;
end function;
end package body Image3DProcessing;
-- 使用例
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.Image3DProcessing.all;
entity ImageProcessingExample is
end ImageProcessingExample;
architecture Behavioral of ImageProcessingExample is
constant WIDTH : integer := 3;
constant HEIGHT : integer := 3;
constant DEPTH : integer := 3;
signal input_image : Image3D(0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1);
signal gray_image : Image3D(0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1);
signal bright_image : Image3D(0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1);
signal edge_image : Image3D(0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1);
begin
process
begin
-- 入力画像の初期化
for i in 0 to DEPTH-1 loop
for j in 0 to HEIGHT-1 loop
for k in 0 to WIDTH-1 loop
input_image(i, j, k).r := to_unsigned(i * 50 + j * 20 + k * 10, 8);
input_image(i, j, k).g := to_unsigned(i * 40 + j * 30 + k * 15, 8);
input_image(i, j, k).b := to_unsigned(i * 30 + j * 40 + k * 20, 8);
end loop;
end loop;
end loop;
-- 画像処理の適用
gray_image <= grayscale(input_image);
bright_image <= brightness_adjust(input_image, 1.5);
edge_image <= edge_detect(input_image);
wait for 10 ns;
-- 結果の一部を表示
report "Original image at (0,0,0): R=" & integer'image(to_integer(input_image(0,0,0).r)) &
", G=" & integer'image(to_integer(input_image(0,0,0).g)) &
", B=" & integer'image(to_integer(input_image(0,0,0).b));
report "Grayscale image at (0,0,0): R=" & integer'image(to_integer(gray_image(0,0,0).r)) &
", G=" & integer'image(to_integer(gray_image(0,0,0).g)) &
", B=" & integer'image(to_integer(gray_image(0,0,0).b));
report "Brightness adjusted image at (0,0,0): R=" & integer'image(to_integer(bright_image(0,0,0).r)) &
", G=" & integer'image(to_integer(bright_image(0,0,0).g)) &
", B=" & integer'image(to_integer(bright_image(0,0,0).b));
report "Edge detected image at (1,1,1): R=" & integer'image(to_integer(edge_image(1,1,1).r)) &
", G=" & integer'image(to_integer(edge_image(1,1,1).g)) &
", B=" & integer'image(to_integer(edge_image(1,1,1).b));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity ArrayBoundaryCheck is
end ArrayBoundaryCheck;
architecture Behavioral of ArrayBoundaryCheck is
type Integer3D is array (0 to 3, 0 to 3, 0 to 3) of integer;
signal my_array : Integer3D;
function safe_access(arr : Integer3D; x, y, z : integer) return integer is
begin
if x >= arr'low(1) and x <= arr'high(1) and
y >= arr'low(2) and y <= arr'high(2) and
z >= arr'low(3) and z <= arr'high(3) then
return arr(x, y, z);
else
report "Array index out of bounds: (" & integer'image(x) & "," &
integer'image(y) & "," & integer'image(z) & ")" severity warning;
return 0; -- デフォルト値を返す
end if;
end function;
begin
process
variable x, y, z : integer;
begin
-- 配列の初期化
for i in my_array'range(1) loop
for j in my_array'range(2) loop
for k in my_array'range(3) loop
my_array(i, j, k) <= i * 100 + j * 10 + k;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 安全なアクセス
x := 2; y := 2; z := 2;
report "Safe access (2,2,2): " & integer'image(safe_access(my_array, x, y, z));
-- 境界外アクセス
x := 4; y := 2; z := 2;
report "Unsafe access (4,2,2): " & integer'image(safe_access(my_array, x, y, z));
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity TypeMismatchResolution is
end TypeMismatchResolution;
architecture Behavioral of TypeMismatchResolution is
type UnsignedArray is array (0 to 2, 0 to 2, 0 to 2) of unsigned(7 downto 0);
type IntegerArray is array (0 to 2, 0 to 2, 0 to 2) of integer;
signal unsigned_arr : UnsignedArray;
signal integer_arr : IntegerArray;
function convert_to_integer(u_arr : UnsignedArray) return IntegerArray is
variable result : IntegerArray;
begin
for i in u_arr'range(1) loop
for j in u_arr'range(2) loop
for k in u_arr'range(3) loop
result(i, j, k) := to_integer(u_arr(i, j, k));
end loop;
end loop;
end loop;
return result;
end function;
function convert_to_unsigned(i_arr : IntegerArray) return UnsignedArray is
variable result : UnsignedArray;
begin
for i in i_arr'range(1) loop
for j in i_arr'range(2) loop
for k in i_arr'range(3) loop
result(i, j, k) := to_unsigned(i_arr(i, j, k), 8);
end loop;
end loop;
end loop;
return result;
end function;
begin
process
begin
-- unsigned_arrの初期化
for i in unsigned_arr'range(1) loop
for j in unsigned_arr'range(2) loop
for k in unsigned_arr'range(3) loop
unsigned_arr(i, j, k) <= to_unsigned(i * 100 + j * 10 + k, 8);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 型変換: unsigned -> integer
integer_arr <= convert_to_integer(unsigned_arr);
wait for 10 ns;
-- 結果の表示
for i in integer_arr'range(1) loop
for j in integer_arr'range(2) loop
for k in integer_arr'range(3) loop
report "integer_arr(" & integer'image(i) & "," & integer'image(j) & "," &
integer'image(k) & ") = " & integer'image(integer_arr(i, j, k));
end loop;
end loop;
end loop;
-- 型変換: integer -> unsigned
unsigned_arr <= convert_to_unsigned(integer_arr);
wait for 10 ns;
-- 結果の表示
for i in unsigned_arr'range(1) loop
for j in unsigned_arr'range(2) loop
for k in unsigned_arr'range(3) loop
report "unsigned_arr(" & integer'image(i) & "," & integer'image(j) & "," &
integer'image(k) & ") = " & integer'image(to_integer(unsigned_arr(i, j, k)));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use STD.TEXTIO.ALL;
entity MemoryOptimizationExample is
generic (
WIDTH : integer := 100;
HEIGHT : integer := 100;
DEPTH : integer := 100
);
end MemoryOptimizationExample;
architecture Behavioral of MemoryOptimizationExample is
type SmallArray is array (0 to 9) of integer;
type LargeArray is array (0 to WIDTH-1, 0 to HEIGHT-1, 0 to DEPTH-1) of integer;
-- 大規模配列をファイルに格納する関数
procedure store_array_to_file(arr : LargeArray; filename : string) is
file data_file : text open write_mode is filename;
variable row : line;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
write(row, arr(i, j, k));
writeline(data_file, row);
end loop;
end loop;
end loop;
end procedure;
-- ファイルから大規模配列を読み込む関数
procedure load_array_from_file(filename : string; arr : out LargeArray) is
file data_file : text open read_mode is filename;
variable row : line;
variable data : integer;
begin
for i in arr'range(1) loop
for j in arr'range(2) loop
for k in arr'range(3) loop
readline(data_file, row);
read(row, data);
arr(i, j, k) := data;
end loop;
end loop;
end loop;
end procedure;
-- 部分配列を処理する関数
function process_subarray(sub_arr : SmallArray) return SmallArray is
variable result : SmallArray;
begin
for i in sub_arr'range loop
result(i) := sub_arr(i) * 2; -- 簡単な処理例:各要素を2倍にする
end loop;
return result;
end function;
signal small_array : SmallArray;
signal processed_array : SmallArray;
begin
process
variable large_array : LargeArray;
variable sub_array : SmallArray;
variable total_sum : integer := 0;
begin
-- 大規模配列の初期化とファイルへの保存
for i in large_array'range(1) loop
for j in large_array'range(2) loop
for k in large_array'range(3) loop
large_array(i, j, k) := i * 10000 + j * 100 + k;
end loop;
end loop;
end loop;
store_array_to_file(large_array, "large_array_data.txt");
-- メモリを解放
large_array := (others => (others => (others => 0)));
-- ファイルからデータを読み込んで処理
load_array_from_file("large_array_data.txt", large_array);
-- 部分的に処理
for i in 0 to WIDTH-1 loop
for j in 0 to HEIGHT-1 loop
for k in 0 to DEPTH-1 / 10 loop
for l in 0 to 9 loop
sub_array(l) := large_array(i, j, k * 10 + l);
end loop;
processed_array <= process_subarray(sub_array);
wait for 1 ns; -- シミュレーションの進行を確認するため
-- 処理結果の集計
for l in 0 to 9 loop
total_sum := total_sum + processed_array(l);
end loop;
end loop;
end loop;
end loop;
report "Total sum of processed array: " & integer'image(total_sum);
wait;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Image3DFilter is
generic (
WIDTH : integer := 64;
HEIGHT : integer := 64;
DEPTH : integer := 64
);
end Image3DFilter;
architecture Behavioral of Image3DFilter is
type Image3D is array (0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1) of unsigned(7 downto 0);
signal input_image, output_image : Image3D;
function apply_3d_filter(img : Image3D; x, y, z : integer) return unsigned is
variable sum : unsigned(10 downto 0) := (others => '0');
variable count : integer := 0;
begin
for i in -1 to 1 loop
for j in -1 to 1 loop
for k in -1 to 1 loop
if (x+i >= 0 and x+i < DEPTH) and
(y+j >= 0 and y+j < HEIGHT) and
(z+k >= 0 and z+k < WIDTH) then
sum := sum + img(x+i, y+j, z+k);
count := count + 1;
end if;
end loop;
end loop;
end loop;
return sum / count;
end function;
begin
process
begin
-- 入力画像の初期化(ここでは簡単な勾配を生成)
for i in 0 to DEPTH-1 loop
for j in 0 to HEIGHT-1 loop
for k in 0 to WIDTH-1 loop
input_image(i, j, k) <= to_unsigned((i + j + k) mod 256, 8);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 3Dフィルタの適用
for i in 0 to DEPTH-1 loop
for j in 0 to HEIGHT-1 loop
for k in 0 to WIDTH-1 loop
output_image(i, j, k) <= apply_3d_filter(input_image, i, j, k);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
for i in 0 to 2 loop
for j in 0 to 2 loop
for k in 0 to 2 loop
report "Filtered value at (" & integer'image(i) & "," &
integer'image(j) & "," & integer'image(k) & "): " &
integer'image(to_integer(output_image(i, j, k)));
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
このコードでは、3x3x3の平均フィルタを3D画像に適用しています。
各ピクセルの値を、周囲27個のピクセル(自身を含む)の平均値で置き換えます。
フィルタリング処理により、ノイズの軽減や画像の平滑化が行われます。
実行結果
# KERNEL: Filtered value at (0,0,0): 0
# KERNEL: Filtered value at (0,0,1): 0
# KERNEL: Filtered value at (0,0,2): 1
# KERNEL: Filtered value at (0,1,0): 0
# KERNEL: Filtered value at (0,1,1): 1
# KERNEL: Filtered value at (0,1,2): 1
# KERNEL: Filtered value at (0,2,0): 1
# KERNEL: Filtered value at (0,2,1): 1
# KERNEL: Filtered value at (0,2,2): 2
# KERNEL: Filtered value at (1,0,0): 0
# KERNEL: Filtered value at (1,0,1): 1
# KERNEL: Filtered value at (1,0,2): 1
# KERNEL: Filtered value at (1,1,0): 1
# KERNEL: Filtered value at (1,1,1): 1
# KERNEL: Filtered value at (1,1,2): 2
# KERNEL: Filtered value at (1,2,0): 1
# KERNEL: Filtered value at (1,2,1): 2
# KERNEL: Filtered value at (1,2,2): 2
# KERNEL: Filtered value at (2,0,0): 1
# KERNEL: Filtered value at (2,0,1): 1
# KERNEL: Filtered value at (2,0,2): 2
# KERNEL: Filtered value at (2,1,0): 1
# KERNEL: Filtered value at (2,1,1): 2
# KERNEL: Filtered value at (2,1,2): 2
# KERNEL: Filtered value at (2,2,0): 2
# KERNEL: Filtered value at (2,2,1): 2
# KERNEL: Filtered value at (2,2,2): 3
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity FrequencyAnalysis3D is
generic (
N : integer := 8 -- 各次元のサイズ
);
end FrequencyAnalysis3D;
architecture Behavioral of FrequencyAnalysis3D is
type Real3D is array (0 to N-1, 0 to N-1, 0 to N-1) of real;
type Complex is record
re : real;
im : real;
end record;
type Complex3D is array (0 to N-1, 0 to N-1, 0 to N-1) of Complex;
signal input_signal : Real3D;
signal output_spectrum : Complex3D;
function dft_3d(signal_in : Real3D; u, v, w : integer) return Complex is
variable result : Complex := (re => 0.0, im => 0.0);
variable theta : real;
begin
for x in 0 to N-1 loop
for y in 0 to N-1 loop
for z in 0 to N-1 loop
theta := -2.0 * MATH_PI * (real(u*x + v*y + w*z) / real(N));
result.re := result.re + signal_in(x, y, z) * cos(theta);
result.im := result.im + signal_in(x, y, z) * sin(theta);
end loop;
end loop;
end loop;
return result;
end function;
begin
process
variable magnitude : real;
begin
-- 入力信号の初期化(簡単な3D正弦波)
for x in 0 to N-1 loop
for y in 0 to N-1 loop
for z in 0 to N-1 loop
input_signal(x, y, z) <= sin(2.0 * MATH_PI * real(x) / real(N)) *
sin(2.0 * MATH_PI * real(y) / real(N)) *
sin(2.0 * MATH_PI * real(z) / real(N));
end loop;
end loop;
end loop;
wait for 10 ns;
-- 3D DFTの計算
for u in 0 to N-1 loop
for v in 0 to N-1 loop
for w in 0 to N-1 loop
output_spectrum(u, v, w) <= dft_3d(input_signal, u, v, w);
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
for u in 0 to 1 loop
for v in 0 to 1 loop
for w in 0 to 1 loop
magnitude := sqrt(output_spectrum(u, v, w).re**2 + output_spectrum(u, v, w).im**2);
report "Magnitude at (" & integer'image(u) & "," &
integer'image(v) & "," & integer'image(w) & "): " &
real'image(magnitude);
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;
このコードでは、3次元の離散フーリエ変換を実装しています。
入力信号として3D正弦波を生成し、それをフーリエ変換して周波数スペクトルを得ています。
結果として、各周波数成分の振幅(マグニチュード)を計算しています。
実行結果
# KERNEL: Magnitude at (0,0,0): 0.000000000000000E+00
# KERNEL: Magnitude at (0,0,1): 2.828427124746190E+00
# KERNEL: Magnitude at (0,1,0): 2.828427124746190E+00
# KERNEL: Magnitude at (0,1,1): 0.000000000000000E+00
# KERNEL: Magnitude at (1,0,0): 2.828427124746190E+00
# KERNEL: Magnitude at (1,0,1): 0.000000000000000E+00
# KERNEL: Magnitude at (1,1,0): 0.000000000000000E+00
# KERNEL: Magnitude at (1,1,1): 2.828427124746190E+00
多次元信号の周波数解析は、複雑な波形や空間パターンを理解するのに役立ちます。
例えば、地震データの解析では、地下構造を推定するために3D周波数解析が用いられます。
VHDLを使用することで、このような計算集約型の処理をハードウェアで効率的に実行できます。
○サンプルコード26:三次元空間における物体追跡
三次元空間での物体追跡は、自動運転車や監視システムなどで重要な役割を果たします。
ここでは、簡単な3D物体追跡アルゴリズムをVHDLで実装してみましょう。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity ObjectTracking3D is
generic (
SPACE_SIZE : integer := 10; -- 空間の大きさ
MAX_OBJECTS : integer := 5 -- 追跡する最大オブジェクト数
);
end ObjectTracking3D;
architecture Behavioral of ObjectTracking3D is
type Position is record
x, y, z : integer;
end record;
type ObjectArray is array (0 to MAX_OBJECTS-1) of Position;
type Space3D is array (0 to SPACE_SIZE-1, 0 to SPACE_SIZE-1, 0 to SPACE_SIZE-1) of boolean;
signal current_space : Space3D;
signal previous_space : Space3D;
signal tracked_objects : ObjectArray;
function find_nearest_object(pos : Position; prev_objects : ObjectArray) return integer is
variable min_dist : real := real'high;
variable min_index : integer := -1;
variable dist : real;
begin
for i in 0 to MAX_OBJECTS-1 loop
dist := sqrt(real((pos.x - prev_objects(i).x)**2 +
(pos.y - prev_objects(i).y)**2 +
(pos.z - prev_objects(i).z)**2));
if dist < min_dist then
min_dist := dist;
min_index := i;
end if;
end loop;
return min_index;
end function;
begin
process
variable new_objects : ObjectArray;
variable object_count : integer := 0;
variable nearest_index : integer;
begin
-- 初期状態の設定
for i in 0 to MAX_OBJECTS-1 loop
tracked_objects(i) <= (x => i, y => i, z => i);
end loop;
wait for 10 ns;
-- 新しい空間状態の生成(ランダムに物体を配置)
for x in 0 to SPACE_SIZE-1 loop
for y in 0 to SPACE_SIZE-1 loop
for z in 0 to SPACE_SIZE-1 loop
if (x + y + z) mod 7 = 0 then -- 単純化のため、規則的に配置
current_space(x, y, z) <= true;
else
current_space(x, y, z) <= false;
end if;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 物体追跡
object_count := 0;
for x in 0 to SPACE_SIZE-1 loop
for y in 0 to SPACE_SIZE-1 loop
for z in 0 to SPACE_SIZE-1 loop
if current_space(x, y, z) = true and object_count < MAX_OBJECTS then
nearest_index := find_nearest_object((x, y, z), tracked_objects);
new_objects(object_count) := (x, y, z);
report "Object " & integer'image(nearest_index) & " moved to (" &
integer'image(x) & "," & integer'image(y) & "," & integer'image(z) & ")";
object_count := object_count + 1;
end if;
end loop;
end loop;
end loop;
-- 追跡結果の更新
for i in 0 to MAX_OBJECTS-1 loop
if i < object_count then
tracked_objects(i) <= new_objects(i);
else
tracked_objects(i) <= (x => -1, y => -1, z => -1); -- 無効な位置
end if;
end loop;
wait;
end process;
end Behavioral;
# KERNEL: Object 0 moved to (0,0,0)
# KERNEL: Object 1 moved to (1,3,3)
# KERNEL: Object 2 moved to (2,5,0)
# KERNEL: Object 3 moved to (3,0,4)
# KERNEL: Object 4 moved to (4,2,1)
三次元空間における物体追跡は、複雑な環境下での対象の動きを把握するために重要です。
例えば、自動運転車では周囲の車両や歩行者の動きを追跡し、衝突回避や経路計画に活用します。
VHDLを使用することで、リアルタイムで高速な物体追跡処理を実現できます。
○サンプルコード27:気象データシミュレーション
気象データのシミュレーションは、天気予報や気候変動研究に欠かせません。
ここでは、簡略化された3D気象モデルをVHDLで実装してみましょう。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity WeatherSimulation3D is
generic (
WIDTH : integer := 10;
HEIGHT : integer := 10;
DEPTH : integer := 5;
TIME_STEPS : integer := 10
);
end WeatherSimulation3D;
architecture Behavioral of WeatherSimulation3D is
type WeatherData is record
temperature : real;
humidity : real;
pressure : real;
end record;
type WeatherGrid is array (0 to DEPTH-1, 0 to HEIGHT-1, 0 to WIDTH-1) of WeatherData;
type WeatherHistory is array (0 to TIME_STEPS-1) of WeatherGrid;
signal weather : WeatherHistory;
function update_weather(current : WeatherData; neighbors : WeatherData) return WeatherData is
variable result : WeatherData;
variable temp_diff, humid_diff, press_diff : real;
begin
temp_diff := (neighbors.temperature - current.temperature) * 0.1;
humid_diff := (neighbors.humidity - current.humidity) * 0.05;
press_diff := (neighbors.pressure - current.pressure) * 0.02;
result.temperature := current.temperature + temp_diff;
result.humidity := current.humidity + humid_diff;
result.pressure := current.pressure + press_diff;
return result;
end function;
function average_neighbors(grid : WeatherGrid; x, y, z : integer) return WeatherData is
variable sum : WeatherData := (temperature => 0.0, humidity => 0.0, pressure => 0.0);
variable count : integer := 0;
begin
for dx in -1 to 1 loop
for dy in -1 to 1 loop
for dz in -1 to 1 loop
if x+dx >= 0 and x+dx < DEPTH and
y+dy >= 0 and y+dy < HEIGHT and
z+dz >= 0 and z+dz < WIDTH then
sum.temperature := sum.temperature + grid(x+dx, y+dy, z+dz).temperature;
sum.humidity := sum.humidity + grid(x+dx, y+dy, z+dz).humidity;
sum.pressure := sum.pressure + grid(x+dx, y+dy, z+dz).pressure;
count := count + 1;
end if;
end loop;
end loop;
end loop;
sum.temperature := sum.temperature / real(count);
sum.humidity := sum.humidity / real(count);
sum.pressure := sum.pressure / real(count);
return sum;
end function;
begin
process
variable rand : real;
begin
-- 初期状態の設定
for t in 0 to TIME_STEPS-1 loop
for x in 0 to DEPTH-1 loop
for y in 0 to HEIGHT-1 loop
for z in 0 to WIDTH-1 loop
uniform(seed1 => 1, seed2 => 2, x => rand);
weather(t)(x, y, z).temperature <= 20.0 + rand * 10.0;
uniform(seed1 => 3, seed2 => 4, x => rand);
weather(t)(x, y, z).humidity <= 50.0 + rand * 20.0;
uniform(seed1 => 5, seed2 => 6, x => rand);
weather(t)(x, y, z).pressure <= 1000.0 + rand * 50.0;
end loop;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 気象シミュレーション
for t in 1 to TIME_STEPS-1 loop
for x in 0 to DEPTH-1 loop
for y in 0 to HEIGHT-1 loop
for z in 0 to WIDTH-1 loop
weather(t)(x, y, z) <= update_weather(weather(t-1)(x, y, z),
average_neighbors(weather(t-1), x, y, z));
end loop;
end loop;
end loop;
end loop;
wait for 10 ns;
-- 結果の一部を表示
for t in 0 to TIME_STEPS-1 loop
report "Time step " & integer'image(t) & ":";
report "Temperature at (0,0,0): " & real'image(weather(t)(0, 0, 0).temperature);
report "Humidity at (0,0,0): " & real'image(weather(t)(0, 0, 0).humidity);
report "Pressure at (0,0,0): " & real'image(weather(t)(0, 0, 0).pressure);
end loop;
wait;
end process;
end Behavioral;
このコードでは、三次元格子上で気温、湿度、気圧の変化をシミュレートしています。
各時間ステップで、周囲のセルの平均値に基づいて各セルの値を更新します。
実行結果
# KERNEL: Time step 0:
# KERNEL: Temperature at (0,0,0): 2.682339191436768E+01
# KERNEL: Humidity at (0,0,0): 5.655465126037598E+01
# KERNEL: Pressure at (0,0,0): 1.031453704833984E+03
# KERNEL: Time step 1:
# KERNEL: Temperature at (0,0,0): 2.677570343017578E+01
# KERNEL: Humidity at (0,0,0): 5.656945037841797E+01
# KERNEL: Pressure at (0,0,0): 1.031434326171875E+03
# KERNEL: Time step 2:
# KERNEL: Temperature at (0,0,0): 2.673229598999023E+01
# KERNEL: Humidity at (0,0,0): 5.658305740356445E+01
# KERNEL: Pressure at (0,0,0): 1.031415405273438E+03
# ...(以下、時間ステップ9まで続く)