%% Define Custom Board and Reference Design for Deep Learning Processor IP Core Workflow
% This example shows how to define and register a custom board and
% reference design for the deep learning processor IP core workflow.
% If you have a system that has preprocessing and postprocessing design
% under test (DUT) blocks, you can iterate on those
% blocks to improve your performance and resource utilization by using HDL Coder(TM).
% Create a custom reference design that includes
% the DUT blocks and the definition for your custom deep learning processor
% IP core.


% Copyright 2021 The MathWorks, Inc.

%% Introduction
% First create a custom board and reference design. Register the deep learning
% processor IP core in your custom board and reference design. Deploy the
% deep learning processor IP core to your custom board by generating a
% custom bitstream. Use MATLAB(R) to interface with the deep learning
% processor IP core.
%
%% Workflow
% The image shows the workflow to deploy the deep learning processor IP
% core to a custom board.
%
% <<../customboardworkflow.png>>
%% Register Custom Board
% Register a custom board in HDL Workflow Advisor.
%
% 1. Create a board registration file with the name
% |hdlcoder_board_customization.m| and add it to the MATLAB path. The
% |hdlcoder_board_customization.m| function must return a second output
% for workflow. Set the workflow to:
%
%   workflow = hdlcoder.Workflow.DeepLearningProcessor;
%
%
%   function [boardList, workflow] = hdlcoder_board_customization
%   % Board plugin registration file
%   % 1. Any registration file with this name on MATLAB path will be picked up
%   % 2. Registration file returns a cell array pointing to the location of 
%   %    the board plugins
%   % 3. Board plugin must be a package folder accessible from MATLAB path,
%   %    and contains a board definition file
%
%   %   Copyright 2019 The MathWorks, Inc.
%
%   boardList = { ...
%       'DLZCU102.plugin_board', ...
%       'DLZC706.plugin_board', ...
%       };
%
%   workflow = hdlcoder.Workflow.DeepLearningProcessor;
%
%   end
%
%
% 2. Create the board definition file.
%
%   %   Copyright 2019 The MathWorks, Inc.
%   
%   % Board definition of ZCU102
%   function hB = plugin_board
%   
%   % Construct board object
%   hB = hdlcoder.Board;
%
%   hB.BoardName    = 'Xilinx Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit';
%
%   % FPGA device information
%   hB.FPGAVendor   = 'Xilinx';
%   hB.FPGAFamily   = 'Zynq UltraScale+';
%   hB.FPGADevice   = 'xczu9eg-ffvb1156-2-e';
%   hB.FPGAPackage  = '';
%   hB.FPGASpeed    = '';
%
%   % Tool information
%   hB.SupportedTool = {'Xilinx Vivado'};
%
%   % FPGA JTAG chain position
%   hB.JTAGChainPosition = 1;
%
%   %% Add interfaces
%   % Standard "External Port" interface
%   hB.addExternalPortInterface( ...
%       'IOPadConstraint', {'IOSTANDARD = LVCMOS18'});
%
%   % GPIO LEDs
%   hB.addExternalIOInterface( ...
%      'InterfaceID',    'LEDs General Purpose', ...
%       'InterfaceType',  'OUT', ...
%      'PortName',       'GPIO_LED', ...
%       'PortWidth',      8, ...
%       'FPGAPin',        {'AG14', 'AF13', 'AE13', 'AJ14', 'AJ15', 'AH13', 'AH14', 'AL12'}, ...
%       'IOPadConstraint', {'IOSTANDARD = LVCMOS33'});

%% Register Custom Reference Design
%
% Register the custom reference design in HDL Workflow Advisor.
%
% 1. Create a reference design registration file named
% |hdlcoder_ref_design_customization.m| containing a list of reference
% design plugins associated with an SoC board.
%
%   function [rd, boardName] = hdlcoder_ref_design_customization
%   % Reference design plugin registration file
%   % 1. The registration file with this name inside of a board plugin folder 
%   %    will be picked up
%   % 2. Any registration file with this name on MATLAB path will also be picked up
%   % 3. The registration file returns a cell array pointing to the location of 
%   %    the reference design plugins
%   % 4. The registration file also returns its associated board name
%   % 5. Reference design plugin must be a package folder accessible from 
%   %    MATLAB path, and contains a reference design definition file
%
%   %   Copyright 2019 The MathWorks, Inc.
%
%
%   rd = {...
%           'DLZCU102.matlab_libiio_3axi4_master_2019_1.plugin_rd', ...
%   		};
%
%   boardName = 'Xilinx Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit';
%
%   end
%
% 2. Create the reference design definition file.
%
%   function hRD = plugin_rd
%   % Reference design definition
%
%   %   Copyright 2019-2020 The MathWorks, Inc.
%
%   % Construct reference design object
%   hRD = hdlcoder.ReferenceDesign('SynthesisTool','Xilinx Vivado');
%
%   hRD.ReferenceDesignName = 'AXI-Stream DDR Memory Access : 3-AXIM';
%   hRD.BoardName = 'Xilinx Zynq UltraScale+ MPSoC ZCU102 Evaluation Kit';
%
%   % Tool information
%   hRD.SupportedToolVersion = {'2019.1','2019.2','2020.1'};
%
%   %% Add custom design files
%   % add custom Vivado design
%   hRD.addCustomVivadoDesign( ...
%       'CustomBlockDesignTcl','system_top.tcl');
%
%   % Add constraint files
%   hRD.CustomConstraints = {'ZCU102_DDR4.xdc'};
%
%   % Post Create Project Callback function to improve timing closure
%   hRD.PostCreateProjectFcn   = @DLZCU102.matlab_libiio_3axi4_master_2019_1.callback_PostCreateProject;
%
%   % Add HDL Verifier JTAG as AXI Master IP from support package
%   msg = message('hdlcommon:plugin:IPRepositoryHDLVerifierXilinxNotFound').getString;
%   hRD.addIPRepository( ...
%   	'IPListFunction','hdlverifier.fpga.vivado.iplist', ...
%   	'NotExistMessage', msg);	
%
%   % Add AXI4-Stream to AXI4-Master DDR Access IP
%   hRD.addIPRepository( ...
%   	'IPListFunction','hdlcoder.fpga.vivado.hdlcoder_axis2axim_iplist', ...
%   	'NotExistMessage', 'AXI4-Stream to AXI4-Master IP not found.');	
%
%
%   %% Add interfaces
%   % add clock interface
%   hRD.addClockInterface( ...
%       'ClockConnection',     'core_clkwiz/clk_out1', ...
%       'ResetConnection',     'sys_dut_rstgen/peripheral_aresetn',...
%       'DefaultFrequencyMHz', 50,...
%       'MinFrequencyMHz',     5,...
%       'MaxFrequencyMHz',     500,...
%       'ClockModuleInstance', 'core_clkwiz',...
%       'ClockNumber',         1);
%
%   % add AXI4 and AXI4-Lite slave interfaces
%   hRD.addAXI4SlaveInterface( ...
%       'InterfaceConnection', 'axi_cpu_interconnect/M03_AXI', ...
%       'BaseAddress',         {'0xA0000000','0x00A0000000'}, ...
%       'MasterAddressSpace',  {'hdlverifier_axi_master_0/axi4m','sys_cpu/Data'}, ...
%       'InterfaceType',       'AXI4', ...
%       'IDWidth',             13);
%    
% 3. Add deep learning processor information to the reference design
% file. 
% The reference design plugin file must contain information about the
% target interface and the deep learning processor IP core, the memory address
% space for the deep learning processor IP core, and a command to validate
% the reference design.
% 
%   % Deep learning specific properties
%   hRD.registerDeepLearningTargetInterface("JTAG");
%   hRD.registerDeepLearningTargetInterface("Ethernet");
%   hRD.registerDeepLearningMemoryAddressSpace(0x80000000, 0x20000000); % 512 MB
%
%
%   hRD.ResourcesUsed.LogicElements = 35000;
%   hRD.ResourcesUsed.DSP = 3;
%   hRD.ResourcesUsed.RAM = 77.5;
%
% The completed board and reference design registration files for the
% Xilinx(R) Zynq(R) Ultrascale+(R) MPSoC ZCU102 board can be found at,
%
% |supportpackages\R2021b\toolbox\dnnfpga\supportpackages\xilinx\boards|
% and
% 
% |supportpackages\R2021b\toolbox\dnnfpga\supportpackages\xilinx\boards\+DLZCU102|.
%
% For more details on how to set up, define, and register the custom board refer to the
% <docid:hdlcoder_ug#example-hdlcoder_ip_core_tutorial_zynq_MPSoC Getting
% Started with Targeting Zynq UltraScale+ MPSoC Platform>.

