Реализация искусственных нейронных сетей на языке описания аппаратуры VHDL. Учебное пособие-1
.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 МГц)
