You are on page 1of 11

MATLAB Fixed-point Toolbox for FPGA Algorithm Optimization

John Ruddy February, 2012

Introduction
When designing and implementing an algorithm on an FPGA, there is usually a need to convert the algorithm from oating point to xed point representation. The design ow generally follows a verication process that begins with a oating point verication of the algorithm. Once the algorithm is developed, it is often converted to xed point format in order to eciently utilize the FPGA logic. This process can be very time-consuming since every data element needs to be analyzed in order to determine the correct wordlength and radix point. Fortunately, the MATLAB Fixed-Point toolbox contains a library of xed point data types and functions that operate on them, providing a simulation environment that can accurately represent the computations to be performed on an FPGA. By setting certain global properties for operation rules and handling overow, the error between simulation and implementation can be reduced. The following discusses the process of implementing an algorithm in Matlab using oating point and converting it to a xed-point calculation with a desired output precision.

Discussion
Floating to Fixed-Point Conversion Process
The development process used here for converting an algorithm to xed point follows these steps:

1. Write and verify oating-point model in MATLAB 2. Analyze dynamic range of intermediate and output variables 3. Convert to Fixed-Point data types and turn on data logging 4. Use logged min and max values to determine word length and radix point 5. Optimize by comparing results to those of oating-point model

These steps will be explained in the following sections.

Write Floating-Point Model The rst step of the conversion process is to establish and verify the algorithm in MATLAB using oating-point representation. For this project, the algorithm has already been implemented and veried in C. This step then is simply to convert the C code into MATLAB code and verify that the results match those of the C code.

Analyze Dynamic Range When converting to xed-point, it helps to understand the range of the intermediate and output variables in order to choose starting values for the word length and radix point. One way to do this is to run through many dierent input values and examine the ranges of the variables. The Fixed-Point toolbox provides a N umericT ypeScope object that can log the ranges of values that a variable takes on and then displays a histogram of the range, some statistics, and the recommended xed-point data type. The following code listing shows how the scope is dened and used for each variable. Lines 4-6 each dene a scope, while lines 23-25 use the step command to process the current variables value. This code example uses the direction calculation part of the algorithm. The inputs are the variables x and i, which are varied from 0 to 2 to simulate the possible inputs. It is faster to run the simulations in batches, analyzing only one or two variables at a time, than analyzing all of the variables at once. The simulations run much slower when there are too many step functions to process the data. 2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

| | | | | | | | | | | | | | | | | | | | | | | | | | |

% Direction function range analysis %Define hscopex hscopey hscopez scopes = NumericTypeScope; = NumericTypeScope; = NumericTypeScope;

% Loop for different elevation(i) and azimuth(x) values for i = 0:10:360 for x = 0:5:360 dir1x = cos(degtorad(x)); dir1y = sin(degtorad(x)); dir1z = tan(degtorad(i)); sumSqrs = dir1x^2 + dir1y^2 + dir1z^2; %Outputs dirx = dir1x/sqrt(sumSqrs); diry = dir1y/sqrt(sumSqrs); dirz = dir1z/sqrt(sumSqrs); %Process data step(hscopex, step(hscopey, step(hscopez, end end and update scope dirx); diry); dirz);

Output:
The output of the scope for the dirx variable, which is the output direction for the x-axis, is shown in Figure 1. The data values that the variable takes on is plotted in a histogram vs. its number (or percentage) of occurrences. Each bin represents a power of two that values lie within. The wordlength can be set to be chosen automatically and then the fractional bits can be graphically controlled. The display gives the percentage of output values that fall outside of the range of the current numeric type being displayed. In the gure, it can be seen that 8% of values fall below the numeric type chosen with a word length of 8 and fractional length of 7. Dragging the green line allows control over the displayed numeric type. Here, if dragged so that the yellow bins are included, the percentage of numbers outside the range falls to 0.1%, but the wordlength is increased to 59 bits. This gives two clear options, use a word length of 8 or 59, depending on the required precision needed. 3

Figure 1: MATLAB NumericTypeScope Display Utilizing the NumericTypeScope tool on the variables in the oating point algorithm helps speed up the determination of numeric type properties. As shown in the direction calculation, it can clearly be seen what the best options for choosing wordlength are. This is true as long as the input values are carefully thought out. They need to accurately represent the possible real world inputs in order to gather the correct statistics.

Convert to Fixed-Point The next step is to convert the input data types to xed point, and modify any math operations that do not have built in support for f i objects, or MATLAB xed point objects. Fixed-point objects are created using the f i(v, s, w, f ) constructor, where v is value, s is signedness, w is worlength, and f is the number of fractional bits. If only called using the value parameter, the best precision number of fractional bits is given for either a given word length or a default word length of 16 bits. The following code is the direction calculation from the previous listing but using f i objects: 1 | function dir = calcDirRadsFixed(azimuth, elevation, iters, T) 4

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20| 21| 22|

% % % % % % %

Calculates direction vector using azimuth and elevation inputs as radians in fixed point format. T is a numerictype for the fixed-point divisions defining the wordlength and fractionlength for the result. iters defines how many iterations the cordic calculation uses.

if nargin<3, iters = 14; end; if nargin<4 T = numerictype(Wordlength, 33, FractionLength, 32); end [dir(2), dir(1)] = cordicsincos(azimuth, iters); [tmpsin, tmpcos] = cordicsincos(elevation, iters); dir(3) = divide(T, tmpsin, tmpcos); sumSqrs = dir(1)^2 + dir(2)^2 + dir(3)^2; dir(1) = divide(T,dir(1),sqrt(sumSqrs)); dir(2) = divide(T,dir(2),sqrt(sumSqrs)); dir(3) = divide(T,dir(3),sqrt(sumSqrs));

In the xed-point version, the math operation divide needed to be changed from / to divide(T, a, b), where T is the numerictype, a is the dividend, and b is the divisor. Also, the built-in trigonometric functions need to be replaced with CORDIC functions. The CORDIC is an approximation of sin and cos in xed point using vector rotation. The function is used to generate the sine and cosine values for the azimuth input. It is also used for the elevation input, but the result is divided, sin divided by cos, to give a result of tangent. These values are then used to calculate the direction. The function in the listing calculates the outputs using the inputted values numeric type and the divide functions numeric type. The numeric types of the direction outputs should be pre dened with the numeric types determined in the range analysis. This can be done using dir(1) = f i(0, numerictype , T ), where T is the desired numeric type. The next step is to turn on overow and underow warnings along with data logging. To turn on the warnings the rst three lines of the following are used:

warning on fi:overflow warning on fi:underflow warning off backtrace 5

fp = fipref; fipref(LoggingMode, on); iters = 14; T = numerictype(Wordlength, 33, FractionLength, 32); % Loop for different elevation(i) and azimuth(x) values for i = 0:10:360 for x = 0:5:360 azimuth = fi(deg2rad(x), 1, 6, 5); elevation = fi(deg2rad(i), 1, 6, 5); [dir(2), dir(1)] = cordicsincos(azimuth, iters); [tmpsin, tmpcos] = cordicsincos(elevation, iters); dir(3) = divide(T, tmpsin, tmpcos); sumSqrs = dir(1)^2 + dir(2)^2 + dir(3)^2; dir(1) = divide(T,dir(1),sqrt(sumSqrs)); dir(2) = divide(T,dir(2),sqrt(sumSqrs)); dir(3) = divide(T,dir(3),sqrt(sumSqrs));

end end

Output Example : ... Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 overflow(s) occurred in the divide operation. Warning: 1 overflow(s) occurred in the fi assignment operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. Warning: 1 underflow(s) occurred in the fi bitshift operation. 6

Warning: 1 underflow(s) occurred in the fi bitshift ...

Backtrace can be turned on to see what line numbers the warnings occur at. The line f ipref ( LoggingM ode , on ) turns on data logging. A report can be printed with the logreport(var1, var2, ...) function. An output of the log report function is shown below:

Figure 2: Logreport output

Figure 3: Logreport output with Scaled Double data type In Figure 2, the minimum and maximum numbers logged, and the lower and upper bounds are given in a table. In order to gather a better log of the values, the datatype can be overridden to a scaled double data type, which is a f i object that logs the values it takes on with double precision. The output of this log is given in Figure 3.

Finalizing the Conversion After converting to xed-point format and logging the ranges of data for both the oating and xed point formats, the determination of word length is eased greatly. The xed-point algorithm is tested against the oating point outputs. If the error is greater than the specied threshold, the word length can be iterated until it meets specications.

Current Progress
Currently, the wvalue calculation is broken up into its mathematical components, and each one is being optimized separately. This makes the process of range analysis and representation conversion much simpler. The process documented in the previous section is used on each part of the algorithm to ne tune the xed point numeric types 7

of the variables. This has currently been completed for the direction calculation, the distance calculation, and the integration limits calculation. Remaining are the subray direction calculation, the integration, and the basis function. Data is being compiled on all of these and will be included in the next report, with the determined data types and logged values for all of the variables. The outputs of each part of the xed-point algorithm will also be compared to those of the oating-point version to determine the error.

current algorithm progress in xed point conversion: wvalueFixed.m: %function result = wvalue(losAzi, losEle, gvNor, gvEas, gvAlt) %WVALU Calculate the next element in the projection matrix % % clear %% Fixed-Point Properties % fimath F = fimath(RoundMode, Floor, ... OverflowMode, Saturate, ... ProductMode, SpecifyPrecision, ... ProductWordLength, 128, ... ProductFractionLength, 64, ... SumMode, SpecifyPrecision, ... SumWordLength, 65, ... SumFractionLength, 32, ... CastBeforeSum, false); G = globalfimath(RoundMode, Floor, ... OverflowMode, Saturate, ... ProductMode, SpecifyPrecision, ... ProductWordLength, 128, ... ProductFractionLength, 64, ... SumMode, SpecifyPrecision, ... SumWordLength, 65, ... SumFractionLength, 32, ... CastBeforeSum, false); % numerictype T = numerictype(Wordlength, 64, FractionLength, 32);

%% INPUTS (manual, FI objects) losAzi = fi(281.6, T); losEle = fi(0, T); gvNor = fi(3692751.8, T); gvEas = fi(589562.5, T); gvAlt = fi(1326.4, T); % Parameters(FI objects) PI = fi(3.14159265359, T); Northing = fi(1, T); Easting = fi(2, T); Altitude = fi(3, T); maxRootSubRays = fi(19, T); maxNumSubRays = fi(361, T); vxSizNE = fi(10, T); vxSizA = fi(10, T); dim = fi(3, T); losFOV = fi(.5, T); losLoc(1) = fi(3692489.8, T); %N losLoc(2) = fi(590730, T); %E losLoc(3) = fi(1330, T); %A gvoxel(1) = gvNor; gvoxel(2) = gvEas; gvoxel(3) = gvAlt;

%% DATA-TYPE INDEPENDENT ALGORITHM basisDomain = fi(4, T)*sqrt(2*vxSizNE^2 + vxSizA^2); %calculate dir vector dir =calcDirRadsFixed(deg2rad(losAzi), deg2rad(losEle)); %calculate distance from sensor to voxel sens2vox = distanceFixed(losLoc, gvoxel, dim); %% integration limits pointOnLOS = vectorline(losLoc, sens2vox - basisDomain, dir); t1 = distance(losLoc, pointOnLOS,3); pointOnLOS = vectorline(losLoc, sens2vox + basisDomain, dir); t2 = distance(losLoc, pointOnLOS,3);

%% Integration % intStep = 1; rootNumSubRays = 15;

%SubRays % totSubRays = rootNumSubRays^2; %Calculate sub Directions subStep = divide(T,losFOV,rootNumSubRays); startAzi = losAzi - losFOV/2; startEle = losEle + losFOV/2; for j = 0:rootNumSubRays-1 for i = 0:rootNumSubRays-1 subAzi = startAzi + subStep/2 + i*subStep; subEle = startEle - subStep/2 - j*subStep; k = i + j * rootNumSubRays; subDirFixed(k+1,1:3) = calcDirRadsFixed(deg2rad(subAzi),deg2rad(subEle end end %% numLosSteps = divide(T,(t2-t1),intStep+.5); stepLOS = divide(T,(t2-t1),numLosSteps); integrateResult = 0; for n = 0:double(numLosSteps) t = t1 + n*stepLOS;%distance from sensor FOVsumAtLOSPos = 0; for k = 0:totSubRays-1 %calculate pt on subray at t pointOnLOS = vectorline(losLoc, %get x,y,z prime ??? absCoord(1) = abs(pointOnLOS(1) absCoord(2) = abs(pointOnLOS(2) absCoord(3) = abs(pointOnLOS(3)

t, subDirFixed(k+1,1:3)); - gvoxel(1)); - gvoxel(2)); - gvoxel(3));

%get basis function value at relative position %to grid point loc b = basisFunction(vxSizNE, absCoord(1)) * ... basisFunction(vxSizNE, absCoord(2)) * ... basisFunction(vxSizA, absCoord(3));

10

FOVsumAtLOSPos = FOVsumAtLOSPos + b; end %Half first and last integration if (n==0 || n==numLosSteps) FOVsumAtLOSPos = FOVsumAtLOSPos * 0.5; end integrateResult = integrateResult + FOVsumAtLOSPos; end

integrateResult = integrateResult / totSubRays; integrateResult = integrateResult * stepLOS;

result =

integrateResult

11

You might also like