Реализация искусственных нейронных сетей на языке описания аппаратуры VHDL. Учебное пособие
.pdf
Этап 4. Уточнение параметров функциональной схемы сети (на основе расчета этапа 3) (рис. 6).
Рис. 6. Уточненная функциональная схема сети (примечание: block14 показан на схеме дважды)
Этап 5. Добавление конвейерных регистров в функциональную схему для обеспечения требуемой производительности схемы (рис. 7).
На рис. 7 параметр Lat=n задает количество конвейерных регистров в блоке; примечание: block14 показан на схеме дважды.
На рис. 7 имеют место следующие обозначения: MUL – умножитель;
ADD – сумматор;
COMP – компаратор.
Рис. 7. Функциональная схема сети с учетом конвейерных регистров
Этап 6. Разработка программы.
LIBRARY ieee;
USE ieee.std_logic_1164.all; LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
entity laba1 is Port (
c : in std_logic; -- синхронизация
--x1, x2, x3 – входные сигналы x1:in std_logic_vector (7 downto 0); x2:in std_logic_vector (7 downto 0); x3:in std_logic_vector (7 downto 0);
--w1, w2, w3 – весовые коэффициенты, воздействующие на вход 1-го
--нейрона 1-го слоя
w1:in std_logic_vector (4 downto 0); w2:in std_logic_vector (4 downto 0);
w3:in std_logic_vector (4 downto 0);
--v1, v2, v3 – весовые коэффициенты, воздействующие на вход 2-го нейрона
--2-го слоя
v1:in std_logic_vector (4 downto 0); v2:in std_logic_vector (4 downto 0); v3:in std_logic_vector (4 downto 0);
-- a, b – параметры функции активации 1-го слоя
a:in std_logic_vector (4 downto 0);
b:in std_logic_vector (4 downto 0); -- t1, t2 – выходы нейронов 1-го слоя
t1_o: out std_logic_vector (20 downto 0); t2_o: out std_logic_vector (20 downto 0);
--k1_1, k2_1 - весовые к-ты, действующие на вход 1-го нейрона второго слоя k1_1:in std_logic_vector (4 downto 0);
k2_1:in std_logic_vector (4 downto 0);
--k1_2, k2_2 - весовые к-ты, действующие на вход 2-го нейрона второго слоя k1_2:in std_logic_vector (4 downto 0);
k2_2:in std_logic_vector (4 downto 0);
-- por1, por2 – параметры функции активации 2-го слоя por1: in std_logic_vector (26 downto 0);
por2: in std_logic_vector (26 downto 0); -- f1, f2 – выходы нейронов 2-го слоя f1, f2: out std_logic
);
end laba1;
architecture Behavioral of laba1 is
--s1, s2, s3, s4 – выходы суммирующих устройств нейронов signal S1, S2: std_logic_vector (14 downto 0);
signal S3, S4: std_logic_vector (26 downto 0);
--y1, y2, y3 – произведения w*x
signal y1: std_logic_vector (12 downto 0); signal y2: std_logic_vector (12 downto 0); signal y3: std_logic_vector (12 downto 0); -- p1, p2, p3 – произведения v*x
signal p1: std_logic_vector (12 downto 0); signal p2: std_logic_vector (12 downto 0); signal p3: std_logic_vector (12 downto 0); signal z1, q1: std_logic_vector (13 downto 0); signal y3b, p3b: std_logic_vector (13 downto 0); signal z2, q2, bb: std_logic_vector (19 downto 0); signal t1, t2: std_logic_vector (20 downto 0);
signal m1, m2, m3, m4: std_logic_vector (25 downto 0);
component mul8_5 IS -- компонент умножителя 8 разрядов * 5 разрядов
PORT
(
dataa |
: IN STD_LOGIC_VECTOR (7 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (4 DOWNTO 0); |
result |
: OUT STD_LOGIC_VECTOR (12 DOWNTO 0); |
clock |
: in std_logic |
); |
|
END component; |
|
component add13 -- компонент 13-рязрядного сумматора |
|
PORT |
|
( |
|
dataa |
: IN STD_LOGIC_VECTOR (12 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (12 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (12 DOWNTO 0); |
cout |
: OUT STD_LOGIC |
); |
|
end component; |
|
component add14 -- компонент 14-рязрядного сумматора |
|
PORT |
|
( |
|
dataa |
: IN STD_LOGIC_VECTOR (13 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (13 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (13 DOWNTO 0); |
cout |
: OUT STD_LOGIC |
); |
|
end component; |
|
component mul15_5 -- компонент умножителя 15 разрядов * 5 разрядов
PORT |
|
( |
|
dataa |
: IN STD_LOGIC_VECTOR (14 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (4 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (19 DOWNTO 0) |
); |
|
end component; |
|
component add20 |
|
PORT |
|
( |
|
dataa |
: IN STD_LOGIC_VECTOR (19 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (19 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (19 DOWNTO 0); |
cout |
: OUT STD_LOGIC |
); |
|
end component;
component mul21_5 -- компонент умножителя 21 разрядов * 5 разрядов
PORT
(
dataa |
: IN STD_LOGIC_VECTOR (20 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (4 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (25 DOWNTO 0) |
); |
|
end component; |
|
component add26 -- компонент 26-рязрядного сумматора
PORT
(
dataa |
: IN STD_LOGIC_VECTOR (25 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (25 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
result |
: OUT STD_LOGIC_VECTOR (25 DOWNTO 0); |
cout |
: OUT STD_LOGIC |
); |
|
end component; |
|
component comp_eq27 -- компонент 27-разрядного компаратора на равенство
PORT
(
dataa |
: IN STD_LOGIC_VECTOR (26 DOWNTO 0); |
datab |
: IN STD_LOGIC_VECTOR (26 DOWNTO 0); |
clock |
: IN STD_LOGIC ; |
AgeB |
: OUT STD_LOGIC |
); |
|
end component; |
|
begin
-- block1
block1: mul8_5 PORT MAP( dataa => x1 (7 downto 0), datab => w1 (4 downto 0), clock => c,
result => y1 (12 downto 0)
);
-- block2
block2: mul8_5 PORT MAP( dataa => x2 (7 downto 0), datab => w2 (4 downto 0), clock => c,
result => y2 (12 downto 0)
);
-- block3
block3: mul8_5 PORT MAP( dataa => x3 (7 downto 0), datab => w3 (4 downto 0), clock => c,
result => y3 (12 downto 0)
);
-- block4
block4: mul8_5 PORT MAP( dataa => x1 (7 downto 0), datab => v1 (4 downto 0), clock => c,
result => p1 (12 downto 0)
);
-- block5
block5: mul8_5 PORT MAP( dataa => x2 (7 downto 0), datab => v2 (4 downto 0), clock => c,
result => p2 (12 downto 0)
);
-- block6
block6: mul8_5 PORT MAP( dataa => x3 (7 downto 0), datab => v3 (4 downto 0), clock => c,
result => p3 (12 downto 0)
);
-- block7
block7 : add13 PORT MAP (
dataa |
=> y1 (12 downto 0), |
|
datab |
=> y2 (12 downto 0), |
|
clock |
=> c, |
|
result => z1 |
(12 downto 0), |
|
cout |
=> z1 |
(13) |
); |
|
|
-- block9
block9 : add13 PORT MAP (
dataa |
=> p1 |
(12 downto 0), |
datab |
=> p2 |
(12 downto 0), |
clock |
=> c, |
|
result => q1 |
(12 downto 0), |
|
cout |
=> q1 |
(13) |
);
--block8
process(c) begin
if (c='1' and c'event) then
y3b(12 downto 0) <= y3(12 downto 0); y3b(13) <= y3b(12);
end if; end process;
--block10
process(c) begin
if (c='1' and c'event) then
p3b(12 downto 0) <= p3(12 downto 0); p3b(13) <= p3b(12);
end if; end process;
-- block11
block11 : add14 PORT MAP (
dataa |
=> z1 |
(13 downto 0), |
datab |
=> y3b (13 downto 0), |
|
clock |
=> c, |
|
result => s1 |
(13 downto 0), |
|
cout |
=> s1 |
(14) |
); |
|
|
-- block12
block12 : add14 PORT MAP (
dataa => q1 (13 downto 0),
datab |
=> p3b (13 downto 0), |
|
clock |
=> c, |
|
result => s2 |
(13 downto 0), |
|
cout |
=> s2 |
(14) |
); |
|
|
-- block13
block13: mul15_5 PORT MAP( dataa => s1 (14 downto 0), datab => a (4 downto 0), clock => c,
result => z2 (19 downto 0)
);
-- block15
block15: mul15_5 PORT MAP( dataa => s2 (14 downto 0),
datab => a (4 downto 0), clock => c,
result => q2 (19 downto 0)
);
--block14 (блок знакового расширения) process(c)
begin
if (c='1' and c'event) then
bb(4 downto 0) <= b(4 downto 0); bb(19) <= b(4);
bb(18) <= b(4); bb(17) <= b(4); bb(16) <= b(4); bb(15) <= b(4); bb(14) <= b(4); bb(13) <= b(4); bb(12) <= b(4); bb(11) <= b(4); bb(10) <= b(4); bb(9) <= b(4); bb(8) <= b(4); bb(7) <= b(4); bb(6) <= b(4); bb(5) <= b(4); end if;
end process;
--block17
block17 : add20 PORT MAP (
dataa |
=> z2 (19 downto 0), |
|
datab |
=> bb (19 downto 0), |
|
clock |
=> c, |
|
result => t1 |
(19 downto 0), |
|
cout |
=> t1 |
(20) |
);
-- block18
block18 : add20 PORT MAP (
dataa |
=> q2 (19 downto 0), |
|
datab |
=> bb (19 downto 0), |
|
clock |
=> c, |
|
result => t2 |
(19 downto 0), |
|
cout |
=> t2 |
(20) |
);
-- View signals to output
t2_o <= t2;
t1_o <= t1;
-- block19
block19: mul21_5 PORT MAP( dataa => t1 (20 downto 0), datab => k1_1 (4 downto 0), clock => c,
result => m1 (25 downto 0)
);
-- block20
block20: mul21_5 PORT MAP( dataa => t2 (20 downto 0), datab => k2_1 (4 downto 0), clock => c,
result => m2 (25 downto 0)
);
-- block21
block21: mul21_5 PORT MAP( dataa => t1 (20 downto 0), datab => k1_2 (4 downto 0), clock => c,
result => m3 (25 downto 0)
);
-- block22
block22: mul21_5 PORT MAP( dataa => t2 (20 downto 0), datab => k2_2 (4 downto 0), clock => c,
result => m4 (25 downto 0)
);
-- block23
block23 : add26 PORT MAP (
dataa |
=> m1 (25 downto 0), |
|
datab |
=> m2 (25 downto 0), |
|
clock |
=> c, |
|
result => s3 |
(25 downto 0), |
|
cout |
=> s3 |
(26) |
); |
|
|
-- block24
block24 : add26 PORT MAP (
dataa => m3 (25 downto 0), datab => m4 (25 downto 0), clock => c,
result => s4 |
(25 downto 0), |
cout => s4 |
(26) |
);
-- block25
block25 : comp_eq27 PORT MAP ( dataa => s3 (26 downto 0),
datab => por1 (26 downto 0), clock => c,
AgeB => f1
);
-- block26
block26 : comp_eq27 PORT MAP ( dataa => s4 (26 downto 0),
datab => por2 (26 downto 0), clock => c,
AgeB => f2
);
END Behavioral;
Соответствие требованиям быстродействия задает отчет компилятора (рис. 8). Отчет о занимаемых ресурсах проектом показан на рис. 9.
Рис. 8. Быстродействие проекта (5.525 ns, 180 МГц)
