大致题意
为实现 FPGA 上的信号处理,通常要经过算法的设计,算法的定点化以及顶点算法的实现三个步骤。这里要实现定点数乘累加器的第二阶段设计——用 MATLAB 设计算法的定点化。
s u m = ∑ i a i b i sum=\sum_{i}a_{i} b_{i} sum=∑iaibi
MATLAB 的仿真结果要与 HDL 模拟结果一致,即模拟出的定点数能够与算法在硬件中实现后的对应信号在每个bit 上都匹配(bit-true)。
Fixed-Point Designer 工具可以高效的进行算法的定点化设计。用Fixed-PointDesigner工具来描述定点数,每一个定点数都是一个 fi 对象;“定点格式”用 numerictype 对象给出;而定点数之间的运算规则,对应的是 fimath 对象。
乘累加器类
支持自定义输入输出的定点数格式,且在溢出发生后饱和处理,并模拟电路复位的过程,以保证其持续工作。通过字符串修改操作数的 hex 属性完成对操作数实数值的修改。定点数运算同时在乘累加器内部进行一致的浮点数运算,以方便观察定点数与浮点数结果差异以及引入的噪声。
classdef fixed_mac < handle
% Mutiply accumulator that support fixed point number
properties
a;
b;
res;
ref_res;
F;
end
methods
function obj = fixed_mac(din_a_numerictype, din_b_numerictype, ...
dout_numerictype)
%Construct
obj.F = fimath('RoundingMethod', 'Floor', ...
'SumMode', 'SpecifyPrecision', ...
'SumWordLength', dout_numerictype.WordLength, ...
'SumFractionLength', ...
dout_numerictype.FractionLength);
obj.a = fi(0, din_a_numerictype);
obj.b = fi(0, din_b_numerictype);
obj.res = fi(0, dout_numerictype, obj.F);
obj.ref_res = 0;
end
function mul_ac(obj, hex_a, hex_b)
% Simulate a reset clock
if(obj.res.double == 7.9375 || obj.res.double == -8)
obj.res.double = 0;
obj.ref_res = 0;
else
% Multiply and accumulate
obj.a.hex = hex_a;
obj.b.hex = hex_b;
obj.res = obj.res + fi(obj.a * obj.b, obj.F);
obj.ref_res = obj.ref_res + obj.a.double * obj.b.double;
end
end
function [dout_hex, dout, ref_dout] = output(obj)
%Print the result of fixed_mac
dout_hex = obj.res.hex;
dout = obj.res.double;
ref_dout = obj.ref_res;
end
end
end
testbench
定义输入输出的定点数格式,通过读取 txt 文件的数据模拟乘累加器模块的输入信号。din_a, din_b 算术操作完成后同步打印结果(实际输入输出相差一个时钟),绘制定点数与浮点数结果曲线并分析信噪比。
clear all;
Ta = numerictype(0, 7, 3);
Tb = numerictype(1, 5, 7);
Tr = numerictype(1, 8, 4);
% Create a fixed_mac object
mac = fixed_mac(Ta, Tb, Tr);
% Open a txt file to read data
fid = fopen('test_data.txt');
% Multiply and accumulate synchronously
i = 1;
while 1
tline1 = fgetl(fid);
% Determine whether input is character array
if ~ischar(tline1), break, end
% The file has one empty line every 14 hex numbers
if tline1 == "", continue, end
tline2 = fgetl(fid);
if ~ischar(tline2), break, end
% Simulate multiply and accumulate in fixed_number
mac.mul_ac(tline1, tline2);
[res_hex, res(i), ref_res(i)] = mac.output();
i = i + 1;
disp(['din_a = ' tline1 ', din_b = ' tline2 ', Dout = ' res_hex]);
end
% Print dout, ref_dout
plot([res', ref_res']);
title('fixed_mac dout & ref dout');
legend('fixed mac dout', 'ref dout');
% Calculate the SNR
err = res - ref_res;
err_energy = err * err';
ref_energy = ref_res * ref_res';
snr_db = 10 * log10(ref_energy / err_energy)
数据格式
70
0F
72
0F
74
0F
76