В этом примере показано, как сгенерировать HDL-код из проекта MATLAB®, реализующего адаптивный средний алгоритм фильтра, которому удовлетворяют для генерации HDL-кода.
design_name = 'mlhdlc_median_filter'; testbench_name = 'mlhdlc_median_filter_tb';
Давайте смотреть на проект MATLAB
type(design_name);
%#codegen function [pixel_val, pixel_valid] = mlhdlc_median_filter(c_data, c_idx) % Copyright 2011-2015 The MathWorks, Inc. smax = 9; persistent window; if isempty(window) window = zeros(smax, smax); end cp = ceil(smax/2); % center pixel; w3 = -1:1; w5 = -2:2; w7 = -3:3; w9 = -4:4; r3 = cp + w3; % 3x3 window r5 = cp + w5; % 5x5 window r7 = cp + w7; % 7x7 window r9 = cp + w9; % 9x9 window d3x3 = window(r3, r3); d5x5 = window(r5, r5); d7x7 = window(r7, r7); d9x9 = window(r9, r9); center_pixel = window(cp, cp); % use 1D filter for 3x3 region outbuf = get_median_1d(d3x3(:)'); [min3, med3, max3] = getMinMaxMed_1d(outbuf); % use 2D filter for 5x5 region outbuf = get_median_2d(d5x5); [min5, med5, max5] = getMinMaxMed_2d(outbuf); % use 2D filter for 7x7 region outbuf = get_median_2d(d7x7); [min7, med7, max7] = getMinMaxMed_2d(outbuf); % use 2D filter for 9x9 region outbuf = get_median_2d(d9x9); [min9, med9, max9] = getMinMaxMed_2d(outbuf); pixel_val = get_new_pixel(min3, med3, max3, ... min5, med5, max5, ... min7, med7, max7, ... min9, med9, max9, ... center_pixel); % we need to wait until 9 cycles for the buffer to fill up % output is not valid every time we start from col1 for 9 cycles. persistent datavalid if isempty(datavalid) datavalid = false; end pixel_valid = datavalid; datavalid = (c_idx >= smax); % build the 9x9 buffer window(:,2:smax) = window(:,1:smax-1); window(:,1) = c_data; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [min, med, max] = getMinMaxMed_1d(inbuf) max = inbuf(1); med = inbuf(ceil(numel(inbuf)/2)); min = inbuf(numel(inbuf)); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [min, med, max] = getMinMaxMed_2d(inbuf) [nrows, ncols] = size(inbuf); max = inbuf(1, 1); med = inbuf(ceil(nrows/2), ceil(ncols/2)); min = inbuf(nrows, ncols); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function new_pixel = get_new_pixel(... min3, med3, max3, ... min5, med5, max5, ... min7, med7, max7, ... min9, med9, max9, ... center_data) if (med3 > min3 && med3 < max3) new_pixel = get_center_data(min3, med3, max3,center_data); elseif (med5 > min5 && med5 < max5) new_pixel = get_center_data(min5, med5, max5,center_data); elseif (med7 > min7 && med7 < max7) new_pixel = get_center_data(min7, med7, max7,center_data); elseif (med9 > min9 && med9 < max9) new_pixel = get_center_data(min9, med9, max9,center_data); else new_pixel = center_data; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function [new_data] = get_center_data(min,med,max,center_data) if center_data <= min || center_data >= max new_data = med; else new_data = center_data; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % perform median 1d computation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function outbuf = get_median_1d(inbuf) numpixels = length(inbuf); tbuf = inbuf; for ii=coder.unroll(1:numpixels) if bitand(ii,uint32(1)) == 1 tbuf = compare_stage1(tbuf); else tbuf = compare_stage2(tbuf); end end outbuf = tbuf; end function outbuf = compare_stage1(inbuf) numpixels = length(inbuf); tbuf = compare_stage(inbuf(1:numpixels-1)); outbuf = [tbuf(:)' inbuf(numpixels)]; end function outbuf = compare_stage2(inbuf) numpixels = length(inbuf); tbuf = compare_stage(inbuf(2:numpixels)); outbuf = [inbuf(1) tbuf(:)']; end function [outbuf] = compare_stage(inbuf) step = 2; numpixels = length(inbuf); outbuf = inbuf; for ii=coder.unroll(1:step:numpixels) t = compare_pixels([inbuf(ii), inbuf(ii+1)]); outbuf(ii) = t(1); outbuf(ii+1) = t(2); end end function outbuf = compare_pixels(inbuf) if (inbuf(1) > inbuf(2)) outbuf = [inbuf(1), inbuf(2)]; else outbuf = [inbuf(2), inbuf(1)]; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % perform median 2d computation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function outbuf = get_median_2d(inbuf) outbuf = inbuf; [nrows, ncols] = size(inbuf); for ii=coder.unroll(1:ncols) colData = outbuf(:, ii)'; colDataOut = get_median_1d(colData)'; outbuf(:, ii) = colDataOut; end for ii=coder.unroll(1:nrows) rowData = outbuf(ii, :); rowDataOut = get_median_1d(rowData); outbuf(ii, :) = rowDataOut; end end
type(testbench_name);
% % Copyright 2011-2015 The MathWorks, Inc. I = imread('mlhdlc_img_pattern_noisy.tif'); J = I; smax = 9; [nrows, ncols] = size(I); ll = ceil(smax/2); ul = floor(smax/2); for ii=1:ncols-smax for jj=1:nrows-smax c_idx = ii; c_data = double(I(jj:jj+smax-1, ii)); [pixel_val, pixel_valid] = mlhdlc_median_filter(c_data, c_idx); if pixel_valid J(jj, ii) = pixel_val; end end end h = figure; set( h, 'Name', [ mfilename, '_plot' ] ); subplot( 1, 2, 1 ); imshow( I, [ ] ); subplot( 1, 2, 2 ); imshow( J, [ ] );
Выполнение следующих линий копирует необходимые файлы во временную папку
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_med_filt']; % create a temporary folder and copy the MATLAB files cd(tempdir); [~, ~, ~] = rmdir(mlhdlc_temp_dir, 's'); mkdir(mlhdlc_temp_dir); cd(mlhdlc_temp_dir); % copy files to the temp dir copyfile(fullfile(mlhdlc_demo_dir, [design_name,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [testbench_name,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, 'mlhdlc_img_pattern_noisy.tif'), mlhdlc_temp_dir);
Это всегда - хорошая практика, чтобы симулировать проект с испытательным стендом до генерации кода, чтобы убедиться, что нет никаких ошибок периода выполнения.
Этот проект занимает хорошее количество времени, когда симулировано в MATLAB. Однако мы могли использовать MATLAB Coder, чтобы создать файл MEX и использовать файл MEX, чтобы симулировать испытательный стенд быстрее. Обратите внимание на то, что Советник по вопросам HDL автоматизирует эти шаги при выполнении симуляций фиксированной точки проекта.
codegen -o mlhdlc_median_filter -args {zeros(9,1), 0} mlhdlc_median_filter [~, tbn] = fileparts(testbench_name);
Перечисленный выше шаг создает файл MEX в текущем каталоге с тем же именем как функция проекта. Испытательный стенд берет файл MEX и запускается быстрее через codegen ускорение.
mlhdlc_median_filter_tb
Позволяет очистке файл MEX и codegen директория прежде, чем переместиться в шаги HDL Workflow Advisor
clear mex; rmdir('codegen', 's'); delete(['mlhdlc_median_filter', '.', mexext]);
coder -hdlcoder -new mlhdlc_med_filt_prj
Затем добавьте файл 'mlhdlc_median_filter.m' в проект как функция MATLAB и 'mlhdlc_median_filter_tb.m' как Испытательный стенд MATLAB.
Можно обратиться к Началу работы с MATLAB к примеру по Рабочему процессу HDL для более полного примера при создании и заполнении проектов HDL Coder MATLAB.
Запустите Советника по вопросам Рабочего процесса от вкладки Build, и щелчок правой кнопкой по 'Генерации кода' продвигаются и выбирают опцию, 'Запущенную к выбранной задаче', чтобы запустить все шаги с начала через генерацию HDL-кода.
Исследуйте сгенерированный HDL-код путем нажатия на гиперссылки в окне Code Generation Log.
Можно запустить следующие команды, чтобы очистить временную папку проекта.
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_med_filt']; clear mex; cd (mlhdlc_demo_dir); rmdir(mlhdlc_temp_dir, 's');