Skip to content

Commit

Permalink
NN ALU concept
Browse files Browse the repository at this point in the history
  • Loading branch information
tqml committed Jun 18, 2020
1 parent 5307260 commit f7dfa22
Show file tree
Hide file tree
Showing 7 changed files with 513 additions and 0 deletions.
94 changes: 94 additions & 0 deletions vivado/NN_IP/EggNet_1.0/concepts/conv_arch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import numpy as np

def convolution2d(image, kernel, bias):
m, n = kernel.shape
if (m == n):
y, x = image.shape
y = y - m + 1
x = x - m + 1
new_image = np.zeros((y,x))
for i in range(y):
for j in range(x):
new_image[i][j] = np.sum(image[i:i+m, j:j+m]*kernel) + bias
return new_image


# Define Input Image Data
I = np.array([
1,4,7,
2,5,8,
3,6,9,
]).reshape((3,3))



# Define Weights
W = np.array([
2,2,2,
2,2,2,
2,2,2,
]).reshape((3,3))

Ipad = np.pad(I, pad_width=(1,1))
Y = convolution2d(Ipad,W,0)

Y1 = np.zeros(shape=(3,5))
Y2 = np.zeros(shape=(3,3))

Y2[1,0] = np.sum(I[:,:-1]*W[:,:-1])
Y2[1,1] = np.sum(I*W)
Y2[1,2] = np.sum(I[:,1:]*W[:,1:])



w1 = W[:,0]
w2 = W[:,1]
w3 = W[:,2]

i1 = I[:,0]
i2 = I[:,1]
i3 = I[:,2]



a3_1 = 0
a3_2 = 0
a3_3 = 0

type = 'conv'
# type = 'fc'

for i in range(0,5):
i_patch = Ipad[1:-1,i]

# MUL
z1_1 = w1 * i_patch
z1_2 = w2 * i_patch
z1_3 = w3 * i_patch

# ADD
z2_1 = np.sum(z1_1)
z2_2 = np.sum(z1_2)
z2_3 = np.sum(z1_3)


if type == 'conv':
# ACCUM + SHIFT
Y1[1,i] = a3_3 + z2_3
a3_3 = a3_2 + z2_2
a3_2 = a3_1 + z2_1
a3_1 = 0
elif type == 'fc':
# ONLY ACCUM
a3_3 = a3_3 + z2_3
a3_2 = a3_2 + z2_2
a3_1 = a3_1 + z2_1
else:
raise Exception()





print(Y)
print(Y1)
66 changes: 66 additions & 0 deletions vivado/NN_IP/EggNet_1.0/concepts/nn_alu.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
------------------------------------
-- NN ALU
------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.nnpkg.all;

-- NN ALU Component
entity nn_alu is
generic (
PARALLEL_INPUT : natural := 3;
INPUT_BITS : natural := 8;
WEIGHT_BITS : natural := 8;
OUTPUT_BITS : natural := INPUT_BITS + WEIGHT_BITS
-- OUTPUT_BITS : natural := INPUT_BITS + nlog2(PARALLEL_INPUT) -- prevent overflow
);
port (
clk : in std_logic;
rst : in std_logic;

-- SWITCH
-- mode : in std_logic;

-- x_i : in std_logic_vector(0 to PARALLEL_INPUT - 1, INPUT_BITS - 1 downto 0);
x_i : in vec1d_t(0 to PARALLEL_INPUT - 1)(INPUT_BITS - 1 downto 0);
w_i : in vec1d_t(0 to PARALLEL_INPUT - 1)(WEIGHT_BITS - 1 downto 0);
y_o : out std_logic_vector(OUTPUT_BITS - 1 downto 0)
);
end nn_alu;

architecture arch of nn_alu is
constant z1_ZERO : vec1d_t(0 to PARALLEL_INPUT - 1)(OUTPUT_BITS - 1 downto 0) := (others => (others => ('0')));
constant z2_ZERO : std_logic_vector(OUTPUT_BITS - 1 downto 0) := (others => '0');

signal z1 : vec1d_t(0 to PARALLEL_INPUT - 1)(OUTPUT_BITS - 1 downto 0) := z1_ZERO;
signal z2 : std_logic_vector(OUTPUT_BITS - 1 downto 0) := z2_ZERO;
begin

process (clk, rst)

variable temp : unsigned(INPUT_BITS - 1 downto 0);

begin
if rst = '1' then
z1 <= z1_ZERO;
z2 <= z2_ZERO;

elsif rising_edge(clk) then

-- MUL
MUL : for i in 0 to PARALLEL_INPUT - 1 loop
--z1(i) (OUTPUT_BITS -1 downto INPUT_BITS) <= (others => '0');

z1(i) <= std_logic_vector(unsigned(x_i(i)) * unsigned(w_i(i)));

--z1(i) (INPUT_BITS-1 downto 0) <= x_i(i);
end loop; -- MUL

-- ADD
-- # TODO This needs to be generic in one step
y_o <= std_logic_vector(unsigned(z1(0)) + unsigned(z1(1)) + unsigned(z1(2)));
end if;
end process;
end architecture; -- arch
83 changes: 83 additions & 0 deletions vivado/NN_IP/EggNet_1.0/concepts/nn_conv_kernel.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.nnpkg.all;
entity nn_conv_kernel is

generic (
FILTER_WIDTH : natural := 3;
FILTER_HEIGHT : natural := 3;
INPUT_BITS : natural := 8;
CONV_MODE_ENABLE : boolean := true;
WEIGHT_BITS : natural := 8;
OUTPUT_BITS : natural := INPUT_BITS + WEIGHT_BITS
-- OUTPUT_BITS : natural := INPUT_BITS + nlog2(PARALLEL_INPUT) -- prevent overflow
);

port (
clk : in std_logic;
rst : in std_logic;

w_i : in vec2d_t(0 to FILTER_HEIGHT - 1, 0 to FILTER_WIDTH - 1)(WEIGHT_BITS - 1 downto 0);
x_i : in vec1d_t(0 to FILTER_HEIGHT - 1)(INPUT_BITS - 1 downto 0);

y_o : out std_logic_vector(OUTPUT_BITS - 1 downto 0)

);
end entity nn_conv_kernel;

architecture rtl of nn_conv_kernel is

-- type weight_array_t is array (0 to FILTER_WIDTH - 1) of vec1d_t(0 to FILTER_HEIGHT - 1)(WEIGHT_BITS - 1 downto 0);
type weight_array_t is array (natural range <>) of vec1d_t;
constant w_n_ZERO : weight_array_t(0 to FILTER_WIDTH - 1)(0 to FILTER_HEIGHT - 1)(WEIGHT_BITS - 1 downto 0) := (others => (others => (others => '0')));
signal w_n : weight_array_t(0 to FILTER_WIDTH - 1)(0 to FILTER_HEIGHT - 1)(WEIGHT_BITS - 1 downto 0) := w_n_ZERO;

constant a_n_ZERO : vec1d_t(0 to FILTER_WIDTH - 1)(OUTPUT_BITS - 1 downto 0) := (others => (others => '0'));
signal z_n : vec1d_t(0 to FILTER_WIDTH - 1)(OUTPUT_BITS - 1 downto 0) := a_n_ZERO;
signal a_n : vec1d_t(0 to FILTER_WIDTH - 1)(OUTPUT_BITS - 1 downto 0) := a_n_ZERO;
begin

update_weights : process (w_i)
begin
for i in 0 to FILTER_WIDTH - 1 loop
for j in 0 to FILTER_HEIGHT - 1 loop
w_n(i)(j) <= w_i(j, i);
end loop;
end loop;
end process; -- update_weights

--- Generate ALU's
gen_alu : for i in 0 to FILTER_WIDTH - 1 generate
nn_alu_0 : entity work.nn_alu
generic map(
PARALLEL_INPUT => FILTER_HEIGHT,
INPUT_BITS => INPUT_BITS,
WEIGHT_BITS => WEIGHT_BITS,
OUTPUT_BITS => OUTPUT_BITS
)
port map(
clk => clk,
rst => rst,
x_i => x_i,
w_i => w_n(i),
y_o => z_n(i)
);
end generate;

process (clk, rst)
begin
if rst = '1' then
a_n <= a_n_ZERO;
elsif rising_edge(clk) then

a_n(0) <= (others => '0');
y_o <= std_logic_vector(unsigned(a_n(FILTER_WIDTH - 1)) + unsigned(z_n(FILTER_WIDTH - 1)));
accum : for i in 1 to FILTER_WIDTH - 1 loop
a_n(i) <= std_logic_vector(unsigned(a_n(i - 1)) + unsigned(z_n(i - 1)));
end loop; -- accum
end if;
end process;

end architecture;
29 changes: 29 additions & 0 deletions vivado/NN_IP/EggNet_1.0/concepts/nnpkg.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use ieee.math_real.ceil;
use IEEE.math_real.log2;

-- A Package
package nnpkg is

type vec1d_t is array (natural range <>) of std_logic_vector;
type vec2d_t is array (natural range <>, natural range <>) of std_logic_vector;

-- LOG2 for natural numbers
function nlog2 (x : natural) return natural;


-- function shift_mul (x : vec2d_t, w : vec2d_t, sgn : std_logic) return natural;

end nnpkg;

package body nnpkg is

function nlog2 (x : natural) return natural is
begin
return natural(ceil(log2(real(x))));
end function;

end nnpkg;
32 changes: 32 additions & 0 deletions vivado/NN_IP/EggNet_1.0/concepts/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
"""
Top Level VUNIT
===============
Created on Mon Mar 23 12:20:15 2020
@author: lukas
@author: Benjamin
"""

import pathlib
from vunit import VUnit



# ---------------------------
# -- Setup Constants
# ---------------------------
ROOT = pathlib.Path(__file__).parent

# ---------------------------
# -- Setup VU_Run and start simulation
# ---------------------------
VU = VUnit.from_argv()
lib = VU.add_library(library_name="EggNet",vhdl_standard="08")
lib.add_source_files(ROOT / "*.vhd")


if __name__ == "__main__":
VU.main()
Loading

0 comments on commit f7dfa22

Please sign in to comment.