如果您正在使用 MATLAB 建模数字信号处理(DSP)或者视频和图像处理算法,并且最终将其用于 FPGA 或 ASIC,本文可能将为你带来帮助。
从 MATLAB 生成 HDL 代码
FPGA 在通用处理器(GPP)和专用集成电路(ASIC)之间提供了很好的折中方案。GPP 是完全可编程的,但在功率和性能方面效率较低;ASIC 可实现专用的功能,并展现出最佳的功率和性能特性,但需要极其昂贵的设计验证和实现周期。FPGA 也用于 ASIC 工作流中的原型设计,以进行硬件验证和早期软件开发。
由于在运行高吞吐量、高性能的应用程序时,性能有了大幅度的提高,算法设计者越来越多地使用 FPGA 而不是传统的处理器来原型化和验证创新。然而,由于 MATLAB 简单易用的编程模型和丰富的分析和可视化能力,许多算法都是在其中实现的。当针对 FPGA 或 ASIC 时,这些 MATLAB 算法必须手动转换为 HDL。
对于许多精通软件编程的算法开发人员来说,掌握 FPGA 设计工作流是一项挑战。与软件算法开发不同,硬件开发要求并行思想。存在的其他障碍包括:学习 VHDL 或 Verilog 语言,掌握 FPGA 供应商的 IDE,理解深奥的术语,如“多周期路径”和“延迟平衡”等。
在这篇文章中,我将介绍一个从 MATLAB 转换为 FPGA 的简单路径。我将展示如何从 MATLAB 算法自动生成 HDL 代码,在 FPGA 上实现 HDL 代码,并使用 MATLAB 来验证您的 HDL 代码。
MATLAB 到硬件工作流
将 MATLAB 设计转换为硬件的过程包括以下步骤:
1. 在 MATLAB 中建模您的算法——使用 MATLAB 来模拟、调试、迭代测试并优化设计。
2. 生成 HDL 代码——自动创建用于 FPGA 原型的 HDL 代码。
3. 验证 HDL 代码——重用您的 MATLAB test bench 来验证生成的 HDL 代码。
4. 创建和验证 FPGA 原型——在 FPGA 上实现和验证您的设计。
将 MATLAB 转换为硬件存在一些独特的挑战。MATLAB 代码是过程性的,可以高度抽象;它可以使用浮点数据,并且没有时间概念。复杂的循环可以从矩阵运算和工具箱函数推断出来。
在硬件中实现 MATLAB 代码包含以下操作:
HDL Coder™ 可通过工作流自动化简化上述任务。
MATLAB 算法示例
让我们用MATLAB函数来实现直方图均衡化并完成此工作流。该算法在 MATLAB 中实现,通过变换灰度像中的值来增强图像对比度,使输出图像的直方图近似平坦。
type mlhdlc_heq.m
% Histogram Equalization Algorithm
function [pixel_out] = mlhdlc_heq(x_in, y_in, pixel_in, width, height)
persistent histogram
persistent transferFunc
persistent histInd
persistent cumSum
if isempty(histogram)
histogram = zeros(1, 2^8);
transferFunc = zeros(1, 2^8);
histInd = 0;
cumSum = 0;
end
% Figure out indices based on where we are in the frame
if y_in < height && x_in < width % valid pixel data
histInd = pixel_in + 1;
elseif y_in == height && x_in == 0 % first column of height+1
histInd = 1;
elseif y_in >= height % vertical blanking period
histInd = min(histInd + 1, 2^8);
elseif y_in < height % horizontal blanking - do nothing
histInd = 1;
end
%Read histogram
histValRead = histogram(histInd);
%Read transfer function
transValRead = transferFunc(histInd);
%If valid part of frame add one to pixel bin and keep transfer func val
if y_in < height && x_in < width
histValWrite = histValRead + 1; %Add pixel to bin
transValWrite = transValRead; %Write back same value
cumSum = 0;
elseif y_in >= height %In blanking time index through all bins and reset to zero
histValWrite = 0;
transValWrite = cumSum + histValRead;
cumSum = transValWrite;
else
histValWrite = histValRead;
transValWrite = transValRead;
end
%Write histogram
histogram(histInd) = histValWrite;
%Write transfer function
transferFunc(histInd) = transValWrite;
pixel_out = transValRead;
MATLAB Test Bench 示例
下面是一个 test bench,用于验证算法是否对示例图像起作用。(注意,此 testbench 使用 Image Processing Toolbox 的内置函数来读取原始图像,并在均衡后绘制转换的图像。)
type mlhdlc_heq_tb.m
%% Test bench for Histogram Equalization Algorithm
clear mlhdlc_heq;
testFile = 'office.png';
RGB = imread(testFile);
% Get intensity part of color image
YCBCR = rgb2ycbcr(RGB);
imgOrig = YCBCR(:,:,1);
[height, width] = size(imgOrig);
imgOut = zeros(height,width);
hBlank = 20;
% make sure we have enough vertical blanking to filter the histogram
vBlank = ceil(2^14/(width+hBlank));
for frame = 1:2
disp(['working on frame: ', num2str(frame)]);
for y_in = 0:height+vBlank-1
%disp(['frame: ', num2str(frame), ' of 2, row: ', num2str(y_in)]);
for x_in = 0:width+hBlank-1
if x_in < width && y_in < height
pixel_in = double(imgOrig(y_in+1, x_in+1));
else
pixel_in = 0;
end
[pixel_out] = mlhdlc_heq(x_in, y_in, pixel_in, width, height);
if x_in < width && y_in < height
imgOut(y_in+1,x_in+1) = pixel_out;
end
end
end
end
% Make color image from equalized intensity image
% Rescale image
imgOut = double(imgOut);
imgOut(:) = imgOut/max(imgOut(:));
imgOut = uint8(imgOut*255);
YCBCR(:,:,1) = imgOut;
RGBOut = ycbcr2rgb(YCBCR);
figure(1)
subplot(2,2,1); imshow(RGB, []);
title('Original Image');
subplot(2,2,2); imshow(RGBOut, []);
title('Equalized Image');
subplot(2,2,3); hist(double(imgOrig(:)),2^14-1);
title('Histogram of original Image');
subplot(2,2,4); hist(double(imgOut(:)),2^14-1);
title('Histogram of equalized Image');
我们来仿真一下此算法,看看结果。
mlhdlc_heq_tb
HDL Workflow Advisor
HDL Workflow Advisor(请参见下面的快照)有助于自动执行步骤,并提供从MATLAB到硬件的引导。您可以在 Workflow Advisor 的左窗格中看到工作流的以下关键步骤:
1. 定点转换
2. HDL 代码生成
3. HDL 验证
4. HDL 综合与分析
我们来详细看看工作流中的每个步骤。
定点转换
信号处理应用程序通常使用 MATLAB 中的浮点运算来实现。但是,出于功耗、成本和性能的原因,在面向硬件时,需要将这些算法转换为使用定点运算。定点转换非常具有挑战性并且非常耗时,通常需要占用整个设计和实施时间的 25% 到 50%。HDL Coder™ 中用于浮点到定点自动转换的工作流可以极大地简化和加速转换过程。
浮点到定点转换工作流包括以下步骤:
1. 验证浮点设计与代码生成兼容。
2. 根据计算范围,通过模拟 test bench 或通过静态分析(将传播设计范围以计算所有变量的派生范围)提出定点类型。
3. 通过应用建议的定点类型生成定点 MATLAB 代码。
4. 验证生成的定点代码,并将生成的定点代码的数值精度与原始浮点代码进行比较。
请注意,此步骤是可选的。如果您的 MATLAB 设计已在定点实现,则可以跳过此步骤。
HDL 代码生成
HDL 代码生成步骤通过定点 MATLAB 代码生成 HDL 代码。您可以生成实现 MATLAB 设计的 VHDL 或 Verilog 代码。除了生成可综合的HDL代码外,HDL Coder™ 还可生成各种报告,包括可帮助您在 MATLAB 代码和生成的 HDL 代码之间导航的可跟踪报告,以及在算法级别显示实现设计所需硬件资源(加法器、乘法器和 RAM)的资源利用率报告。
在代码生成期间,您可以指定各种优化选项来探索设计空间,而无需修改算法。在下面的“设计空间探索和优化选项”部分中,您可以看到如何修改代码生成选项以及如何针对速度或面积来优化设计。
HDL 验证
独立 HDL test bench 的生成:
HDL Coder™ 可通过您的 MATLAB 脚本生成 VHDL 和 Verilog test bench,以快速验证生成的 HDL 代码。您可以使用将激励应用于 HDL 代码的多个选项来自定义 HDL test bench。您还可以生成脚本文件,以自动执行在 HDL 模拟器中编译和模拟代码的过程。这些步骤有助于确保 MATLAB 仿真的结果与 HDL 仿真的结果相匹配。
HDL Coder™ 还与 HDL Verifier 一起使用,以自动生成两种类型的协同仿真 test bench:
HDL 综合
除了与语言相关的挑战外,FPGA 编程还需要使用复杂的 EDA 工具。从 HDL 设计中生成比特流并对 FPGA 进行编程可能是一项艰巨的任务。HDL Coder™ 通过为 Xilinx® 和 Altera® 创建用生成的HDL代码配置的项目文件,可在此处提供自动化。您可以使用工作流步骤在MATLAB 环境中综合 HDL 代码,查看综合结果,并迭代 MATLAB 设计以改善综合结果。
设计空间探索和优化选项
HDL Coder™ 提供以下优化,以帮助您探索如何在设计空间的面积和速度之间进行权衡。您可以使用这些选项来探索各种架构并进行各种权衡,而不必手动重写算法。
速度优化
面积优化
最佳实践方法
现在,我们来看几个在面向 FPGA 来编写 MATLAB 代码时的最佳实践方法。
编写 MATLAB 设计时:
编写 MATLAB test bench 时:
结论
HDL Coder™ 提供了在 FPGA 中实现算法的无缝工作流。在本文中,我向您展示了如何采用 MATLAB 图像处理算法、将其转换为定点、生成 HDL 代码、使用 test bench 验证生成的 HDL 代码,以及最终综合设计并在硬件中实现它。
通过本文对 HDL Coder™ 以及 MATLAB 转 HDL 代码生成和验证框架的简要介绍,我们希望能助您了解如何开始快速实施 MATLAB 设计和目标 FPGA。
文章转载自:MATLAB微信公众号