forked from kayaleitner/FPGA_MNIST
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
513 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Oops, something went wrong.