Engineering presentation
FPGA Workshop, OIST 1
Implementing Image Processing Implementing Image Processing Algorithms on FPGAsAlgorithms on FPGAs
Donald Bailey School of Engineering and Advanced Technology
Massey University, Palmerston North, New Zealand
[email protected] http://sprg.massey.ac.nz
FPGA Workshop, OIST 2
Workshop AimsWorkshop Aims • Demonstrate that FPGAs and image processing are
a natural fit • Introduce development tools
– VHDL, Quartus II • Develop basic interfaces to camera and display • Provide hands on experience in implementing basic
image processing operations – Colour, histograms, basic filters, object tracking
• Provide solid foundation for implementing more advanced designs
FPGA Workshop, OIST 3
TimetableTimetable Tuesday 21 Wednesday 22
9:00 1: Image Processing and FPGAs 5: FPGA Based Design and Algorithm Implementation9:30
10:00 10:30 Break Break 11:00 2: Introduction to VHDL 6: Histogram Processing 11:30 Lab: Using Quartus
VHDL display driver Lab: Histogram display, histogram
equalisation12:00 12:30 Lunch Lunch 1:00 1:30 3: Image Capture 7: Colour 2:00 Lab: Camera interface, Bayer filtering
Auto-exposure Lab: Colour detection
Colour tracking2:30 3:00 Break Break 3:30 4: Image Filters, convolution, morphology 8: Frequency domain processing 4:00 Lab: Sobel filter
CORDIC arithmetic Lab: FFT
4:30
FPGA Workshop, OIST 4
Session 1:Session 1: Image ProcessingImage Processing
and and FPGAsFPGAs
FPGA Workshop, OIST 5
Image Processing and Image Processing and FPGAsFPGAs
• Objectives: – Present basic definitions – Outline issues of embedded image processing on a
conventional platform – Show how image processing is inherently parallel
• Particularly low level pre-processing operations
– Describe basic architecture of FPGAs – Overview of the design flow for programming FPGAs
FPGA Workshop, OIST 6
ImagesImages • A spatial representation of an object or scene
– Photograph (a pictorial record formed by a sensor) – Map (a representation of physical or cultural features)
• More formally: – A continuous function of 2 or more variables defined on
some bounded region of space • Digital image
– An image in a form suitable for processing by computer
– Basically an array of numbers Pixel
FPGA Workshop, OIST 7
Digital Image ProcessingDigital Image Processing • Subjecting an image to a series of mathematical
operations in order to obtain a desired result Digital Image
An array of numbers (or vectors for colour)
Desired result
Enhanced image Measurement Classification Grading Description
A sequence of image processing operations
Operation
Operation
Operation
Image Processing Algorithm
FPGA Workshop, OIST 8
for i=1 to rows for j=1 to columns diff = a[i,j]–b[i,j] if diff < 0 c[i,j] = 0
else c[i,j] = diff
Image Processing AlgorithmsImage Processing Algorithms
Operation level algorithm – Programme sequence
implementing the image processing operation
Application level algorithm – Sequence of image processing operations
greyscale opening
subtract original
threshold
FPGA Workshop, OIST 9
Image RepresentationsImage Representations • Low level
– Array of pixels • Intermediate level: image
– Regions – Chain codes – Linear approximation of edges
• Intermediate level: feature – Sets of features – Labels
• High level – Description of object or scene
6 corners Hole area = 760 pixels
Hexagonal ¼ inch nut
Increasing abstraction
D ecreasing
volum e
Increasing value
FPGA Workshop, OIST 10
Operation PyramidOperation Pyramid
Low level
High level
Intermediate level
Pixels
Features
Objects
Image representations
Preprocessing
Segmentation
Classification
Recognition
Operations
Regions
FPGA Workshop, OIST 11
Typical Processing StepsTypical Processing Steps • Preprocessing: Image to image transformation
– Enhance relevant information – Suppress irrelevant information
• Segmentation: Image to region transformation – Detects objects or regions in an image which have a
common property • Classification: Region to feature to label transformation
– Identification of parts of objects – Data no longer image based
• Recognition: Label to description transformation
FPGA Workshop, OIST 12
Real Time Image ProcessingReal Time Image Processing • Real-time systems
– Response must occur within specified time to avoid failure • Machine vision, robot vision, video transmission
• Hard real time – Complete system fails if response is not produced in time
• Grading: decision must be made before activation point • Image capture and display subsystems
• Soft real time – Performance deteriorates if response time not met
• Video transmission
• Not necessarily the same as high performance
FPGA Workshop, OIST 13
• More pixels and higher frame rates means more computation required to process an image – VGA resolution video
• 640 x 480 x 60 frames per second = 18.5 million pixels per second
– HDTV (1080p) • 1920 x 1080 x 50 frames per second = 104 million pixels per second
– Ultra high definition TV • 7680 x 4320 x 60 frames per second
= 2 billion pixels per second
• Image processing requires many operations per pixel!
Processor Power RequiredProcessor Power Required
FPGA Workshop, OIST 14
Embedded VisionEmbedded Vision • Vision embedded within a product or component • Constraints on embedded systems
– Small size – Light weight – Low power
• Smart cameras – Intelligent surveillance – Robot vision – Machine vision – Industrial inspection – Using vision for control
FPGA Workshop, OIST 15
Traditional ComputingTraditional Computing • Basic architecture:
– Fetch instruction / Decode / Execute instruction – Serial processing
• All of the work done by the ALU • Rest of CPU designed to feed ALU as fast as possible
• So much to do, so little time to do it! – With serial processors, time is often the critical resource
• Because can only do one thing to one pixel at a time
– Some problems don’t “fit” serial processors
FPGA Workshop, OIST 16
Von Neumann BottleneckVon Neumann Bottleneck • Serial processing is memory oriented
– Most variables are in memory – A significant proportion of the time is spent accessing
memory • Reading operands • Writing intermediate results
– Memory uses a single monolithic address space • Consequences
– Data passes between the ALU and memory many times during a complex calculation
– Memory bandwidth ultimately limits the algorithm speed
FPGA Workshop, OIST 17
Solution: Parallel ProcessingSolution: Parallel Processing • Dedicated hardware for critical parts
– Hardware is parallel – Uses local registers for intermediate results
• Do more things at once – Parallel processing – Each processor has its own local memory
• Parallel processing is not new – Almost as old as image processing itself
• Image processing has often been a driver for parallel computing
– Only recently have FPGAs had sufficient resources to make them a practical platform
FPGA Workshop, OIST 18
Temporal ParallelismTemporal Parallelism • Algorithms usually consist of a sequence of separate
operations – Use a separate processor for each operation
– Leads to a pipelined architecture at the operation level • Limitations
– Less suited to iterative algorithms – Bandwidth in passing data between operations
Processor 1 Operation 1
Processor 2 Operation 2
Processor 3 Operation 3
FPGA Workshop, OIST 19
Spatial ParallelismSpatial Parallelism • Many operations perform the same function
independently on a large number of pixels – Split the image over a number of separate processors
– Can lead to a single instruction multiple data (SIMD) type architecture
– Most efficient when communication between processors is minimised • When operations only require data from a local region
Row Column Block
FPGA Workshop, OIST 20
Logical ParallelismLogical Parallelism • Functional block reuse in an algorithm
– Example: compare and swap for a bubble sort (rank filter)
<
Min Max
FPGA Workshop, OIST 21
Stream ProcessingStream Processing • Image is scanned to produce a
sequential stream of pixels – Converts spatial parallelism into
temporal parallelism – Each pixel is processed sequentially
• Removes need for parallel data access
• Fits with a pipelined architecture – Data is streamed between operations in a pipeline – Fine grained pipelining with an operation
0 1 2 3 … M 0 1 2 3 … M 0 1 2 3 … M 0 1 2 3 … M 0 1 2 3 … M 0 1 2 3 … M
0 1 2 3 4 5 6 7
… N
0 1 2 3 4 5 6 7 … M Column
R ow
Row 0 Row 1 Row 2 Row 3 … Row N
Time
FPGA Workshop, OIST 22
Parallelism SummaryParallelism Summary • Image processing algorithms have parallelism at a
wide range of granularities – Pipelining operations in the algorithm
• Temporal parallelism – Unrolling the outer loop through
the pixels of an image • Spatial parallelism
– Unrolling the inner loops • Logical parallelism
• All of these can be exploited in a hardware based implementation – FPGAs are just programmable hardware
for { XXXX
}
XXXX XXXX XXXX
FPGA Workshop, OIST 23
Basic FPGA ArchitectureBasic FPGA Architecture
I/O block
I/O block
I/O block
I/O block
I/O block
I/O block
I/O block
I/O block
I/O block
I/O block
Configuration control
Clock control
Programmable logic blocks
Programmable interconnects
FPGA Workshop, OIST 24
Logic CellLogic Cell • Smallest unit of logic on an FPGA • Based on a lookup table
– Output is an arbitrary function of its inputs • Early devices had 3 or 4 inputs • Modern devices have 5 or 6 inputs
– Used to implement logic, adders, counters, multiplexers, etc
– More complex functions require multiple LUTs
• Output also has a flip-flop – Used to build registers, finite state machines, etc
FPGA Workshop, OIST 25
Logic BlockLogic Block • Several logic cells combined together
– Typically 4-10 logic cells – Share common control signals (clock, clock enable)
• Outputs directly available to other inputs – Reduces propagation delay for deeper logic
• Additional dedicated logic – Reduces propagation delay for more complex logic
functions • Some FPGAs allow logic cells or logic blocks to be
used as RAM or shift registers
FPGA Workshop, OIST 26
Dedicated LogicDedicated Logic • Carry chains
– A full adder requires 2 outputs • Sum and carry
– Separate carry hardware allows 1 LUT per bit added • Multiplexer controls
– Combines outputs of multiple LUTs for wider functions – Enables wide multiplexers and more complex logic
functions to be built more efficiently • DSP blocks
– Hardware multiplier or multiply and accumulate • Reduces logic required and propagation delay for DSP applications
FPGA Workshop, OIST 27
Fabric RAMFabric RAM • Adapts structure of LUTs to enable them to be used
as small memories – 16×1 or 32×1 memory (depending on FPGA) – Adjacent blocks combine to make a dual-port memory – True dual-port
• Both ports can be used for read and write – Simple dual-port
• One port is read only and one write only – Used for banks of registers or coefficient memory
• Only one access per port per clock cycle
• Some FPGAs also allow LUTs to be configured as short shift registers
FPGA Workshop, OIST 28
Other Memory ResourcesOther Memory Resources • Dual port block RAM
– Larger blocks • 512 bits – 576 Kbits depending on family
– Flexible word width • Eg 36 Kbit block can be configured from 32K×1 to 512×72
– Each block is independent • Local memories • Potentially wide bandwidth
– Used for FIFO buffers, data caching, large lookup tables • External RAM
– Used for larger blocks (frame buffers, etc)
FPGA Workshop, OIST 29
InterconnectInterconnect • Flexibly connects the logic resources • Based on a grid structure
– Crossbar switches enable connection between horizontal and vertical routing lines
– Often a segmented structure is used • Not every routing line is switched at every junction • Reduces propagation delay
• Some FPGAs have busses as well – Requires tri-state drivers – Only one source may drive the line at a time
FPGA Workshop, OIST 30
Input and OutputInput and Output • Connects FPGA to
external devices • Basic interface
– LVTTL and LVCMOS • Advanced signalling
– Double data rate (DDR) • Data transferred on rising and falling edges of the clock
– Differential signalling (LVDS) • Uses two differential I/O bits to improve noise immunity
– High speed communication signals include parallel-to-serial and serial-to-parallel conversion • Serialisation and deserialisation (SERDES) logic
FPGA Workshop, OIST 31
ClockingClocking • FPGAs are synchronous devices • Each register, memory, I/O controlled by a clock
– Each block can be controlled by only one clock – A clock domain is all of the logic controlled by a clock
• FPGAs use a dedicated clock network – Minimises the skew between parts of a design – Manages the large fan-out required
• Special clock control blocks – Delay locked loops
• Synchronise clocks with external sources and minimise skew – Phase locked loops:
• Synthesise different clock frequencies from a reference clock
FPGA Workshop, OIST 32
FPGA ConfigurationFPGA Configuration • FPGA contents controlled internally by SRAM cells
– Allows infinite reprogrammability – Configuration is volatile
• Must be reloaded on power on • Commonly loaded from a small ROM • Some FGPAs enable encryption and
compression of configuration file – Configuration specifies
• LUT function • Register controls • Interconnect • I/O configuration • Memory contents
ROM
SRAM FPGA
Configuration file
FPGA Workshop, OIST 33
FPGAsFPGAs for Image Processingfor Image Processing • FPGAs are programmable hardware
– Each logic block is independent hardware – Parallel algorithm implemented on parallel hardware
• Able to exploit parallelism inherent in images – Separate hardware built for each operation
• Coarse grained pipelining – Partition image over several parallel function blocks
• Spatial parallelism / SIMD type parallelism – Stream processing can feed image data serially through a
single function block – Duplicated logic from unrolling inner loops
• Functional parallelism
FPGA Workshop, OIST 34
FPGAsFPGAs for Embedded Visionfor Embedded Vision • Parallelism enables a lower clock speed
– Often by 2 or 3 orders of magnitude – Slower clock enables a lower power design
• If whole algorithm can be implemented on an FPGA – Small form factor
• Only 1 or 2 chips (plus power supplies)
– Enables vision to be embedded into a design • Smart sensors and cameras • Integrated applications
FPGA Workshop, OIST 35
Benefits of Benefits of FPGAsFPGAs • FPGAs if used correctly can give
– Significant acceleration of the processing – Improvements in both latency and throughput
• While achieving – Lower clock speed – Lower power
• Enabling – Embedded vision – Smart cameras – Efficient real-time processing
FPGA Workshop, OIST 36
Limitations of Limitations of FPGAsFPGAs • FPGAs are hard to programme
– FPGA based design is hardware design not software – Image processing normally thought of as software
• Large code base of image processing software • Algorithms have to be redeveloped for efficient hardware
implementation
• Parallel hardware requires a hardware mindset – Parallel programming is difficult
• Concurrency, synchronisation, contention, bandwidth • FPGAs are fine grained parallelism
– Results in an explosion in design space complexity
FPGA Workshop, OIST 37
Programming Programming FPGAsFPGAs
• Representation – Basically parallel languages describing hardware – Range of styles and levels of abstractions
• Structural – describes connections between blocks • Concurrent – describes in terms of assignments to registers • Behavioural – describes behaviour in terms of events and
responses
– Compiles to enable a simulation
Behavioural and functional simulation
Design
Representation
FPGA Workshop, OIST 38
Programming Programming FPGAsFPGAs
• Synthesis – Converts logical representation to a device or gate level net-
list • Constraints control aspects of the synthesis
– Optimising for speed or area, type of resets, etc
Synthesis constraints
Behavioural and functional simulation
Gate level simulation
Design
Representation
Synthesis
FPGA Workshop, OIST 39
Programming Programming FPGAsFPGAs
• Mapping – maps the logic onto the resources • Place and route – associates these with particular logic
blocks, I/Os etc on the FPGA
Synthesis constraints
Implementation constraints
Behavioural and functional simulation
Timing simulation
Gate level simulation
Design
Representation
Map Place & route
Synthesis
FPGA Workshop, OIST 40
Programming Programming FPGAsFPGAs
Synthesis constraints
Implementation constraints
Behavioural and functional simulation
Timing simulation
Gate level simulation
In system verification
Design
Representation
Map Place & route
Generate configuration file
Synthesis
Implementation
FPGA Workshop, OIST 41
Session 2:Session 2: VHDLVHDL
FPGA Workshop, OIST 42
VHDLVHDL • Objectives:
– Introduce basic structure and syntax of VHDL • Different programming styles and where they are used
– Develop a basic display driver
• Laboratory objectives – Familiarise with Quartus II tools
• Creating project • Design entry • Timing • Compilation • Implementation
FPGA Workshop, OIST 43
• Main standards: – VHDL, Verilog
• Hierarchical structural languages – Design can be broken into a series of hierarchical blocks
• Main purposes – Documentation – Modelling and verification – Simulation – Synthesis was added later
• Only a subset of the language is synthesisable
Hardware Description LanguagesHardware Description Languages
FPGA Workshop, OIST 44
Hierarchical DesignHierarchical Design • VHDL enables a hierarchical design
– Design can be built in terms of component blocks – Top level contains all inputs and outputs for a design
• Each component is defined by an entity – Entity specifies the interface to the component
• Inputs and outputs • Constant parameters
– Architecture contains the component implementation • An entity may have multiple architectures for different implementations
FPGA Workshop, OIST 45
VHDL EntitiesVHDL Entities • Each component is defined by an entity
– The entity specifies the interface to the component • The view from the outside (black box representation)
– Example we will use is an adder / subtracter
add / subtract
n
n n
a
b
control
q
FPGA Workshop, OIST 46
VHDL EntitiesVHDL Entities • Each component is defined by an entity
– The entity specifies the interface to the component – Implementation is in the corresponding architecture
• An entity may have multiple architectures for different implementations library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;
entity add_sub is generic (n : positive := 4); port (a, b : in signed (n-1 downto 0);
control : in std_logic; q : out signed (n-1 downto 0));
end entity add_sub;
architecture implement of add_sub is … end architecture implement;
Implementation
External libraries
generics provide parameterisation ports define input and output connections
FPGA Workshop, OIST 47
VHDL TypesVHDL Types • Built in types:
• boolean, integer, real, bit, character, string, time, file
– Subtypes: • positive, natural
• Hardware types (in std_logic_1164 library) • std_logic
– Signal on a wire: '0', '1', 'U', '-', 'Z', 'L', 'H', 'X', 'W' • std_logic_vector
– An array or bundle of wires: "00100110", x"26"
• Numeric types (in numeric_std library) • signed, unsigned
FPGA Workshop, OIST 48
Structural Coding StyleStructural Coding Style • Builds a component in terms of other components
– Design is built as a hierarchy of components
n
n
n
a
control
q
b
sumb a
q
diffb a
q
muxb a
q sel
s
d
add:
sub:
sel:
FPGA Workshop, OIST 49
Structural Coding StyleStructural Coding Style • Builds a component in terms of other components
– Design is built as a hierarchy of components architecture structural of add_sub is
component sum generic (n : positive); port (a,b : in signed (n-1 downto 0);
q : out signed (n-1 downto 0)); end component; component diff … end component; component mux … end component;
signal s, d : signed (n-1 downto 0); begin
add: sum generic map(n=> ) port map( a=> , b=> , q=> );
sub: diff generic map(n=> ) port map( a=> , b=> , q=> );
sel: mux generic map(n=> ) port map( a=> , b=> , sel=> , q=> );
end architecture structural;
Definition of constituent components
Local connection signals
add: sum generic map(n=>n) port map( a=>a, b=>b, q=>s );
sub: diff generic map(n=>n) port map( a=>a, b=>b, q=>d );
sel: mux generic map(n=>n) port map( a=>s, b=>d, sel=>control, q=>q );
end architecture structural;
Instantiating components
Explicit port mapping
FPGA Workshop, OIST 50
Concurrent Coding StyleConcurrent Coding Style • Focus is on concurrent signal assignments
– Models the operation of the component in terms of the data flow through the logic
– Whenever a variable on RHS changes, the statement is evaluated and immediately assigned to LHS • Order of assignments is not important – they are in parallel architecture concurrent of add_sub is
signal s, d : signed (n-1 downto 0); begin
s <= a + b; d <= a – b;
mux: for i = 0 to n-1 generate
q(i) <= (control and s(i)) or (not control and d(i)); end generate mux;
end architecture concurrent;
Local connections
generate loop
Concurrent assignments
FPGA Workshop, OIST 51
Concurrent AssignmentsConcurrent Assignments • Straight signal assignment
• Conditional assignment – Builds a multiplexer – Priority coded if have a sequence of conditions
• Selected assignment
sum <= a + b;
q <= a + b when control = '1' else a – b;
with control select q <= a + b when '1',
a – b when '0', (others => 'X') when others;
FPGA Workshop, OIST 52
Behavioural Coding StyleBehavioural Coding Style • Describes the behaviour of a system
– How it responds to events • Implemented as one or more process statements
– Process triggered when signals in sensitivity list change architecture behavioural of add_sub is begin
process variable result : signed (n-1 downto 0 );
begin if control = '1' then
result := a + b; else
result := a – b; end if; q <= result;
end process; end architecture behavioural;
Local process variables
Sensitivity list
Conditional statement
Signal assignments within a process are parallel and are assigned at the end
(a, b, control)
FPGA Workshop, OIST 53
Behavioural Coding StyleBehavioural Coding Style • Statements in a process are sequential
– Variable assignments take place immediately in order of execution
– However, all signal assignments take place concurrently at the end of the process • Before they change, all signals retain the old values • They receive the last value assigned to them
• Both signals and variables can be registers or connections depending on context – Registers are changed in synchronisation with a clock
FPGA Workshop, OIST 54
• Assigned within a process controlled by a clock
281.384 Donald Bailey 54
Registers in VHDLRegisters in VHDL
entity counter is port( clock, reset : in std_logic;
count : out unsigned (3 downto 0)); end entity counter;
architecture ctr of counter is begin
process (clock, reset) variable i_count : unsigned (3 downto 0);
begin if reset = '1' then
i_count := (others => '0'); elsif rising_edge( clock ) then
i_count := i_count + 1; end if; count <= i_count;
end process; end architecture ctr;
Interface definition
Internal counter variable
Asynchronous reset
Synchronous counting
Connect count to the output
FPGA Workshop, OIST 55
VHDLVHDL • Different programming styles can be mixed within
a design – All statements within the architecture are parallel
• Strongly typed language – Types must match exactly – Necessary to specifically perform any type casting
• This is partly what makes VHDL verbose
– Can define own types, including • records, arrays, enumerated types • functions, procedures
FPGA Workshop, OIST 56
Control LogicControl Logic • A lot of control is implemented using finite state
machines – State provides context for
• Selecting register inputs (multiplexing)
• Enabling the clock on registers
– Enables control logic to be separated from computation logic
FPGA Workshop, OIST 57281.384 Donald Bailey 57
Finite State Machines in VHDLFinite State Machines in VHDL entity state_machine is
port( A : in std_logic; Q : out std_logic);
end entity state_machine;
architecture fsm of state_machine is type states is (S1, S2, S3); signal state : states := S1;
begin process (clock) begin
if rising_edge( clock ) then case state is
when S1 => if A = '1' then state <= S2; end if;
when S2 => state <= S3; when S3 => if A = '0' then state <= S1;
end if; end case;
end if; end process; q <= '1' when state = S2 else '0';
end architecture fsm;
State transitions
Output logic
Definitions
FPGA Workshop, OIST 58
DE0DE0
FPGA Workshop, OIST 59
DE0DE0
FPGA Workshop, OIST 60
Video TimingVideo Timing
Horizontal Sync
Vertical Blanking
Visible region
Horizontal Blanking
Vertical Sync
FPGA Workshop, OIST 61
VGA TimingVGA Timing • Image sent to the display in a raster format
– Sync signals indicate start and end of each row
• Timing for 640×480 @ 60 Hz refresh Active Front porch Sync Back porch Total Clock
Horizontal 640 16 96 48 800 pixels 25.175 MHz Vertical 480 10 2 33 525 lines 31.5 kHz
FPGA Workshop, OIST 62
VGA TimingVGA Timing • Timing controlled by counters
– X and Y counters give pixel location currently displayed – Testing for equality is more efficient than ≥ – Use tests to set and reset latches
FPGA Workshop, OIST 63
VGA OutputVGA Output • Analogue video signal output
– Use x and y counters to control which pixel to output – High speed D/A converters required on RGB channels
• Can be provided by an external DAC chip
• Sync signals – Sent directly to the display – 3.3V TTL signal output levels are suitable – Polarity depends on video mode
FPGA Workshop, OIST 64
Laboratory:Laboratory: Using Quartus IIUsing Quartus II
VHDL display driverVHDL display driver
Laboratory: Using Quartus II, VHDL Display Driver
The aim of this laboratory is to familiarise you with Altera’s Quartus II development environment. In this laboratory, you will develop a basic VHDL display driver, and use it to display a simple test pattern.
1: Setting up the project Start Quartus II. In this you see the four main panels: the project navigator, tasks, messages, and file panel on the right (where document and information files are displayed).
Create a new project. From the File menu, select New Project Wizard… (File » New Project Wizard…). This steps you through setting up the project.
First select an appropriate working directory. Ensure that there are no spaces in the path name or filename (i.e. DO NOT put the project on the desktop or in My Documents folders). Then select the project name. It automatically uses the project name as the top-level entity, although this can be changed later if desired.
If necessary, click Yes to create the directory.
Click Next. Copy the file VGA.vhd into the project working directory. Then click Add All to add the file into your project.
Click Next to advance to page 3, where you select the following device:/
Finally, Click Next to get to the end (keep the defaults) or Finish to complete the setup.
2: Enter the top level of the design The next step is to create the top level design file. In the Project Navigator, select the Files tab, and double-click VGA.vhd. Within this, we have already defined the top level entity, which defines the FPGA inputs and outputs used by the design.
50 Mhz Clock
clk_50
VGA Sync signals
Pixel value displayed
vga_hs vga_vs
vga_r vga_g vga_b
This declares that it will use the logic definitions and the numeric functions (signed and unsigned arithmetic) from the IEEE library. The entity VGA has the following interface:
• one input: the 50 MHz clock from the board • three 4 bit outputs: the RGB colour to be displayed • two 1 bit logic outputs: the horizontal and vertical sync signals
The architecture here is currently empty (apart from some comments). The next step is to populate this with the driver and test pattern generator. The pixel clock for standard VGA is 25 MHz, so the 50 MHz from the board will need to be divided down. Within the top level we will have two main components:
• The VGA driver itself which provides the sync signals for the display, two counters to indicate which pixel we are currently at, and blanking signals which indicate when we are in the blanking periods.
• A pattern generator which will determine which colour is displayed for each pixel on the display.
clk x y
hb vb hs vs
x y r g b
VGA Driver
Pattern Generator
–2:
clk_50
To display
The first thing to do is declare the components within the top module. Edit VGA.vhd to first declare the internal signals (lines 12-17) and then wire everything up (lines 20-41), as shown on the following page.
• The first block (lines 21-26) uses the behavioural coding style. clk_50 is in the sensitivity list so the process executes whenever clk_50 changes. On the rising edge of clk_50 we toggle clk_25 signal, which effectively divides it by 2. This is the clock signal passed on to the VGA driver.
• The second block (lines 29-32) uses the structural coding style to instantiate the VGA driver and pattern generator sub-blocks from the work library (these are files within the project). We will create these files shortly.
• The next block (lines 35-41) uses the concurrent dataflow coding style. The AND gates implementing the blanking are represented using conditional signal assignments (the when statements).
Check the syntax of your file with Processing » Analyze Current File (or click the toolbar icon). If you have any errors, correct the offending lines and recheck the file.
3: Enter remaining components If you have not done so already, copy the file VGA_Driver.vhd to your working directory. Then, within the Project Navigator, right-click on Files and select Add/Remove Files in Project…
Within the Settings dialog, click the … button, and select the file VGA_Driver.vhd. Then click Add to actually add the file to the project. It should then appear in the file list within the dialog.
Finally click OK, to add the file to the project. Open the file to explore its contents:
Basically, the VGA driver consists of two counters, xx and yy, one for the x direction and one for the y. We need to use internal signals, because to count, and to determine the positions of sync and blanking, we need to read the current values. We cannot read from output ports, so we use internal signals, and connect these to the output ports using signal assignments.
A process statement, controlled by the clock makes the counters and output control signals synchronous. Based on each counter, tests are used to set or reset the corresponding sync and blanking signals at the appropriate times.
Finally, we will create the pattern generator. File » New… and select VHDL File to create a new VHDL file. Enter the VHDL code on the following page. This simply wires the pixel counters to the RGB outputs to create a coloured test pattern by using the position to directly control the colour.
Check the syntax of each file (Processing » Analyze Current File or ) after you have entered it, and eliminate any errors as you go.
If you Start Analysis and Synthesis ( ) you should have no errors, and an estimate of the resource requirements is provided:
A schematic representation of the design can be viewed in the netlist viewer: Tools » Netlist Viewers » RTL Viewer. Double-click on the VGA driver to go down a level and explore the implementation.
Once you have explored your design, you can close the RTL viewer.
4: Setting up design constraints The next step is to assign pin numbers to the input an output pins. To do this, it is necessary to open the pin planner: Assignments » Pin Planner ( ). This will list the pins and show the corresponding pin location on the pinout for the FPGA. In the Location field in the bottom panel, enter the pin assignments:
These pin numbers correspond to the FPGA pins that these particular peripherals are connected to, and can be found in the DE0 User Manual. Close the Pin Planner after entering in the pins.
Next it is necessary to set up some of the pin options within the project. First we need to tell Quartus what to do with all of the pins which are not used by a design. Select Assignments » Device ( ) and click the Device and Pin Options button. Select Unused Pins and set to As input tri-stated in the dropdown menu.
Then set the Dual-Purpose Pins as Use as regular I/O. This will require double-clicking each entry and selecting the option from the drop-down menu.
Click OK to make the changes and close the settings box.
Next compile your design: Processing » Start Compilation ( ). This will give a number of critical warnings relating to timing requirements not being met. That is because we have not yet specified any timing constraints.
Having done the fitting we can now set these up with Tools » TimeQuest Timing Analyzer ( ). Within the TimeQuest Tasks panel, double-click Create Timing Netlist to initialise the timing netlist for the project:
Then Constraints » Create Clock… to set up the clk_50 clock. Set the Clock name to clk_50, the Period to 20 ns, and the Targets to clk_50 and click Run. Repeat for clk_25, setting the Period to 40 ns.
Next Constraints » Set False Path… to inform TimeQuest that any signals from clk_25 will not be latched by clk_50: Set From to clk_25 and To to clk_50 and press Run.
Next, in the Console panel, enter the command derive_clock_uncertainty to set up the uncertainties associated with clock jitter.
Double click Update Timing Netlist in the Tasks panel to actually derive the uncertainty values.
Finally, at the bottom of the Tasks panel, double click Write SDC File… to save the constraints.
Change the SDC file name to VGA.sdc, uncheck the Expand checkbox and click OK.
You can now close the TimeQuest window and return to the main Quartus II window. Here, recompile your design by clicking on the toolbar button. The design should compile without any timing errors. The flow summary panel summarises the resources used by the design
5: Downloading your design to the FPGA The final stage is to download your configuration file to the FPGA board. First ensure that your DE0 board is connected to your computer using the programming cable, and the VGA outputis connected to a VGA monitor. Check that the RUN – PROG switch on the board is in the RUN position (the other position programmes the configuration ROM on the DE0), and switch the DE0 on.
Open the programmer by double clicking Program Device in the Tasks panel, or by clicking the programmer toolbar button ( ).
This will open the programmer.
If “No Hardware” appears in the top panel, ensure that the DE0 is switched on and connected to the computer. Click the Hardware Setup… button, and select the USB Blaster [USB-0] from the drop down menu, and then Close to return to the programmer.
Click the Start button to send the file to the FPGA. On the DE0, the LOAD LED should light up while the configuration is downloading, and when loading is complete, the design will automatically begin executing, and the test pattern will appear on the VGA display.
6: Further work If you have further time, experiment by creating different test patterns within the pattern generator. The simplest way of doing this is to add a new architecture (with a different name) into pat_gen.vhd, and change the instantiation in VGA.vhd. For example:
7: Summary In this laboratory we have:
• Set up a project within Quartus II • Entered our design for a basic VGA driver and test pattern using VHDL • Viewed our design using the RTL viewer • Used the Pin Planner to specify the input and output pins • Set up pin options for unused pins • Used TimeQuest to set the timing constraints for our design • Compiled our design • Downloaded the design onto the FPGA for testing
FPGA Workshop, OIST 65
Session 3:Session 3: Image CaptureImage Capture
FPGA Workshop, OIST 66
Image CaptureImage Capture • Objectives:
– Describe interface of D5M camera module – Discuss I2C control – Introduce Bayer pattern interpolation
• Laboratory objectives – Implement a simple image capture and display system – Implement Bayer pattern demosaicing – Implement a simple automatic gain control on the camera
FPGA Workshop, OIST 67
D5M CameraD5M Camera • 5 MPixel colour sensor
• 2592×1944
– Bayer pattern readout • Individual pixels have a
red, green or blue filter • Twice as many green
as other colour pixels
– Programmable window • Only part of image needs to be read out • Allows resolution to be traded off for frame rate • Enables electronic pan and scroll
FPGA Workshop, OIST 68
D5M InterfaceD5M Interface
CMOS Image Sensor
MCLK
PIXCLK FVAL LVAL DATA
SCL SDA
Master clock
Pixel data and framing
I2C camera control
FPGA Workshop, OIST 69
Displaying an ImageDisplaying an Image • Cannot just output from camera to VGA display
– Different resolution • Can programme the D5M window to give 640x480 VGA output
– Different clock rates – Different blanking intervals
• Require a buffer buffer to smooth timing – Camera and display are set up as line synchronous
Camera Camera control
FIFO Line buffer
Display
FPGA Workshop, OIST 70
II22C ProtocolC Protocol – Host provides the clock signal – Start bit pulls data low while clock is high – First byte always address and direction (read or write) – Each byte is acknowledged by receiver
FPGA Workshop, OIST 71
II22C CommunicationsC Communications • Send command
– Sends I2C device address with Write direction – Sends register address to be programmed – Sends one or more data values
• Register address usually auto-increments
• Receive command – Sends I2C device address with Write direction – Sends register address to be read – Sends I2C device address with Read direction – Receives one or more data values
• Register address usually auto-increments – Terminate transfer by not acknowledging last byte
FPGA Workshop, OIST 72
Bayer Pattern ProcessingBayer Pattern Processing
• Single chip cameras use a colour filter array – Each pixel is filtered with only one colour – Most common pattern is the Bayer pattern
• Forming a full colour image requires interpolating missing values in each channel – Called demosaicing
FPGA Workshop, OIST 73
Bayer DemosaicingBayer Demosaicing • Nearest neighbour
– Simplest (2×2 window) – Multiplexer selects required pixel
FPGA Workshop, OIST 74
Bayer Pattern DemosaicingBayer Pattern Demosaicing • Bilinear interpolation
– Requires 3×3 window – Optimise resources by reusing calculations
FPGA Workshop, OIST 75
Automatic Gain ControlAutomatic Gain Control • Detect highlights
– Threshold incoming pixel stream • Adjust gain incrementally
– If too many bright pixels, reduce camera gain – If bright pixels are too dark, increase camera gain
• Program camera gain using I2C Black White
Highlights Too bright decrement
gain
Too dark increment
gain
No change
FPGA Workshop, OIST 76
Laboratory:Laboratory: Interfacing to D5M cameraInterfacing to D5M camera Bayer pattern interpolationBayer pattern interpolation
Laboratory: Basic Image Capture and Display
The aim of this laboratory is to develop a basic image capture and display. The D5M digital camera is controlled from the FPGA via an I2C interface, and simple Bayer pattern interpolation is used to generate the corresponding colour image.
1: Basic top level design A block diagram of what we will initially construct is shown here:
Camera
I C control
2
Memory buffer
VGA timing
Camera timing
Sync generator
PLL
Display
50 MHz clock
48.825 MHz 25.2 MHz
The VGA display displays a 640×480 image at 60 frames per second. Including blanking, the total frame size is 800×525, which requires a pixel clock of 25.2 MHz (800×525×60). Although the camera has 5 megapixels, we will operate it in windowed mode, where we will read out a 640×480 window. The timing requirements of the camera are different – to read out one row of the image will take 1550 clock cycles.
In our design, to minimize the latency, we will run the camera and display line synchronous. That is the camera will produce exactly one line of data in the time that it takes to display the line. This requires running the camera at 25.2×1550/800 = 48.825 MHz. We will use one of the phase-locked loops (PLL) on the FPGA to synthesise the two clock frequencies from the on-board 50 MHz clock.
The memory buffer is used to transfer pixel data between the two clock domains, allowing them to run at different clock speeds. This is basically a FIFO with the input in the camera clock domain, and the output in the display clock domain. In addition, a synchronisation signal is passed between the clock domains to reset the VGA display appropriately so that line 0 from the camera appears on the first line of the display.
Rather than spending a lot of time setting up the project, we will start with an initial pre-built project and add features from there. Copy the files for this laboratory into a new directory, and double-click the top.qpf file. This will open the project.
2: Setting up the PLL On the board, we only have a 50 MHz clock available. From this we will generate the 25.2 MHz and 48.825 MHz clocks. Within Quartus, select Tools » MegaWizard Plug-In Manager….
• Select Create a new custom megafunction variation • Expand the I/O tab and select ALTPLL • In the output file, add pll
• Click Next > to continue • Change the frequency of inclk0 to 50 MHz, and Next > to continue
• Click Next > to continue • Uncheck Create an ‘areset’ input and Create a ‘locked’ output.
• Click Next > four more times until you get to the c0 output clock • Select Enter output clock frequency as 25.2 MHz
• Click Next > to move to c1 clock output. • Select Use this clock • Select Enter output clock frequency as 48.825 MHz
• Finally, click on the Finish to get to the summary, and Finish again to create the PLL file.
This process will have added the pll.qip file to the project. This contains the link to the PLL entity which configures the PLL to produce the desired output frequencies.
Within top.vhd, we see the instantiation of the PLL:
First we declare a signal corresponding to the 25 MHz clock. We will use the return clock from the camera as our 48 MHz system clock. Rather than assigning it to another signal, we simply use an alias for this. The alias just uses another name (clock_48) for the signal (cam_pixclk) coming from the camera.
In the instantiation of the PLL, the inclk0 PLL input is mapped to the 50 MHz board clock, c0 to our clock_25 (which we will use for the display domain) and c1 directly to the clock input pin on the camera.
3: Configuring the camera The camera is configured by programming registers within the camera using the I2C protocol. By default, the camera captures a 2592×1944. We need to programme appropriate registers to read out a 640×480 window from the centre of the image. We also need to modify the timing slightly to make it consistent with the VGA display. Each register within the camera is 16 bits wide (the registers are documented in the D5M Hardware Specification) so requires two 8-bit I2C transfers to set.
Within the library, we have an I2C setup module that programmes an I2C device from a table of initialisation data. For this we can use a VHDL constant array.
We then pass this data to the I2C setup block as a generic (since it is a constant parameter).
Since the camera I2C runs at a frequency of 400 kHz, we also need to specify the clock frequency, so that the clock can be divided down appropriately.
I2C uses a 2-wire protocol. One wire is the clock, cam_i2c_scl, which passes from the FPGA to the device. The other is the data wire, cam_i2c_sda, which is bidirectional. This bi-directionality must be managed at the top level, and requires the setup module to have 3 data connections:
• Input data from the camera to the controller, sda_in • Output data from the FPGA controller to the camera, sda_out • Output enable (tri-state control), sda_zo, which determines whether the data is input or output.
Line 69 above controls the tri-stating of the output signal as appropriate.
4: Camera interface Coming from the camera is the pixel data (12 bits per pixel) along with two control signals: line valid and frame valid. The line valid signal differentiates between valid pixel data and horizontal blanking. The frame valid signal differentiates between valid lines and vertical blanking. The timing of these is shown below (from the camera datasheet), with all of the signals (pixel data and synchronisation signals) switching on the rising edge of the clock.
The camera interface block is responsible for registering the input signals from the camera. The following declares the synchronised signals coming from the camera interface.
pixel_sync is a record (declared in the DE_Lib.globals package) containing the line and frame valid signals, as well as two counters indicating where we are in the pixel stream.
It is important for the camera interface block to work with the pixel clock from the camera, since the timing is relative to this, not the clock signal sent to the camera.
Examine the provided camera_interface.vhd file. It consists of two process statements:
• The first, triggered on the falling edge of pixel_clock, samples the incoming data signals while they are stable (they could be changing on the rising edge).
• The second, triggered on the rising edge, aligns all data on the rising edge for the rest of our design. It also provides pixel counters so we know where we are in the stream.
5: Cross domain synchronisation The camera and display are running at quite different clock speeds. However, we have configured them to run line synchronously, that is the time taken for one line of pixel data (including blanking) is identical for both the camera and display. This means that we do not need to save the complete image, but only need to buffer one line of data, and we can display the data as it comes from the camera.
The buffer between the two clock domains is a synchronous dual-port memory, with one port in each clock domain. The pixels from the camera are written into the memory, and the pixels are read and sent to the display (or processing in later labs). A signal is also sent between the domains at the start of each frame to synchronise the VGA display to the camera (vga_reset), so that the first row from the camera corresponds to the top row on the display.
Examine camera_buffer.vhd, and see how it operates. Note that the memory is just declared as an array of values. The synthesis tools will infer that this is dual port memory from the way in which we use it.
There are four processes within camera_buffer: • The first is controlled by the camera clock, and writes pixels into the memory buffer using the pixel
counter as the address. It also detects row 0 for synchronisation. • The second process, controlled by the display clock, reads pixels from the memory buffer, again
using the pixel counter as the address. • The third process is a synchroniser chain to transfer a signal from the camera clock domain into the
display clock domain. This is necessary because these clocks are different frequencies, and there is a danger of metastability if the signal in the camera domain changes within the setup-hold window of the display clock.
• The final process generates a reset pulse if the display is not already synchronised with the camera.
6: VGA controller The final step is to generate the VGA timing and synchronisation pulses. For this we will use a slightly more sophisticated version of what we developed in the last lab. We separate the timing from the sync pulse generation because later we will add image processing operations in between, and we need to account for their latency.
We simply map the 4 most significant bits of the raw pixels from the camera to the red, green, and blue channels of the display to show the greyscale version of the raw image.
Compile your design (Processing » Start Compilation, or ). With the FPGA switched off, carefully plug the camera into the 40 pin GPIO0 connector (this is the inner of the two connectors), facing outwards. Once seated, turn on the FPGA again and programme it with your design. You should see the image from the camera on the VGA monitor. The regular pattern of dot is from the Bayer colour filter array.
7: Bayer pattern demosaicing Within the camera, each pixel has associated with it a colour filter, so that it only captures one of the red, green or blue components. To recover a full colour image, it is necessary to interpolate the missing values for each colour plane. We will use simple bilinear interpolation to give the colour values.
Add the bayer.vhd file to your project. Edit top.vhd, to add the following signal declarations:
Next, we need to instantiate the Bayer interpolation filter, and link it into the processing chain:
Compile the design, and download it onto the FPGA.
Open the file bayer.vhd. The entity has 5 ports: the pixel clock, the input pixel stream and its corresponding timing signals, and the output stream with its timing signals. The output stream is 3 times wider, consisting of the RGB components concatenated together.
Within the architecture, we declare a window, and functions which calculate the averages of 2 and 4 numbers (as required by the filters).
G B G B R G R G G B G B R G R G
We first instantiate a 3×3 make_window component. This gives us the pixels within a 3×3 neighbourhood as required to interpolate the missing pixels. Row buffers are used to cache 2 whole lines of pixels, enabling the whole system to operate on streamed data. The EDGE_MODE generic specifies what to do when the window extends past the edge of the image. In this case we duplicate with a period of 2 pixels (to preserve the Bayer pattern).
The latency of the Bayer filter consists of the following delays:
• It takes 1 clock cycle for the input pixels to be loaded into the edge of the window (this includes the time taken to read the pixels from the row buffers).
• The output pixel corresponds to the centre of the window, which is offset 1 row, and 1 pixels from the start of the window. This means that the latency (time from when a pixel comes into the window to the corresponding output position) is 1 row and 1 clock cycle.
• The interpolation calculations from the window pixels are registered on the output, adding a further clock cycle delay.
• Adding these gives the total latency of the filter as 1 row + 3 pixels. Our output timing signals need to be delayed by this amount, which is achieved through the sync_delay component.
The actual interpolation takes place in the process statement. Since the location of each colour component depends on which clock cycle we are in, the least significant bits of the x and y addresses are combined to give the context. For each context, we average the appropriate pixels together to give the output. The case statement is effectively multiplexing the outputs for the different offset combinations. Note no attempt has been made here to optimise the logic required.
8: Automatic gain control The exposure in the previous design was fixed. The last step we will take is to modify the design to automatically adjust the gain within the camera (via I2C) depending on the light level. This analyses the pixel stream from the camera, looks at the brightest pixels in the image. If there are too many bright pixels, the gain for the next frame is reduced. If the bright pixels are not bright enough, the gain is increased. The camera gain varies between 1 and 128 using a combination of both analogue and digital gain (while high gain will allow us to operate in lower light levels, the resulting images will be quite noisy).
First add the following signal declarations.
Then modify the I2C controller to include the connection from the auto-exposure module. Replace the i2c_setup instantiation with i2c_multi_port as shown here.
Finally instantiate the auto-exposure block itself. This monitors the pixel stream from the camera, and interfaces with the I2C controller to adjust the appropriate camera settings. Generics parameters specify the minimum and maximum levels for the highlights within the image. EXP_N defines what we mean by highlights; here the image is too bright if 1023 pixels are above EXP_MAX, and too dark if fewer than 1023 pixels are below EXP_MIN. Having a dead band reduces flicker as a result of continually changing the exposure.
The last two lines display the current gain on the seven segment displays.
Compile the design and download onto the FPGA. Test the automatic gain control by changing holding various objects in front of the camera, and seeing the exposure change on the display. Switch 9 (the leftmost switch) turns automatic gain control on and off. Since the exposure is only incrementing or decrementing one step per frame, it can take about 2 seconds to change from minimum to maximum.
If the exposure adjustment is continually changing and flickering (for example because of the statistics of the image, or as a result of lighting), then increase the dead band by reducing EXP_MIN.
9: Summary In this laboratory we have:
• Configured a PLL using the Megafunction Wizard • Configured the digital camera using I2C • Received a video stream from the camera • Transferred the data between clock domains using a dual-port memory • Synchronised the VGA display with the camera • Interpolated the Bayer pattern to give a full colour image • Monitored the pixel stream to implement automatic gain control
FPGA Workshop, OIST 77
Session 4:Session 4: Image FiltersImage Filters
Convolution and MorphologyConvolution and Morphology
FPGA Workshop, OIST 78
FiltersFilters • Objectives:
– Derive mechanisms for efficient filtering • Row buffers • Priming and flushing issues
– Outline filter structures for linear and morphological filters – Describe separability and optimisation issues – Illustrate with a Sobel filter
• Introduce CORDIC for Cartesian to polar conversion
• Laboratory objectives – Implement a Sobel filter
• Detect edges and edge orientation image
FPGA Workshop, OIST 79
Local Image FiltersLocal Image Filters • Each output pixel is some function of pixels within a
small local window
Input image Output image
Filter function
FPGA Workshop, OIST 80
Implementation IssuesImplementation Issues • Software approach
– Have entire image stored in a frame buffer (an array) – Loop through for each output pixel – Retrieve input pixels within window in input image – Apply the filter function
• Problems for hardware implementation – Multiple pixels must be read for each window position – Each pixel is read multiple times – Memory bandwidth constraints prevail – Requires some caching arrangement
FPGA Workshop, OIST 81
Window registers
Caching to Reduce BandwidthCaching to Reduce Bandwidth • Filters use multiple pixels
– Stream processing has significant overlap between windows
• Reuse data by shifting it – Only need to load new pixels
• Use row buffers to cache incoming stream – Unrolls inner loop which
accesses pixels – Only need to load one pixel
for each window position
New pixels
Row buffer
Row buffer
Input stream
N ew
pi xe
ls
From row buffer
FPGA Workshop, OIST 82
• Feed image through the window (streaming) – Row buffers can be implemented using
• Shift register • Circular memory (dual-port)
Filter CachingFilter Caching
Dual-port memory
A dd
re ss
D at
a
Shift register Window
Filter function
Input stream
Output stream
Shift register
Row buffers
RAM
Address counter
RAM
FPGA Workshop, OIST 83
Row BufferingRow Buffering • Cache data using row buffers
– A W×W window requires W-1 row buffers • Two basic configurations
– Parallel with window – Series with window pixels
FPGA Workshop, OIST 84
Filter LatencyFilter Latency • Need to load whole window before output starts
– For a W×W window, requires loading W-1 rows • Latency from a pixel input to corresponding output
pixel is produced – Half window height: (W-1)/2 rows +
Half window width: (W-1)/2 columns + Latency of filter function
• Further complicated if input stream has horizontal and vertical blanking – Invalid data during blanking intervals – Also issues of managing image borders
FPGA Workshop, OIST 85
Border PixelsBorder Pixels • Problem around the borders of the image
– Window extends past edge of the image – What pixel values should be used as inputs?
FPGA Workshop, OIST 86
• Just wrap the input stream (ignore the problem) • Truncate the output image (make it smaller) • Modify the filter function • Constant extension
– Often 0, but can be any value • Periodic extension (eg FFT) • Duplicate border pixels
– Nearest neighbour extrapolation • Mirror border pixels
– With or without duplication of the border
Border Pixel Management OptionsBorder Pixel Management Options
FPGA Workshop, OIST 87
Filter Priming and FlushingFilter Priming and Flushing • Example: edge duplication with 3x3
window – Priming: loading of duplicated rows
0 and N and columns 0 and M – Flushing: ignoring invalid outputs
0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 …
0 1 2 3 4 5 6 7
… N
0 1 2 3 4 5 6 7 … M Column
R ow
Row 0 (duplicate) Row 0 Row 1 Row 2 …Row 3
X X X X X X X X X X X X X X X X X X 0 1 2 3 … M X X 0 1 2 3 … M X X 0 1 2 3 … M X X 0 … Row 0 Row 1 Row 2 …
Input stream
Output stream
M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 1 2 3 … M M 0 0 … Row N-1 Row N Row 0 (duplicate) …Row 0
M X X 0 1 2 3 … M X X 0 1 2 3 … M X X 0 1 2 3 … M X X X X X X X X X X X X X X X X X X 0 Row NRow N-2 Row N-1
Row N (duplicate)
Next frame
Latency
FPGA Workshop, OIST 88
Two Dimensional PrimingTwo Dimensional Priming
●
Output image
First output pixel Row priming
Column priming
Latency
Flushing
FPGA Workshop, OIST 89
Filter PrimingFilter Priming • Only load each pixel once
– Hold pixels at start of row to enable loading multiple times – Recirculate pixels at end or row for flushing – Recirculate first and last rows from first row buffer
Duplicating border pixels
FPGA Workshop, OIST 90
Linear Filter StructureLinear Filter Structure • Output is a weighted sum of input pixels
FPGA Workshop, OIST 91
Pipelined StructurePipelined Structure • Apply transpose structure to rows
– Automatically makes filter structure pipelined
FPGA Workshop, OIST 92
Reducing the ComputationReducing the Computation • Multiplication by powers of 2 is trivial • Exploiting symmetry
– Many filters are symmetric – Can perform add before the multiplication
• Separable filters – Filter decomposes to two 1D filters – Column filter replaces delays
with row buffers
[ , ] [ ] [ ]x yw i j w i w j=
FPGA Workshop, OIST 93
Morphological FiltersMorphological Filters • Erosion
– Output 1 if all inputs are 1 logical AND within window – Object shrinks and background expands
• Dilation – Output 0 if all inputs are 0 logical OR of flipped window – Object expands and background shrinks
• Opening – Erosion followed by dilation
• Closing – Dilation followed by erosion
, [ , ] [ , ]erosion i jQ x y I S I x i y j∈= = + +∧S�
, [ , ] [ , ]dilation i jQ x y I S I x i y j∈= ⊕ = − −∨S
( )I S I S S= ⊕� �
( )I S I S S• = ⊕ �
FPGA Workshop, OIST 94
Erosion and DilationErosion and Dilation • Duality enables one circuit to be used for both
– Dilation is erosion of the complement (with a flipped window)
FPGA Workshop, OIST 95
Filter DecompositionsFilter Decompositions • Decomposes large filters into a
combination of simpler smaller filters • Sequential decomposition
– Dilation is associative • Dilation • Erosion
• Parallel decomposition – Combines parallel filters
• Dilation • Erosion
– Simplify by making composite filters rectangular
( ) ( )1 2 1 2I S S I S S⊕ ⊕ = ⊕ ⊕ ( ) ( )1 2 1 2I S S I S S= ⊕� � �
( ) ( ) ( )1 2 1 2I S S I S I S⊕ ∨ = ⊕ ∨ ⊕ ( ) ( ) ( )1 2 1 2I S S I S I S∨ = ∧� � �
FPGA Workshop, OIST 96
3x3 Erosion Filter3x3 Erosion Filter • Effectively removes isolated pixels
– Also removes 1 pixel layer from edges • Separable
– 1x3 row and 3x1 column filters • Erosion
– Output 1 if all inputs are 1 logical AND
1x3 filter Row buffer
Row buffer
3x1 filter
Input stream Output
stream
FPGA Workshop, OIST 97
Sobel FilterSobel Filter • Combines horizontal and vertical edge filters
– Constituent filters are separable • Sobel output
– Simplified approximation
2 2H V+
H V+
FPGA Workshop, OIST 98
CORDICCORDIC • Method for calculating trigonometric functions
– Based on incremental rotations
– Rearranging
– Trick is choosing factors to be powers of 2: • Multiplications then become shifts
1
1
cos sin sin cos
k k k k
k k k k
x x y y
θ θ θ θ
+
+
− =
1
2 1
1 21 2 11 2
k k k
kk k k
x x y y
− +
−− +
− =
+
tan 2 kkθ −=
1
1
1 tan cos
tan 1 k k k
k k k k
x x y y
θ θ
θ +
+
− =
( , )k kx y
1 1( , )k kx y+ +
kθ
FPGA Workshop, OIST 99
CORDICCORDIC • Rotate by an arbitrary angle through a series of
rotations – Where dk is direction of rotation
– Result rotates the input vector by • Problem is scale factor at front
– By choosing to always rotate, , this will be constant regardless of angle rotated
– Uncompensated • Gives a gain of approximately 1.64676
1
2 2 1
1 21 2 11 2
k k kk
kk k kkk
x xd y ydd
− +
−− +
− =
+ 1
1
0 tan 2
K k
k k dθ
− − −
=
= ∑
{ 1,1}kd ∈ −
FPGA Workshop, OIST 100
CORDIC Operation ModesCORDIC Operation Modes • Rotation mode
– Starts with desired rotation angle in z – Chooses dk = sign(zk) to converge the angle to zero – Result is to rotate the vector by that angle – Can be used to calculate sine and cosine of an angle
• Vectoring mode – Aligns the vector with the x axis – Chooses dk = -sign(yk) to converge y to zero – Result is magnitude and angle of the vector – Can be used to calculate arctangent
• Each iteration gives 1 bit of the result
FPGA Workshop, OIST 101
CORDIC ImplementationCORDIC Implementation • Direct implementation builds
separate hardware for each iteration – Each iteration gives 1 bit of the
result – Scaled magnitude is not a
problem for edge detection • If necessary may be
pipelined for speed
FPGA Workshop, OIST 102
Laboratory:Laboratory: Streamed Sobel filterStreamed Sobel filter
Laboratory: Sobel Filter and CORDIC Arithmetic
The aim of this laboratory is to implement a Sobel filter and use CORDIC arithmetic to obtain the edge orientation map.
This laboratory will make use of the colour image capture and display developed in the previous session. A clean set of files has been provided (in case you did not get the last laboratory completed). Copy the files into a new directory to work on this laboratory.
1: Top level design for the Sobel filter A block diagram of the key part of the top level design is
Memory buffer
VGA timing
Sync generator
Display
Bayer filter to grey
Sobel filter
We use a 2x2 average filter to convert the raw image into a greyscale image (lines 114-118 in top.vhd). This greyscale image is then passed to the Sobel filter (lines 120-124) which produces the image for the display. The Sobel filter is actually produces 3 outputs. Initially it will provide the linear filtered horizontal and vertical derivative images, along with a delayed input image for comparison. Switches sw(1) and sw(0) are used to multiplex these onto the display (lines 126-128). Later we will produce the edge strength and edge orientation maps.
2: Horizontal and vertical edge filters From the lecture, we can factorise each of the edge filters making up the Sobel filter, enabling us to process with a 1×3 window followed by a 3×1 window. We can share the 1×3 window with the two parallel filters.
1
1 2
1
-1 0 1 1 1 1
-1 0 1
1 3 window
×
1 3 filters× 3 1 filters× Outputs
×2
vf(0)
hf(0)
vf(1)
hf(1)
vf(2)
hf(2)
First we instantiate the make_window entity to build the vertical window. We will handle the image borders by duplicating boundary pixels.
The next step is to perform the actual vertical filtering. The vertical filter uses vertical differentiation, and the horizontal filter uses vertical averaging, as illustrated above. The separate horizontal filters then produce the filtered outputs. The signal declarations define an array of registers
with the first process performing the actual filtering:
Variables are used for intermediate signals. Since they are used immediately, they do not retain their values, and consist of just wires. Four bits are added to width of the intermediate variables. This allows three extra bits (including sign bit) for the filters since the Sobel calculations are not normalised, and one extra bit to allow for the growth in magnitude as a result of the CORDIC rotation.
With the two output images, the three LSBs are dropped, effectively scaling the filter output by dividing by 8. An offset is added to adjust zero to mid-grey, with darker values representing negative gradient, and lighter values representing positive gradient.
The filter has a latency of 1 row and 3 pixels, made up of
• 1 row and 1 pixel for forming the 1×3 window at the start • Combinatorial logic is used for the 1×3 filter calculations, so this takes no clock cycles • The 3×1 filters have 2 pixels latency, including the output register. Although there are 3 registers,
with 3 clock cycles delay, the output corresponds to the centre of the window, after 2 clock cycles.
Build the code and download it to the FPGA to see the effects of the filters:
• sw(1) switches between unfiltered and filtered outputs • sw(0) switches between the horizontal and vertical edge filters.
3: Combining the outputs The final stage is to combine the outputs. We will use CORDIC arithmetic to do this. The algorithm is essentially iterative, although we will unroll it and build separate hardware for each iteration, taking only a single clock cycle.
First, adjust the latency on line 32 to delay the output by an extra clock cycle:
Then comment out lines 57-59, which provide the individual filter outputs, and uncomment lines 87-98 which connect the outputs to the output of the CORDIC block.
Within the second process, we are using CORDIC arithmetic to perform an arctangent of the x and y gradient vector components to get the edge strength and edge orientation.
• The declarations on lines 62 and 63 are arrays of intermediate variables for holding the x, y and angle components at each iteration.
• The tan table on line 64 contains arctangents of successive negative powers of 2, scaled so that 360° = 4096. These will be used later for calculating the arctangent
We are using vectoring mode, which selects the rotation direction at each iteration to adjust the y component to 0. This leaves us with the vector magnitude in the x component, and the vector angle.
• The initial (0th) iteration (lines 67-75) performs an optional rotation by 180 degrees if the x component is negative.
• The initial angle has 4 added to automatically perform rounding (we will truncate the 3 LSB from the angle).
• Subsequent iterations (the loop in lines 76-86) select the rotation direction based on the sign of the y component.
• The remaining lines (87-98) register the outputs.
Compile your design, and download it onto the board. Use sw(0) to select either the orientation or edge strength, and sw(1) to toggle between the original and filtered image.
4: Further work Some possibilities:
• Switch the Bayer filter back to a colour image, and instantiate 3 Sobel filters, one for each colour channel. Hint – you can use a for … generate loop to create multiple copies of the Sobel filter.
• One problem with the orientation image is that it is very noisy (the angle of a low magnitude number is strongly dependent on noise). We can colour code the edge strength by treating the angle as a hue. Add an operation in the processing chain between the Sobel filter and display to perform an HSV to RGB conversion. The conversion is shown on the following page:
o Use the edge strength as the value, V. o Set the saturation, S, to 1, to give fully saturated colours for the edges. o In the CORDIC algorithm, adjust the angle scale to have 360° correspond to 3074 rather
than 4096 (to divide the hue into 6 sectors). The edge orientation is then set as the hue, H.
• Implement another filter (create a new vhdl file).
5: Summary In this laboratory we have:
• Implemented linear gradient filters, using separable filter design techniques • Used CORDIC to determine the magnitude and angle of the edge vector
FPGA Workshop, OIST 103
Session 5:Session 5: FPGA Based Design and FPGA Based Design and Algorithm ImplementationAlgorithm Implementation
FPGA Workshop, OIST 104
Architecture Selection
System Implementation
Problem Specification
Design ProcessDesign Process
Algorithm Development
Defines the problem Determines engineering and functional constraints
Determines sequence of image processing operations
Selects configuration for implementation
Maps the algorithm onto the architecture
FPGA Workshop, OIST 105
Problem SpecificationProblem Specification • Same for FPGA and software based systems
– Translate often vague problem description into an engineering specification useful for design
• Requirements analysis – System functionality – Performance (processing rate, success rate) – Operating environment
• Lighting and optics • Interfacing with support hardware and machinery
– System behaviour in exceptional circumstances – Maintenance issues
• Tradeoff between speed, accuracy and cost
FPGA Workshop, OIST 106
Problem SpecificationProblem Specification • Define the desired result of image processing
– Inputs and outputs • Requires comprehensive knowledge of problem
– Allows valid assumptions to be made • Selection of features to measure
– Selection of set of test images for development • Representative of the imaging task performed
– Appropriate lighting is essential • Much of an image processing problem can be simplified by using
appropriate lighting
FPGA Workshop, OIST 107
Algorithm DevelopmentAlgorithm Development • Heuristic development process
– Trial and error (and experience) – Relies on human vision to evaluate operations
• Requires – System with large number of imaging operations – Interactive system to experiment with alternatives
• FPGA development issues: – Algorithm cannot be developed directly on the FPGA
• FPGAs have no operating system • Place and route times for FPGAs are not interactive
– Requires a separate development environment
FPGA Workshop, OIST 108
Typical Algorithm StructureTypical Algorithm Structure • Preprocessing
– Enhance required information – Suppress irrelevant information
• Extract the required results – Transform data from pixel values to more descriptive symbolic form – Segmentation
• Detect regions which have a common property – Classification
• Identification of parts of objects • Data no longer image based (but may contain position)
– Measurement / update models to reflect input image
• Post-processing – Convert extracted information into the required form
FPGA Workshop, OIST 109
Algorithm DevelopmentAlgorithm Development • Not all software algorithms map well to hardware
– Individual operations need to be architecturally compatible – Algorithm must be developed with computational
architecture in mind • Simulation on development platform limited
– Parallel architecture must be simulated on a serial computer • Relatively slow, especially for clock accurate simulation
– Evaluating effectiveness on a continuous, noisy, real-time video stream is difficult
FPGA Workshop, OIST 110
Development ProcedureDevelopment Procedure • Algorithm developed and tested as software first
– Standard software development techniques used – Enables algorithm to be tested and verified
• Algorithm is then modified to match architecture – Selection of alternative operations where necessary – Algorithm retested
• Algorithm is then mapped to hardware – Matching of algorithm steps to available resources – May require further changes
• Introduction of operation specific caching
FPGA Workshop, OIST 111
Architecture SelectionArchitecture Selection • System level architecture
– Peripheral devices and memory • Computational architecture
– How the computation is actually performed – Split between hardware and software execution
• Design issues – Computational architecture is fixed for a serial processor – For FPGAs, must develop architecture as well as algorithm
- nothing is provided – Must select configuration and computational mode
• Hosted / standalone, streaming / random access
FPGA Workshop, OIST 112
System ArchitectureSystem Architecture
FPGA Workshop, OIST 113
Integrated ConfigurationIntegrated Configuration • FPGA is part of CPU
– Key instructions accelerated within host processor – Data passed through shared registers
• With modern FPGAs, CPU is usually soft processor within the FPGA – FPGA implements custom instructions
• Limitations – Limited data may be passed with each instruction – Limited time to perform the processing
• Usually too fine-grained for image processing
FPGA Workshop, OIST 114
FPGA CoprocessorFPGA Coprocessor • FPGA accelerates particular types of operations
– Like a floating point co-processor • FPGA operates relatively independently of host
processor – Still controlled by instructions from host processor – Used to accelerate time critical or computationally dense
sections of an algorithm • Too tightly coupled for many image processing tasks
FPGA Workshop, OIST 115
Hosted ConfigurationHosted Configuration • FPGA multi-processor with conventional computer
• Host system – Configures FPGA – Stores image in shared memory – Signals to FPGA to begin processing – Results returned in shared memory or FPGA registers
Shared memory FPGA
Host computer system
FPGA Workshop, OIST 116
Hosted ConfigurationHosted Configuration • Computationally intensive tasks are compiled to
hardware – Parallelism of FPGA is exploited – Low-level image processing operations
• Software is used for tasks that cannot be performed efficiently in hardware – Serially bound tasks – Data dependent control – High-level image processing operations
• Primarily used for algorithm acceleration and high performance computing
FPGA Workshop, OIST 117
Hosted ConfigurationHosted Configuration • Host computer usually responsible for
– Image capture and display – User interaction – System communication
• Host operating system is augmented to enable – FPGA reconfiguration – Task scheduling – Debugging
• Key terms – Reconfigurable computing
FPGA Workshop, OIST 118
Standalone ConfigurationStandalone Configuration • All processing is performed
on the FPGA – Image capture – Image processing – Image display – User interaction
• No operating system – Tuning, calibration, user interaction, debugging are more
complex • Configuration usually from flash memory • Primarily used for embedded vision applications
FPGA Workshop, OIST 119
Computational ArchitectureComputational Architecture • Simply porting software generally does not work
– Software is usually optimised for processing on a serial computer – Generally memory bound
• Always reading and writing to memory
• Important to obtain a good match between the architecture and the algorithm – Poor match limits acceleration available
• Makes inefficient use of available resources
• Considerations – Form of parallelism being exploited – Memory architecture – Hardware and software mix
FPGA Workshop, OIST 120
Algorithm TransformationAlgorithm Transformation • Algorithm analysis
– Determines the data flow within algorithm • Both within and between operations
– Software dominated by memory accesses • Computational architecture design
– Exploit the available parallelism – Aim to perform as much processing on
FPGA before writing data to memory • Replace memory storage of variables with registers
• Map algorithm onto architecture
Image processing algorithm
Identify algorithm
architecture
Design hardware
architecture
Hardware implementation
Software
Hardware
FPGA Workshop, OIST 121
Pipelined ProcessingPipelined Processing
• Limited bandwidth between operations – Image is transferred using frame buffer (memory) – Each operation has a latency of one image
• Outer loop of many operations is a raster scan
– Implement using stream processing
Processor 1 Operation 1
Processor 2 Operation 2
Processor 3 Operation 3
Image Image
for {
Operation 1
}
for {
Operation 2
}
for {
Operation 3
}
FPGA Workshop, OIST 122
Pipelined Stream ProcessingPipelined Stream Processing • Serialises the parallelism in a way
that efficiently supports pipelining – Ideal close to image capture or display
• Pixel stream is already serialised
Processor 1 Operation 1
Processor 2 Operation 2
Processor 3 Operation 3
Pixel Pixel
for { Operation 1 Operation 2 Operation 3
}
– Separate processors for each operation – Data passed directly to next processor
rather than via memory • Reduces memory overhead and latency
0 1 2 3 4 5 6 7
… N
0 1 2 3 4 5 6 7 … M Column
R ow
FPGA Workshop, OIST 123
Stream ProcessingStream Processing • Fixed clock rate
– Usually one clock cycle per pixel – Limits the memory bandwidth available
• Acceleration gained through pipelining – Use low level pipelining to meet timing constraints
• Suited to low level image processing operations – Point operations and local filters
• Local operations will require caching – Caching will provide data from previous rows for filters and
other operations
FPGA Workshop, OIST 124
Random Access ProcessingRandom Access Processing • Relaxes hard timing constraint
– Data accessed directly from a frame buffer
• No explicit data access requirements – Pixels can be accessed randomly, as needed – May use several clock cycles per pixel accessed
• Can vary from pixel to pixel
Processor Frame buffer
FPGA Workshop, OIST 125
Random Access ProcessingRandom Access Processing • Most similar to software process
– Easiest to map the software algorithm to • Goal is to reduce the combinatorial delay
– Tries to maximise clock speed to maximise throughput – Use low-level pipelining to minimise clock period
• Acceleration gained by identifying parallel branches – Usually gives less acceleration than stream processing
FPGA Workshop, OIST 126
Loop UnrollingLoop Unrolling • Replace innermost loops with multiple copies of
hardware – Allows longer pipelines to be built
• Innermost loop is parallel in many image processing algorithms – Often only a loop because of serial processing – May enable whole loop to be implemented in parallel
• Functional parallelism
for { for {
XXXX }
}
for { XXXX XXXX XXXX
}
FPGA Workshop, OIST 127
Strip MiningStrip Mining • Replace outermost loops with multiple copies of
hardware – Copies work on different sets of data in parallel – Partition the image or other data over the processors
for { for {
XXXX }
}
for { XXXX
} for {XXXX } for {XXXX } for {XXXX } for {XXXX }
FPGA Workshop, OIST 128
Image partitioningImage partitioning • Distributes different parts of image to different
processors – Requires multiple copies of hardware
Stream input
Stream output
Local memory
Local memory
Local memoryBlock
process
Block process
Block process
FPGA Workshop, OIST 129
Strip Rolling & MultiplexingStrip Rolling & Multiplexing • Strip mining results in separate processor for each
partition – Sometimes only one processor is active in any clock cycle – A single processor can be shared among partitions
• Data is multiplexed based on processor index
Processor Data
Processor Data
Processor Data
Processor Data
Processor Data
Data
Data
Processor Data
Data
Data
Memory
FPGA Workshop, OIST 130
Algorithm RearrangementAlgorithm Rearrangement • Rearrange order of operations to simplify processing
complexity
• Exploit factorisation or separability – Simplifies computational complexity
• Reduce data volume through coding – Run length coding for example
• Enables complete runs to be processed as a single unit
Grayscale morphological
filter Threshold
Binary morphological
filter Threshold≡
FPGA Workshop, OIST 131
Operation SubstitutionOperation Substitution • Replace one or more operations with functionally
similar operations – Gain computational efficiency – Will change the results – Usually the image processing algorithm may be adapted to
compensate
Sobel filter output Colour space conversion
2 2H V+
H V+
.299 .587 .114
-.147 -.289 .436
.615 -.515 -.100
.25 .5 .25
.25 -.5 .25
.5 0 -.5
True output
Approximation RGB to YUV Simplification
FPGA Workshop, OIST 132
Software Based ProcessingSoftware Based Processing • Can be used for higher level image processing
– Large amounts of complex code • Largely sequential in nature
– Called occasionally • Once or twice per frame or less frequently
• Better for handling communication protocols than a purely hardware based approach – Interpreting application protocols is largely sequential
• Hard or soft processor cores can be augmented – User instructions that “call” hardware acceleration blocks
FPGA Workshop, OIST 133
Hardware / Software PartitioningHardware / Software Partitioning • Hardware tasks
– Those that can exploit parallelism – Slow when implemented in software
• Software tasks – Those that are called infrequently or are inherently serial – Inefficient use of resources when implemented in hardware
• Not an either / or selection – Spectrum of mix between hardware and software – Skill is finding the optimum mix for an application
FPGA Workshop, OIST 134
Hardware / Software SpectrumHardware / Software Spectrum Hosted Stand-alone
Hardware / Software mix
C P
U F
P G
A
Software only
Custom instructions
Task partitioning
Hardware only
Custom processor
Custom instructions
partitioning
CPU may be separate or built on the FPGA
FPGA Workshop, OIST 135
System ImplementationSystem Implementation • Differs significantly from software based design • Tasks:
– Map imaging operations onto hardware resources • May require modifying the algorithm • Make full use of available parallelism
– Develop device drivers for peripherals • Provided by OS in software based systems
• Important consideration: – This is hardware design, NOT software design
• Even though languages look like software • Efficient design requires a hardware mindset
FPGA Workshop, OIST 136
Implementation IssuesImplementation Issues • Operations are often expressed in parallel
– Eg filters apply an operation to a local neighbourhood
• BUT algorithms are generally represented serially – Optimised for implementation on serial processors – Parallelising serial algorithms is non-trivial
• Not all software algorithms map well to hardware – Limited memory access under real-time constraints
• Particularly so with streaming mode – Hardware has no program counter, stack, etc
• Recursive algorithms must be redesigned – Must redesign algorithm and/or add caching
• Remap operation rather than translate the algorithm
FPGA Workshop, OIST 137
Implementation ConstraintsImplementation Constraints • Real-time implementation imposes constraints
– Timing constraints • Throughput • Latency
– Memory bandwidth • Memory can only be accessed once per clock cycle • Requires data caching
– Resource constraints • Contention of shared resources between parallel sections • Logic block and other resource limits of FPGA
FPGA Workshop, OIST 138
Algorithm MappingAlgorithm Mapping • Best to develop the algorithm in software first
– FPGAs are not ideal for algorithm development • Long compile, place and route times • Simulation times slow for image processing
• Mapping process – Don’t necessarily map the software algorithm
• Unless it was developed with hardware in mind • Most software is optimised for serial implementation
– Map what the software is doing • Not necessarily the same image processing operations • But performs much the same function • Must redesign algorithm for the architecture • May need to design operation specific caching
FPGA Workshop, OIST 139
Design FlowDesign Flow
Develop working algorithm in software
Map algorithm to hardware
Implement on FPGA
Algorithm Tuning
Define problem
Debug / Test
Simulation test bench
Hardware test
Matlab C++
VHDL
Important to implement a working algorithm
Mapping may require changes to the algorithm
Verifies that hardware algorithm behaves identically to software
Again check that the hardware implementation behaves identically
FPGA Workshop, OIST 140
System DebuggingSystem Debugging • Important to debug the algorithm as much as
possible in software before mapping to FPGA – Not always possible with real-time video processing – Algorithm may be modified during mapping process
• Standalone configuration would require video output even if application doesn’t require it – Enable the developer to see algorithm operation
FPGA Workshop, OIST 141
• Conventional approach is through a test bench – Designed to exercise all components of a design
• Does not actually check if the underlying algorithm actually works • Test bench only validates the implementation of the algorithm • Test bench can load input and processed images from file
141
Simulation Test BenchSimulation Test Bench
281.384 Donald Bailey
Operation under test
Stimulus generator
Response checker
Data file
Test bench
FPGA Workshop, OIST 142
Operation Testing on FPGAOperation Testing on FPGA • Structure
has two parts • Communication with host
– Loads test images into frame buffer – Retrieves results
• Stream interface – Streams image from frame buffer to operation
• Simulates image capture and any preprocessing stages
– Stores output stream back into frame buffer • Host can then compare results with software
implementation
FPGA Workshop, OIST 143
System DebuggingSystem Debugging • Control may be required to
– Freeze the input image • To enable closer examination of what is happening for a particular
input
– View the image after any of the operations, not just the output
– Step through the algorithm one operation at a time • For streaming mode there is not necessarily a frame buffer • Output for display must be generated on the fly
– Show non-image information on the display • Eg detected objects
• All requires extra resources and development!
FPGA Workshop, OIST 144
System TuningSystem Tuning • Many algorithms require tuning
– Setting threshold levels and other parameters • Hosted configuration
– Host system provides user interface – Can write control parameters to registers on FPGA
• Standalone configuration – Must build user interface using the FPGA – May require a separate application for tuning
• Tune the algorithm, and store parameters in flash • Reconfigure the FPGA for the application • Load configuration parameters from flash
FPGA Workshop, OIST 145
Algorithm TuningAlgorithm Tuning • Requires a mechanism for dynamically changing
algorithm parameters – Standard approach is through a set of addressable registers – Can also be used for monitoring algorithm status – Interface often through low speed serial interface
FPGA Workshop, OIST 146
Actual application RGB
to YUV conversion
Colour thresholding
Morphological filter
Bounding Box
Control
Thresholds
Example ApplicationExample Application
Frame buffer
VGA
Box overlay
generator
Histogram accumulation
U-V histogram
accumulation
Histogram display
generator
Additional resources for tuning and debugging
FPGA Workshop, OIST 147
SummarySummary • Design process
– Problem specification – Algorithm development – Architecture selection – System implementation – Design entry
• Necessary to transform to a parallel algorithm – Makes stages architecturally compatible
• Reduces memory access through pipelining and caching – Exploits parallelism within the algorithm
• Important to design for debugging and tuning
Architecture Selection
Algorithm Development
System Implementation
Problem Specification
FPGA Workshop, OIST 148
Session 6:Session 6: Histogram ProcessingHistogram Processing
FPGA Workshop, OIST 149
HistogramsHistograms • Objectives:
– Outline basic flow of histogram processing – Describe histograms accumulation issues – Present an efficient technique for histogram equalisation
• Laboratory objectives – Display histograms of each colour channel of an image – Apply histogram equalisation to a greyscale image
FPGA Workshop, OIST 150
Uses of HistogramsUses of Histograms • Data extraction
– From image statistics • Exposure control • Contrast enhancement
– Histogram equalisation • Threshold selection
– Find valleys between peaks corresponding to object and background regions
• Object classification – Histogram similarity
FPGA Workshop, OIST 151
Building the HistogramBuilding the Histogram • Reset accumulators at start
of each frame • Accumulate the pixel count
for each pixel value – Array of counters or registers
(expensive) • Addressed or indexed by the
incoming pixel value
– RAM • Read / Modify / Write cycle • Dual port (requires a late write)
FPGA Workshop, OIST 152
Building the HistogramBuilding the Histogram • If late write not available
– Cannot meet setup time, or are using synchronous pipelined memory • Must delay write to next clock cycle
– Wrong value read if it is currently being updated • Cache previous pixel
value and count • Use cached count if
current pixel value same as previous
FPGA Workshop, OIST 153
Histogram EqualisationHistogram Equalisation • Enhances contrast
– Monotonic transformation – Makes each pixel value
equally likely
– Expands peaks – Compresses valleys
– Mapping is a scaled cumulative histogram
FPGA Workshop, OIST 154
Calculating the MappingCalculating the Mapping • Cumulate histogram, scale by number of pixels
• Division is expensive (in both delay and resources) – Number of pixels is constant
• Calculate inverse offline and use a multiplication – Use powers of 2
• Only take histogram of centre of image
Address counter
sum
index
+
H istogram m
em ory
÷
scale
LU T
m em
ory
Cumulative histogram
Normalisation
FPGA Workshop, OIST 155
Histogram EqualisationHistogram Equalisation • Cumulative histogram is monotonic
– Avoid division by using repeated subtraction if (sum <= 0) if (sum > 0) sum += hist[index]; hist[index] = 0; lut[index] = map; index++;
sum -= scale; map++;
FPGA Workshop, OIST 156
TimingTiming • Four phases or processes
– Clearing the histogram accumulators – Building the histogram – Process histogram to get mapping LUT – Apply the LUT to the image
• State machine to control timing – Multiplexers to switch histogram memory – Handled by high-level language approaches
Streamed image data Blanking Streamed image data Clear Build histogram Process Clear Build histogram Process
Time
FPGA Workshop, OIST 157
Applying the TransformationApplying the Transformation • Construction requires data from whole image • Modes:
– Frame buffering • Holds image while gathering
data
– Use histogram from previous frame • Assumes image changes slowly • Requires no frame memory
FPGA Workshop, OIST 158
Laboratory:Laboratory: Histogram DisplayHistogram Display
Histogram EqualisationHistogram Equalisation
Laboratory: Histogram Display and Equalisation
The aim of this laboratory is to implement basic histogram processing.
This laboratory will make use of the colour image capture and display developed in an earlier session. Copy the files into a new directory to work on this laboratory.
1: Histogram Accumulation As we saw in the lecture, histogram based processing is divided into four phases. Two of these require read access to the histogram (histogram accumulation, and histogram processing), and two require write access (clearing the histogram, and histogram accumulation). This complicates the design of our system because it is necessary to coordinate access between these various phases.
We use a finite state machine to coordinate access in the design presented here. For histogram display, we will have three states:
• Accumulation of the histogram from the incoming image. • Transfer of the accumulated histogram to a display histogram. This is necessary because we will be
displaying the histogram as an overlay for the next frame, so we need somewhere to display the histogram from while we are accumulating the histogram for the next frame. During the transfer, we will also clear the histogram accumulators for the next image.
• Idle, waiting for the start of the next frame.
Note, the transition from the ACCUMULATE to TRANSFER states must wait until both the input stream, and the display stream are both in the blanking period. The transition goes via INIT_TRANSFER to initialise the signals required for the transfer.
For our colour image, we will accumulate data from the raw image (before Bayer pattern demosaicing). This has the advantage that each raw pixel has only one colour, and a single histogram memory can be used for the colour image (rather than 3 separate histogram memories, one for each colour channel).
Incrementing a histogram bin requires two memory accesses, one to read and one to write the incremented bin. Since this must be performed every clock cycle, a dual-port memory is required. Because of the complexity of integrating the accesses between the different phases, we will separate the processes for reading from the histogram bin, and writing the accumulated result back.
The first step in the accumulator read process (shown on the next page) is to determine the read address (lines 60-76):
• When accumulating, the top two address bits comes from the least significant bits of the y and x address. This is used to determine which phase of the Bayer pattern we are in, hence which histogram the pixel value is accumulated into. The actual pixel value selects the bin.
• In the INIT_TRANSFER state, we initialise the address to 0 for the histogram transfer. • In the TRANSFER state, we systematically step through reading successive bins.
The actual reading of the histogram bin is performed in lines 78-84. Incrementing a bin takes two clock cycles (one to read the value, and the other to write the result). If two successive pixels have the same pixel value, the result from the first pixel is not written to the memory before it is read for the second pixel. Therefore, in this case we simply increment the previous count, rather than reading it from memory.
Lines 85 and 86 ensure that the read is followed in the following clock cycle by a write.
The write process is a little simpler:
• In the ACCUMULATE state, the incremented data is written to the histogram memory. • Otherwise, in the TRANSFER state, the histogram accumulator just read is cleared, and the data
written to the display histogram. • While doing the transfer, we also find the maximum count so that we can scale the histogram
appropriately for the display.
2: Histogram display The “simplest” thing to do with a histogram is display it. Since the width of the display (640) is too narrow for 3 full histograms, we will reduce the histograms for display to 128 bins. For this reason, although each pixel has 12 bits, we will use only 128 bins (7 bits) for each histogram during accumulation. The display is divided into 5 parts, of which histograms will be displayed in 3.
The display process is the final process within the entity:
Within this process we will start at the bottom. This is because we are using internal variables, and we want to use registered values, rather than intermediate values.
• Lines 144-151 determines the histogram scaling. To have the histogram approximately 256 pixels high, we divide the maximum count by 256 to get the count associated with each display row (step). Multiplying this by 479 gives the level corresponding to the top row of the screen. (This makes the bottom row 0, so will always be turned on, enabling the width of the histogram to be seen.)
• At the end of each display row (lines 148-149) the threshold level is adjusted for the next row. • Lines 136-142 read the histogram count for the bin corresponding to the current column during the
display streaming. Bits 8 and 9 are used to select the appropriate histogram, with bits 6 downto 0 selecting the bin.
0 128
256
384
512
640
• Lines 127-134 compare the bin count with the threshold level corresponding to the current row. If the count exceeds the threshold, the output is set with the appropriate colour (1 bit for each of RGB).
Edit top.vhd and make the following changes:
• In the declaration section, declare the 3 bit signal for the histogram display output:
• Next, instantiate the histogram display (lines 120-123). We connect the input to the raw pixel stream before Bayer filtering (raw_pix and raw_s), and produce the output in synchronisation with the display stream (disp_s). In the generic map, we set the histogram to 18 bits (sufficient to count to 218=262144), and the number of bins to 128, *4 for the four phases of the raw Bayer image.
• Finally, use the histogram display output to overlay the histogram on lines 127-132.
Compile the design, and download onto to the FPGA and observe the histograms. You should clearly see the histograms shift as the automatic gain control adjusts the camera gain. Observe the effects of different coloured objects on the histograms.
In the display, the histograms are semi-transparent. For example, the red histogram only affects the red component. Modify the display code (lines127-132) to make them opaque (for example when displaying the red histogram, the blue and green channels are set to 0).
3: Histogram Equalisation The last part of the design is to apply histogram equalisation to the image. Initially we will work on a greyscale image (histogram equalisation is only defined for greyscale images).
Building the histogram is much the same as in the previous example, with the exception that we build a single histogram rather than three.
Instead of transferring the histogram, we will calculate the equalisation mapping. Calculating the mapping follows the division by repeated subtraction described in the lecture. The complicating factor is getting the pipeline timing correct with reading the value from histogram memory (which needs to be done in advance because it takes a whole clock cycle).
The actual mapping is trivial, simply looking up the input pixel in the mapping lookup table. The control signal used to select whether the signal is mapped or passed through.
Edit top.vhd and make the following changes to implement histogram equalisation within the processing chain.
• First change the size of the bayer pixel to 12 bits to represent greyscale rather than colour. • Then declare the signals for the output of the equalisation: eq_p and eq_s.
• We will reuse the Bayer to grey conversion to get the greyscale image for equalisation. Edit the instantiation of the Bayer interpolation filter to the bayer_grey version, and adjust the parameters accordingly.
• Instantiate the histogram equalisation we have just developed. In the code here, we are building a full histogram of the 12-bit input image (4096 bins). In performing the equalisation, we are transferring the result to an 8-bit output image.
• Modify the display to use the timing and equalised pixel outputs.
Compile your design and download it onto the FPGA. Use sw(0) to switch the histogram equalisation on and off.
4: Further work Some possibilities:
• Switch the Bayer filter back to a colour image, and instantiate 3 histogram equalisation modules, one for each colour channel. Hint – you can use a for … generate loop to create multiple copies of the histogram equalisation.
• Modify the histogram display routine to add the histogram display (with 256 bins) to the output of the greyscale histogram equalisation.
• Modify the histogram equalisation to give some other output target histogram shape. (The easiest way to do this is to replace the SCALE constant by a signal that changes with each step. The SCALE gives the target number of pixels for each output bin.)
5: Summary In this laboratory we have:
• Accumulated and displayed histograms associated with a colour image. • Obtained the histogram of a greyscale image and used it to perform histogram equalisation on the
input image.
FPGA Workshop, OIST 159
Session 7:Session 7: ColourColour
FPGA Workshop, OIST 160
ObjectivesObjectives • Objectives
– Explain why RGB is generally unsuited for colour detection – Simple conversion to more suitable spaces – Develop rectangular region detection in 3D colour space
• Laboratory objectives – Implement a simple colour thresholding algorithm – Introduce algorithm tuning issues
FPGA Workshop, OIST 161
Colour DetectionColour Detection • Detect pixels belonging to a set of colours
– Label based on colour – Point operation
– Input • RGB pixel value
– Output • Colour label for each pixel
Input stream
Output stream
Function block
FPGA Workshop, OIST 162
Colour ThresholdingColour Thresholding • Computationally simple approach
– Assign pixels within a box in RGB space to a particular label
– Separate thresholds for R, G, and B • Problem:
– Strong correlation between R, G, and B – All 3 depend strongly on illumination
• Illumination level scales all R,G,B • Movement is generally diagonally • Requires large boxes for each colour detected
– Poor colour discrimination
R
B
G
FPGA Workshop, OIST 163
YUV Colour DetectionYUV Colour Detection
• Change colour space – Reduces correlation between channels
• Eg YUV
– Problem: transformation is expensive because of all the multiplications • YUV based on human perception – not necessary here
0.299 0.587 0.114 0.169 0.331 0.500 0.500 0.419 0.081
Y R U G V B
= − −
− −
FPGA Workshop, OIST 164
V ′
U′
YUV Colour DetectionYUV Colour Detection • Solution – use powers of 2
• Simple Implementation
– Shifts come for free in hardware
1 1 1 4 2 4 1 1 1 4 2 4 1 1 2 20
Y R U G V B
′ ′ = −
′ −
V ′
U ′
Y′
–
+ –
+ Y’
U’
V’
G
R B
÷2
÷2
÷2
÷2
FPGA Workshop, OIST 165
Colour ThresholdingColour Thresholding • Threshold each component independently
– One set of comparisons per colour class
min max
min max
min max
U U U V V V Y Y Y
′< < ′< < ′< <
U′
V ′
FPGA Workshop, OIST 166
Colour ThresholdingColour Thresholding • Lookup table approach
– Represent mapping as LUT – Separate LUT for Y,U and V – One bitplane per colour class 0
1
Vmin Vmax
0
1
Umin Umax
0
1
Ymin Ymax 3 2 1 0Bit
Out
Y’
U’
V’
Y LUT
U LUT
V LUT
FPGA Workshop, OIST 167
Bounding BoxBounding Box • Determines leftmost, rightmost, topmost and
bottommost pixels associated with an object – Position – Size – Aspect ratio
• Works on labelled image – Input pixels are labelled
individually, not as a group • Thresholding • Colour segmentation
– A separate bounding box produced for each label
FPGA Workshop, OIST 168
Streamed ImplementationStreamed Implementation • Resetting: Set init flipflop to 1 • First pixel: If init is 1
– Write forced to xmin, xmax and ymin – Resets init to 0
• Otherwise: Write if box boundary is affected
FPGA Workshop, OIST 169
Multiple ObjectsMultiple Objects • Have an array of structures
– Index by pixel label (object id) – Share update logic – Implement using dual-port RAM
• RAM addressing is effectively acting as a multiplexer
FPGA Workshop, OIST 170
Advantages and LimitationsAdvantages and Limitations • Advantages
– Simplicity – Low processing costs
• Disadvantages – Does not require connectivity of points with the label
• Bounding box may include multiple objects with same label
– Measurements are sensitive to noise – Isolated noise points can make data meaningless
• Requires filtering to remove noise first
FPGA Workshop, OIST 171
Object TrackingObject Tracking • Simple tracking
– Detect target within field of view – Move sensor readout window to centre target within the
image • Issues:
– Improve tracking performance by predicting position in next frame • Kalman filter for example
– Repositioning window flushes image capture pipeline – Ideally, should all be implemented on images streamed
from camera to minimise latency
FPGA Workshop, OIST 172
Laboratory:Laboratory: Colour DetectionColour Detection
and Trackingand Tracking
Laboratory: Colour Detection and Tracking
The aim of this laboratory is to perform colour thresholding (after a colour space conversion), and group the detected pixels with a bounding box. Finally, the bounding box will be used to control the digital camera, adjusting the position of the readout window to keep the target object in the centre of the field of view. The block diagram shows the dataflow for the final design at the end of the laboratory.
Memory buffer
I C controller
2
Bayer filter
Erosion filter
RGB to YUV
YUV to RGB
Colour threshold
Display
Colour tuning
Bounding box
This laboratory will make use of the colour image capture and display developed in an earlier session. Copy the files into a new directory to work on this laboratory.
1: Colour space conversion While we could detect colours directly in RGB colour space, as the brightness changes, this will have a strong effect on all three colour channels. To improve this, we can convert the image into a different colour space which separates the luminance component from the chrominance components. This allows us to allow a broad range on the luminance (to account for changes in brightness) while having tighter selection on the colour components.
Therefore we will convert the image into a variation of YUV colour space, using a conversion matrix which consists of powers of 2 to simplify calculation.
The forward conversion is given by
1 1 1 4 2 4 1 1 1 4 2 4 1 1 2 20
Y R U G V B
= − −
, with the reverse as 1 1 1 1 1 0 1 1 1
R Y G U B V
= − −
In the Y component, twice the weight is given to G since in the Bayer sensor, there are twice as many green pixels as other components. The U component gives a colour difference between magenta and green, while the V gives a colour difference between orange and blue.
To view the difference components, we will use the switch inputs to turn on and off the different colour components , with sw(2) switching the Y, sw(1) switching the U and sw(0) switching the V. Note, when Y is switched off, mid grey will be used, rather than black otherwise the colours will not be seen correctly. However, to see the results on an RGB monitor it is necessary to use the reverse conversion.
The colour space conversions are developed as different architectures within the colour_space entity (see colour_space.vhd). Each conversion has a latency of 1 clock cycle. The values r, g, and b are defined from the concatenated input as aliases to make the code more readable, and functions are defined for the sums and differences. Otherwise, it implements the conversion as in the lecture:
The conversions have already been instantiated within top.vhd to save time. (Additional logic has also been added for displaying detected pixels and displaying the box. These will be used later; don’t worry about them for now.) Compile your design onto the FPGA and experiment with the switches to see the representation of different colours within YUV colour space.
2: Threshold setting The next task in detecting a colour is thresholding the colour components to select the combination that corresponds to the desired colour. There are two aspect to this:
• setting the thresholds (colour tuning), and • determining whether each pixel is within the selected range.
We will use key(2) to control whether we are tuning or not. For tuning, we will analyse the statistics of a 32×32 patch within the centre of the image. The average colour of the pixels within this patch will be used as the target colour, and the thresholds will be offset a fixed amount from that target.
When we are not tuning, we will detect pixels within the tuned thresholds and highlight these in red on the display.
Edit top.vhd to instantiate the colour thresholding component:
This operates on the YUV pixels and works in parallel with the YUV to RGB conversion block. Thresholding has a latency of 1 clock cycle, as does YUV to RGB conversion, therefore the detected pixel stream will be in synch with the displayed RGB pixels.
Compile the design and download it onto the FPGA. Tune colours by pressing push-button key(2) and holding the target colour within the marked square. When you release key(2), the thresholds will be set, and the detected pixels will display. With movement, the automatic gain changes the brightness within the image. The simplest way of handling this is to switch off the automatic gain control (recall that this is controlled by sw(9)). If too many other colours are being detected, you may want to tighten the thresholds. These are set by additional generics of colour_threshold. Set these to narrower values (by adding these to the instantiation above), and recompile to test the design.
3: Bounding box In the previous exercise, each pixel was labelled as belonging to an object or the background on the basis of its colour. Each pixel was considered independently of all the others. The next step is to consider all the detected pixels as belonging to an object region, and to determine the position of the object within the image.
For this we will use the bounding box. It assumes that all detected pixels belong to the target object, and finds the top-most, bottom-most, left-most and right- most pixels within the object. These define a box which bounds the object, determining the object’s position and extent.
The implementation in bounding_box.vhd follows the approach from the lecture.
Like with histogram processing, the bounding box is not completed until the end of the frame. We cannot display the box with the data, because the image was streamed directly from the camera and has not been saved in a frame buffer. Therefore we will display the detected box on the following frame. If the target object is moving, then this will not coincide with the location in the new frame, but does give an indication, and is fine with a static target.
Box_display consists purely of combinatorial logic, so will take no clock cycles.
Instantiate the bounding box within top.vhd. First declare the bounding box structure:
Finally, instantiate our bounding box construction and display components after the threshold:
Compile the design, and download it onto the FPGA to test.
4: Morphological filtering While the bounding box is very simple to calculate, there are three main limitations:
• It does not require that the detected pixels to be connected in any way. All of the pixels detected are considered to belong to a single object. If there are multiple objects within the image, the bounding box will consider them all to part of a single object.
• Any noise pixels on the boundary of the object will cause the boundary to jitter. The bounding box is sensitive to correctly detecting the pixels on the edge of the object.
• It is very sensitive to isolated noise pixels. These pixels, misclassified as object pixels, will cause the bounding box to extend to include them. Since these are unrelated to the target object, they completely distort the bounding box, reducing the usefulness of the data obtained.
Modifying the algorithm to solve the first problem is non-trivial. It requires using connected component labelling, which is beyond the scope of this laboratory. Instead, we will assume only a single target, and use a filter to solve the other two problems. A 5×5 morphological erosion filter will shrink the image by 2 pixels from all sides, and eliminate and noise points smaller than 5×5 pixels. An erosion filter with a square window is separable, so we can efficiently perform the 2-dimensional filtering with a row filter followed by a column filter.
The filter will add latency to the image stream (2 rows and 5 pixels), so it is necessary to also delay the colour pixel stream by the same amount. This will be accomplished through the image_delay component. Note that when we are tuning, we use the detected output to display the tuning box. This will get eliminated by the filter, so we need to add the box back in manually.
Edit top.vhd and add the following declarations:
Next, instantiate the morphological filter and image delay components. Make the other changes as highlighted below to determine the bounding box of the filtered stream:
• The bounding box on line 171 operates on the filtered pixel stream. • Line 174 redraws the tuning box when key(2) is pressed. • The overlay takes the combined bounding box / tuning box for display. • The timing of the display is of the filtered pixel stream. • The filtered detected pixel, and delayed RGB image are shown on the display.
Compile the design, and download it to the FPGA. Check that the bounding box now behaves adequately.
5: Tracking The last step is to use the bounding box position to adjust the location of the camera readout window. This is achieved by writing the new window position to the appropriate register within the camera.
As a result of the way the camera operates, the change in window position is not instantaneous. When the command is sent, the camera has already started exposing the next frame. Therefore, whenever we change the start row, the frame after the following frame is invalid. This causes two problems:
• the data received from the camera for that frame is invalid, and • there is a timing bubble (the timing of the camera is reset).
This timing bubble causes a problem because the camera and display get out of synchronisation. Our logic therefore resets the VGA timing generator to resynchronise, however the monitor goes blank for about a second until it synchronises with the new timing. To solve this problem, rather than have the camera free- running, we provide a periodic trigger signal to the camera to initiate capture. This will reduce the bubble allowing us to perform vertical tracking. We have already instantiated a regular trigger within top.vhd (camera_trigger on lines 99-101), however we need to set the camera into trigger mode. Do this by uncommenting line 45 of the camera initialisation data:
Add the declarations of i2c_trk_req (line 51), i2c_trk_cmp (line 53), wpos_x and wpos_y (line 55). Also change the size of i2c_ack:
Next, edit the definition of i2c_multi_port to add the additional port for tracking commands. We add an additional port (N_PORT has been increased to 2), and additional entries have been added to req and ports to link in the new I2C tracking control signals via this additional port.
Finally, instantiate the tracker logic.
The HOLD_OFF generic causes the tracker to delay 3 frames (1/20 second) after making an adjustment before making another adjustment. We have also connected the enable for the tracker to sw(3). This will allow us to turn tracking on and off.
Compile your design, turn sw(3) off, and tune it for a target colour, and move the target within the field of view. Switch sw(3) on, and see what happens. The display might blank for the first 2 or 3 movements, but after that, it should track vertically without resetting the monitor. The flickering is a result of the bad frames that appear after adjusting the vertical position of the window. (Remember that the image is not being stored anywhere – we are operating directly on the streamed data from the camera.) Press key(0) if you need to reset the system to start again.
6: Further work One possibility:
• Comment out the display of the current camera gain, and program the seven segment display with the current position (wpos_x and wpos_y). With only 2 displays for each, use bits (10 downto 7) and (6 downto 3).
7: Summary In this laboratory we have:
• Use colour space conversion to transform and RGB to a simplified YUV colour space, and back. • Performed thresholding within YUV colour space to detect a target colour. • Used a bounding box to group colour pixels into a target object. • Filtered noise using a morphological erosion filter. • Maintained timing between parallel paths within a pipelined system by introducing appropriate delay. • Implemented target tracking to keep the target object in the centre of the field of view.
FPGA Workshop, OIST 173
Session 8:Session 8: Frequency Domain ProcessingFrequency Domain Processing
FPGA Workshop, OIST 174
Objectives • Objectives
– Look at how information is represented in the frequency domain
– Introduce FFT • Radix 2, Radix 4, Radix 22
– Complex multiplication resources – Application of FFT to filtering
• Laboratory objectives – Implement 2D FFT
FPGA Workshop, OIST 175
Fourier TransformFourier Transform • Decomposes an image in terms of spatial frequency
• Basis functions are periodic – Implies image is periodic in both space and frequency – Real images have conjugate symmetric Fourier transforms
• Fast Fourier transform – An efficient implementation of the discrete Fourier transform
2 ( )( , ) ( , ) j xu yv x y
F u v f x y e π− +=∑∑
FPGA Workshop, OIST 176
• A periodic pattern will have distinct peaks in the frequency domain – Position of peaks gives spatial
frequency – Amplitude of peaks gives
amplitude of corresponding spatial sinusoid
– Phase gives position within the image
– Shape of peaks gives information on the shape and size of pattern
Information in Frequency DomainInformation in Frequency Domain
Computation RequiredComputation Required • For an N×N image:
– Each of the N2 frequencies is a weighted sum of N2 pixels – Requires N4 multiplications (for N=256 => 4.3×109)
• Separability:
– Perform transform on rows then on columns – Requires 2N N-point transforms (2N3) (for N=256 => 3.5×107)
• Factorisability: gives fast transform – Each N-point transform requires N log2N operations – Image requires 2N2log2N operations (for N=256 => 1×106)
FPGA Workshop, OIST 177
2 ( )( , ) ( , ) j xu yv x y
F u v f x y e π− += ∑∑
2 2( , ) ( , ) j xu j yv y x
F u v f x y e eπ π− −
=
∑ ∑
FPGA Workshop, OIST 178
RadixRadix--2 Decimation in Time FFT2 Decimation in Time FFT • Splits input into odd
and even samples – Takes FT of each half
and combines results – Applied recursively
gives FFT • Inputs are in bit
reversed order
FPGA Workshop, OIST 179
RadixRadix--2 Decimation in Frequency FFT2 Decimation in Frequency FFT • Calculates even and
odd frequency components separately – Combines inputs and
takes FT of each half – Applied recursively gives
FFT • Frequency outputs are
in bit reversed order
FPGA Workshop, OIST 180
Complex MultiplicationComplex Multiplication • All multiplications are by
complex twiddle factors
– Requires 4 real multiplications – Reduce to 3 with factorisation – Lifting makes it reversible even with truncation
Factorised
Conventional
Lifting
2 / 2 2cos sinj NN N NW e j π π π−= = −
FPGA Workshop, OIST 181
RadixRadix--4 Decimation in Frequency Butterfly4 Decimation in Frequency Butterfly
• Reduces number of multiplies • Decimates by factor of 4
– Uses 4-point FT as “butterflies”
1 1 1 1 1 1 1 1 1 1 1 1
j j
j j
− − =
− − − −
F f
FPGA Workshop, OIST 182
• Butterflies operate in place on data in memory • First data is streamed in • Then streamed through
a butterfly for each level – Output after last level
• With pipeline delays, the multiplication can be shifted out of radix-4 butterfly
FFT ImplementationFFT Implementation
FPGA Workshop, OIST 183
Pipelined RadixPipelined Radix--2222 ButterflyButterfly • Streamed input and streamed output
– Splits radix-4 into two radix-2 butterflies – Each stage has pipeline delay memory
Address bits
FPGA Workshop, OIST 184
Two Dimensional FFTTwo Dimensional FFT • FFT is separable
– Apply 1D FFT to rows then columns • Multiple rows/columns can be transformed in parallel
– Building parallel hardware blocks • With real data, symmetry can be exploited
– Row FFTs are conjugate symmetric • Two row FFTs can be performed at once by a single FFT unit
– 2D output is conjugate symmetric • Half of column FFTs do not need to be calculated explicitly
– Reduces computation by a factor of 4
FPGA Workshop, OIST 185
Frequency Domain FilteringFrequency Domain Filtering • Linear convolution filters become a product in
frequency domain – Filter function is just weighting frequency components – Linear filter can be thought of in terms of its frequency
response • Most images are dominated by low frequencies
– Low pass filtering will improve signal to noise ratio – High frequencies (edges, fine detail) will be attenuated
• Boosting high frequencies will enhance edges – Will also tend to amplify noise
[ , ] [ , ] [ , ]Q u v W u v I u v=
FPGA Workshop, OIST 186
Wiener FilterWiener Filter • Optimal filter in least squares sense
– Minimises errors resulting from • Attenuation of signal by filter • Noise within the image
• Need to know signal and noise frequency content
– Gain is approximately 1 for frequencies where signal is much larger than noise are
– Frequencies where noise dominates are attenuated • Effective for both random and pattern noise
2
2 2
[ , ] [ , ]
[ , ] [ , ] F u v
W u v F u v N u v
= +
FPGA Workshop, OIST 187
Laboratory:Laboratory: Fast Fourier TransformFast Fourier Transform
Laboratory: Pipelined FFT
The aim of this laboratory is to take and display the Fourier transform of an image. Since the FFT requires the size to be a power of 2, and to enable the image to be displayed and transformed we will restrict the processing to 256 pixels. We will use the radix-22 FFT because each stage requires only a radix-2 butterfly, and a complex multiplier is only required after every second stage.
This laboratory will make use of the image capture and display developed in an earlier session. Copy the files into a new directory to work on this laboratory.
1: Basic butterfly The FFT is built on a butterfly. A radix-2 butterfly effectively divides the image in half, and performs both a sum and a difference between the two halves. When working on streamed data, as the image is streamed in, the first half is saved into a buffer. Then when the second half is streamed in, the butterfly is used to add it and subtract it to the first half. While the sum is streamed out, the difference is recirculated back into the buffer for reading out when the sum is finished. While the difference is reading out, for continuous operation, the next row can be streamed in.
Buffer
Butter!y
Compile the project, within Quartus, and download the design to the FPGA. The design processes the first 256 pixels of each row, displaying the sum and difference on the right side of the display. Experiment, with the camera focussed on some text (for example a business card).
Edit fft.vhd, and change N_BUFF on line 59 to 64 or 32. This will control the length of the buffer. Recompile the design and observe the effects.
2: 1-D FFT The FFT consists of a series of butterflies, with buffer lengths decreasing by powers of 2. After each butterfly, the values are multiplied by a corresponding twiddle factor. In a radix-22 FFT, the butterflies are divided into pairs, with the twiddle factors for the first butterfly being 1 or –j (which is trivial), and a complex multiply is required only after the second butterfly in a pair. The addition and subtraction of each butterfly increases the word length by 1. After the complex multiply, the words are rounded back to their original length. Four such pairs are required for a 256 point FFT.
To implement the FFT, first change the DELAY on line 28 to119. This changes the delay to align the FFT correctly on the display.
Next, comment out the butterfly section on line 58 to 62. Select these 5 lines and Edit » Comment Selection (or the toolbar button). Uncomment the FFT section, from lines 64 to 97 (select those lines and Edit » Uncomment Selection or the toolbar button). This performs the 256 element FFT, then uses CORDIC to determine the magnitude of the result, followed by a logarithm to compress the dynamic range to enable the display to be seen clearly.
Compile the design and download to the FPGA to see the FFT of the first 256 pixels in each line.
The output is hard to interpret because the frequencies appear in bit-reversed order. Much of the next process buffers the FFT log magnitude output and displays it in natural order. Change the output on line 96 from log_mag to br. This will display instead the image in natural order.
Compile this design, an experiment by placing different patterns in the left part of the image to see their Fourier transforms.
3: 2-D FFT To perform a 2-D FFT, we next need to perform an FFT down the columns of the row FFTs. For the size of image we are using, this would be a 256×256 FFT, which requires saving the row FFT data in external memory. Unfortunately, on the DE0, the external memory is DRAM, which is more complex to interface to. It is not just a matter of providing an address and getting the data. DRAM uses a paged structure, and each page (or row) must be opened before access (whether read or write) and then closed before moving to another row. Fortunately the DRAM also uses a banked structure, with the memory divided into 4 banks. One row in each bank can be open simultaneously, enabling the row opening and closing to be pipelined with careful memory mapping.
Streamed 1D-FFT
Camera Display Streamed 1D-FFT
Row FFT Column FFT
Memory Memory
A single FFT block can be used to transform both of the rows as they are streamed in, and of the columns during the remaining frame period. This will necessitate displaying the Fourier transform with the following frame.
The first stage is the streamed row FFT, which performs the transform directly on the data streamed from the camera. For a 256×256 FFT, there are 256 complex frequency values produced. However, since the input
image is real, the output will be conjugate symmetric, requiring only 2 real and 127 complex values to be saved. This is a total of 256 real values which are streamed to the memory by row. The column FFT requires those values to be streamed in by column, There are 129 FFTs required, each of which requires 256 samples (512 real values). However, accessing these by column is more difficult when using DRAM memory.
Working with 16 bits per fixed point real number (minimum for satisfactory results), each row would take 256 16-bit words in memory. While this fits exactly into a single row of DRAM, reading down the column would incur significant overhead, opening and closing each DRAM row for two words.
A better arrangement is to distribute each image row across 4 banks within DRAM (64 words in each). This would give time to open each bank, to enable a continuous stream to be formed, maximising the bandwidth. To avoid the problem of the column scan being in the same bank for successive reads, every 4 rows should be offset by a bank to allow activation and precharge commands to be interleaved. The Write memory map would therefore be:
128 values per row
Column addressRow addressBank
256 rows
0
r0 c0c1c2c3c4c5c6r1r2r3r4r5r6r7
Since all 4 banks can be open simultaneously, it is straight forward to do the bit reversing of the data column address as the samples are written.
128 bit reversed values
Column addressRow addressBank
256 rows
0
r 0
c 0
c 0
c 1
c 1
c 2
c 2
c 3
c 3
c 4
c 4
c 5
c 5
c 6
c 6
r 1
r 2
r 3
r 4
r 5
r 6
r 7
This is also convenient because only every second sample needs to be saved (the other samples are the complex conjugates), enabling 2 writes per pair of samples. DC and Nyquist frequency (the two real values) can be saved together since they are available from the FFT in the same clock cycle. The most convenient memory mode would therefore be bursts of 2 samples in successive addresses.
For reading back, the rows and columns are reversed, so are swapped. Only 128 columns need to be read, but each column has 256 rows. Since each entry has 2 words (for the complex number), the least significant bit remains:
256 values per column
Column addressRow addressBank
128 columns
0
r0c0c1c2c3c4c5c6 r1r2r3r4r5r6r7
The 2 reads per sample will therefore either require buffering, or running the FFT at half speed.
When writing the results back to the second transpose buffer, converting from bit-reversed rows to natural rows would require successive accesses to be in different rows of the DRAM, which is not worth doing. The rows can be read out for display in bit reversed order, without any problem. However, when reading out for display, we also need to read out the negative frequencies (not saved). Since these are complex conjugates from the row transform, the Fourier transform of those columns would be in the reverse order. Therefore two rows must be read out for each row on the display. Readout would be simplified if both rows were in the same DRAM rows. This is achieved by using the most significant bit of the row number to negate the address of the remaining bits:
256 bit-reversed values
Column addressRow addressBank
128 columns
1
r 0
-r 0
c 0
c 1
c 2
c 3
c 4
c 5
c 6
r 1
-r 1
r 2
-r 4
-r 2
r 3
-r 5
-r 3
r 4
-r 4
r 5
-r 5
r 6
-r 6
r 7
r 7
When reading out, the negative frequencies are read first, then the positive frequencies. Note that since the column FFT of both the DC and Nyquist frequencies were done together, they will require additional processing when reading out for the display at the end.
Reading out for display will take 512 clock cycles to read out the 256 complex values. Since these are displayed at 1 per clock cycle, the data will need to start loading earlier to achieve the display rate.
4: Further work Some possibilities (challenging):
• Implement the DRAM controller to display the 2-D FFT on the fly. • Implement frequency domain filtering by multiplying the frequency domain image by the filter
frequency response, and performing an inverse FFT. (The single FFT block can be used for both with appropriate buffering).
5: Summary In this laboratory we have:
• Examined the basic butterfly operation used by the FFT. • Implemented a 1-D FFT. • Outlined the design and memory management scheme for a 2-D FFT.
Supplement: Programming the ROM
Up until now, we have been programming the FPGA directly from the computer. The DE0 also contains a flash memory which can be used to provide an initial configuration on power-up. By downloading the configuration into this, we can create a stand-alone system.
The direct configuration is via a .sof file. We need to get Quartus II to produce a .pof file for programming the flash. Assignments » Device will show the FPGA device. Click on the Device and Pin Options… button and select the Configuration category. Perform the following selections:
Then click OK twice to return to Quartus.
Rebuild the project. This will create two output programming files: <Project>.sof for programming directly, and <Project>.pof which is used for programming the configuration flash, where <Project> is the name of your project file.
Switch the Run – Prog switch on the DE0 to the Prog position to set up for programming the flash. Open the programmer, and change the mode from JTAG to Active Serial Programming. At the prompt, click Yes to clear the current device list. Click Add Device… select EPCS4 to select the configuration EPROM, and click OK.
Select the first line (with the file <none>) in the file pane, click Change File… and select the <Project>.pof file for downloading. Finally tick the Program/Configure checkbox to enable the device to be programmed.
Next click the Start button to download the configuration file. If successful, this will load the configuration into the serial flash device in the board.
The final steps are:
• Power the DE0 down • Change the Run – Prog switch back to the Run position • Power on the board again.
This time, the FPGA should automatically load the configuration from the flash memory.