├── .gitattributes ├── Block Diagrams ├── 10_max_pooling.jpeg ├── 11_cnn_top_module.jpeg ├── 1_mac_generic.jpeg ├── 2_matrix_multiplier.jpeg ├── 3_mux_g.jpeg ├── 4_conv.jpeg ├── 5_slide_window_conv.jpeg ├── 6_relu.jpeg ├── 7_relu_activation.jpeg ├── 8_max_value.jpeg └── 9_max_data.jpeg ├── Matlab functions ├── 2Image_3Filter_0Bias_Conv_Input_Output.txt ├── 2Image_3Filter_0Bias_Conv_Output.mat ├── FileName.txt ├── FileName1.txt ├── cnn2dConvolution.m ├── cnnConvolution.m ├── cnnNdConvolution.m ├── cnnPool.m ├── cnnRelu.m ├── conv2Mat.m ├── grayImage.mat ├── images.png └── normalization.m ├── README.md ├── Testing └── Convolution │ ├── Matlab │ ├── cnn2dConvolution.m │ ├── conv.mat │ ├── conv_output.txt │ ├── gray_img.mat │ ├── rgb2Gray2Mat.m │ └── test.m │ ├── bias.txt │ ├── filter_input1.txt │ ├── filter_input2.txt │ ├── images.png │ └── mat_input.txt ├── Verilog Codes ├── ReLU.v ├── ReLU_Activation.v ├── cnn_module.v ├── conv.v ├── counter_g.v ├── mac_generic.v ├── matrix_multiplier.v ├── max_data.v ├── max_pooling.v ├── max_value.v ├── mux_2x1.v ├── mux_g.v └── slide_window_conv.v └── Verilog Modules using Vivado ├── CNN Top Module.rar ├── Matrix Multiplication.rar ├── Matrix convolution.rar ├── Max Pooling.rar ├── ReLU Module.rar ├── Sliding Window Convolution.rar ├── generic mac.rar └── mux_generic.rar /.gitattributes: -------------------------------------------------------------------------------- 1 | .m 2 | .v 3 | -------------------------------------------------------------------------------- /Block Diagrams/10_max_pooling.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/10_max_pooling.jpeg -------------------------------------------------------------------------------- /Block Diagrams/11_cnn_top_module.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/11_cnn_top_module.jpeg -------------------------------------------------------------------------------- /Block Diagrams/1_mac_generic.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/1_mac_generic.jpeg -------------------------------------------------------------------------------- /Block Diagrams/2_matrix_multiplier.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/2_matrix_multiplier.jpeg -------------------------------------------------------------------------------- /Block Diagrams/3_mux_g.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/3_mux_g.jpeg -------------------------------------------------------------------------------- /Block Diagrams/4_conv.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/4_conv.jpeg -------------------------------------------------------------------------------- /Block Diagrams/5_slide_window_conv.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/5_slide_window_conv.jpeg -------------------------------------------------------------------------------- /Block Diagrams/6_relu.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/6_relu.jpeg -------------------------------------------------------------------------------- /Block Diagrams/7_relu_activation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/7_relu_activation.jpeg -------------------------------------------------------------------------------- /Block Diagrams/8_max_value.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/8_max_value.jpeg -------------------------------------------------------------------------------- /Block Diagrams/9_max_data.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Block Diagrams/9_max_data.jpeg -------------------------------------------------------------------------------- /Matlab functions/2Image_3Filter_0Bias_Conv_Input_Output.txt: -------------------------------------------------------------------------------- 1 | A(:,:,1)=[2 1 2 0 1; 2 2 0 0 1; 1 1 1 0 1; 2 0 0 1 0; 0 0 0 1 1] 2 | 3 | A(:,:,2)=[0 0 0 1 1; 0 1 0 1 0; 2 0 0 1 0; 0 0 2 2 0; 0 0 1 1 1] 4 | 5 | A(:,:,3)=[2 0 0 1 0; 0 0 0 1 1; 0 0 2 2 0; 2 2 0 0 1; 0 1 0 1 0] 6 | 7 | 8 | A1(:,:,1)=[2 1 0 0 1; 2 2 0 3 1; 1 1 1 0 4; 2 0 0 1 3; 1 2 0 0 1] 9 | 10 | A1(:,:,2)=[0 2 0 1 1; 0 1 0 1 1; 2 0 0 1 4; 0 4 2 2 0; 0 0 1 0 0] 11 | 12 | A1(:,:,3)=[2 0 0 1 4; 1 0 2 1 1; 1 0 2 2 0; 2 4 0 0 0; 0 1 0 1 1] 13 | 14 | 15 | 16 | B(:,:,1)=[1 0 0; 0 1 0; 0 0 1] 17 | 18 | B(:,:,2)=[2 0 0; 0 2 0; 0 0 2] 19 | 20 | B(:,:,3)=[1 0 -3; -3 0 0; 0 -3 -1] 21 | 22 | 23 | B1(:,:,1)=[1 0 -2; 0 1 0; 2 0 1] 24 | 25 | B1(:,:,2)=[-2 0 1; 0 2 0; -1 0 2] 26 | 27 | B1(:,:,3)=[-1 0 -3; -1 0 0; 0 2 -1] 28 | 29 | 30 | B2(:,:,1)=[0 0 1; 0 1 -2; -2 0 0] 31 | 32 | B2(:,:,2)=[2 0 2; 0 1 0; -2 0 -1] 33 | 34 | B2(:,:,3)=[0 0 3; -3 0 1; 1 0 -1] 35 | 36 | 37 | 38 | D5 = conv(A1,B2) 39 | 40 | -5 -1 8 41 | 0 7 -11 42 | 6 -8 6 43 | 44 | D4 = conv(A1,B1) 45 | 46 | 2 1 8 47 | 11 -6 -5 48 | 0 -1 1 49 | 50 | D3 = conv(A1,B) 51 | 52 | 2 -4 -7 53 | -14 7 -4 54 | 0 -14 3 55 | 56 | D2 = conv(A,B2) 57 | 58 | -3 1 3 59 | -3 10 -8 60 | 4 1 2 61 | 62 | D1 = conv(A,B1) 63 | 64 | -1 5 10 65 | 15 4 -8 66 | -9 0 6 67 | 68 | D = conv(A,B) 69 | 70 | 5 -8 -1 71 | 1 7 -8 72 | -8 -5 6 -------------------------------------------------------------------------------- /Matlab functions/2Image_3Filter_0Bias_Conv_Output.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Matlab functions/2Image_3Filter_0Bias_Conv_Output.mat -------------------------------------------------------------------------------- /Matlab functions/FileName.txt: -------------------------------------------------------------------------------- 1 | 253 254 247 235 220 246 249 252 2 | 253 247 231 232 187 178 247 252 3 | 252 212 235 227 201 192 211 249 4 | 249 226 201 213 215 203 226 249 5 | 253 251 211 223 238 223 250 251 6 | 252 254 238 240 103 240 254 254 7 | 252 252 250 196 65 254 251 253 8 | 251 251 251 212 215 252 253 252 9 | -------------------------------------------------------------------------------- /Matlab functions/FileName1.txt: -------------------------------------------------------------------------------- 1 | 253 254 247 235 220 246 249 252 2 | 253 247 231 232 187 178 247 252 3 | 252 212 235 227 201 192 211 249 4 | 249 226 201 213 215 203 226 249 5 | 253 251 211 223 238 223 250 251 6 | 252 254 238 240 103 240 254 254 7 | 252 252 250 196 65 254 251 253 8 | 251 251 251 212 215 252 253 252 9 | -------------------------------------------------------------------------------- /Matlab functions/cnn2dConvolution.m: -------------------------------------------------------------------------------- 1 | function convolvedFeature = cnn2dConvolution(image, W, b) 2 | %cnnConvolve Returns the convolution of the features given by W and b with 3 | %the given images 4 | % 5 | % Parameters: 6 | % filterDim - filter (feature) dimension 7 | % numFilters - number of feature maps 8 | % images - large images to convolve with, matrix in the form 9 | % images(r, c, image number) 10 | % W, b - W, b for features from the sparse autoencoder 11 | % W is of shape (filterDim,filterDim,numFilters) 12 | % b is of shape (numFilters,1) 13 | % 14 | % Returns: 15 | % convolvedFeatures - matrix of convolved features in the form 16 | % convolvedFeatures(imageRow, imageCol, featureNum, imageNum) 17 | [imageDim, imageDim] = size(image); 18 | [filterDim, filterDim] = size(W); 19 | convDim = imageDim - filterDim + 1; 20 | 21 | % Instructions: 22 | % Convolve every filter with every image here to produce the 23 | % (imageDim - filterDim + 1) x (imageDim - filterDim + 1) x numFeatures x numImages 24 | % matrix convolvedFeatures, such that 25 | % convolvedFeatures(imageRow, imageCol, featureNum, imageNum) is the 26 | % value of the convolved featureNum feature for the imageNum image over 27 | % the region (imageRow, imageCol) to (imageRow + filterDim - 1, imageCol + filterDim - 1) 28 | % 29 | % Expected running times: 30 | % Convolving with 100 images should take less than 30 seconds 31 | % Convolving with 5000 images should take around 2 minutes 32 | % (So to save time when testing, you should convolve with less images, as 33 | % described earlier) 34 | 35 | % convolution of image with feature matrix 36 | convolvedImage = zeros(convDim, convDim); 37 | 38 | % Obtain the feature (filterDim x filterDim) needed during the convolution 39 | 40 | %%% YOUR CODE HERE %%% 41 | 42 | % Flip the feature matrix because of the definition of convolution, as explained later 43 | filter = rot90(squeeze(W),2); 44 | 45 | % Obtain the image 46 | im = squeeze(image(:, :)); 47 | 48 | % Convolve "filter" with "im", adding the result to convolvedImage 49 | % be sure to do a 'valid' convolution 50 | 51 | %%% YOUR CODE HERE %%% 52 | convolvedImage = conv2(im,filter,'valid'); 53 | 54 | % Add the bias unit 55 | % Then, apply the sigmoid function to get the hidden activation 56 | 57 | %%% YOUR CODE HERE %%% 58 | convolvedImage = convolvedImage + b; 59 | 60 | convolvedFeature(:, :) = convolvedImage; 61 | 62 | end -------------------------------------------------------------------------------- /Matlab functions/cnnConvolution.m: -------------------------------------------------------------------------------- 1 | function convolvedFeatures = cnnConvolution(images, W, b) 2 | 3 | [imageDim, imageDim, imageChannel, numImages] = size(images); 4 | [filterDim, filterDim, filterChannel, numFilters] = size(W); 5 | [numImages, numFilters] = size(b); 6 | convDim = imageDim - filterDim + 1; 7 | 8 | convolvedFeatures = zeros(convDim, convDim, numFilters, numImages); 9 | 10 | for imageNum = 1:numImages 11 | for filterNum = 1:numFilters 12 | 13 | convolvedFeatures(:,:,filterNum,imageNum) = cnnNdConvolution(images(:,:,:,imageNum),W(:,:,:,filterNum),b(imageNum,filterNum)); 14 | 15 | end 16 | end 17 | 18 | end -------------------------------------------------------------------------------- /Matlab functions/cnnNdConvolution.m: -------------------------------------------------------------------------------- 1 | function convolvedFeature = cnnNdConvolution(image, W, b) 2 | 3 | [imageDim, imageDim, imageChannel] = size(image); 4 | [filterDim, filterDim, filterChannel] = size(W); 5 | 6 | convDim = imageDim - filterDim + 1; 7 | 8 | convolvedFeature = zeros(convDim, convDim); 9 | 10 | for channel = 1:filterChannel 11 | 12 | convolvedImage(:,:,channel) = cnn2dConvolution(image(:,:,channel),W(:,:,channel),b); 13 | 14 | convolvedFeature = convolvedFeature + convolvedImage(:,:,channel); 15 | 16 | end 17 | 18 | end -------------------------------------------------------------------------------- /Matlab functions/cnnPool.m: -------------------------------------------------------------------------------- 1 | function pooledFeatures = cnnPool(poolDim, convolvedFeatures) 2 | %cnnPool Pools the given convolved features 3 | % 4 | % Parameters: 5 | % poolDim - dimension of pooling region 6 | % convolvedFeatures - convolved features to pool (as given by cnnConvolve) 7 | % convolvedFeatures(imageRow, imageCol, featureNum, imageNum) 8 | % 9 | % Returns: 10 | % pooledFeatures - matrix of pooled features in the form 11 | % pooledFeatures(poolRow, poolCol, featureNum, imageNum) 12 | % 13 | 14 | numImages = size(convolvedFeatures, 4); 15 | numFilters = size(convolvedFeatures, 3); 16 | convolvedDim = size(convolvedFeatures, 1); 17 | 18 | pooledFeatures = zeros(convolvedDim / poolDim, ... 19 | convolvedDim / poolDim, numFilters, numImages); 20 | 21 | % Instructions: 22 | % Now pool the convolved features in regions of poolDim x poolDim, 23 | % to obtain the 24 | % (convolvedDim/poolDim) x (convolvedDim/poolDim) x numFeatures x numImages 25 | % matrix pooledFeatures, such that 26 | % pooledFeatures(poolRow, poolCol, featureNum, imageNum) is the 27 | % value of the featureNum feature for the imageNum image pooled over the 28 | % corresponding (poolRow, poolCol) pooling region. 29 | % 30 | % Use mean pooling here. 31 | 32 | %%% YOUR CODE HERE %%% 33 | testMatrix = reshape(convolvedFeatures, convolvedDim, convolvedDim); 34 | 35 | for i=(0:((convolvedDim / poolDim)-1)) 36 | for j=(0:((convolvedDim / poolDim)-1)) 37 | pooledFeatures(i+1,j+1) = max(max(testMatrix((2.*(i+1)-1):(2.*(i+1)),(2.*(j+1)-1):(2.*(j+1))))); 38 | end 39 | end 40 | end -------------------------------------------------------------------------------- /Matlab functions/cnnRelu.m: -------------------------------------------------------------------------------- 1 | % Step 2 2 | % takes an input image (3d array) and performs a thresholding opreation on it 3 | % set all neg numbers to 0 4 | 5 | function out = relu(in) 6 | out = max(in, 0); 7 | end 8 | -------------------------------------------------------------------------------- /Matlab functions/conv2Mat.m: -------------------------------------------------------------------------------- 1 | % Following MATLAB function will take a grayscale 2 | % or an RGB image as input and will return a 3 | % binary image as output 4 | 5 | function [img] = conv2Mat(img) 6 | 7 | [x, y, z]=size(img); 8 | 9 | % if Read Image is an RGB Image then convert 10 | % it to a Gray Scale Image For an RGB image 11 | % the value of z will be 3 and for a Grayscale 12 | % Image the value of z will be 1 13 | 14 | if z==3 15 | img=rgb2gray(img); 16 | end 17 | 18 | % change the class of image 19 | % array from 'unit8' to 'double' 20 | %img=double(img); 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /Matlab functions/grayImage.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Matlab functions/grayImage.mat -------------------------------------------------------------------------------- /Matlab functions/images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Matlab functions/images.png -------------------------------------------------------------------------------- /Matlab functions/normalization.m: -------------------------------------------------------------------------------- 1 | % Step 1 2 | % takes an input image (3d array) and normalizes it. 3 | % the output values should be between -.5 and .5 4 | 5 | function out = normalization(in) 6 | out = in/255.0 - .5; 7 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image Classification using CNN on FPGA 2 | Project is about designing a Trained Neural n/w (CIFAR-10 dataset) on FPGA to classify an Image I/P using deep-learning concept(CNN- Convolutional Neural Network). 3 | 4 | There are 6 Layers(Sliding Window Convolution, ReLU Activation, Max Pooling, Flattening, Fully Connected and Softmax Activation) which decides the class of our I/P Image. Kernels/Filters are used for feature detection from an Image I/P. Image I/P can be a Greyscale/Colored one. 5 | 6 | # Tools Used 7 | 1. Xilinx Vivado v17.4 8 | 2. Matlab vR2018.a 9 | 10 | # Languages Used 11 | 1. Verilog HDL 12 | 13 | # Tasks Achieved 14 | 1. Got some basic knowledge about FPGA and its Resources, Vivado 17.4, Matlab R2018a. 15 | 2. Verilog modules were created(Matrix Multiplication, Generic MUX, Matrix Convolution, ReLU Activation, Max Pooling) using Vivado 17.4. 16 | 3. Matrix functions were created using Matlab R2018a for reference purpose and matching results. 17 | 4. A Grey-scale Image was considered first (Took a Colored Image(3D Matrix) and Converted to Greyscale Image(2D Matrix) using Matlab) and compared results for both (Verilog modules & Matlab functions) for Matrix Multiplication and ReLU Activation. Results were matching. 18 | 19 | # Contributor 20 | 1. Abhinas Padhi(FPGA Design Engineer) 21 | 2. Shivkumar V(B. M. S. College of Engineering, Bangalore) 22 | -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/cnn2dConvolution.m: -------------------------------------------------------------------------------- 1 | function convolvedFeature = cnn2dConvolution(image, W, b) 2 | 3 | [imageDim, imageDim] = size(image); 4 | 5 | [filterDim, filterDim] = size(W); 6 | 7 | convDim = imageDim - filterDim + 1; 8 | 9 | convolvedImage = zeros(convDim, convDim); 10 | 11 | filter = rot90(squeeze(W),2); 12 | 13 | im = squeeze(image(:, :)); 14 | 15 | convolvedImage = conv2(im,filter,'valid'); 16 | 17 | convolvedImage = convolvedImage + b; 18 | 19 | convolvedFeature(:, :) = convolvedImage; 20 | 21 | end -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/conv.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Testing/Convolution/Matlab/conv.mat -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/conv_output.txt: -------------------------------------------------------------------------------- 1 | -448 -188 -1048 -778 992 1372 2 | -868 -128 -638 -988 812 1772 3 | -1068 -258 72 -448 332 1312 4 | -1038 -548 -938 -98 1742 882 5 | -578 -978 -2928 582 3492 412 6 | -158 -1088 -3558 982 3752 132 7 | -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/gray_img.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Testing/Convolution/Matlab/gray_img.mat -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/rgb2Gray2Mat.m: -------------------------------------------------------------------------------- 1 | % Following MATLAB function will take a grayscale 2 | % or an RGB image as input and will return a 3 | % binary image as output 4 | 5 | function [img] = rgb2Gray2Mat(img) 6 | 7 | [x, y, z]=size(img); 8 | 9 | % if Read Image is an RGB Image then convert 10 | % it to a Gray Scale Image For an RGB image 11 | % the value of z will be 3 and for a Grayscale 12 | % Image the value of z will be 1 13 | 14 | if z==3 15 | img=rgb2gray(img); 16 | end 17 | 18 | % change the class of image 19 | % array from 'unit8' to 'double' 20 | %img=double(img); 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /Testing/Convolution/Matlab/test.m: -------------------------------------------------------------------------------- 1 | clc; 2 | clear all; 3 | close all; 4 | 5 | img = imread('C:\Users\asus2\Desktop\FPGA\Testing & Matching\Convolution\images.png'); 6 | 7 | gray_img = rgb2Gray2Mat(img); 8 | 9 | imshow(gray_img); 10 | 11 | save gray_img.mat 12 | 13 | data = load('gray_img.mat'); 14 | 15 | dlmwrite('C:\Users\asus2\Desktop\FPGA\Testing & Matching\Convolution\mat_input.txt',data.gray_img,'delimiter','\t'); 16 | 17 | %Reading from Text files 18 | 19 | image = dlmread('C:\Users\asus2\Desktop\FPGA\Testing & Matching\Convolution\mat_input.txt'); 20 | 21 | W = dlmread('C:\Users\asus2\Desktop\FPGA\Testing & Matching\Convolution\filter_input2.txt'); 22 | 23 | b = dlmread('C:\Users\asus2\Desktop\FPGA\Testing & Matching\Convolution\bias.txt'); 24 | 25 | %Convolution Operation 26 | 27 | conv = cnn2dConvolution(image,W,b); 28 | 29 | imshow(conv); 30 | 31 | save conv.mat 32 | 33 | data = load('conv.mat'); 34 | 35 | dlmwrite('conv_output.txt',data.conv,'delimiter','\t'); -------------------------------------------------------------------------------- /Testing/Convolution/bias.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /Testing/Convolution/filter_input1.txt: -------------------------------------------------------------------------------- 1 | 10 0 -10 2 | 10 0 -10 3 | 10 0 -10 -------------------------------------------------------------------------------- /Testing/Convolution/filter_input2.txt: -------------------------------------------------------------------------------- 1 | -10 0 10 2 | -10 0 10 3 | -10 0 10 -------------------------------------------------------------------------------- /Testing/Convolution/images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/padhi499/Image-Classification-using-CNN-on-FPGA/18accf9a7e84eb2b3db8c1e451f8ac0c3cb460cb/Testing/Convolution/images.png -------------------------------------------------------------------------------- /Testing/Convolution/mat_input.txt: -------------------------------------------------------------------------------- 1 | 253 254 247 235 220 246 249 252 2 | 253 247 231 232 187 178 247 252 3 | 252 212 235 227 201 192 211 249 4 | 249 226 201 213 215 203 226 249 5 | 253 251 211 223 238 223 250 251 6 | 252 254 238 240 103 240 254 254 7 | 252 252 250 196 65 254 251 253 8 | 251 251 251 212 215 252 253 252 9 | -------------------------------------------------------------------------------- /Verilog Codes/ReLU.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 12/23/2019 12:38:00 PM 7 | // Design Name: 8 | // Module Name: ReLU 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module ReLU #(parameter In_d_W=18)( 24 | input clk, clr, en_act, en_act_out, 25 | input signed [In_d_W-1:0] A, 26 | output reg signed [In_d_W-1:0] Y 27 | ); 28 | reg signed [In_d_W-1:0] X; 29 | always@(posedge clk) 30 | begin 31 | if(clr==1) 32 | begin Y<=0; X<=0; end 33 | else if(clr==0) begin 34 | case({en_act,en_act_out}) 35 | 2'b00: Y<=Y; 36 | 2'b01: Y<=X; 37 | 2'b10: begin 38 | if(A<0) X<='d0; 39 | else if(A>=0) X<=A; 40 | end 41 | 2'b11: begin 42 | if(A<0) X<='d0; 43 | else if(A>=0) X<=A; 44 | Y<=X; 45 | end 46 | endcase 47 | end 48 | end 49 | endmodule 50 | -------------------------------------------------------------------------------- /Verilog Codes/ReLU_Activation.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 12/23/2019 01:35:53 PM 7 | // Design Name: 8 | // Module Name: ReLU_Activation 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module ReLU_Activation #(parameter In_d_W=18,R=3,C=3) ( // 23 | input clk,clr,en_act,en_act_out, 24 | input [(In_d_W * R * C)-1:0] X, 25 | output [(In_d_W * R * C)-1:0] Z 26 | ); 27 | 28 | wire [In_d_W-1:0] B [0:R*C-1]; 29 | wire [In_d_W-1:0] D [0:R*C-1]; 30 | 31 | generate 32 | genvar i; 33 | for(i=0; i=R*C*In_d_W) 46 | begin 47 | assign Wrow[j+In_d_W-1:j]='d0; 48 | assign Wcol[j+In_d_W-1:j]='d0; 49 | end 50 | end 51 | endgenerate 52 | 53 | c_counter_binary_0 common( 54 | .CLK(clk), // input wire CLK 55 | .CE(clk_en), // input wire CE 56 | .SCLR(clr), // input wire SCLR 57 | .Q(addr_com) // output wire [3 : 0] Q 58 | ); 59 | 60 | mux_g #((In_d_W*(2**In_Add_W)),In_Add_W) MUXrow(.A(Wrow),.S(addr_com),.Y(din_r)); 61 | 62 | mux_g #((In_d_W*(2**In_Add_W)),In_Add_W) MUXcol(.A(Wcol),.S(addr_com),.Y(din_c)); 63 | 64 | matrix_multiplier #(In_d_W,In_Add_W,R*C,Timeperiod) DUT(.clk(clk),.rst(rst),.clr(clr),.ena_r(en_wr),.ena_c(en_wr),.enb_r(en_rd), 65 | .enb_c(en_rd),.wea_r(wr),.wea_c(wr),.din_r(din_r),.din_c(din_c),.addra_r(addr_com),.addrb_r(addr_com),.addra_c(addr_com), 66 | .addrb_c(addr_com),.en_MAC(en_MAC),.en_MAC_out(en_MAC_out),.y(Y)); 67 | 68 | endmodule -------------------------------------------------------------------------------- /Verilog Codes/counter_g.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 01/17/2020 01:18:19 PM 7 | // Design Name: 8 | // Module Name: counter_g 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module counter_g #(Add_W=4)( 24 | input CLK,RST, 25 | input CE, 26 | input SCLR, 27 | output reg [Add_W-1:0] Q 28 | ); 29 | 30 | always@(posedge CLK) 31 | begin 32 | if(RST==0) 33 | Q<=0; 34 | else if(SCLR==1) 35 | Q<=0; 36 | else if(CE==0) 37 | Q<=Q; 38 | else if(CE==1) 39 | Q<=Q+1; 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /Verilog Codes/mac_generic.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/12/2019 12:02:06 PM 7 | // Design Name: 8 | // Module Name: mac_generic 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module mac_generic #(parameter I_W=8)( 23 | input clk, 24 | input rst, 25 | input clr, 26 | input en_MAC, 27 | input signed [I_W-1:0] A, 28 | input signed [I_W-1:0] B, 29 | input en_MAC_out, 30 | output reg signed [(2*I_W)+1:0] Y 31 | ); 32 | reg [(2*I_W)+1:0] temp1,temp2; 33 | always@(posedge clk) 34 | begin 35 | if(rst==0) begin temp1<=0; temp2<=0; Y<=0; end 36 | 37 | else if(clr==1) begin temp1<=0; temp2<=0; Y<=0; end 38 | 39 | else if(rst==1 & clr==0) begin 40 | case({en_MAC,en_MAC_out}) 41 | 2'b00: begin temp1<=0; temp2<=temp2+temp1; Y<=0; end 42 | 2'b01: begin temp1<=0; temp2<=temp2+temp1; Y<=temp2; end 43 | 2'b10: begin temp1<=A*B; temp2<=temp2+temp1; Y<=0; end 44 | 2'b11: begin temp1<=A*B; temp2<=temp2+temp1; Y<=temp2; end 45 | endcase 46 | end 47 | end 48 | endmodule 49 | -------------------------------------------------------------------------------- /Verilog Codes/matrix_multiplier.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 11/12/2019 12:32:33 PM 7 | // Design Name: 8 | // Module Name: matrix_multiplier 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module matrix_multiplier #(parameter In_W=8,In_D_Add_W=4,In_Items=6,Timeperiod=10)( 23 | input clk, 24 | input rst, 25 | input clr, 26 | input ena_r,ena_c, 27 | input enb_r,enb_c, 28 | input wea_r,wea_c, 29 | //input web_r,web_c, 30 | input signed [In_W-1:0] din_r,din_c, 31 | input [In_D_Add_W-1:0] addra_r,addrb_r,addra_c,addrb_c, 32 | input en_MAC, 33 | input en_MAC_out, 34 | output signed [((2*In_W)+2)-1:0] y ); 35 | 36 | wire [In_D_Add_W-1:0] addr_r,addr_c; 37 | wire [In_W-1:0] row_in,col_in; 38 | 39 | blk_mem_gen_0 ROW ( 40 | .clka(clk), // input wire clka 41 | .ena(ena_r), // input wire ena 42 | .wea(wea_r), // input wire [0 : 0] wea 43 | .addra(addra_r), // input wire [3 : 0] addra 44 | .dina(din_r), // input wire [7 : 0] dina 45 | .clkb(clk), // input wire clkb 46 | .enb(enb_r), // input wire enb 47 | .addrb(addrb_r), // input wire [3 : 0] addrb 48 | .doutb(row_in) // output wire [7 : 0] doutb 49 | ); 50 | 51 | blk_mem_gen_0 COLUMN ( 52 | .clka(clk), // input wire clka 53 | .ena(ena_c), // input wire ena 54 | .wea(wea_c), // input wire [0 : 0] wea 55 | .addra(addra_c), // input wire [3 : 0] addra 56 | .dina(din_c), // input wire [7 : 0] dina 57 | .clkb(clk), // input wire clkb 58 | .enb(enb_c), // input wire enb 59 | .addrb(addrb_c), // input wire [3 : 0] addrb 60 | .doutb(col_in) // output wire [7 : 0] doutb 61 | ); 62 | 63 | mac_generic #(In_W) MAC(.clk(clk),.rst(rst),.clr(clr),.en_MAC(en_MAC),.A(row_in),.B(col_in),.en_MAC_out(en_MAC_out),.Y(y)); 64 | 65 | endmodule -------------------------------------------------------------------------------- /Verilog Codes/max_data.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 01/02/2020 01:05:13 PM 7 | // Design Name: 8 | // Module Name: max_data 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module max_data #(parameter In_d_W=8, R=3, C=3)( 23 | input [(In_d_W*R*C)-1:0] A, 24 | output [In_d_W-1:0] Y 25 | ); 26 | 27 | wire [In_d_W-1:0] X [0:(R*C)-1]; 28 | wire [In_d_W-1:0] Z [0:(R*C)-1]; 29 | 30 | generate 31 | genvar i; 32 | for(i=0;i<(In_d_W*R*C);i=i+In_d_W) 33 | begin 34 | assign X[i/In_d_W]=A[i+In_d_W-1:i]; 35 | end 36 | endgenerate 37 | 38 | generate 39 | genvar j; 40 | assign Z[0]=X[0]; 41 | for(j=0;j<(R*C)-1;j=j+1) 42 | begin 43 | max_value #(In_d_W) DUT(.A(Z[j]),.B(X[j+1]),.Y(Z[j+1])); 44 | end 45 | assign Y=Z[(R*C)-1]; 46 | endgenerate 47 | endmodule 48 | -------------------------------------------------------------------------------- /Verilog Codes/max_pooling.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 01/06/2020 11:56:13 AM 7 | // Design Name: 8 | // Module Name: max_pooling 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module max_pooling #(parameter In_W=18, R=3, C=3, R_P=2, C_P=2, P=0, S=1, Timeperiod=10) ( 24 | input clk, 25 | input rst, 26 | input clr, 27 | input en_pool, 28 | input en_pool_out, 29 | input [(In_W*R*C)-1:0] N, //[161:0] N 30 | output reg [((In_W)*(((R+(2*P)-R_P)/S)+1)*(((C+(2*P)-C_P)/S)+1))-1:0] Y //[71:0] Y 31 | ); 32 | 33 | wire [(In_W*(((R+(2*P)-R_P)/S)+1))-1:0] Z [0:(((((R+(2*P)-R_P)/S)+1)*C)-1)]; // [35:0] Z [0:5] 34 | wire [(In_W*R_P*C_P)-1:0] X [0:((((((R+(2*P)-R_P)/S)+1)*(((C+(2*P)-C_P)/S)+1)))-1)]; // [71:0] X [0:3] 35 | //wire [In_W-1:0] W1 [0:((((((R+(2*P)-R_P)/S)+1)*(((C+(2*P)-C_P)/S)+1)))-1)]; // [17:0] W1 [0:3] 36 | wire [((((R+(2*P)-R_P)/S)+1)*(((C+(2*P)-C_P)/S)+1)*In_W)-1:0] W; // [71:0] W 37 | reg [((((R+(2*P)-R_P)/S)+1)*(((C+(2*P)-C_P)/S)+1)*In_W)-1:0] temp; 38 | 39 | generate 40 | genvar i,j; 41 | for(i=0;iB) 31 | Y<=A; 32 | else if(A<=B) 33 | Y<=B; 34 | end 35 | endmodule 36 | -------------------------------------------------------------------------------- /Verilog Codes/mux_2x1.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 01/14/2020 04:51:34 PM 7 | // Design Name: 8 | // Module Name: mux_2x1 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module mux_2X1 #(parameter In_d_W=8)( 24 | input [In_d_W-1:0] I0, 25 | input [In_d_W-1:0] I1, 26 | input Sel, 27 | output [In_d_W-1:0] Y 28 | ); 29 | 30 | assign Y=(Sel==0)?I0:I1; 31 | endmodule 32 | -------------------------------------------------------------------------------- /Verilog Codes/mux_g.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 01/16/2020 01:03:24 PM 7 | // Design Name: 8 | // Module Name: mux_g 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module mux_g #(parameter In_d_W=16*8, S_W=4)( //Over here, this mux works like, I have 128 bit as I/P and I need 8 bit O/P. So, 128/8=16 24 | //Therefore, S=4 as 2^4=16 25 | input [In_d_W-1:0] A, 26 | input [S_W-1:0] S, 27 | output [(In_d_W/(2**S_W))-1:0] Y 28 | ); 29 | parameter Out_d_W=In_d_W/(2**S_W); 30 | wire [Out_d_W-1:0] W [0:(2**S_W)-1]; 31 | generate 32 | genvar i; 33 | for(i=0; i<(2**S_W); i=i+1) 34 | begin 35 | assign W[i]=A[ (i*Out_d_W)+Out_d_W-1 : i*Out_d_W ]; 36 | end 37 | endgenerate 38 | 39 | assign Y=W[S]; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /Verilog Codes/slide_window_conv.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 12/16/2019 01:03:43 PM 7 | // Design Name: 8 | // Module Name: slide_window_conv 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | module slide_window_conv #(parameter In_d_W=8, In_Add_W=4, R_N=5, C_N=5, R_F=3, C_F=3, P=0, S=1, Timeperiod=10) ( 23 | input clk,clk_en,rst,clr,en_wr,en_rd,wr,en_MAC,en_MAC_out, //wr=1 (Write), wr=0 (Read) 24 | input [(C_N*R_N*In_d_W)-1:0] N, // [199:0] N 25 | input [(C_F*R_F*In_d_W)-1:0] F, // [71:0] F 26 | output [(((2*In_d_W)+2)*(((R_N+(2*P)-R_F)/S)+1)*(((C_N+(2*P)-C_F)/S)+1))-1:0] Y // [161:0] Y 27 | ); 28 | parameter R_O=(((R_N+(2*P)-R_F)/S)+1); //3 29 | parameter C_O=(((C_N+(2*P)-C_F)/S)+1); //3 30 | parameter Out_d_W=((2*In_d_W)+2); //18 31 | //wire [(In_d_W*R_N)-1:0] X [0:(C_N-1)]; // [39:0] X [0:4] 32 | wire [(In_d_W*R_O)-1:0] Z [0:((R_O*C_N)-1)]; // [23:0] Z [0:14] 33 | wire [(In_d_W*R_F*C_F)-1:0] A [0:(R_O*C_O)-1]; // [71:0] A [0:8] 34 | wire [Out_d_W-1:0] W [0:(R_O*C_O)-1]; // [17:0] W [0:8] 35 | 36 | generate 37 | genvar i,j; 38 | for(i=0;i