summaryrefslogtreecommitdiffstats
path: root/sobel.cpp
blob: 3654422e36e2d08cd116c1932af637e27a20b477 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
////////////////////////////////////////////////////////////////////////////////
//  _____                           _       _    _____      _ _
// |_   _|                         (_)     | |  / ____|    | | |
//   | |  _ __ ___  _ __   ___ _ __ _  __ _| | | |     ___ | | | ___  __ _  ___
//   | | | '_ ` _ \| '_ \ / _ \ '__| |/ _` | | | |    / _ \| | |/ _ \/ _` |/ _ \
//  _| |_| | | | | | |_) |  __/ |  | | (_| | | | |___| (_) | | |  __/ (_| |  __/
// |_____|_| |_| |_| .__/ \___|_|  |_|\__,_|_|  \_____\___/|_|_|\___|\__, |\___|
//                 | |                                                __/ |
//                 |_|                                               |___/
//  _                     _
// | |                   | |
// | |     ___  _ __   __| | ___  _ __
// | |    / _ \| '_ \ / _` |/ _ \| '_ \
// | |___| (_) | | | | (_| | (_) | | | |
// |______\___/|_| |_|\__,_|\___/|_| |_|
//
////////////////////////////////////////////////////////////////////////////////
//  File:           sobel.cpp
//  Description:    video to vga sobel filter - real-time processing
//  By:             rad09
////////////////////////////////////////////////////////////////////////////////
// this hardware block receives the VGA stream and then produces a blured output
// based on the FIR design - page 230 of HLS Blue Book
////////////////////////////////////////////////////////////////////////////////
// Catapult Project options
// Constraint Editor:
//  Frequency: 50 MHz
//  Top design: sobel
//  clk>reset sync: disable; reset async: enable; enable: enable
// Architecture Constraints:
//  interface>vin: wordlength = 90, streaming = 90
//  interface>vout: wordlength = 30, streaming = 30
//  core>main: pipeline + distributed + merged
//  core>main>frame: merged
//  core>main>frame>shift, mac1, mac2: unroll + merged
////////////////////////////////////////////////////////////////////////////////


#include <ac_fixed.h>
#include "sobel.h"
#include <iostream>

// shift_class: page 119 HLS Blue Book
#include "shift_class.h" 




#pragma hls_design top
void sobel(ac_int<PIXEL_WL*KERNEL_WIDTH,false> vin[NUM_PIXELS], ac_int<PIXEL_WL,false> vout[NUM_PIXELS])
{
    ac_int<16, false> intensity, inte[KERNEL_WIDTH];
    

// #if 1: use filter
// #if 0: copy input to output bypassing filter
#if 1

    // shifts pixels from KERNEL_WIDTH rows and keeps KERNEL_WIDTH columns (KERNEL_WIDTHxKERNEL_WIDTH pixels stored)
    static shift_class<ac_int<PIXEL_WL*KERNEL_WIDTH,true>, KERNEL_WIDTH> regs;
    int i;

    FRAME: for(int p = 0; p < NUM_PIXELS; p++) {
		// init
		intensity = 0;
		RESET: for(i = 0; i < KERNEL_WIDTH; i++) {
			inte[i] = 0;
		}
	    
		// shift input data in the filter fifo
		regs << vin[p]; // advance the pointer address by the pixel number (testbench/simulation only)
		// accumulate
		ACC1: 
		for (i = 0; i < KERNEL_WIDTH; ++i)
		{
		    inte[0] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL))*XMATRIX[0][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL))*XMATRIX[0][i])+((regs[i].slc<COLOUR_WL>(0))*XMATRIX[0][i])) / 3;
		    inte[0] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL))*YMATRIX[0][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL))*YMATRIX[0][i])+((regs[i].slc<COLOUR_WL>(0))*YMATRIX[0][i])) / 3;
		    
		    inte[1] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL + PIXEL_WL))*XMATRIX[1][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL + PIXEL_WL))*XMATRIX[1][i])+((regs[i].slc<COLOUR_WL>(PIXEL_WL))*XMATRIX[1][i])) / 3;
		    inte[1] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL + PIXEL_WL))*YMATRIX[1][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL + PIXEL_WL))*YMATRIX[1][i])+((regs[i].slc<COLOUR_WL>(PIXEL_WL))*YMATRIX[1][i])) / 3;
		    
		    inte[2] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL + 2*PIXEL_WL))*XMATRIX[2][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL + 2*PIXEL_WL))*XMATRIX[2][i])+((regs[i].slc<COLOUR_WL>(2*PIXEL_WL))*XMATRIX[2][i])) / 3;
		    inte[2] += (((regs[i].slc<COLOUR_WL>(2*COLOUR_WL + 2*PIXEL_WL))*YMATRIX[2][i])+((regs[i].slc<COLOUR_WL>(COLOUR_WL + 2*PIXEL_WL))*YMATRIX[2][i])+((regs[i].slc<COLOUR_WL>(2*PIXEL_WL))*YMATRIX[2][i])) / 3;
		}
		// add the accumualted value for all processed lines
		ACC2: 
		for(i = 0; i < KERNEL_WIDTH; i++) 
		{    
			intensity += inte[i];
		}
		

		
		// normalize result
		intensity /= 2*KERNEL_NUMEL;
	    
		// group the RGB components into a single signal
		vout[p] = ((((ac_int<PIXEL_WL, false>)intensity) << (2*COLOUR_WL)) | (((ac_int<PIXEL_WL, false>)intensity) << COLOUR_WL) | (ac_int<PIXEL_WL, false>)intensity);
	    
    }
}   
     
     
     
     
#else    
// display input  (test only)
    FRAME: for(p = 0; p < NUM_PIXELS; p++) {
        // copy the value of each colour component from the input stream
        red = vin[p].slc<COLOUR_WL>(2*COLOUR_WL);
        green = vin[p].slc<COLOUR_WL>(COLOUR_WL);
        blue = vin[p].slc<COLOUR_WL>(0);

		// combine the 3 color components into 1 signal only
        vout[p] = ((((ac_int<PIXEL_WL, false>)red) << (2*COLOUR_WL)) | (((ac_int<PIXEL_WL, false>)green) << COLOUR_WL) | (ac_int<PIXEL_WL, false>)blue);   
    }
}
#endif


// end of file