OpenCores
URL https://opencores.org/ocsvn/artificial_neural_network/artificial_neural_network/trunk

Subversion Repositories artificial_neural_network

[/] [artificial_neural_network/] [trunk/] [ANN_kernel/] [RTL_VHDL_files/] [layerPS_top.vhd] - Blame information for rev 9

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 ojosynariz
----------------------------------------------------------------------------------
2
-- Company: CEI
3
-- Engineer: David Aledo
4
--
5
-- Create Date:    12:41:19 06/10/2013
6
-- Design Name:    Configurable ANN
7
-- Module Name:    layerSP_top - Behavioral
8
-- Project Name:
9
-- Target Devices:
10
-- Tool versions:
11
-- Description: neuron layer top for artificial neural networks. Parallel input and
12
--             serial output.
13
--
14
-- Dependencies:
15
--
16
-- Revision:
17
-- Revision 0.01 - File Created
18
-- Additional Comments:
19
--
20
----------------------------------------------------------------------------------
21
library IEEE;
22
use IEEE.STD_LOGIC_1164.ALL;
23
use ieee.numeric_std.all;
24
 
25 8 jstefanowi
library work;
26
use work.wb_init.all; -- initialization package, comment out when not used
27
 
28 3 ojosynariz
-- Deprecated XPS library:
29
--library proc_common_v3_00_a;
30
--use proc_common_v3_00_a.proc_common_pkg.all; -- Only for simulation ( pad_power2() )
31
 
32
entity layerPS_top is
33
 
34
   generic
35
   (
36 8 jstefanowi
      WBinit  : boolean := false;
37
      LNum    : natural := 0;   ------- layer number (needed for initialization)
38
      NumN    : natural := 34;  ------- Number of neurons of the layer
39
      NumIn   : natural := 27;   ------- Number of inputs of each neuron
40
      NbitIn  : natural := 8;  ------- Bit width of the input data
41
      NbitW   : natural := 1;   ------- Bit width of weights and biases
42 3 ojosynariz
      NbitOut : natural := 8;   ------- Bit width of the output data
43 8 jstefanowi
      lra_l   : natural := 11;  ------- Layer RAM address length. It should value log2(NumN)+log2(NumIn)
44
      wra_l   : natural := 5;   ------- Weight RAM address length. It should value log2(NumIn)
45 3 ojosynariz
      bra_l   : natural := 6;   ------- Bias RAM address length. It should value log2(NumN)
46 8 jstefanowi
      LSbit   : natural := 6    ------- Less significant bit of the outputs
47 3 ojosynariz
   );
48
 
49
   port
50
   (
51
      -- Input ports
52
      reset   : in  std_logic;
53
      clk     : in  std_logic;
54
      run_in  : in  std_logic; -- Start and input data validation
55
      m_en    : in  std_logic; -- Memory enable (external interface)
56
      b_sel   : in  std_logic; -- Bias memory select
57
      m_we    : in  std_logic_vector(((NbitW+7)/8)-1 downto 0);  -- Memory write enable (external interface)
58
      inputs  : in  std_logic_vector((NbitIn*NumIn)-1 downto 0); -- Input data (parallel)
59
      wdata   : in  std_logic_vector(NbitW-1 downto 0);  -- Write data of weight and bias memories
60
      addr    : in  std_logic_vector(lra_l-1 downto 0); -- Address of weight and bias memories
61
 
62
      -- Output ports
63
      run_out : out std_logic; -- Output data validation, run_in for the next layer
64
      rdata   : out std_logic_vector(NbitW-1 downto 0);  -- Read data of weight and bias memories
65
      outputs : out std_logic_vector(NbitOut-1 downto 0) -- Output data (serial)
66
   );
67
 
68
end layerPS_top;
69
 
70
architecture Behavioral of layerPS_top is
71
 
72
   type ramd_type is array (NumN-1 downto 0) of std_logic_vector(NbitW-1 downto 0); -- Optimal: 32 or 64 spaces
73
   type layer_ram is array (NumIn-1 downto 0) of ramd_type;
74
   type outm_type is array (NumIn-1 downto 0) of std_logic_vector(NbitW-1 downto 0);
75
 
76 8 jstefanowi
   function fw_init(LNum : natural) return layer_ram is
77
     variable tmp_arr : layer_ram := (others =>(others => (others => '0')));
78
   begin
79
      if WBinit = true then
80
         for i in 0 to NumIn-1 loop
81
            for j in 0 to NumN-1 loop
82
               tmp_arr(i)(j) := w_init(LNum)(i)(j);
83
            end loop;
84
         end loop;
85
      end if;
86
      return tmp_arr ;
87
   end fw_init;
88
 
89
 
90
 
91
 
92
   function fb_init(LNum : natural) return ramd_type is
93
      variable tmp_arr : ramd_type := (others => (others => '0')) ;
94
   begin
95
      if WBinit = true then
96
         for i in 0 to NumN-1 loop
97
           tmp_arr(i) := b_init(LNum)(i);
98
         end loop;
99
      end if;
100
      return tmp_arr;
101
   end fb_init;
102
 
103
   --function fb_init(LNum : natural) return ramd_type is
104
   --begin
105
   -- return ramd_type(b_init(LNum));
106
   --end fb_init;
107
 
108
   signal lram  : layer_ram := fw_init(LNum); -- Layer RAM. One RAM per input. It stores the weights
109
   signal breg  : ramd_type := fb_init(LNum); -- Bias RAM. They can be RAM because they are not accessed simultaneously
110 3 ojosynariz
   signal outm  : outm_type; -- RAM outputs to be multiplexed into rdata
111
   signal m_sel : std_logic_vector(NumIn-1 downto 0);   --------- RAM select
112
   signal Wyb   : std_logic_vector((NbitW*NumIn)-1 downto 0); -- Weight vectors
113
   signal bias  : std_logic_vector(NbitW-1 downto 0);   -------- Bias
114
   signal Nouts : std_logic_vector(NbitOut-1 downto 0);   ------ Outputs from neurons
115
   signal uaddr : unsigned(lra_l-1 downto 0); -- Unsigned address of weight and bias memories
116
 
117 8 jstefanowi
   -- Señales de control
118 3 ojosynariz
   signal cont : integer range 0 to NumN-1; -- Neuron counter
119
   signal cntb : integer range 0 to NumN-1; -- Delayed counter for biases
120
   signal st  : bit;  ------- State
121
   signal en1 : std_logic; -- First step enable
122
   signal en2 : std_logic; -- Second stage enable
123
   signal en3 : std_logic; -- Shift register enable
124
   signal en_out : std_logic;
125
 
126 8 jstefanowi
   signal input_aux1 : std_logic_vector((NbitIn*NumIn)-1 downto 0);
127
   signal input_aux2 : std_logic_vector((NbitIn*NumIn)-1 downto 0);
128 9 jstefanowi
--   signal input_aux3 : std_logic_vector((NbitIn*NumIn)-1 downto 0);
129 3 ojosynariz
begin
130
 
131
layerPS_inst: entity work.layerPS
132
   generic map
133
   (
134
      NumN    => NumN,
135
      NumIn   => NumIn,
136
      NbitIn  => NbitIn,
137
      NbitW   => NbitW,
138
      NbitOut => NbitOut,
139
      LSbit   => LSbit
140
   )
141
   port map
142
   (
143
      -- Input ports
144
      reset  => reset,
145
      clk    => clk,
146
      en     => en1,
147
      en2    => en2,
148
      en_r   => en3,
149 8 jstefanowi
      inputs => input_aux2,
150 3 ojosynariz
      Wyb    => Wyb,
151
      bias   => bias,
152
 
153
      -- Output ports
154
      en_out  => en_out,
155
      outputs => Nouts
156
   );
157
 
158
   uaddr <= unsigned(addr(lra_l-1 downto 0));
159
 
160
ram_selector:
161
   process (uaddr(wra_l-1 downto 0),b_sel) -- Bottom part of memory address and b_sel
162
   begin
163
      m_sel <= (others => '0'); -- Default
164
      for i in (NumIn-1) downto 0 loop
165
         -- The bottom part of memory address selects which RAM
166
         if ( (to_integer(uaddr(wra_l-1 downto 0)) = i) and (b_sel = '0')) then
167
            m_sel(i) <= '1'; -- Enables the selected RAM
168
         end if;
169
      end loop;
170
   end process;
171
 
172
rams: -- Instence as weight and bias memories as inputs there are in the layer
173
   for i in (NumIn-1) downto 0 generate
174
      process (clk)
175
         variable d : std_logic_vector(NbitW-1 downto 0); -- Beware of elements whose length is not a multiple of 8
176
      begin
177
         if (clk'event and clk = '1') then
178
            if (m_en = '1' and m_sel(i) = '1') then
179
               for j in ((NbitW+7)/8)-1 downto 0 loop -- we byte to byte
180
                  if (m_we(j) = '1') then
181
                     d((8*(j+1))-1 downto 8*j) := wdata((8*(j+1))-1 downto 8*j);
182
                  else
183
                     d((8*(j+1))-1 downto 8*j) := lram(i)(to_integer(uaddr(lra_l-1 downto wra_l)))((8*(j+1))-1 downto 8*j);
184
                  end if;
185
               end loop;
186
               -- Top part of weight and bias memory selects weights inside the selected RAM
187
               lram(i)(to_integer(uaddr(lra_l-1 downto wra_l))) <= d; -- Write
188
               --
189
            end if;
190
         end if;
191
      end process;
192
      -- Outpus are read in parallel, resulting in a bus of weights:
193
      --Wyb((NbitW*(i+1))-1 downto NbitW*i) <= lram(i)(cont); -- Asynchronous read (forces distributed RAM)
194
      process (clk) -- Synchronous read
195
      begin
196
         if clk'event and clk = '1' then
197
            if reset = '1' then
198
               --Wyb((NbitW*(i+1))-1 downto NbitW*i) <= (others => '0');
199
            else
200
               Wyb((NbitW*(i+1))-1 downto NbitW*i) <= lram(i)(cont);
201
            end if;
202
         end if;
203
      end process;
204
      outm(i) <= lram(i)(to_integer(uaddr(lra_l-1 downto wra_l))); -- Read all RAM
205
   end generate;
206
 
207
   -- Synchronous read including breg:
208
   process (clk)
209
   begin
210
      if (clk'event and clk = '1') then
211
         if (m_en = '1') then
212
            if (b_sel = '1') then
213
               rdata <= breg(to_integer(uaddr(bra_l-1 downto 0))); -- Bias RAM selected
214
            else -- Other RAM selected:
215
               rdata <= outm(to_integer(uaddr(wra_l-1 downto 0))); -- Multiplexes RAM outputs
216
               -- May be safer if accesses to bottom address grater than NumIn are avoided
217
            end if;
218
         end if;
219
      end if;
220
   end process;
221
 
222
bias_ram:
223
   process (clk)
224
      variable d : std_logic_vector(NbitW-1 downto 0); -- Beware of elements whose length is not a multiple of 8
225
   begin
226
      if (clk'event and clk = '1') then
227
         if ( (m_en = '1') and (b_sel = '1') ) then
228
            for i in ((NbitW+7)/8)-1 downto 0 loop -- we byte to byte
229
               if (m_we(i) = '1') then
230
                  d((8*(i+1))-1 downto 8*i) := wdata((8*(i+1))-1 downto 8*i);
231
               else
232
                  d((8*(i+1))-1 downto 8*i) := breg(to_integer(uaddr(bra_l-1 downto 0)))((8*(i+1))-1 downto 8*i);
233
               end if;
234
            end loop;
235
            -- The bottom part (extended) of memories address selects the bias
236
            breg(to_integer(uaddr(bra_l-1 downto 0))) <= d;
237
         end if;
238
      end if;
239
   end process;
240
 
241
-- Bias read: -- Here, parallel read of bias is not necessary, so it can be RAM
242
   --bias <= breg(cont); -- Asynchronous read
243
   process (clk) -- Synchronous read
244
   begin
245
      if clk'event and clk = '1' then
246
         if reset = '1' then
247
            --bias <= (others => '0');
248
         else
249
            bias <= breg(cntb);
250
         end if;
251
      end if;
252
   end process;
253
 
254
   outputs <= Nouts;
255
 
256
control: -- With counter and control signal shifts
257
   process (clk)
258
   begin
259
      if (clk'event and clk = '1') then
260
         if (reset = '1') then
261
            cont <= 0;
262
            cntb <= 0;
263
            st  <= '0';
264
            en1 <= '0';
265
            en2 <= '0';
266
            run_out <= '0';
267
         else
268 8 jstefanowi
            input_aux1 <= inputs;
269
            input_aux2 <= input_aux1;
270
            --input_aux3 <=input_aux3 input_aux2;
271
 
272 3 ojosynariz
            cntb <= cont; -- Bias counter is delayed to assure correctness of pipeline data
273
            case st is
274
               when '0' =>
275
                  en1 <= '0'; -- en1 is delayed 1 cycle in order to insert a register for Wyb
276
                  case run_in is
277
                     when '1' => st <= '1';
278
                     when '0' => st <= '0';
279
                     when others => st <= '0';
280
                  end case;
281
               when '1' =>
282
                  en1 <= '1'; -- en1 is delayed 1 cycle in order to insert a register for Wyb
283 8 jstefanowi
                  if cont = NumN-1 then
284
                     cont <= 0;
285
                     st <= '0';
286
                  else
287
                     cont <= cont +1;
288
                  end if;
289 3 ojosynariz
            end case;
290
 
291
            en2 <= en1;
292
 
293
            run_out <= en3; -- It lasts for 1 cycle, just after the output enable of the layer (when all outputs have just updated)
294
         end if;
295
      end if;
296
   end process;
297
 
298
   en3 <= en_out;
299
 
300
end Behavioral;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.