1 |
3 |
ojosynariz |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company: CEI
|
3 |
|
|
-- Engineer: David Aledo
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 11:24:24 05/28/2013
|
6 |
|
|
-- Design Name: Configurable ANN
|
7 |
|
|
-- Module Name: layerPS - arq
|
8 |
|
|
-- Project Name:
|
9 |
|
|
-- Target Devices:
|
10 |
|
|
-- Tool versions:
|
11 |
|
|
-- Description: basic and parametrizable neuron layer for hardware artificial
|
12 |
|
|
-- neural networks. Paralel input and serial output.
|
13 |
|
|
-- It implemnts one neuron reused to calculate all.
|
14 |
|
|
--
|
15 |
|
|
-- Dependencies:
|
16 |
|
|
--
|
17 |
|
|
-- Revision:
|
18 |
|
|
-- Revision 0.01 - File Created
|
19 |
|
|
-- Additional Comments:
|
20 |
|
|
--
|
21 |
|
|
----------------------------------------------------------------------------------
|
22 |
|
|
|
23 |
|
|
library ieee;
|
24 |
|
|
use ieee.std_logic_1164.all;
|
25 |
|
|
use ieee.numeric_std.all;
|
26 |
|
|
|
27 |
|
|
-- Deprecated XPS library: -- Needed functions have been implemented in layers_pkg
|
28 |
|
|
--library proc_common_v3_00_a;
|
29 |
|
|
--use proc_common_v3_00_a.proc_common_pkg.all;
|
30 |
|
|
|
31 |
|
|
use work.layers_pkg.all;
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
entity layerPS is
|
35 |
|
|
|
36 |
|
|
generic
|
37 |
|
|
(
|
38 |
|
|
NumN : natural := 64; -- Number of neurons of the layer
|
39 |
|
|
NumIn : natural := 8; -- Number of inputs of each neuron
|
40 |
|
|
NbitIn : natural := 12; -- Bit width of the input data
|
41 |
|
|
NbitW : natural := 8; -- Bit width of weights and biases
|
42 |
|
|
NbitOut : natural := 8; -- Bit width of the output data
|
43 |
|
|
LSbit : natural := 4 -- Less significant bit of the outputs
|
44 |
|
|
);
|
45 |
|
|
|
46 |
|
|
port
|
47 |
|
|
(
|
48 |
|
|
-- Input ports
|
49 |
|
|
reset : in std_logic;
|
50 |
|
|
clk : in std_logic;
|
51 |
|
|
en : in std_logic; -- First step enable
|
52 |
|
|
en2 : in std_logic; -- Second stage enable
|
53 |
|
|
en_r : in std_logic; -- Output register enable
|
54 |
|
|
inputs : in std_logic_vector((NbitIn*NumIn)-1 downto 0); -- Input data (parallel)
|
55 |
|
|
Wyb : in std_logic_vector((NbitW*NumIn)-1 downto 0); -- Weight vectors
|
56 |
|
|
bias : in std_logic_vector(NbitW-1 downto 0); --------- Bias
|
57 |
|
|
|
58 |
|
|
-- Output ports
|
59 |
|
|
en_out : out std_logic; -- Output data validation
|
60 |
|
|
outputs : out std_logic_vector(NbitOut-1 downto 0) -- Output data (serial)
|
61 |
|
|
);
|
62 |
|
|
end layerPS;
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
architecture arq of layerPS is
|
67 |
|
|
|
68 |
|
|
constant NbOvrf : natural := log2(NumIn); -- Extra bits avoid overflow in adders
|
69 |
|
|
constant sat_max : signed(NbitIn+NbitW+NbOvrf downto 0) := (NbitIn+NbitW+NbOvrf downto LSbit+NbitOut-1 => '0') & (LSbit+NbitOut-2 downto 0 => '1'); -- E.g. "0001111"
|
70 |
|
|
constant sat_min : signed(NbitIn+NbitW+NbOvrf downto 0) := (NbitIn+NbitW+NbOvrf downto LSbit+NbitOut-1 => '1') & (LSbit+NbitOut-2 downto 0 => '0'); -- E.g. "1110000"
|
71 |
|
|
|
72 |
|
|
type v_res is array(NumIn-1 downto 0) of signed((NbitIn+NbitW)-1 downto 0); -- Array type for results from multipliers
|
73 |
|
|
|
74 |
|
|
signal res : v_res := (others => (others => '0')); -- Results from multipliers
|
75 |
|
|
signal sum : std_logic_vector(NbitIn+NbitW+NbOvrf downto 0) := (others => '0'); -- Addition result
|
76 |
|
|
signal reg : std_logic_vector(NbitOut-1 downto 0) := (others => '0'); ----------- Output register
|
77 |
|
|
signal sum_aux : std_logic_vector(((NbitIn+NbitW+NbOvrf+1)*(NumIn+1))-1 downto 0); -- Pipeline registers for adders
|
78 |
|
|
|
79 |
|
|
begin
|
80 |
|
|
|
81 |
|
|
muls: -- Instances as multipliers as NumIn
|
82 |
|
|
for i in (NumIn-1) downto 0 generate
|
83 |
|
|
process (clk) -- Multiplier
|
84 |
|
|
begin
|
85 |
|
|
if (clk'event and clk = '1') then
|
86 |
|
|
if (reset = '1') then
|
87 |
|
|
res(i) <= (others => '0');
|
88 |
|
|
else
|
89 |
|
|
if (en = '1') then
|
90 |
|
|
-- Multiplies every input with its weight:
|
91 |
|
|
res(i) <= signed(inputs((NbitIn*(i+1))-1 downto NbitIn*i)) * signed(Wyb((NbitW*(i+1))-1 downto NbitW*i));
|
92 |
|
|
end if;
|
93 |
|
|
end if;
|
94 |
|
|
end if;
|
95 |
|
|
end process;
|
96 |
|
|
end generate;
|
97 |
|
|
|
98 |
|
|
asign_adder_tree_inputs:
|
99 |
|
|
for i in NumIn-1 downto 0 generate
|
100 |
|
|
sum_aux(((NbitIn+NbitW+NbOvrf+1)*(i+1))-1 downto (NbitIn+NbitW+NbOvrf+1)*i) <= std_logic_vector(resize(res(i),NbitIn+NbitW+NbOvrf+1));
|
101 |
|
|
end generate;
|
102 |
|
|
sum_aux(((NbitIn+NbitW+NbOvrf+1)*(NumIn+1))-1 downto (NbitIn+NbitW+NbOvrf+1)*NumIn) <= std_logic_vector(resize(signed(bias),NbitIn+NbitW+NbOvrf+1)); -- Bias is added placed in the last position
|
103 |
|
|
|
104 |
|
|
recursive_adder_tree: entity work.adder_tree
|
105 |
|
|
generic map
|
106 |
|
|
(
|
107 |
|
|
NumIn => NumIn+1, -- +bias
|
108 |
|
|
Nbit => NbitIn+NbitW+NbOvrf+1
|
109 |
|
|
)
|
110 |
|
|
port map
|
111 |
|
|
(
|
112 |
|
|
clk => clk,
|
113 |
|
|
reset => reset,
|
114 |
|
|
en => en2,
|
115 |
|
|
inputs => sum_aux,
|
116 |
|
|
en_out => en_out,
|
117 |
|
|
output => sum
|
118 |
|
|
);
|
119 |
|
|
|
120 |
|
|
|
121 |
|
|
process(clk)
|
122 |
|
|
begin
|
123 |
|
|
if(rising_edge(clk)) then
|
124 |
|
|
if(reset = '1') then -- Synchronous reset, active high
|
125 |
|
|
reg <= (others => '0');
|
126 |
|
|
else
|
127 |
|
|
|
128 |
|
|
if en_r = '1' then -- Output register enable (clipping)
|
129 |
|
|
|
130 |
|
|
if signed(sum) > sat_max then
|
131 |
|
|
-- Saturating result to the maximum value:
|
132 |
|
|
reg <= '0' & (NbitOut-2 downto 0 => '1');
|
133 |
|
|
elsif signed(sum) < sat_min then
|
134 |
|
|
-- Saturating result to the minimum value:
|
135 |
|
|
reg <= '1' & (NbitOut-2 downto 0 => '0');
|
136 |
|
|
else
|
137 |
|
|
-- Configured window of result bits are assigned to the output:
|
138 |
|
|
reg <= sum(LSbit+NbitOut-1 downto LSbit);
|
139 |
|
|
end if;
|
140 |
|
|
|
141 |
|
|
end if;
|
142 |
|
|
end if;
|
143 |
|
|
|
144 |
|
|
end if;
|
145 |
|
|
end process;
|
146 |
|
|
|
147 |
|
|
-- Assigns output register to output data port:
|
148 |
|
|
outputs <= reg;
|
149 |
|
|
|
150 |
|
|
end arq;
|