├── .gitignore
├── README.md
├── SECURITY.md
├── license.txt
├── mvdr_beamformer
├── FPGA_Adaptive_Beamforming_with_HDL_Coder_and_Zynq_RFSoC.pdf
├── README.md
├── common
│ ├── compareData.m
│ ├── deinterleave_complex.m
│ ├── generate_qpsk_signal.m
│ ├── interleave_complex.m
│ ├── maxabs.m
│ ├── plot_beam_patterns.m
│ ├── qpsk_receive.m
│ ├── sim_with_progress.m
│ └── unpack_complex.m
├── mvdr_app.png
├── mvdr_hdl_sim
│ └── mvdr_4x4
│ │ ├── model_init.m
│ │ ├── mvdr_4x4_partial_systolic.slx
│ │ ├── mvdr_reference.m
│ │ └── tb_mvdr_4x4_partial_systolic.m
├── xm500_wiring.png
└── zcu111_mvdr_demo
│ ├── RFSoCMVDRDemo.m
│ ├── RFSoC_MVDR_Demo.mlapp
│ ├── TxSteering_RxMVDR_4x4_HDL_IQ.slx
│ ├── calibrate_channels.m
│ ├── model_init.m
│ ├── prebuilt
│ ├── RF_Init.cfg
│ └── zcu111_mvdr.bit
│ ├── program_board.m
│ ├── setup_fpgaio.m
│ └── setup_rfsoc.m
└── rangedoppler
└── hw_only
├── 2dFFT.jpg
├── README.md
├── RangeDoppler.jpg
├── bandwidth_cornerturn.jpg
├── partA_TransposeMatrix
├── part0_SoCB
│ ├── MatrixWrRd_transpose_SoCB_TopLevel.slx
│ ├── hdlcoder_external_memory_read_ctrl_custom.m
│ ├── hdlcoder_external_memory_write_ctrl_custom.m
│ ├── matrix_init.m
│ ├── matrix_rdwr_transpose_fpga.slx
│ └── validate_matrix_out.m
├── part1_hdl_wrready
│ ├── matrix_init.m
│ ├── validate_matrix_out.m
│ └── wrQueue_RFSoC_MatrixTranspose.slx
└── part2_hdl_bram_burst
│ ├── AXIBusObjects.m
│ ├── bramBurst_TransposeMatrix.slx
│ ├── matrix_init.m
│ ├── model_init_sim.m
│ ├── run_fpgaIO.m
│ ├── transpose_fpgaIO_setup.m
│ └── validateTranspose.m
└── partB_MatchedFilterFFTTranspose
├── MatchedFilterFFT_Transpose.prj
├── part0_rangedoppler_ml
└── run_Range_Doppler.m
├── part1_transpose_radar_cube
├── BramBurst_FFT2D_validate_matrix_out.m
├── bramBurst_TransposeMatrix.slx
├── matrix_init.m
├── socmemlib.slx
└── validateTranspose.m
├── part2_rangedoppler_hdl
├── BramBurst_FFT2D_validate_matrix_out.m
├── RangeDopplerLoop_fpgaIO.m
├── bramBurst_TransposeMatrix.slx
├── matched_filter_fft_hdl_init.m
├── setup_fpgaIO.m
├── simCheckOutput_rangeDoppler.m
├── socmemlib.slx
├── validateTranspose.m
└── writeDopplerInput_fpgaIO.m
├── resources
└── project
│ ├── 1AK6k8_2MMsrq1VagZS1umPpphk
│ ├── -LsZ8HXJj2Q_3Mm_5RR2W21dUukd.xml
│ ├── -LsZ8HXJj2Q_3Mm_5RR2W21dUukp.xml
│ ├── 0avZ0B7B9QBO8c3kVcoPdfvh0a4d.xml
│ ├── 0avZ0B7B9QBO8c3kVcoPdfvh0a4p.xml
│ ├── 4SII37bbmPr-uDt2KwUOF17LD3Md.xml
│ ├── 4SII37bbmPr-uDt2KwUOF17LD3Mp.xml
│ ├── hVqQ-9HgOfR-miUHZ1Olro2oO1Ed.xml
│ ├── hVqQ-9HgOfR-miUHZ1Olro2oO1Ep.xml
│ ├── tKvNkHTpbT6GAm3k-7n7cooRcn0d.xml
│ ├── tKvNkHTpbT6GAm3k-7n7cooRcn0p.xml
│ ├── ySwxmLB6i3-U3ibpDX9G5VF_qIkd.xml
│ └── ySwxmLB6i3-U3ibpDX9G5VF_qIkp.xml
│ ├── CAsOFWEXbRicMJSXkpnan34QAz4
│ ├── 4SVYQZsILIuEyZXh7AZiBXaAzWId.xml
│ ├── 4SVYQZsILIuEyZXh7AZiBXaAzWIp.xml
│ ├── TDGNiicbXqPcaT25VpzQ4PfNaGEd.xml
│ ├── TDGNiicbXqPcaT25VpzQ4PfNaGEp.xml
│ ├── TnMVnPKCYgLFQp-huKXjIUP3g50d.xml
│ ├── TnMVnPKCYgLFQp-huKXjIUP3g50p.xml
│ ├── XI63F3DpcFZVEmLxabCze_1yGYUd.xml
│ ├── XI63F3DpcFZVEmLxabCze_1yGYUp.xml
│ ├── u09gIjf84mrcY04PvVsIqz_A2nId.xml
│ ├── u09gIjf84mrcY04PvVsIqz_A2nIp.xml
│ ├── ytXa1Px-hQUhxMW6RexuadiW05Md.xml
│ └── ytXa1Px-hQUhxMW6RexuadiW05Mp.xml
│ ├── EEtUlUb-dLAdf0KpMVivaUlztwA
│ ├── EP7gYHkiKJzsbwl1Kmg0OEWqO4od.xml
│ ├── EP7gYHkiKJzsbwl1Kmg0OEWqO4op.xml
│ ├── fSmbuBCUit5i5wOBPuJA2g5w9NId.xml
│ ├── fSmbuBCUit5i5wOBPuJA2g5w9NIp.xml
│ ├── lJnjawKd-WsGvgvgCWqsl0Tg_aUd.xml
│ ├── lJnjawKd-WsGvgvgCWqsl0Tg_aUp.xml
│ ├── pJPJd6FiWRygNl9o0EVnymaY7Ykd.xml
│ └── pJPJd6FiWRygNl9o0EVnymaY7Ykp.xml
│ ├── NwDM1JfMyUKVVWcp71u8HzQ1GJc
│ ├── ErjdZpt4SMkWn8v-1ahF4A3siMMd.xml
│ ├── ErjdZpt4SMkWn8v-1ahF4A3siMMp.xml
│ ├── MnQp2l-5jErytlj-zxMUdpGpr5cd.xml
│ └── MnQp2l-5jErytlj-zxMUdpGpr5cp.xml
│ ├── WZRuNzqc-Db7NcQAZO8Y-R8U9cc
│ ├── 66WgGCcF5RIH9MCEgPmgjZK9k3Ud.xml
│ ├── 66WgGCcF5RIH9MCEgPmgjZK9k3Up.xml
│ ├── AtMjXDrOSm8YDv3_4UFXiyrWqNEd.xml
│ └── AtMjXDrOSm8YDv3_4UFXiyrWqNEp.xml
│ ├── qaw0eS1zuuY1ar9TdPn1GMfrjbQ
│ ├── 1AK6k8_2MMsrq1VagZS1umPpphkd.xml
│ ├── 1AK6k8_2MMsrq1VagZS1umPpphkp.xml
│ ├── CAsOFWEXbRicMJSXkpnan34QAz4d.xml
│ ├── CAsOFWEXbRicMJSXkpnan34QAz4p.xml
│ ├── NwDM1JfMyUKVVWcp71u8HzQ1GJcd.xml
│ ├── NwDM1JfMyUKVVWcp71u8HzQ1GJcp.xml
│ ├── tczr9cMCNMOtxnSsL6yRolFxYBId.xml
│ └── tczr9cMCNMOtxnSsL6yRolFxYBIp.xml
│ ├── root
│ ├── EEtUlUb-dLAdf0KpMVivaUlztwAp.xml
│ └── WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml
│ └── tczr9cMCNMOtxnSsL6yRolFxYBI
│ ├── EGS-wA3-Ks6urVqBkUEHtwtFE_Ed.xml
│ ├── EGS-wA3-Ks6urVqBkUEHtwtFE_Ep.xml
│ ├── KRklbgq8aG-kfYmOgOLRLkm3QDId.xml
│ ├── KRklbgq8aG-kfYmOgOLRLkm3QDIp.xml
│ ├── Q6dDcsN2OKbQzgD58TRr8ONsFJMd.xml
│ ├── Q6dDcsN2OKbQzgD58TRr8ONsFJMp.xml
│ ├── WSzvG5f_5Cvt8a1ZYLPc6xfuSq4d.xml
│ ├── WSzvG5f_5Cvt8a1ZYLPc6xfuSq4p.xml
│ ├── Xi_uJVws7Ulmwu5Gll1EDSreybMd.xml
│ ├── Xi_uJVws7Ulmwu5Gll1EDSreybMp.xml
│ ├── b9vcJ5kLPMvo3kZz_IJEYIN8Z6cd.xml
│ ├── b9vcJ5kLPMvo3kZz_IJEYIN8Z6cp.xml
│ ├── haKPcoVMP6OfLpW27bivJk-zciAd.xml
│ ├── haKPcoVMP6OfLpW27bivJk-zciAp.xml
│ ├── rKuGYAHY8-cXC9XRh5EcCRlNuEQd.xml
│ ├── rKuGYAHY8-cXC9XRh5EcCRlNuEQp.xml
│ ├── uPQ5MtfZJq79kMUTlWx4p0q_8hod.xml
│ └── uPQ5MtfZJq79kMUTlWx4p0q_8hop.xml
└── shared_files
├── AXIBusObjects.m
├── createRadarDataCubeMod.m
├── getLogged.m
├── range_doppler_system_param_init.m
└── window_taper.slx
/.gitignore:
--------------------------------------------------------------------------------
1 | **/slprj/
2 | *.mexw64
3 | **/*_ert_rtw
4 | **/hdl_prj
5 | *.asv
6 | *.bak
7 | *.exp
8 | *.lib
9 | *.slxc
10 | *.zip
11 | *.pdf
12 | RFTool_Log.txt
13 | init.sh
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FPGA Adaptive Beamforming and Radar Examples with HDL Coder and Zynq RFSoC
2 |
3 | ## Overview
4 |
5 | This repository contains FPGA/HDL demonstrations several beamforming and
6 | radar designs. Simulink models and MATLAB reference code are provided to showcase
7 | high-level simulation and HDL designs of various radar and array processing algorithms.
8 |
9 | The license is available in the License.txt file in this GitHub repository.
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting Security Vulnerabilities
2 |
3 | If you believe you have discovered a security vulnerability, please report it to
4 | [security@mathworks.com](mailto:security@mathworks.com). Please see
5 | [MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
6 | for additional information.
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021, The MathWorks, Inc.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 | 3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
9 |
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 |
--------------------------------------------------------------------------------
/mvdr_beamformer/FPGA_Adaptive_Beamforming_with_HDL_Coder_and_Zynq_RFSoC.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/mvdr_beamformer/FPGA_Adaptive_Beamforming_with_HDL_Coder_and_Zynq_RFSoC.pdf
--------------------------------------------------------------------------------
/mvdr_beamformer/README.md:
--------------------------------------------------------------------------------
1 | # FPGA Adaptive Beamforming with HDL Coder and Zynq RFSoC
2 |
3 | ## Overview
4 |
5 | These models will demonstrate how to design and implement the minimum-variance
6 | distortionless-response (MVDR) adaptive beamforming algorithm on the Xilinx®
7 | Zynq UltraScale+™ RFSoC platform. By following a Model-Based Design strategy,
8 | we show how the MVDR beamformer can be articulated in MATLAB, Simulink,
9 | Fixed-Point and HDL. We further demonstrate a prototyping workflow by deploying
10 | the beamformer to the ZCU111 RFSoC evaluation board for run-time testing,
11 | debugging and visualization.
12 |
13 |
14 | ## MVDR Demo Files
15 |
16 | ### mvdr_hdl_sim ###
17 |
18 | This model uses the phased array toolbox to demonstrate high-level modeling
19 | of adaptive beamforming processing. Comparisons are made to various elaborated
20 | versions of the same design starting originally in floating point then
21 | to eventual fixed-point HDL. Blocks from the fixed-point toolbox were used
22 | to aid in this design for computing the adaptive weights using QR decomposition.
23 |
24 | Two examples for 4x4 and 16x16 MVDR matrix solves have been provided.
25 |
26 | ### zcu111_mvdr_demo ###
27 |
28 | This HDL model uses the same algorithm from the previous design but now integrates
29 | it for a ZCU111 RFSoC evaluation kit. Using 4 channels of ADC and DAC looped
30 | back on itself, a beam is electronically steered out the DAC and then processed
31 | by the ADC. Using four inputs, a 4x4 covariance matrix is composed and then
32 | QR decomposition is applied to yield optimal steering weights that augment the
33 | desired steering angle. A QPSK signal of interest is resolved in the presence of
34 | interference which is artificially introduced in the transmit signal.
35 |
36 | ##### Required software #####
37 |
38 | Xilinx Vivado 2020.2
39 |
40 | MATLAB R2023a with the following add-ons:
41 | - Simulink
42 | - HDL Coder
43 | - Fixed-Point Designer
44 | - DSP System Toolbox
45 | - DSP HDL Toolbox
46 | - Communications Toolbox
47 | - Phased Array System Toolbox
48 | - [HDL Coder Support Package for Xilinx RFSoC Devices](https://www.mathworks.com/hardware-support/rfsoc-hdl-coder.html )
49 |
50 | ##### Run the demo #####
51 |
52 | 1. Ensure the ZCU111 board has been configured with the SD card provided by the HDL Coder RFSoC Support Package.
53 | See [this page](https://www.mathworks.com/help/releases/R2021b/supportpkg/xilinxrfsocdevices/ug/guided-sd-card-setup.html) for more information.
54 |
55 | 2. On the XM500 balun card, connect the differential ADC cables for the ADC Tile 2 (Channel 0 and 1) and Tile 3 (Channel 0 and 1)
56 | to the DAC Tile 0 Channel 0 1 2 and 3. See [section below](#adcdac-loopback-wiring-details) for more details.
57 |
58 | 3. Power-on the board and program the prebuilt FPGA bitstream:
59 |
60 | `>> program_board('BitfilePath','prebuilt/zcu111_mvdr.bit')`
61 |
62 | 4. After the board reboots, run the setup script to configure the RF Data Converter:
63 |
64 | `>> setup_rfsoc`
65 |
66 | 5. Run "RFSoC_MVDR_Demo.mlapp" by right clicking on it and selecting "run" or running it from the MATLAB command prompt:
67 |
68 | `>> RFSoC_MVDR_Demo`
69 |
70 |
71 |
72 | You can use this UI app to adjust the angle of arrival for the signal of interest and the interference.
73 | To regain stable constellation, change the "Azimuth Angle" value to the signal of interest by adjusting the slider
74 | to the same angle. Measurements from the MVDR optimized weights are read back from the device to show the beamforming
75 | response and how nulls are placed to minimize interference.
76 |
77 | ##### Build the demo #####
78 |
79 | To rebuild the bitstream from scratch, follow these instructions.
80 |
81 | 1. Open "TxSteering_RxMVDR_4x4_HDL_IQ.slx"
82 |
83 | 2. Right-click on the "DUT" subsystem, then click HDL Code → HDL Workflow Advisor
84 |
85 | 3. In the HDL Workflow Advisor, right-click on step 4.3, then click "Run to selected task".
86 | For more details on the individual steps of HDLWFA, please see this [example](https://www.mathworks.com/help/releases/R2021b/supportpkg/xilinxrfsocdevices/ug/DACAndADCLoopbackDataCaptureExample.html).
87 |
88 | 4. Wait for the Vivado command window to show that bitstream generation has finished.
89 |
90 | 5. Run provided utility function to program the board:
91 |
92 | NOTE: You must use this to program the board instead of HDL WFA step 4.4.
93 |
94 | `>> program_board`
95 |
96 | 6. Proceed from step 4 in the Demo instructions.
97 |
98 |
99 | ##### ADC/DAC Loopback Wiring Details #####
100 |
101 | To loop back the 4 DAC and ADC channels with the XM500 board you will need to make the following connections:
102 |
103 |
104 |
105 | Because these connections are differential, you will need SMA DC Blocks.
106 |
107 | Connection details:
108 | - RFMC_ADC_04 connects to RFMC_DAC_00
109 | - RFMC_ADC_05 connects to RFMC_DAC_01
110 | - RFMC_ADC_06 connects to RFMC_DAC_02
111 | - RFMC_ADC_07 connects to RFMC_DAC_03
112 |
113 | The above names refer to labels on the XM500. Match the SMA connectors to the above physical labels of the XM500.
114 | Each label represents a specific tile/channel:
115 | - ADC Tile 2 Ch0 maps to RFMC_ADC_04
116 | - ADC Tile 2 Ch1 maps to RFMC_ADC_05
117 | - ADC Tile 3 Ch0 maps to RFMC_ADC_06
118 | - ADC Tile 3 Ch1 maps to RFMC_ADC_07
119 | - DAC Tile 0 Ch0 maps to RFMC_DAC_00
120 | - DAC Tile 0 Ch1 maps to RFMC_DAC_01
121 | - DAC Tile 0 Ch2 maps to RFMC_DAC_02
122 | - DAC Tile 0 Ch3 maps to RFMC_DAC_03
123 |
124 | Note that the PN differential connections pair up such that P connects to N.
125 |
126 |
127 | ## Documentation: Background Theory of Operation ##
128 | A PDF file "FPGA_Adaptive_Beamforming_with_HDL_Coder_and_Zynq_RFSoC.pdf" has been included.
129 |
130 | ### Introduction: Motivation and Challenges
131 | - Applications: Radar, Comms and Wireless (5G)
132 | - Hardware FPGA challenges
133 |
134 | ### Theory and Implementation
135 | - Linear algebra
136 | - QR Decomposition
137 | - Matrix Divide
138 |
139 | ### Zynq RFSoC and HDL Coder Implementation
140 | - MATLAB MVDR reference code
141 | - HDL Coder implementation
142 | - Hardware Prototyping – live demo
143 |
144 | The license used in this contribution is the XSLA license, which is the most common license for MathWorks staff contributions.
145 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/compareData.m:
--------------------------------------------------------------------------------
1 | function err_vec = compareData(reference,actual,figure_number,textstring)
2 |
3 | % Vector input only
4 | if ~isvector(reference) || ~isvector(actual)
5 | error('Input signals must be vector');
6 | else
7 | if isrow(reference)
8 | reference = transpose(reference);
9 | end
10 | if isrow(actual)
11 | actual = transpose(actual);
12 | end
13 | end
14 |
15 | % Make signals same length if necessary
16 | if length(reference) ~= length(actual)
17 | warning(['Length of reference (%d) is not the same as actual signal (%d).'...
18 | ' Truncating the longer input.'],length(reference),length(actual));
19 | len = 1:min(length(reference),length(actual));
20 | reference = reference(len);
21 | actual = actual(len);
22 | end
23 |
24 | % Turn complex into vector
25 | if xor(isreal(reference),isreal(actual))
26 | error('Input signals are not both real or both complex');
27 | elseif ~isreal(reference)
28 | ref_vec = double([real(reference) imag(reference)]);
29 | act_vec = double([real(actual) imag(actual)]);
30 | tag = {'(Real)','(Imag)'};
31 | cmplx = 1;
32 | else
33 | ref_vec = double(reference);
34 | act_vec = double(actual);
35 | tag = {''};
36 | cmplx = 0;
37 | end
38 |
39 | % Configure figure
40 | if iscell(figure_number)
41 | if size(figure_number,2) == 3
42 | figure(figure_number{3});
43 | else
44 | figure(1); % for backward compatability
45 | end
46 | else
47 | figure(figure_number);
48 | end
49 | c = get(groot,'defaultAxesColorOrder');
50 |
51 | % Compute error
52 | err_vec = ref_vec - act_vec;
53 | max_err = max(abs(err_vec));
54 | max_ref = max(abs(ref_vec));
55 | fprintf('\nMaximum error for %s out of %d values\n',textstring,length(actual));
56 |
57 | % 4 layouts:
58 | % fig = #, signal = real: subplot(111)
59 | % fig = #, signal = cmplx: subplot(211) & (212)
60 | % fig = {X,Y}, signal = real: subplot(X1Y)
61 | % fig = {X,Y}, signal = cmplx: subplot(X,1,Y*2-1) & (X,2,Y*2)
62 |
63 | for n = 1:size(ref_vec,2)
64 | fprintf('%s %d (absolute), %d (percentage)\n',tag{n},max_err(n),max_err(n)/max_ref(n)*100);
65 | if isnumeric(figure_number)
66 | row_num = size(ref_vec,2);
67 | col_num = 1;
68 | plot_num = n;
69 | else
70 | row_num = figure_number{1};
71 | col_num = size(ref_vec,2);
72 | plot_num = figure_number{2};
73 | if cmplx
74 | plot_num = (figure_number{2}-1)*2+n;
75 | end
76 | end
77 | subplot(row_num,col_num,plot_num);
78 | plot(ref_vec(:,n),'Color',c(3,:));
79 | hold on
80 | plot(act_vec(:,n),'Color',c(1,:));
81 | plot(err_vec(:,n),'Color',c(2,:));
82 | legend('Reference','Actual','Error')
83 | hold off
84 | title(sprintf('%s %s\n max error = %.3d',textstring,tag{n},max_err(n)));
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/deinterleave_complex.m:
--------------------------------------------------------------------------------
1 | function out = deinterleave_complex(in)
2 | %DEINTERLEAVE_COMPLEX Deinterleave real and imaginary components from input vector.
3 | % Output is a vector with half the length of the input.
4 |
5 | out = complex(in(1:2:end),in(2:2:end));
6 |
7 | end
8 |
9 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/generate_qpsk_signal.m:
--------------------------------------------------------------------------------
1 | function [txData,matchedFilterCoeffs,rrcFilterCoeffs] = generate_qpsk_signal( ...
2 | NFrames,FrameLength,PreambleLength,SamplesPerSymbol)
3 | % QPSK signal generation
4 | %
5 | % Copyright 2021 The MathWorks, Inc.
6 |
7 | % Use QPSK modulation
8 | M=4;
9 |
10 | % Calculate payload length
11 | NPayloadLength=FrameLength-PreambleLength;
12 |
13 | % use Barker code for preamble
14 | barkerCode = step(comm.BarkerCode('Length',PreambleLength,'SamplesPerFrame',PreambleLength));
15 |
16 | % map preamble to Gray code symbols.
17 | % -1 -> 1, +1 -> 0
18 | temp = (-barkerCode + 1) / 2;
19 | temp = [temp temp]';
20 | temp = temp(:);
21 | preamble = bit2int(temp,2);
22 |
23 | % copy preamble so it can be inserted at start of each frame
24 | preamble_frames=preamble*ones(1,NFrames);
25 |
26 | % QPSK payload data
27 | payload=randi([0 M-1],NPayloadLength,NFrames);
28 |
29 | % append preamble to payload data
30 | txdata=[preamble_frames;payload];
31 |
32 | % QPSK modulation data
33 | txconstdata=pskmod(txdata(:),M,pi/M);
34 |
35 | % upsample constellation data
36 | txconstdata_up=upsample(txconstdata,SamplesPerSymbol);
37 |
38 | % generate Root Raised Cosine (RRC) Tx/Rx Filer
39 | rrcFilterCoeffs = rcosdesign(0.25,6,SamplesPerSymbol);
40 |
41 | % apply RRC on tx data
42 | txData=filter(rrcFilterCoeffs,1,txconstdata_up);
43 |
44 | % extract preamble
45 | preamble_temp=filter(rrcFilterCoeffs,1,txconstdata_up(1:PreambleLength*SamplesPerSymbol));
46 |
47 | % convert to matched filter
48 | matchedFilterCoeffs=conj(flipud(preamble_temp));
49 |
50 | end
51 |
52 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/interleave_complex.m:
--------------------------------------------------------------------------------
1 | function out = interleave_complex(in)
2 | %INTERLEAVE_COMPLEX Interleave real and imaginary components.
3 | % Output is a vector with twice the length of the input.
4 |
5 | temp = reshape(in,1,[]);
6 | temp = vertcat(real(temp),imag(temp));
7 | out = reshape(temp,[],1);
8 | if isrow(in)
9 | out = out.';
10 | end
11 |
12 | end
13 |
14 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/maxabs.m:
--------------------------------------------------------------------------------
1 | function val = maxabs(in)
2 | %MAXABS Get the maximum absolute value of the input data
3 |
4 | val = max([max(abs(real(in)),[],'all') max(abs(imag(in)),[],'all')]);
5 |
6 | end
7 |
8 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/plot_beam_patterns.m:
--------------------------------------------------------------------------------
1 | function plot_beam_patterns(hAxes,mvdrResponse,phaseShiftResponse,signalAngle,interfererAngle)
2 | % Helper function for beam-pattern plotting
3 | %
4 | % Copyright 2021 The MathWorks, Inc.
5 |
6 | az = -90:90;
7 | sigAzIdx = find(az==signalAngle,1);
8 | intAzIdx = find(az==interfererAngle,1);
9 | sigLevel = mvdrResponse(sigAzIdx);
10 | intLevel = mvdrResponse(intAzIdx);
11 |
12 | mvdrValid = ~isinf(sigLevel) && ~isinf(intLevel);
13 |
14 | hold(hAxes,'off');
15 | plot(hAxes,az,mvdrResponse,'Color','#0072BD','LineStyle','-','LineWidth',2);
16 | hold(hAxes,'on');
17 | plot(hAxes,az,phaseShiftResponse,'Color','#0072BD','LineStyle','--');
18 |
19 | if mvdrValid
20 | yregion(hAxes,sigLevel,intLevel,'FaceColor','#faf5d4');
21 | end
22 |
23 | xline(hAxes,signalAngle,'g');
24 | xline(hAxes,interfererAngle,'r');
25 |
26 | if mvdrValid
27 | yline(hAxes,sigLevel,'--','Color',[0.5 0.5 0.5]);
28 | yline(hAxes,intLevel,'--','Color',[0.5 0.5 0.5]);
29 | end
30 |
31 | xlim(hAxes,[az(1) az(end)]);
32 | ylim(hAxes,[-50 10]);
33 | title(hAxes,'Beamforming Pattern');
34 | xlabel(hAxes,'Azimuth Angle (degrees)');
35 | ylabel(hAxes,'Normalized Power (dB)');
36 | legend(hAxes,{'MVDR','PhaseShift'},'Location','SouthWest');
37 |
38 | end
39 |
40 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/qpsk_receive.m:
--------------------------------------------------------------------------------
1 | function dataOut = qpsk_receive(dataIn, varargin)
2 | % QPSK symbol alignment and decoding
3 | %
4 | % Copyright 2021 The MathWorks, Inc.
5 |
6 | if nargin == 2
7 | assert(isstruct(varargin{1}),'Second argument must be a parameter struct');
8 | paramStruct = varargin{1};
9 | FrameLength = paramStruct.FrameLength;
10 | SamplesPerSymbol = paramStruct.SamplesPerSymbol;
11 | PreambleLength = paramStruct.PreambleLength;
12 | mfCoeffs = paramStruct.mfCoeffs;
13 | rrcCoeffs = paramStruct.rrcCoeffs;
14 | else
15 | assert(nargin == 6,'Invalid number of arguments');
16 | FrameLength = varargin{1};
17 | SamplesPerSymbol = varargin{2};
18 | PreambleLength = varargin{3};
19 | mfCoeffs = varargin{4};
20 | rrcCoeffs = varargin{5};
21 | end
22 |
23 | % Upsampled Frame/Preamble lengths
24 | FrameLengthUp = FrameLength*SamplesPerSymbol;
25 | PreambleLengthUp = PreambleLength*SamplesPerSymbol;
26 |
27 | % match filter against preamble
28 | correlatorOut = filter(mfCoeffs,1,dataIn);
29 |
30 | % compute magnitude squared
31 | correlatorMagSq = real(correlatorOut).^2+imag(correlatorOut).^2;
32 |
33 | % Input contains 3 frames of data.
34 | % Search through 1st+2nd frame to avoid OOB alignment in 3rd frame
35 | searchIdx = 1:(2*FrameLengthUp);
36 |
37 | % find max correlator location
38 | maxIdx = find(correlatorMagSq==max(correlatorMagSq(searchIdx)),1);
39 | if isempty(maxIdx)
40 | maxIdx = 1;
41 | else
42 | maxIdx = maxIdx(1);
43 | end
44 |
45 | % rotation angle to correct
46 | rotationAngle=angle(correlatorOut(maxIdx));
47 |
48 | % index of aligned frame
49 | idxOut = (1:FrameLengthUp) + maxIdx - PreambleLengthUp/2 - 1;
50 |
51 | % get aligned rx frame and correct rotation
52 | rxDataAligned = dataIn(idxOut);
53 |
54 | % apply rotation correction
55 | rxRotated = rxDataAligned*conj(exp(1j*rotationAngle));
56 |
57 | % Apply RRC filter
58 | rxFiltered = filter(rrcCoeffs,1,rxRotated);
59 |
60 | % Downsample after RRC filter (and discard filter transient)
61 | dataOut = rxFiltered((SamplesPerSymbol*8):SamplesPerSymbol:end);
62 |
63 | end
64 |
65 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/sim_with_progress.m:
--------------------------------------------------------------------------------
1 | function varargout = sim_with_progress(model)
2 | % Opens and runs a Simulink model from MATLAB. During simulation dots, ".",
3 | % are displayed in the MATLAB command window indicating simulation progress.
4 | % Each dot represents 10% of the simulation.
5 |
6 | open_system(model);
7 | [~,name,ext] = fileparts(which(model));
8 | disp(['Running ' name ext]);
9 |
10 | stopTime = evalin('base',get_param(model,'StopTime'));
11 |
12 | % Stop and delete timer if it's still running.
13 | t = timerfind('name','simProgress');
14 | if ~isempty(t)
15 | stop(t);
16 | delete(t);
17 | end
18 |
19 | l_showProgress(0,true);
20 |
21 | % Create and start timer.
22 | t = timer('name','simProgress');
23 | t.Period = 0.2;
24 | t.ExecutionMode = 'fixedRate';
25 | t.TimerFcn = @(myTimerObj,thisEvent)l_showProgress(get_param(model,'SimulationTime')/stopTime);
26 | start(t);
27 |
28 | % Run Simulink model.
29 | try
30 | if nargout > 0
31 | simout = sim(model);
32 | varargout{1} = simout;
33 | else
34 | sim(model);
35 | % assign logged signals to base workspace
36 | vars = whos;
37 | for ii=1:numel(vars)
38 | var = vars(ii);
39 | if ~any(strcmp(var.name,{'t','stopTime','model','name','ext'}))
40 | assignin('base',var.name,eval(var.name));
41 | end
42 | end
43 | end
44 | l_showProgress(1);
45 | catch me
46 | % Stop and delete timer.
47 | stop(t); delete(t);
48 | throw(me);
49 | end
50 |
51 | stop(t); delete(t);
52 |
53 | fprintf(newline);
54 |
55 | end
56 |
57 | function l_assignVarsInBase()
58 |
59 | end
60 |
61 | function l_showProgress(progress, initialize)
62 | if nargin < 2
63 | initialize = false;
64 | end
65 |
66 | length = 30;
67 | returnStr = char(8*ones(1,length+11,'uint8'));
68 |
69 | if initialize
70 | prefix = char([]);
71 | else
72 | % Clear previous line
73 | prefix=returnStr;
74 | end
75 | progmark = round(length*progress);
76 | pct = progress*100;
77 | pct_int = floor(pct);
78 | pct_frac = round(100*(pct-pct_int));
79 | if pct_frac>=100
80 | pct_frac=0;
81 | end
82 | str = [prefix '[' repmat('■',1,progmark) repmat('-',1,length-progmark) '] ' sprintf('%3d',pct_int) '.' sprintf('%02d',pct_frac) '%%' newline];
83 | fprintf(str);
84 | end
85 |
--------------------------------------------------------------------------------
/mvdr_beamformer/common/unpack_complex.m:
--------------------------------------------------------------------------------
1 | function y = unpack_complex(u)
2 | % UNPACK_COMPLEX Unpack uint32 to int16 complex
3 | %
4 | % Copyright 2021 The MathWorks, Inc.
5 |
6 |
7 | u_16 = typecast(u,'int16');
8 |
9 | y = complex(u_16(1:2:end),u_16(2:2:end));
10 |
11 | end
12 |
13 |
--------------------------------------------------------------------------------
/mvdr_beamformer/mvdr_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/mvdr_beamformer/mvdr_app.png
--------------------------------------------------------------------------------
/mvdr_beamformer/mvdr_hdl_sim/mvdr_4x4/model_init.m:
--------------------------------------------------------------------------------
1 | % model_init Setup for MVDR HDL models and testbench
2 |
3 | %% Add common folder to path
4 | thisDir = fileparts(mfilename('fullpath'));
5 | addpath(fullfile(thisDir,'..','..','common'));
6 |
7 | %% Sampling rate
8 | fs = 245.76e6;
9 | Ts = 1/fs;
10 |
11 | %% Environment
12 | propSpeed = physconst('LightSpeed'); % Propagation speed
13 | fc = 860.16e6; % Operating frequency
14 | lambda = propSpeed/fc;
15 |
16 | %% Beamformer parameters
17 |
18 | % Number of array elements
19 | numArrayElements = 4;
20 |
21 | % Uniform linar array
22 | sensorArray = phased.ULA('NumElements',numArrayElements,'ElementSpacing',0.5*lambda);
23 |
24 | % Steering vector computation for array
25 | steeringVector = phased.SteeringVector('SensorArray',sensorArray);
26 |
27 | % Moving average window size
28 | windowSize = 4096;
29 |
30 | % Diagonal loading value
31 | diagLoading = 5e-3;
32 |
33 | %% Generate signal of interest and interferer
34 |
35 | rng('default');
36 |
37 | testSrc1 = struct();
38 | testSrc1.NFrames=15;
39 | testSrc1.FrameLength=256;
40 | testSrc1.PreambleLength=13;
41 | testSrc1.SamplesPerSymbol=4;
42 |
43 | [testSrc1.Data,testSrc1.mfCoeffs,testSrc1.rrcCoeffs] = ...
44 | generate_qpsk_signal(testSrc1.NFrames,testSrc1.FrameLength,...
45 | testSrc1.PreambleLength,testSrc1.SamplesPerSymbol);
46 |
47 | testSrc2 = struct();
48 | testSrc2.NFrames=7;
49 | testSrc2.FrameLength=128;
50 | testSrc2.PreambleLength=13;
51 | testSrc2.SamplesPerSymbol=16;
52 | testSrc2.Data = ...
53 | generate_qpsk_signal(testSrc2.NFrames,testSrc2.FrameLength,...
54 | testSrc2.PreambleLength,testSrc2.SamplesPerSymbol);
55 |
56 | %% Fixed point datatypes
57 |
58 | % RFSoC ADC is 12 bits
59 | adc_dt = fixdt(1,12,11);
60 |
61 | % RF Data converter interface pads to 16 bits
62 | input_dt = fixdt(1,16,15);
63 |
64 | % Covariance Matrix
65 | covmat_dt = fixdt(1,18,16);
66 |
67 | % Moving average
68 | movavg_bitgrowth = nextpow2(windowSize);
69 | movavg_accum_dt = fixdt(1,covmat_dt.WordLength+movavg_bitgrowth,covmat_dt.FractionLength);
70 | movavg_bitshift = nextpow2(windowSize);
71 | movavg_out_dt = fixdt(1,movavg_accum_dt.WordLength-movavg_bitshift,movavg_accum_dt.FractionLength);
72 |
73 | % Use helper function to select types for matrix solver
74 | max_abs_A = sqrt(2); % Upper bound on max(abs(A(:))
75 | max_abs_B = sqrt(2); % Upper bound on max(abs(B(:))
76 | matrix_solve_precision = 18; % Number of bits of precision
77 | T = fixed.complexQRMatrixSolveFixedpointTypes(numArrayElements,numArrayElements,...
78 | max_abs_A,max_abs_B,matrix_solve_precision);
79 |
80 | % Matrix solve input
81 | matrixdivin_dt = fixed.extractNumericType(T.A);
82 |
83 | % Matrix solve back-substitition
84 | matrixdivbacksub_dt = fixed.extractNumericType(T.X);
85 |
86 | % Matrix solve output
87 | matrixdivout_dt = fixdt(1,24,matrix_solve_precision);
88 |
89 | % Steering vector
90 | sv_dt = fixdt(1,18,16);
91 |
92 | % Inner product bit growth
93 | ip_bitgrowth = (matrixdivout_dt.WordLength-matrixdivout_dt.FractionLength) + ...
94 | (sv_dt.WordLength - sv_dt.FractionLength) + 2;
95 |
96 | % Reciprocal input
97 | reciprocalin_wl = 26;
98 | reciprocalin_dt = fixdt(1,reciprocalin_wl,reciprocalin_wl-ip_bitgrowth);
99 |
100 | % Reciprocal output
101 | reciprocalout_dt = fixdt(1,reciprocalin_dt.WordLength,reciprocalin_dt.WordLength-4);
102 |
103 | % Weight vector
104 | w_dt = fixdt(1,26,22);
105 |
106 | % Output
107 | output_dt = fixdt(1,32,26);
108 |
109 | %% CORDIC matrix solve parameters
110 |
111 | % N size(data,1))
9 | data = data.';
10 | end
11 |
12 | % FFT each channel
13 | f = fft(double(data),length(data),1);
14 |
15 | % Get the peak for each channel
16 | [~,idx] = max(abs(f),[],1);
17 | peak = f(idx,:);
18 | peak = peak(1,:);
19 |
20 | % Normalize everything to channel 1
21 | coeffs = transpose(peak(1)./peak);
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/mvdr_beamformer/zcu111_mvdr_demo/model_init.m:
--------------------------------------------------------------------------------
1 | %model_init Setup for TxSteering_RxMVDR_4x4_HDL_IQ.slx
2 | %
3 | % Copyright 2021-2023 The MathWorks, Inc.
4 |
5 | %% Add common folder to path
6 | thisDir = fileparts(mfilename('fullpath'));
7 | addpath(fullfile(thisDir,'..','common'));
8 |
9 | %% RF Data Converter parameters
10 |
11 | % RF ADC/DAC sampling rate
12 | ConverterSampleRate = 1966.08e6;
13 |
14 | % DDC/DUC factor
15 | DecimInterpFactor = 8;
16 |
17 | % Effective data sampling rate
18 | DataSampleRate = ConverterSampleRate/DecimInterpFactor;
19 | Ts = 1/DataSampleRate;
20 |
21 | % Samples per clock cycle
22 | VectorSamplingFactor = 1;
23 |
24 | % FPGA clock rate
25 | FPGAClkRate = DataSampleRate/VectorSamplingFactor;
26 |
27 | % Number of ADC/DAC channels
28 | NumChan = 4;
29 |
30 | % Sample data width
31 | SampleDataWidth = 16*2; % 16-bit I/Q samples
32 |
33 | % Channel data width
34 | ChannelDataWidth = SampleDataWidth*VectorSamplingFactor;
35 |
36 | %% Create test source data
37 |
38 | rng('default');
39 |
40 | testSrc1 = struct();
41 | testSrc1.NFrames=15;
42 | testSrc1.FrameLength=256;
43 | testSrc1.PreambleLength=13;
44 | testSrc1.SamplesPerSymbol=4;
45 |
46 | [testSrc1.Data,testSrc1.mfCoeffs,testSrc1.rrcCoeffs] = ...
47 | generate_qpsk_signal(testSrc1.NFrames,testSrc1.FrameLength,...
48 | testSrc1.PreambleLength,testSrc1.SamplesPerSymbol);
49 |
50 | testSrc2 = struct();
51 | testSrc2.NFrames=7;
52 | testSrc2.FrameLength=128;
53 | testSrc2.PreambleLength=13;
54 | testSrc2.SamplesPerSymbol=16;
55 | testSrc2.Data = ...
56 | generate_qpsk_signal(testSrc2.NFrames,testSrc2.FrameLength,...
57 | testSrc2.PreambleLength,testSrc2.SamplesPerSymbol);
58 |
59 | %% DMA capture parameters
60 |
61 | % For QPSK demod we capture 3 frames of data so that it contains at least
62 | % one full contigious frame
63 |
64 | % S2MM DMA frame size
65 | s2mmFrameSize = testSrc1.FrameLength*testSrc1.SamplesPerSymbol*3;
66 |
67 | % Length of FIFO to handle backpressure from DMA
68 | dmaFIFOLength = 2^nextpow2(testSrc1.FrameLength*testSrc1.SamplesPerSymbol*2);
69 |
70 | %% Environment
71 | propSpeed = physconst('LightSpeed'); % Propagation speed
72 | fc = ConverterSampleRate*7/16; % Operating frequency
73 | lambda = propSpeed/fc;
74 |
75 | %% Beamformer parameters
76 |
77 | % Number of array elements
78 | numArrayElements = 4;
79 |
80 | % Uniform linar array
81 | sensorArray = phased.ULA('NumElements',numArrayElements,'ElementSpacing',0.5*lambda);
82 |
83 | % Steering vector computation for array
84 | steeringVector = phased.SteeringVector('SensorArray',sensorArray);
85 |
86 | % Moving average window size
87 | windowSize = 4096;
88 |
89 | % Diagonal loading value
90 | diagLoading = 5e-3;
91 |
92 | % Use internal directivity object for pattern calculation
93 | elemPosition = sensorArray.getElementPosition();
94 | angstep = phased.internal.getPatternIntegrationStepSize(elemPosition,lambda);
95 | beamPattern = phased.internal.Directivity('Sensor',sensorArray,...
96 | 'PropagationSpeed',propSpeed,'WeightsInputPort',true,...
97 | 'AzimuthAngleStepSize',angstep,'ElevationAngleStepSize',angstep);
98 |
99 | %% Calibration Tx NCO parameters
100 |
101 | NCO_bits = 14;
102 | NCO_default_freq = 10e6;
103 | NCO_default_inc = fi(floor(NCO_default_freq*2^NCO_bits/DataSampleRate), 1,NCO_bits,0);
104 |
105 | %% Fixed point datatypes
106 |
107 | % RFSoC ADC is 12 bits
108 | adc_dt = fixdt(1,12,11);
109 |
110 | % RF Data converter interface pads to 16 bits
111 | input_dt = fixdt(1,16,15);
112 |
113 | % Covariance Matrix
114 | covmat_dt = fixdt(1,18,16);
115 |
116 | % Moving average
117 | movavg_bitgrowth = nextpow2(windowSize);
118 | movavg_accum_dt = fixdt(1,covmat_dt.WordLength+movavg_bitgrowth,covmat_dt.FractionLength);
119 | movavg_bitshift = nextpow2(windowSize);
120 | movavg_out_dt = fixdt(1,movavg_accum_dt.WordLength-movavg_bitshift,movavg_accum_dt.FractionLength);
121 |
122 | % Use helper function to select types for matrix solver
123 | max_abs_A = sqrt(2); % Upper bound on max(abs(A(:))
124 | max_abs_B = sqrt(2); % Upper bound on max(abs(B(:))
125 | matrix_solve_precision = 18; % Number of bits of precision
126 | T = fixed.complexQRMatrixSolveFixedpointTypes(numArrayElements,numArrayElements,...
127 | max_abs_A,max_abs_B,matrix_solve_precision);
128 |
129 | % Matrix solve input
130 | matrixdivin_dt = fixed.extractNumericType(T.A);
131 |
132 | % Matrix solve back-substitition
133 | matrixdivbacksub_dt = fixed.extractNumericType(T.X);
134 |
135 | % Matrix solve output
136 | matrixdivout_dt = fixdt(1,24,matrix_solve_precision);
137 |
138 | % Steering vector
139 | sv_dt = fixdt(1,18,16);
140 |
141 | % Inner product bit growth
142 | ip_bitgrowth = (matrixdivout_dt.WordLength-matrixdivout_dt.FractionLength) + ...
143 | (sv_dt.WordLength - sv_dt.FractionLength) + 2;
144 |
145 | % Reciprocal input
146 | reciprocalin_wl = 26;
147 | reciprocalin_dt = fixdt(1,reciprocalin_wl,reciprocalin_wl-ip_bitgrowth);
148 |
149 | % Reciprocal output
150 | reciprocalout_dt = fixdt(1,reciprocalin_dt.WordLength,reciprocalin_dt.WordLength-4);
151 |
152 | % Weight vector
153 | w_dt = fixdt(1,26,22);
154 |
155 | % Rx/Tx channel coefficients
156 | coeff_dt = fixdt(1,18,16);
157 |
158 | % Output
159 | output_dt = fixdt(1,32,26);
160 |
161 | % Tx output gain
162 | tx_gain_dt = fixdt(1,16,14);
163 |
164 | %% Rx magnitude measurement parameters
165 |
166 | rx_mag_window_size = 256;
167 | rx_mag_sum_growth = nextpow2(rx_mag_window_size);
168 |
169 | rx_mag_dt = fixdt(0,input_dt.WordLength,input_dt.FractionLength);
170 | rx_mag_inv_dt = fixdt(1,27,16);
171 | rx_gain_dt = fixdt(1,rx_mag_inv_dt.WordLength-1,rx_mag_inv_dt.FractionLength);
172 |
173 | rx_mag_delay = input_dt.WordLength + 2 + ceil(log2(NumChan)) + 1 + rx_mag_window_size;
174 | rx_mag_inverse_delay = nextpow2(rx_mag_dt.WordLength) + 1 + rx_mag_dt.WordLength + 2 + 7;
175 |
176 | %% CORDIC matrix solve parameters
177 |
178 | % N 245.76
30 | warning('Selected FPGA rate %3.3f MHz exceeds the timing that was used during synthesis (%3.3f MHz) for this design! Timing failures may occur which can lead to unexpected behavior. Re-synthesizing your design may be required to achieve faster rates.',...
31 | FPGAClockRate,245.76);
32 | end
33 |
34 | %% Establish TCP/IP connection
35 | setup(rfobj)
36 |
37 | %% Tile / Channels
38 |
39 | %% Set External Clocking Options
40 | %% Set required clocks for MTS
41 | rfobj.LMKClkSelect = 'SYSREF';
42 | rfobj.configureLMXPLL(ReferenceClock);
43 |
44 |
45 |
46 | %% Setup ADC/DAC Tile sampling and PLL rates
47 | for TileId = 0:(rfobj.TotalADCTiles-1)
48 | rfobj.configureADCTile(TileId,PLLSrc,ReferenceClock,ADCSamplingRate);
49 | for ChId = 0:(rfobj.ADCChannelsPerTile-1)
50 | rfobj.configureADCChannel(TileId,ChId,DecimationFactor);
51 | end
52 | end
53 |
54 | for TileId = 0:(rfobj.TotalDACTiles-1)
55 | rfobj.configureDACTile(TileId,PLLSrc,ReferenceClock,DACSamplingRate);
56 | for ChId = 0:(rfobj.DACChannelsPerTile-1)
57 | rfobj.configureDACChannel(TileId,ChId,InterpolationFactor);
58 | end
59 | end
60 |
61 | %% ADC IQ mode settings
62 |
63 | ADC_DDC_LO = -DDC_DUC_LO;
64 | ADC_MixingScale = '1';
65 | ADC_MixerPhase = 0.0;
66 |
67 | if rfobj.MTSConfigure
68 | EventMode = 'Sysref';
69 | else
70 | EventMode = 'Tile';
71 | end
72 |
73 | for TileId = 0:(rfobj.TotalADCTiles-1)
74 | for ChId = 0:(rfobj.ADCChannelsPerTile-1)
75 | if FineMixMode %Fine Mixing Mode
76 | configureADCMixer(rfobj, TileId, ChId, 'Fine', ADC_DDC_LO, EventMode, ADC_MixerPhase, ADC_MixingScale);
77 | else %Coarse Mixing Mode
78 | configureADCMixer(rfobj, TileId, ChId, 'Coarse', '-Fs/4', EventMode, ADC_MixerPhase, ADC_MixingScale);
79 | end
80 | end
81 | end
82 |
83 | %% DAC IQ mode settings
84 |
85 | DAC_DDC_LO = DDC_DUC_LO;
86 | DAC_MixingScale = '1';
87 | DAC_MixerPhase = 0.0;
88 |
89 | if rfobj.MTSConfigure
90 | EventMode = 'Sysref';
91 | else
92 | EventMode = 'Immediate';
93 | end
94 |
95 | for TileId = 0:(rfobj.TotalDACTiles-1)
96 | for ChId = 0:(rfobj.DACChannelsPerTile-1)
97 | if FineMixMode %Fine Mixing Mode
98 | configureDACMixer(rfobj, TileId, ChId, 'Fine', DAC_DDC_LO, EventMode, DAC_MixerPhase, DAC_MixingScale);
99 | else %Coarse Mixing Mode
100 | configureDACMixer(rfobj, TileId, ChId, 'Coarse', 'Fs/4', EventMode, DAC_MixerPhase, ADC_MixingScale);
101 | end
102 | end
103 |
104 | end
105 |
106 |
107 |
108 |
109 | %% Apply settings to RFTool
110 | applyConfiguration(rfobj)
111 |
112 |
113 |
114 | %% Perform MTS capture
115 | rfobj.enableMTS()
116 |
117 | %% Disconnect and clear system object
118 | %release(rfobj)
119 |
120 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/2dFFT.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/2dFFT.jpg
--------------------------------------------------------------------------------
/rangedoppler/hw_only/README.md:
--------------------------------------------------------------------------------
1 | # Range-Doppler FPGA Examples
2 |
3 | ## Overview
4 |
5 | These models demonstrate how two-dimensional transpose using external DDR4
6 | memory can be used for range-doppler processing for radar applications such as
7 | range-doppler. Some examples will require SoC Blockset for memory simulation.
8 |
9 | ## Demo Files
10 |
11 | ### partA_TransposeMatrix ###
12 |
13 | State-machine logic simulation for handling matrix transpose. Examples in these folders use SoC Blockset for simulating PL-DDR4 access and HDL Coder for deploying a matrix transpose example on the ZCU111. Incremental improvements to DDR4 corner turn memory access is shown by taking advantage of "wr-ready" and using a BRAM memory burst approach instead of bursting in one sample into memory at a time.
14 |
15 |
16 |
17 |
18 | In the BRAM burst approach, several rows of the matrix is stored in block ram first. After accumulation of several rows, a column of data is bursted in. Management of these blockram memory "banks" is done with state machine logic. The above plot comes from analyzing the throughputs of writing memory using BRAM burst transposed then reading it back out.
19 |
20 | ### partB_MatchedFilterFFTTranspose ###
21 |
22 | Building on top of the previous example, this demo shows how a two-dimensional range-doppler processing example can be accomplished on an FPGA using HDL Coder. Similar to the previous example, this can also run on the ZCU111. BRAM Burst writes into memory are done to increase memory write throughputs.
23 |
24 |
25 |
26 | This demo will start with MATLAB code first of running a matched FIR filter then transposing the data and performing an FFT over several radar cubes. An HDL implementation of this is then done to compute the FIR and FFT along with the transpose.
27 |
28 | The license used in this contribution is the XSLA license, which is the most common license for MathWorks staff contributions.
29 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/RangeDoppler.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/RangeDoppler.jpg
--------------------------------------------------------------------------------
/rangedoppler/hw_only/bandwidth_cornerturn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/bandwidth_cornerturn.jpg
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/MatrixWrRd_transpose_SoCB_TopLevel.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/MatrixWrRd_transpose_SoCB_TopLevel.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/hdlcoder_external_memory_read_ctrl_custom.m:
--------------------------------------------------------------------------------
1 | function [valid_out, count_out, ddr_read_done, rd_addr, rd_len, rd_avalid,ToggleTLAST,debug_state] = ...
2 | hdlcoder_external_memory_read_ctrl_custom(burst_len, start, rd_aready, rd_dvalid)
3 | %% hdlcoder_external_memory_read_ctrl_custom
4 | %
5 | % % State-machine behavior for reading DDR4
6 |
7 | % Copyright 2017 The MathWorks, Inc.
8 |
9 | % create persistent variables (registers)
10 | persistent rstate burst_stop burst_count
11 | if isempty(rstate)
12 | rstate = fi(0, 0, 4, 0);
13 | burst_stop = uint32(0);
14 | burst_count = uint32(0);
15 | debug_state = cast(0,'like',rstate);
16 | end
17 |
18 | % state Memory Encoding
19 | IDLE = fi(0, 0, 4, 0);
20 | READ_BURST_START = fi(1, 0, 4, 0);
21 | READ_BURST_REQUEST = fi(2, 0, 4, 0);
22 | DATA_COUNT = fi(3, 0, 4, 0);
23 |
24 | ToggleTLAST = false;
25 |
26 | % state machine logic
27 | switch (rstate)
28 | case IDLE
29 | % output to AXI4 Master
30 | rd_addr = uint32(0);
31 | rd_len = uint32(0);
32 | rd_avalid = false;
33 |
34 | % output to DUT logic
35 | valid_out = false;
36 | count_out = uint32(0);
37 | ddr_read_done = true;
38 |
39 | % State vars
40 | burst_stop = uint32(burst_len);
41 | burst_count = uint32(0);
42 |
43 | if start
44 | rstate(:) = READ_BURST_START;
45 | else
46 | rstate(:) = IDLE;
47 | end
48 |
49 | case READ_BURST_START
50 | % Daren Notes: the two pieces of information below is a read request
51 | %
52 | % rd_addr: Starting address for the read transaction that is sampled at
53 | % the first cycle of the transaction.
54 | % rd_len: The number of data values that you want to read,
55 | % sampled at the first cycle of the transaction.
56 | %
57 | % We only move to READ_BURST_REQUST if rd_aready is HIGH to confirm
58 | % DDR is ready for a readback request
59 |
60 | % output to AXI4 Master
61 | rd_addr = uint32(0);
62 | rd_len = uint32(burst_stop);
63 | rd_avalid = false;
64 |
65 | % output to DUT logic
66 | valid_out = false;
67 | count_out = uint32(0);
68 | ddr_read_done = false;
69 |
70 | if rd_aready
71 | rstate(:) = READ_BURST_REQUEST;
72 | else
73 | rstate(:) = READ_BURST_START;
74 | end
75 |
76 | case READ_BURST_REQUEST
77 | % Daren Notes: read request
78 | %
79 | % rd_avalid: Control signal that specifies whether the read request is valid.
80 | %
81 | %
82 |
83 | % output to AXI4 Master
84 | rd_addr = uint32(0);
85 | rd_len = uint32(burst_stop);
86 | rd_avalid = true;
87 |
88 | % output to DUT logic
89 | valid_out = false;
90 | count_out = uint32(0);
91 | ddr_read_done = false;
92 |
93 | rstate(:) = DATA_COUNT;
94 |
95 | case DATA_COUNT
96 | % output to AXI4 Master
97 | rd_addr = uint32(0);
98 | rd_len = uint32(burst_stop);
99 | rd_avalid = false;
100 |
101 | % output to DUT logic
102 | valid_out = rd_dvalid;
103 | count_out = uint32(burst_count);
104 | ddr_read_done = false;
105 |
106 | % State vars
107 | if ( rd_dvalid )
108 | burst_count = uint32(burst_count + 1);
109 | end
110 |
111 | if ( burst_count == burst_stop )
112 | rstate(:) = IDLE;
113 | if rd_dvalid
114 | ToggleTLAST = true;
115 | end
116 | else
117 | rstate(:) = DATA_COUNT;
118 | end
119 |
120 | otherwise
121 | % output to AXI4 Master
122 | rd_addr = uint32(0);
123 | rd_len = uint32(0);
124 | rd_avalid = false;
125 |
126 | % output to DUT logic
127 | valid_out = false;
128 | count_out = uint32(0);
129 | ddr_read_done = false;
130 |
131 | rstate(:) = IDLE;
132 | end
133 |
134 | debug_state(:) = rstate;
135 |
136 | end
137 |
138 | % LocalWords: AXI
139 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/hdlcoder_external_memory_write_ctrl_custom.m:
--------------------------------------------------------------------------------
1 | function [ram_addr, ddr_write_done, wr_addr, wr_len, wr_valid, wasted_cycle_cnt, matrix_wr_done] = ...
2 | hdlcoder_external_memory_write_ctrl_custom(addr_in,burst_len, start, wr_ready, wr_complete)
3 | %% hdlcoder_external_memory_write_ctrl_custom
4 | %
5 | % % State-machine behavior for writing to DDR4
6 |
7 | % Copyright 2017 The MathWorks, Inc.
8 |
9 | % create persistent variables (registers)
10 | persistent wstate burst_stop burst_count wasted_cycle_count
11 | persistent addr_value addr_offset_add
12 | if(isempty(wstate))
13 | wstate = fi(0, 0, 4, 0);
14 | burst_stop = uint32(0);
15 | burst_count = uint32(0);
16 | wasted_cycle_count = uint32(0);
17 | addr_value = uint32(0);
18 | addr_offset_add = uint32(0);
19 | end
20 | wasted_cycle_cnt = cast(0,'like',wasted_cycle_count);
21 |
22 | % state machine encoding
23 | IDLE = fi(0, 0, 4, 0);
24 | WRITE_BURST_START = fi(1, 0, 4, 0);
25 | DATA_COUNT = fi(2, 0, 4, 0);
26 | ACK_WAIT = fi(3, 0, 4, 0);
27 |
28 | % state machine logic
29 | switch (wstate)
30 | case IDLE
31 | % output to AXI4 Master
32 | wr_addr = uint32(0); % 4-byte address
33 | wr_len = uint32(0);
34 | wr_valid = false;
35 |
36 | % output to DUT logic
37 | ram_addr = uint32(0);
38 | ddr_write_done = true;
39 | matrix_wr_done = false;
40 |
41 | % state variables
42 | burst_stop = uint32(burst_len);
43 | burst_count = uint32(0);
44 |
45 | if start
46 | wstate(:) = WRITE_BURST_START;
47 | else
48 | wstate(:) = IDLE;
49 | end
50 |
51 |
52 | case WRITE_BURST_START
53 | % output to AXI4 Master
54 | wr_addr = uint32(addr_value*4);
55 | wr_len = uint32(burst_stop);
56 | wr_valid = false;
57 |
58 | % output to DUT logic
59 | ram_addr = uint32(burst_count);
60 | ddr_write_done = false;
61 | matrix_wr_done = false;
62 |
63 | if wr_ready
64 | wstate(:) = DATA_COUNT;
65 | else
66 | wstate(:) = WRITE_BURST_START;
67 | wasted_cycle_count = uint32(wasted_cycle_count+1);
68 | end
69 |
70 |
71 | case DATA_COUNT
72 | % output to AXI4 Master
73 | wr_addr = uint32(addr_value*4);
74 | wr_len = uint32(burst_stop);
75 | wr_valid = true;
76 |
77 | % state variables
78 | burst_count = uint32(burst_count + 1);
79 |
80 | % output to DUT logic
81 | ram_addr = uint32(burst_count);
82 | ddr_write_done = false;
83 | matrix_wr_done = false;
84 |
85 | if ( burst_count == burst_stop )
86 | wstate(:) = ACK_WAIT;
87 | else
88 | if ( wr_ready )
89 | wstate(:) = DATA_COUNT;
90 | else
91 | wstate(:) = WRITE_BURST_START;
92 | end
93 | end
94 |
95 |
96 | case ACK_WAIT
97 | % output to AXI4 Master
98 | wr_addr = uint32(0);
99 | wr_len = uint32(0);
100 | wr_valid = false;
101 |
102 | % output to DUT logic
103 | ram_addr = uint32(0);
104 | ddr_write_done = false;
105 | matrix_wr_done = false;
106 |
107 | if wr_complete
108 | wstate(:) = IDLE;
109 |
110 | % will need to throw in additional checks here for ping-poing
111 | % buffer
112 | % ie: first buffer addr offset = 0
113 | % 2nd buffer addr offset = 24*16 + 1
114 | %
115 | if addr_value < (24*16 - 16) % N1 * N2
116 | addr_value(:) = addr_value + 16 + addr_offset_add ;
117 | else
118 | addr_value(:) = 0; % perform reset on address
119 | matrix_wr_done = true;
120 | end
121 | else
122 | wstate(:) = ACK_WAIT;
123 | end
124 |
125 | otherwise
126 | % output to AXI4 Master
127 | wr_addr = uint32(0);
128 | wr_len = uint32(0);
129 | wr_valid = false;
130 | matrix_wr_done = false;
131 |
132 | % output to DUT logic
133 | ram_addr = uint32(0);
134 | ddr_write_done = false;
135 |
136 | wstate(:) = IDLE;
137 |
138 | end
139 |
140 | % For AXI4 MM Diagonstics
141 | wasted_cycle_cnt(:) = wasted_cycle_count;
142 |
143 | end
144 |
145 | % LocalWords: AXI
146 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/matrix_init.m:
--------------------------------------------------------------------------------
1 | %% Model coefficients
2 | N1 = 20; % row
3 | N2 = 20; % columns
4 |
5 | MatrixInputArr = [1:N1*N2];
6 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
7 |
8 |
9 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/matrix_rdwr_transpose_fpga.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/matrix_rdwr_transpose_fpga.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part0_SoCB/validate_matrix_out.m:
--------------------------------------------------------------------------------
1 | %% Run this after reading matrix value out
2 | rdMat = MatrixRd.signals(1).values(MatrixRd.signals(2).values);
3 | rdOut = reshape(rdMat(1:N1*N2),[N2,N1]);
4 |
5 | fprintf('Matrix written to DDR4: \n');
6 | disp(MatrixInput);
7 | disp('------')
8 |
9 | fprintf('Matrix read out of DDR4: \n');
10 | disp(rdOut);
11 | disp('------')
12 |
13 | if rdOut ~= transpose(MatrixInput)
14 | error('Bad transpose!');
15 | end
16 |
17 | if length(rdMat(:)) > N2*N1
18 | rdMatFormat = reshape(rdMat,[N2 N1 length(rdMat)/(N2*N1)]);
19 | three_dim_diff = diff(rdMatFormat,3);
20 | if any(three_dim_diff(:) ~= 0)
21 | error('Matrix values inconsistent across time!');
22 | end
23 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part1_hdl_wrready/matrix_init.m:
--------------------------------------------------------------------------------
1 | %% Model coefficients
2 | N1 = 7; % row
3 | N2 = 6; % columns
4 |
5 | MatrixInputArr = [1:N1*N2];
6 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
7 |
8 |
9 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part1_hdl_wrready/validate_matrix_out.m:
--------------------------------------------------------------------------------
1 | %% Run this after reading matrix value out
2 | MatrixRd = out.ScopeData;
3 | Valid = MatrixRd.signals(2).values(:);
4 | rdMat = MatrixRd.signals(1).values(:);
5 |
6 | rdMat = rdMat(Valid);
7 |
8 | iter = length(rdMat)/(N1*N2);
9 |
10 | for ii = 1:iter
11 | range = (1:N1*N2) + (ii-1)*(N1*N2);
12 | rdOut = reshape(rdMat(range),[N2,N1]);
13 |
14 | fprintf('Matrix read out of DDR4: \n');
15 | disp(rdOut);
16 | disp('------')
17 |
18 |
19 | fprintf('Matrix written to DDR4: \n');
20 | disp(MatrixInput);
21 | disp('------')
22 |
23 | compare = transpose(MatrixInput);
24 | if any(rdOut(:) ~= compare(:))
25 | error('Bad transpose!');
26 | end
27 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part1_hdl_wrready/wrQueue_RFSoC_MatrixTranspose.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partA_TransposeMatrix/part1_hdl_wrready/wrQueue_RFSoC_MatrixTranspose.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/AXIBusObjects.m:
--------------------------------------------------------------------------------
1 | function AXIBusObjects()
2 | % AXIBUSOBJECTS initializes a set of bus objects in the MATLAB base workspace
3 |
4 | % Bus object: BusAXIWriteCtrlM2S
5 | clear elems;
6 | elems(1) = Simulink.BusElement;
7 | elems(1).Name = 'wr_addr';
8 | elems(1).Dimensions = 1;
9 | elems(1).DimensionsMode = 'Fixed';
10 | elems(1).DataType = 'uint32';
11 | elems(1).SampleTime = -1;
12 | elems(1).Complexity = 'real';
13 | elems(1).Min = [];
14 | elems(1).Max = [];
15 | elems(1).DocUnits = '';
16 | elems(1).Description = '';
17 |
18 | elems(2) = Simulink.BusElement;
19 | elems(2).Name = 'wr_len';
20 | elems(2).Dimensions = 1;
21 | elems(2).DimensionsMode = 'Fixed';
22 | elems(2).DataType = 'uint32';
23 | elems(2).SampleTime = -1;
24 | elems(2).Complexity = 'real';
25 | elems(2).Min = [];
26 | elems(2).Max = [];
27 | elems(2).DocUnits = '';
28 | elems(2).Description = '';
29 |
30 | elems(3) = Simulink.BusElement;
31 | elems(3).Name = 'wr_valid';
32 | elems(3).Dimensions = 1;
33 | elems(3).DimensionsMode = 'Fixed';
34 | elems(3).DataType = 'boolean';
35 | elems(3).SampleTime = -1;
36 | elems(3).Complexity = 'real';
37 | elems(3).Min = [];
38 | elems(3).Max = [];
39 | elems(3).DocUnits = '';
40 | elems(3).Description = '';
41 |
42 | BusAXIWriteCtrlM2S = Simulink.Bus;
43 | BusAXIWriteCtrlM2S.HeaderFile = '';
44 | BusAXIWriteCtrlM2S.Description = '';
45 | BusAXIWriteCtrlM2S.DataScope = 'Auto';
46 | BusAXIWriteCtrlM2S.Alignment = -1;
47 | BusAXIWriteCtrlM2S.Elements = elems;
48 | clear elems;
49 | assignin('base','BusAXIWriteCtrlM2S', BusAXIWriteCtrlM2S);
50 |
51 | % Bus object: BusAXIWriteCtrlS2M
52 | clear elems;
53 | elems(1) = Simulink.BusElement;
54 | elems(1).Name = 'wr_ready';
55 | elems(1).Dimensions = 1;
56 | elems(1).DimensionsMode = 'Fixed';
57 | elems(1).DataType = 'boolean';
58 | elems(1).SampleTime = -1;
59 | elems(1).Complexity = 'real';
60 | elems(1).Min = [];
61 | elems(1).Max = [];
62 | elems(1).DocUnits = '';
63 | elems(1).Description = '';
64 |
65 | elems(2) = Simulink.BusElement;
66 | elems(2).Name = 'wr_complete';
67 | elems(2).Dimensions = 1;
68 | elems(2).DimensionsMode = 'Fixed';
69 | elems(2).DataType = 'boolean';
70 | elems(2).SampleTime = -1;
71 | elems(2).Complexity = 'real';
72 | elems(2).Min = [];
73 | elems(2).Max = [];
74 | elems(2).DocUnits = '';
75 | elems(2).Description = '';
76 |
77 | BusAXIWriteCtrlS2M = Simulink.Bus;
78 | BusAXIWriteCtrlS2M.HeaderFile = '';
79 | BusAXIWriteCtrlS2M.Description = '';
80 | BusAXIWriteCtrlS2M.DataScope = 'Auto';
81 | BusAXIWriteCtrlS2M.Alignment = -1;
82 | BusAXIWriteCtrlS2M.Elements = elems;
83 | clear elems;
84 | assignin('base','BusAXIWriteCtrlS2M', BusAXIWriteCtrlS2M);
85 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/bramBurst_TransposeMatrix.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/bramBurst_TransposeMatrix.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/matrix_init.m:
--------------------------------------------------------------------------------
1 | %% Model coefficients
2 | N1 = 65; % row
3 | N2 = 60; % columns
4 | Ts = 1;
5 | MatrixInputArr = [1:N1*N2];
6 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
7 |
8 |
9 | pNumCols = N1;
10 | pNumRows = N2;
11 | run AXIBusObjects;
12 | pAXIDataWidthBytes = 8; % number of bytes (64 bits) for AXI Data-Width
13 | pMaxBankLines = 6;
14 | pMaxNumBanks = 3;
15 |
16 | %Bram address width
17 | pBramAddrWidth = ceil(log2(pMaxBankLines*pMaxNumBanks*pNumCols));
18 |
19 | %% BRAM savings
20 |
21 | bramSaving = ( 1 - pMaxBankLines*pMaxNumBanks*pNumCols / (pNumCols*pNumRows))*100;
22 | fprintf('By using DDR4 memory we reduced BRAM usage of the transpose by %2.1f percent. Address width is %d-bits \n',bramSaving,pBramAddrWidth);
23 |
24 | %% State machine labeling
25 | % LINEBUFFER = fi(1,0,4,0);
26 | % LINESTART = fi(3,0,4,0);
27 | Simulink.defineIntEnumType('stateBRAMfsm', {'IDLE','LINEBUFFER', 'LINESTART'}, [0 1 3]);
28 |
29 |
30 | % BURSTSTART = fi(1,0,4,0);
31 | % BURSTNEXT = fi(3,0,4,0);
32 | % WAITBURSTCOMPLETE = fi(4,0,4,0);
33 | % WAITBURSTREADY = fi(5,0,4,0);
34 | % WAITONBANKRDY =fi(2,0,4,0);
35 | Simulink.defineIntEnumType('stateAXI4Mfsm', {'IDLE',...
36 | 'BURSTSTART',...
37 | 'WAITONBANKRDY',...
38 | 'BURSTNEXT',...
39 | 'WAITBURSTCOMPLETE',...
40 | 'WAITBURSTREADY'}, [0 1 2 3 4 5]);
41 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/model_init_sim.m:
--------------------------------------------------------------------------------
1 | % model_init for DL model
2 | if ~exist('numCols','var')
3 | numCols = 320;
4 | numRows = 200;
5 | end
6 | pixelcontrolbus;
7 | frm2pix = visionhdl.FrameToPixels;
8 | frm2pix.VideoFormat = '1080p';
9 | [~, ~, totalPixels] = getparamfromfrm2pix(frm2pix);
10 | Ts = 1/(totalPixels*60);
11 | clear frm2pix;
12 |
13 | run AXIBusObjects;
14 | pAXIDataWidthBytes = 4; % number of bytes (128 bits) for AXI Data-Width
15 | inputImageDDROffset = uint32(hex2dec('00000000')); % addr = 0x8000-0000
16 |
17 | pMaxBankLines = 8;
18 | pMaxNumBanks = 3;
19 |
20 | pNumCols = 30;
21 | pNumRows = 30;
22 | % Note: based on a 1080p frame and the pNumRows/Cols are sub-ROI
23 | % dimensions, define blanking vars to simulate this
24 | % hBlank = frm2pix.TotalPixelsPerLine - pNumCols;
25 | % vBlank = frm2pix.TotalVideoLines - pNumRows;
26 |
27 | % Note: for demonstration purposes, re-define blanking vars
28 | hBlank = 20;
29 | vBlank = 8;
30 |
31 | %% create input image in case you want defined data to push
32 | clear imageIn;
33 |
34 | % uncomment these lines to just see integers in the LA
35 | imageIn(:,:,1) = repmat(zeros(pNumRows,1,'uint8'),1,pNumCols);
36 | imageIn(:,:,2) = repmat(zeros(pNumRows,1,'uint8'),1,pNumCols);
37 | imageIn(:,:,3) = repmat(uint8([1:pNumRows]'),1,pNumCols);
38 |
39 | % uncomment these lines to just see a yellow gradient in the video viewer
40 | % imageIn(:,:,1) = repmat(linspace(0,255,pNumRows)',1,pNumCols);
41 | % imageIn(:,:,2) = repmat(linspace(0,255,pNumRows)',1,pNumCols);
42 | % imageIn(:,:,3) = repmat([1:pNumRows]',1,pNumCols);
43 |
44 | % testImage = uint8([repmat(1:pNumCols,pNumRows,1,3)]);
45 |
46 | %% BRAM savings
47 | bramAddrWidth = ceil(log2(pMaxBankLines*pMaxNumBanks*pNumCols));
48 | bramSaving = ( 1 - pMaxBankLines*pMaxNumBanks*pNumCols / (pNumCols*pNumRows))*100;
49 | fprintf('By using DDR4 memory we reduced BRAM usage of the transpose by %2.1f percent. Address width is %d-bits \n',bramSaving,bramAddrWidth);
50 |
51 | %% State machine labeling
52 | % LINEBUFFER = fi(1,0,4,0);
53 | % LINESTART = fi(3,0,4,0);
54 | Simulink.defineIntEnumType('stateBRAMfsm', {'IDLE','LINEBUFFER', 'LINESTART'}, [0 1 3]);
55 |
56 |
57 | % BURSTSTART = fi(1,0,4,0);
58 | % BURSTNEXT = fi(3,0,4,0);
59 | % WAITBURSTCOMPLETE = fi(4,0,4,0);
60 | % WAITBURSTREADY = fi(5,0,4,0);
61 | % WAITONBANKRDY =fi(2,0,4,0);
62 | Simulink.defineIntEnumType('stateAXI4Mfsm', {'IDLE',...
63 | 'BURSTSTART',...
64 | 'WAITONBANKRDY',...
65 | 'BURSTNEXT',...
66 | 'WAITBURSTCOMPLETE',...
67 | 'WAITBURSTREADY'}, [0 1 2 3 4 5]);
68 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/run_fpgaIO.m:
--------------------------------------------------------------------------------
1 | %--------------------------------------------------------------------------
2 | % Software Interface Script
3 | %
4 | % Generated with MATLAB 9.10 (R2021a) at 19:37:54 on 13/06/2021.
5 | % This script was created for the IP Core generated from design 'ddrxpose_21a_generic_fft_rdy2'.
6 | %
7 | % Use this script to access DUT ports in the design that were mapped to compatible IP core interfaces.
8 | % You can write to input ports in the design and read from output ports directly from MATLAB.
9 | % To write to input ports, use the "writePort" command and specify the port name and input data. The input data will be cast to the DUT port's data type before writing.
10 | % To read from output ports, use the "readPort" command and specify the port name. The output data will be returned with the same data type as the DUT port.
11 | % Use the "release" command to release MATLAB's control of the hardware resources.
12 | %--------------------------------------------------------------------------
13 |
14 | %% Create fpga object
15 | hFPGA = fpga("Xilinx");
16 |
17 | %% Setup fpga object
18 | % This function configures the "fpga" object with the same interfaces as the generated IP core
19 | N1 = 65;
20 | N2 = 60;
21 | frameSize = 65*60;
22 | transpose_fpgaIO_setup(hFPGA,frameSize);
23 |
24 | %% Write/read DUT ports
25 | % Uncomment the following lines to write/read DUT ports in the generated IP Core.
26 | % Update the example data in the write commands with meaningful data to write to the DUT.
27 | %% AXI4
28 | % writePort(hFPGA, "inputImageDDROffset", zeros([1 1]));
29 | % data_ddrDoneCounter = readPort(hFPGA, "ddrDoneCounter");
30 | % data_fifo_full_event = readPort(hFPGA, "fifo_full_event");
31 |
32 | %% AXI4-Stream DMA
33 | % writePort(hFPGA, "DataIn", zeros([1 1024]));
34 | % data_tdata_o = readPort(hFPGA, "tdata_o");
35 | for ii = 1:50
36 | MatrixInputArr = [1:N1*N2]*ii;
37 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
38 |
39 |
40 | writePort(hFPGA, "DataIn", MatrixInput);
41 |
42 | % pause(1);
43 | data_ddrDoneCounter = readPort(hFPGA, "ddrDoneCounter");
44 | fprintf('DDR4 write done count = %d \n',data_ddrDoneCounter);
45 | data_tdata_o = readPort(hFPGA, "tdata_o");
46 | c = reshape(data_tdata_o,N2,N1); %<--- note we swap N2 and N1 because this is transposed..
47 | diff_data = double(MatrixInput.') - double(c(:,:));
48 | % plot(diff(:))
49 | if any(diff_data~=0)
50 | warning('bad transpose!')
51 | end
52 | end
53 | %% Release hardware resources
54 | release(hFPGA);
55 |
56 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/transpose_fpgaIO_setup.m:
--------------------------------------------------------------------------------
1 | function transpose_fpgaIO_setup(hFPGA,frameSize)
2 | %--------------------------------------------------------------------------
3 | % Software Interface Script Setup
4 | %
5 | % Generated with MATLAB 9.10 (R2021a) at 19:37:54 on 13/06/2021.
6 | % This function was created for the IP Core generated from design 'ddrxpose_21a_generic_fft_rdy2'.
7 | %
8 | % Run this function on an "fpga" object to configure it with the same interfaces as the generated IP core.
9 | %--------------------------------------------------------------------------
10 |
11 | %% AXI4
12 | addAXI4SlaveInterface(hFPGA, ...
13 | "InterfaceID", "AXI4", ...
14 | "BaseAddress", 0xA0000000, ...
15 | "AddressRange", 0x10000);
16 |
17 | hPort_inputImageDDROffset = hdlcoder.DUTPort("inputImageDDROffset", ...
18 | "Direction", "IN", ...
19 | "DataType", numerictype(0,32,0), ...
20 | "Dimension", [1 1], ...
21 | "IOInterface", "AXI4", ...
22 | "IOInterfaceMapping", "0x100");
23 |
24 | hPort_ddrDoneCounter = hdlcoder.DUTPort("ddrDoneCounter", ...
25 | "Direction", "OUT", ...
26 | "DataType", numerictype(1,32,0), ...
27 | "Dimension", [1 1], ...
28 | "IOInterface", "AXI4", ...
29 | "IOInterfaceMapping", "0x104");
30 |
31 | hPort_fifo_full_event = hdlcoder.DUTPort("fifo_full_event", ...
32 | "Direction", "OUT", ...
33 | "DataType", numerictype(0,32,0), ...
34 | "Dimension", [1 1], ...
35 | "IOInterface", "AXI4", ...
36 | "IOInterfaceMapping", "0x108");
37 |
38 | mapPort(hFPGA, [hPort_inputImageDDROffset, hPort_ddrDoneCounter, hPort_fifo_full_event]);
39 |
40 | %% AXI4-Stream DMA
41 | addAXI4StreamInterface(hFPGA, ...
42 | "InterfaceID", "AXI4-Stream DMA", ...
43 | "WriteEnable", true, ...
44 | "WriteDataWidth", 64, ...
45 | "WriteFrameLength", frameSize, ...
46 | "ReadEnable", true, ...
47 | "ReadDataWidth", 64, ...
48 | "ReadFrameLength", frameSize,...
49 | 'WriteTimeout',0,...
50 | 'ReadTimeout',0);
51 |
52 | hPort_DataIn = hdlcoder.DUTPort("DataIn", ...
53 | "Direction", "IN", ...
54 | "DataType", numerictype(1,64,0), ...
55 | "Dimension", [1 1], ...
56 | "IOInterface", "AXI4-Stream DMA");
57 |
58 | hPort_tdata_o = hdlcoder.DUTPort("tdata_o", ...
59 | "Direction", "OUT", ...
60 | "DataType", numerictype(1,64,0), ...
61 | "Dimension", [1 1], ...
62 | "IOInterface", "AXI4-Stream DMA");
63 |
64 | mapPort(hFPGA, [hPort_DataIn, hPort_tdata_o]);
65 |
66 | end
67 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partA_TransposeMatrix/part2_hdl_bram_burst/validateTranspose.m:
--------------------------------------------------------------------------------
1 | dataOut = out.logsout.find('axi4mrd_dataOut').Values.Data;
2 | dataValid = out.logsout.find('axi4mrd_validOut').Values.Data;
3 | % validLength = sum(dataValid == 1) - mod(length(dataValid),N1*N2);
4 | % matrixExtract = dataOut(dataValid(1:validLength));
5 | % numMatrices = length(matrixExtract)/(N1*N2);
6 | matrixExtract = dataOut(dataValid);
7 | trimLen = mod(length(matrixExtract),N1*N2);
8 | matrixExtract = matrixExtract(1:(length(matrixExtract) - trimLen));
9 | c = reshape(matrixExtract,N2,N1,[]); %<--- note we swap N2 and N1 because this is transposed..
10 |
11 | numMatrices = length(matrixExtract)/(N1*N2);
12 | for ii = 1:numMatrices
13 | diff = double(MatrixInput.') - double(c(:,:,ii));
14 | if ~any(diff(:)~=0)
15 | fprintf('transpose good = %d \n',ii);
16 | else
17 | warning('bad transpose!')
18 | end
19 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/MatchedFilterFFT_Transpose.prj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part0_rangedoppler_ml/run_Range_Doppler.m:
--------------------------------------------------------------------------------
1 | %run_Range_Doppler Testbench for Range Doppler processing
2 |
3 | %% Parameters
4 |
5 | % Common parameters
6 | range_doppler_system_param_init;
7 |
8 | % Number of coherent processing intervals (CPI) to run
9 | NumCPI = 10;
10 |
11 | %% Setup processing blocks
12 | % Create radar data cube
13 | radarDataCube = createRadarDataCubeMod(...
14 | txSignalFullPeriod,antennaElement,Fs,Fc, ...
15 | targetPos, targetVel, targetRCS, ...
16 | RngMax, RxActiveTime, RngGate, ...
17 | CPILength, NumCPI, CPILength*pulsePeriod);
18 |
19 | % Range Doppler processing
20 | RangeDopplerResponse = phased.RangeDopplerResponse( ...
21 | 'OperatingFrequency', Fc, ...
22 | 'RangeMethod','Matched filter', ...
23 | 'PropagationSpeed', propSpeed, ...
24 | 'SampleRate', Fs, ...
25 | 'DopplerFFTLengthSource','Property', ...
26 | 'DopplerFFTLength', VelDimLen, ...
27 | 'DopplerWindow', 'Hamming', ...
28 | 'DopplerOutput', 'Speed');
29 |
30 |
31 | %% Simulate radar targets and run Range Doppler processing
32 |
33 | hd = dfilt.dffir(matchingCoeff.');
34 | for CPIIdx = 1:NumCPI
35 | cubeSegment = radarDataCube(:,:,CPIIdx);
36 | cubeSegmentMatched = zeros(RxActiveSamples,CPILength);
37 |
38 | % Matched Filter
39 | for ii = 1:CPILength
40 | cubeSegmentMatched(:,ii) = filter(hd,cubeSegment(:,ii));
41 | end
42 |
43 | % Transpose
44 | cubeTranspose = transpose(cubeSegmentMatched);
45 |
46 | % FFT
47 | cubeTransposeFFT = fft(cubeTranspose.*hamming(64),64,1);
48 | cubeOutput = fftshift(transpose(cubeTransposeFFT),2);
49 | cubeOutput = 20*log10(abs(cubeOutput));
50 |
51 | % Display Targets
52 | displayTargets(VelMax, RngMin, RngMax, cubeOutput);
53 |
54 | pause(0.5);
55 | end
56 |
57 |
58 | function displayTargets(VelMax, RngMin, RngMax, rangeDopplerInput)
59 | imagesc([-VelMax VelMax],[RngMin RngMax],rangeDopplerInput);
60 | title('Range-Doppler');
61 | xlabel('Velocity');
62 | ylabel('Range');
63 | end
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/BramBurst_FFT2D_validate_matrix_out.m:
--------------------------------------------------------------------------------
1 | %% Run this after reading matrix value out
2 |
3 | % pNumCols = N1;
4 | % pNumRows = N2;
5 | Valid = out.rdValid(:);
6 | rdMat = out.rdMat(:);
7 | rdMat = rdMat(Valid);
8 | iter = length(rdMat)/(pNumCols*pNumRows);
9 |
10 |
11 |
12 | %% Compare against original radar data cube
13 |
14 | outputReshape = reshape(rdMat,pNumCols,pNumRows);
15 | expectedOutput = radarDataCube.';
16 | plot(imag(outputReshape(:) - expectedOutput(:)))
17 |
18 |
19 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/bramBurst_TransposeMatrix.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/bramBurst_TransposeMatrix.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/matrix_init.m:
--------------------------------------------------------------------------------
1 | %% Model coefficients
2 | N1 = 256; % row
3 | N2 = 64; % columns
4 | Ts = 1;
5 | MatrixInputArr = [1:N1*N2];
6 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
7 |
8 |
9 | pNumCols = N1;
10 | pNumRows = N2;
11 | run AXIBusObjects;
12 | pAXIDataWidthBytes = 8; % number of bytes (64 bits) for AXI Data-Width
13 | pMaxBankLines = 6;
14 | pMaxNumBanks = 3;
15 |
16 | %Bram address width
17 | pBramAddrWidth = ceil(log2(pMaxBankLines*pMaxNumBanks*pNumCols));
18 |
19 | %% BRAM savings
20 |
21 | bramSaving = ( 1 - pMaxBankLines*pMaxNumBanks*pNumCols / (pNumCols*pNumRows))*100;
22 | fprintf('By using DDR4 memory we reduced BRAM usage of the transpose by %2.1f percent. Address width is %d-bits \n',bramSaving,pBramAddrWidth);
23 |
24 | %% State machine labeling
25 | % LINEBUFFER = fi(1,0,4,0);
26 | % LINESTART = fi(3,0,4,0);
27 | Simulink.defineIntEnumType('stateBRAMfsm', {'IDLE','LINEBUFFER', 'LINESTART'}, [0 1 3]);
28 |
29 |
30 | % BURSTSTART = fi(1,0,4,0);
31 | % BURSTNEXT = fi(3,0,4,0);
32 | % WAITBURSTCOMPLETE = fi(4,0,4,0);
33 | % WAITBURSTREADY = fi(5,0,4,0);
34 | % WAITONBANKRDY =fi(2,0,4,0);
35 | Simulink.defineIntEnumType('stateAXI4Mfsm', {'IDLE',...
36 | 'BURSTSTART',...
37 | 'WAITONBANKRDY',...
38 | 'BURSTNEXT',...
39 | 'WAITBURSTCOMPLETE',...
40 | 'WAITBURSTREADY'}, [0 1 2 3 4 5]);
41 |
42 |
43 | %% Radar cube
44 |
45 | % init parameters
46 | range_doppler_system_param_init;
47 |
48 | % Number of coherent processing intervals (CPI) to run
49 | NumCPI = 1;
50 |
51 |
52 | % Create radar data cube
53 | radarDataCube = createRadarDataCubeMod(...
54 | txSignalFullPeriod,antennaElement,Fs,Fc, ...
55 | targetPos, targetVel, targetRCS, ...
56 | RngMax, RxActiveTime, RngGate, ...
57 | CPILength, NumCPI, CPILength*pulsePeriod);
58 |
59 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/socmemlib.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/socmemlib.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part1_transpose_radar_cube/validateTranspose.m:
--------------------------------------------------------------------------------
1 |
2 | warning('only run this if you are comparing integer non-complex values for the 256x64 transpose');
3 |
4 | dataOut = out.logsout.find('axi4mrd_dataOut').Values.Data;
5 | dataValid = out.logsout.find('axi4mrd_validOut').Values.Data;
6 | % validLength = sum(dataValid == 1) - mod(length(dataValid),N1*N2);
7 | % matrixExtract = dataOut(dataValid(1:validLength));
8 | % numMatrices = length(matrixExtract)/(N1*N2);
9 | matrixExtract = dataOut(dataValid);
10 | trimLen = mod(length(matrixExtract),N1*N2);
11 | matrixExtract = matrixExtract(1:(length(matrixExtract) - trimLen));
12 | c = reshape(matrixExtract,N2,N1,[]); %<--- note we swap N2 and N1 because this is transposed..
13 |
14 | numMatrices = length(matrixExtract)/(N1*N2);
15 | for ii = 1:numMatrices
16 | diff = double(MatrixInput.') - double(c(:,:,ii));
17 | if ~any(diff(:)~=0)
18 | fprintf('transpose good = %d \n',ii);
19 | else
20 | warning('bad transpose!')
21 | end
22 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/BramBurst_FFT2D_validate_matrix_out.m:
--------------------------------------------------------------------------------
1 | %% Run this after reading matrix value out
2 |
3 | % pNumCols = N1;
4 | % pNumRows = N2;
5 | Valid = out.rdValid(:);
6 | rdMat = out.rdMat(:);
7 | rdMat = rdMat(Valid);
8 | iter = length(rdMat)/(N1*N2);
9 |
10 |
11 |
12 | %% Compare against original radar data cube
13 |
14 | % outputReshape = reshape(rdMat,pNumCols,pNumRows,iter);
15 | % expectedOutput = radarDataCube.';
16 | %
17 | % for ii = 1:iter
18 | % matrix_subset = outputReshape(:,:,ii);
19 | % plot(imag(matrix_subset(:) - expectedOutput(:)))
20 | % end
21 |
22 |
23 | %% Compare raw int64 inputs
24 |
25 | int64_matrix_dataIn=getLogged(out.logsout,'int64_raw_transpose_dataIn');
26 | int64_matrix_validIn=getLogged(out.logsout,'int64_raw_transpose_validIn');
27 | transpose_input = int64_matrix_dataIn(int64_matrix_validIn);
28 |
29 | transpose_input_arr = reshape(transpose_input(1:(N1*N2*iter)),N1,N2,iter);
30 | % expected_output = transpose_input_arr.';
31 |
32 | int64_matrix_dataOut=getLogged(out.logsout,'int64_raw_transpose_dataOut');
33 | int64_matrix_validOut=getLogged(out.logsout,'int64_raw_transpose_validOut');
34 | transpose_output = int64_matrix_dataOut(int64_matrix_validOut);
35 | transpose_output_arr = reshape(transpose_output(1:(N1*N2*iter)),N2,N1,iter);
36 |
37 | % plot(expected_output(:) - transpose_output_arr(:))
38 | for ii = 1:iter
39 | expected_output_arr = transpose_input_arr(:,:,ii).';
40 | output_arr = transpose_output_arr(:,:,ii);
41 | plot(expected_output_arr(:) - output_arr(:));
42 | end
43 |
44 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/RangeDopplerLoop_fpgaIO.m:
--------------------------------------------------------------------------------
1 | %--------------------------------------------------------------------------
2 | % Constant Design parameters
3 | %
4 | %--------------------------------------------------------------------------
5 | N1 = 256; % row
6 | N2 = 64; % columns
7 |
8 |
9 | %--------------------------------------------------------------------------
10 | % Adjustable Design parameters
11 | %
12 | %--------------------------------------------------------------------------
13 | % init parameters
14 | range_doppler_system_param_init;
15 |
16 | % Number of coherent processing intervals (CPI) to run
17 | NumCPI = 10;
18 |
19 | % Create radar data cube
20 | radarDataCube = createRadarDataCubeMod(...
21 | txSignalFullPeriod,antennaElement,Fs,Fc, ...
22 | targetPos, targetVel, targetRCS, ...
23 | RngMax, RxActiveTime, RngGate, ...
24 | CPILength, NumCPI, CPILength*pulsePeriod);
25 |
26 | enableFullMatrixWrite = true;
27 | debugInputFrame = false;
28 |
29 | %% Create fpga object
30 | hFPGA = fpga("Xilinx");
31 |
32 |
33 | %% Setup fpga object
34 | % This function configures the "fpga" object with the same interfaces as the generated IP core
35 | frameLenWrite = 256*64;
36 | frameLenRead = 256*64;
37 |
38 | setup_fpgaIO(hFPGA,frameLenWrite,frameLenRead);
39 | writePort(hFPGA, "resetIP", true);
40 |
41 | debugRegInput.bypassFFT = false;
42 | debugRegInput.bypassMatchedFilter = false;
43 | writePort(hFPGA, "debugRegInput", debugRegInput);
44 |
45 | %% Create Radar Cube frame
46 | radarDataCube_fi = packBits(radarDataCube);
47 | radarDataCube_fi_mat = reshape(radarDataCube_fi,256,64,NumCPI);
48 | radarDataCube_fi_mat = fi(radarDataCube_fi_mat,0,64,0);
49 |
50 | %% Setup Rx DMA
51 | % setup rx dma by invoking a read. If this is not done then the DMA will
52 | % NOT be setup to get data correctly and the first frame will get
53 | % corrupted!
54 | data_any = readPort(hFPGA, "axis_s2mm_tdata");
55 |
56 | %% Write frame
57 | for ii = 1:NumCPI
58 |
59 | % Extract a radar cube slice
60 | waveformExtract = radarDataCube_fi_mat(:,:,ii);
61 |
62 | % Write the radar cube slice to FPGA as DMA data
63 | writePort(hFPGA, "axis_mm2s_tdata", waveformExtract(:));
64 |
65 | % Print some debug messages
66 | data_debugRead = readPort(hFPGA, "debugRead");
67 | data_ddrDoneCounter = readPort(hFPGA, "ddrDoneCounter");
68 | measuredValidCount = data_debugRead.FIFO_ValidWriteCount;
69 | fprintf('Total samples written to PL DDR4 memory = %d \n',double(measuredValidCount));
70 | fprintf('DDR4 write count = %d \n', uint32(data_ddrDoneCounter));
71 |
72 | % Read back result of range-doppler data
73 | rangeDopplerRead = readPort(hFPGA, "axis_s2mm_tdata");
74 |
75 | % Format data to expected fixed-point complex data type format
76 | re = reinterpretcast(bitsliceget(rangeDopplerRead,32,1),numerictype(1,32,21)) ;
77 | imag = reinterpretcast(bitsliceget(rangeDopplerRead,64,33),numerictype(1,32,21)) ;
78 | rdMat = complex(re,imag);
79 |
80 | % Plot range-doppler
81 | img = reshape(double(rdMat),64,256);
82 | cubeOutput = fftshift(transpose(img),2);
83 | cubeOutput = 20*log10(abs(cubeOutput));
84 |
85 | imagesc([-VelMax VelMax],[RngMin RngMax],cubeOutput);
86 | title('Range-Doppler');
87 | xlabel('Velocity');
88 | ylabel('Range');
89 | colorbar;
90 | drawnow
91 | end
92 |
93 | %% Some debug port statements
94 | data_debugRead = readPort(hFPGA, "debugRead");
95 | fprintf('Number of samples FIFO outputted = %d \n',data_debugRead.FIFO_ValidWriteCount);
96 | fprintf('Number of DDR4 write bursts completed = %d \n',data_debugRead.AXI4M_WrValidCnt);
97 | fprintf('Number of times BRAM FSM paused input FIFO = %d \n',data_debugRead.BRAM_FSM_StoppingFIFO_Counter);
98 | fprintf('Number of lost samples = %d \n',data_debugRead.FIFO_LostSampleCount);
99 | fprintf('Number of times back-pressure applied on MM2S DMA = %d \n',data_debugRead.FIFO_BackPressureAppliedOnMM2S);
100 | fprintf('Number of times input FIFO was full = %d \n',data_debugRead.FIFO_FullEventCount);
101 |
102 |
103 |
104 | %% Release hardware resources
105 | release(hFPGA);
106 |
107 |
108 | %% Helper functions
109 |
110 | function output = packBits(waveformInput)
111 |
112 | waveformInput_fi = fi(waveformInput,1,20,18);
113 | % [real(waveformInput_fi) imag(waveformInput_fi)]
114 | output = bitconcat(real(waveformInput_fi(:)),imag(waveformInput_fi(:)));
115 |
116 | end
117 |
118 |
119 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/bramBurst_TransposeMatrix.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/bramBurst_TransposeMatrix.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/matched_filter_fft_hdl_init.m:
--------------------------------------------------------------------------------
1 | %% Model coefficients
2 | N1 = 256; % row
3 | N2 = 64; % columns
4 | Ts = 1;
5 | MatrixInputArr = [1:N1*N2];
6 | MatrixInput = reshape(MatrixInputArr,[N1,N2]);
7 |
8 | %% Burst Transpose parameters
9 |
10 | hdlbramBurst.pNumCols = N1; %NOTE: the convention here is BRAM burst writes along the column and
11 | hdlbramBurst.pNumRows = N2; % will burst along the rows, hence why N1 and N2 are swapped around...
12 | run AXIBusObjects;
13 | hdlbramBurst.pAXIDataWidthBytes = 8; % number of bytes (64 bits) for AXI Data-Width
14 | hdlbramBurst.pMaxBankLines = 6;
15 | hdlbramBurst.pMaxNumBanks = 3;
16 |
17 | %Bram address width
18 | hdlbramBurst.pBramAddrWidth = ceil(log2(hdlbramBurst.pMaxBankLines*hdlbramBurst.pMaxNumBanks*hdlbramBurst.pNumCols));
19 |
20 | %BRAM savings
21 | bramSaving = ( 1 - hdlbramBurst.pMaxBankLines*hdlbramBurst.pMaxNumBanks*hdlbramBurst.pNumCols / (hdlbramBurst.pNumCols*hdlbramBurst.pNumRows))*100;
22 | fprintf('By using DDR4 memory we reduced BRAM usage of the transpose by %2.1f percent. Address width is %d-bits \n',bramSaving,hdlbramBurst.pBramAddrWidth);
23 |
24 | % State machine labeling
25 | % LINEBUFFER = fi(1,0,4,0);
26 | % LINESTART = fi(3,0,4,0);
27 | Simulink.defineIntEnumType('stateBRAMfsm', {'IDLE','LINEBUFFER', 'LINESTART'}, [0 1 3]);
28 |
29 |
30 | % BURSTSTART = fi(1,0,4,0);
31 | % BURSTNEXT = fi(3,0,4,0);
32 | % WAITBURSTCOMPLETE = fi(4,0,4,0);
33 | % WAITBURSTREADY = fi(5,0,4,0);
34 | % WAITONBANKRDY =fi(2,0,4,0);
35 | Simulink.defineIntEnumType('stateAXI4Mfsm', {'IDLE',...
36 | 'BURSTSTART',...
37 | 'WAITONBANKRDY',...
38 | 'BURSTNEXT',...
39 | 'WAITBURSTCOMPLETE',...
40 | 'WAITBURSTREADY'}, [0 1 2 3 4 5]);
41 |
42 |
43 | %% Radar cube
44 |
45 | % init parameters
46 | range_doppler_system_param_init;
47 |
48 | % Number of coherent processing intervals (CPI) to run
49 | NumCPI = 1;
50 |
51 |
52 | % Create radar data cube
53 | radarDataCube = createRadarDataCubeMod(...
54 | txSignalFullPeriod,antennaElement,Fs,Fc, ...
55 | targetPos, targetVel, targetRCS, ...
56 | RngMax, RxActiveTime, RngGate, ...
57 | CPILength, NumCPI, CPILength*pulsePeriod);
58 |
59 |
60 | %% Windowing parameters for FFT/Matched Filter
61 |
62 | columnWindowFun = taylorwin(N2,10,-40);%.*(-1.^(1:nCols)');
63 |
64 | DTWindowFun = numerictype(1,16+4,13+4);
65 | DTsig_in = numerictype(1,20,18);
66 | DToutput = numerictype(1,32,22);
67 | DTTransposeInOut = numerictype(1,32,24);
68 | DT_fftColOutput = numerictype(1,32,21);
69 |
70 |
71 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/setup_fpgaIO.m:
--------------------------------------------------------------------------------
1 | function setup_fpgaIO(hFPGA,framesize_wr, framesize_rd)
2 | %--------------------------------------------------------------------------
3 | % Software Interface Script Setup
4 | %
5 | % Generated with MATLAB 9.10 (R2021a) at 02:53:28 on 20/06/2021.
6 | % This function was created for the IP Core generated from design 'bramBurst_TransposeMatrix'.
7 | %
8 | % Run this function on an "fpga" object to configure it with the same interfaces as the generated IP core.
9 | %--------------------------------------------------------------------------
10 |
11 | %% AXI4
12 | addAXI4SlaveInterface(hFPGA, ...
13 | "InterfaceID", "AXI4", ...
14 | "BaseAddress", 0xA0000000, ...
15 | "AddressRange", 0x10000);
16 |
17 | hPort_resetIPCore = hdlcoder.DUTPort("resetIP", ...
18 | "Direction", "IN", ...
19 | "DataType", numerictype(0,32,0), ...
20 | "Dimension", [1 1], ...
21 | "IOInterface", "AXI4", ...
22 | "IOInterfaceMapping", "0x0");
23 |
24 | hPort_inputImageDDROffset = hdlcoder.DUTPort("inputImageDDROffset", ...
25 | "Direction", "IN", ...
26 | "DataType", numerictype(0,32,0), ...
27 | "Dimension", [1 1], ...
28 | "IOInterface", "AXI4", ...
29 | "IOInterfaceMapping", "0x100");
30 |
31 | hPort_debugRegInput_bypassFFT = hdlcoder.DUTPort("bypassFFT", ...
32 | "Direction", "IN", ...
33 | "DataType", numerictype('boolean'), ...
34 | "Dimension", [1 1], ...
35 | "IOInterface", "AXI4", ...
36 | "IOInterfaceMapping", "0x104");
37 |
38 | hPort_debugRegInput_bypassMatchedFilter = hdlcoder.DUTPort("bypassMatchedFilter", ...
39 | "Direction", "IN", ...
40 | "DataType", numerictype('boolean'), ...
41 | "Dimension", [1 1], ...
42 | "IOInterface", "AXI4", ...
43 | "IOInterfaceMapping", "0x130");
44 |
45 | hPort_debugRegInput = hdlcoder.DUTPort("debugRegInput", ...
46 | "Direction", "IN", ...
47 | "DataType", "Bus", ...
48 | "Dimension", [1 1], ...
49 | "IOInterface", "AXI4", ...
50 | "SubPorts", [hPort_debugRegInput_bypassFFT, hPort_debugRegInput_bypassMatchedFilter]);
51 |
52 | hPort_ddrDoneCounter = hdlcoder.DUTPort("ddrDoneCounter", ...
53 | "Direction", "OUT", ...
54 | "DataType", numerictype(1,32,0), ...
55 | "Dimension", [1 1], ...
56 | "IOInterface", "AXI4", ...
57 | "IOInterfaceMapping", "0x108");
58 |
59 | hPort_fifo_full_event = hdlcoder.DUTPort("fifo_full_event", ...
60 | "Direction", "OUT", ...
61 | "DataType", numerictype(0,32,0), ...
62 | "Dimension", [1 1], ...
63 | "IOInterface", "AXI4", ...
64 | "IOInterfaceMapping", "0x10C");
65 |
66 | hPort_debugRead_AXI4M_WrValidCnt = hdlcoder.DUTPort("AXI4M_WrValidCnt", ...
67 | "Direction", "OUT", ...
68 | "DataType", numerictype(0,32,0), ...
69 | "Dimension", [1 1], ...
70 | "IOInterface", "AXI4", ...
71 | "IOInterfaceMapping", "0x110");
72 |
73 | hPort_debugRead_BRAM_FSM_BankRdCompleteCnt = hdlcoder.DUTPort("BRAM_FSM_BankRdCompleteCnt", ...
74 | "Direction", "OUT", ...
75 | "DataType", numerictype(0,32,0), ...
76 | "Dimension", [1 1], ...
77 | "IOInterface", "AXI4", ...
78 | "IOInterfaceMapping", "0x114");
79 |
80 | hPort_debugRead_BRAM_FSM_StoppingFIFO_Counter = hdlcoder.DUTPort("BRAM_FSM_StoppingFIFO_Counter", ...
81 | "Direction", "OUT", ...
82 | "DataType", numerictype(0,32,0), ...
83 | "Dimension", [1 1], ...
84 | "IOInterface", "AXI4", ...
85 | "IOInterfaceMapping", "0x118");
86 |
87 | hPort_debugRead_AXI4M_WriteCounter = hdlcoder.DUTPort("AXI4M_WriteCounter", ...
88 | "Direction", "OUT", ...
89 | "DataType", numerictype(0,32,0), ...
90 | "Dimension", [1 1], ...
91 | "IOInterface", "AXI4", ...
92 | "IOInterfaceMapping", "0x11C");
93 |
94 | hPort_debugRead_BRAM_FSM_Concat = hdlcoder.DUTPort("BRAM_FSM_Concat", ...
95 | "Direction", "OUT", ...
96 | "DataType", numerictype(0,8,0), ...
97 | "Dimension", [1 1], ...
98 | "IOInterface", "AXI4", ...
99 | "IOInterfaceMapping", "0x120");
100 |
101 | hPort_debugRead_FIFO_FullEventCount = hdlcoder.DUTPort("FIFO_FullEventCount", ...
102 | "Direction", "OUT", ...
103 | "DataType", numerictype(0,32,0), ...
104 | "Dimension", [1 1], ...
105 | "IOInterface", "AXI4", ...
106 | "IOInterfaceMapping", "0x124");
107 |
108 | hPort_debugRead_FIFO_LostSampleCount = hdlcoder.DUTPort("FIFO_LostSampleCount", ...
109 | "Direction", "OUT", ...
110 | "DataType", numerictype(0,32,0), ...
111 | "Dimension", [1 1], ...
112 | "IOInterface", "AXI4", ...
113 | "IOInterfaceMapping", "0x128");
114 |
115 | hPort_debugRead_FIFO_BackPressureAppliedOnMM2S = hdlcoder.DUTPort("FIFO_BackPressureAppliedOnMM2S", ...
116 | "Direction", "OUT", ...
117 | "DataType", numerictype(0,32,0), ...
118 | "Dimension", [1 1], ...
119 | "IOInterface", "AXI4", ...
120 | "IOInterfaceMapping", "0x12C");
121 |
122 | hPort_debugRead_FIFO_ValidWriteCount = hdlcoder.DUTPort("FIFO_ValidWriteCount", ...
123 | "Direction", "OUT", ...
124 | "DataType", numerictype(0,32,0), ...
125 | "Dimension", [1 1], ...
126 | "IOInterface", "AXI4", ...
127 | "IOInterfaceMapping", "0x134");
128 |
129 | hPort_debugRead = hdlcoder.DUTPort("debugRead", ...
130 | "Direction", "OUT", ...
131 | "DataType", "Bus", ...
132 | "Dimension", [1 1], ...
133 | "IOInterface", "AXI4", ...
134 | "SubPorts", [hPort_debugRead_AXI4M_WrValidCnt, hPort_debugRead_BRAM_FSM_BankRdCompleteCnt, hPort_debugRead_BRAM_FSM_StoppingFIFO_Counter, hPort_debugRead_AXI4M_WriteCounter, hPort_debugRead_BRAM_FSM_Concat, hPort_debugRead_FIFO_FullEventCount, hPort_debugRead_FIFO_LostSampleCount, hPort_debugRead_FIFO_BackPressureAppliedOnMM2S, hPort_debugRead_FIFO_ValidWriteCount]);
135 |
136 | mapPort(hFPGA, [hPort_resetIPCore hPort_inputImageDDROffset, hPort_debugRegInput, hPort_ddrDoneCounter, hPort_fifo_full_event, hPort_debugRead]);
137 |
138 | %% AXI4-Stream DMA
139 | addAXI4StreamInterface(hFPGA, ...
140 | "InterfaceID", "AXI4-Stream DMA", ...
141 | "WriteEnable", true, ...
142 | "WriteDataWidth", 64, ...
143 | "WriteFrameLength", framesize_wr, ...
144 | "ReadEnable", true, ...
145 | "ReadDataWidth", 64, ...
146 | "ReadFrameLength", framesize_rd,...
147 | "WriteTimeout",0,...
148 | "ReadTimeout",0);
149 |
150 | hPort_axis_mm2s_tdata = hdlcoder.DUTPort("axis_mm2s_tdata", ...
151 | "Direction", "IN", ...
152 | "DataType", numerictype(1,64,0), ...
153 | "Dimension", [1 1], ...
154 | "IOInterface", "AXI4-Stream DMA");
155 |
156 | hPort_axis_s2mm_tdata = hdlcoder.DUTPort("axis_s2mm_tdata", ...
157 | "Direction", "OUT", ...
158 | "DataType", numerictype(0,64,0), ...
159 | "Dimension", [1 1], ...
160 | "IOInterface", "AXI4-Stream DMA");
161 |
162 | mapPort(hFPGA, [hPort_axis_mm2s_tdata, hPort_axis_s2mm_tdata]);
163 |
164 | end
165 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/simCheckOutput_rangeDoppler.m:
--------------------------------------------------------------------------------
1 | %% Run this after reading matrix value out
2 | Valid = out.rdValid(:);
3 | rdMat = out.rdMat(:);
4 | rdMat = rdMat(Valid);
5 | iter = floor(length(rdMat)/(N1*N2));
6 |
7 |
8 |
9 | %% check range-doppler with fft-shift
10 | Valid = out.rdValid(:);
11 | rdMat = out.rdMat(:);
12 | rdMat = rdMat(Valid);
13 | % rdMat = rdMat((1:N1*N2)');
14 |
15 | img = reshape(rdMat(1:N1*N2*iter),N2,N1,iter);
16 |
17 | for ii = 1:iter
18 | cubeOutput = fftshift(transpose(img(:,:,ii)),2);
19 | cubeOutput = 20*log10(abs(cubeOutput));
20 |
21 | % nexttile([1,2]);
22 | imagesc([-VelMax VelMax],[RngMin RngMax],cubeOutput);
23 | title('Range-Doppler');
24 | xlabel('Velocity');
25 | ylabel('Range');
26 | colorbar;
27 | end
28 |
29 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/socmemlib.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/socmemlib.slx
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/validateTranspose.m:
--------------------------------------------------------------------------------
1 |
2 | warning('only run this if you are comparing integer non-complex values for the 256x64 transpose');
3 |
4 | dataOut = out.logsout.find('axi4mrd_dataOut').Values.Data;
5 | dataValid = out.logsout.find('axi4mrd_validOut').Values.Data;
6 | % validLength = sum(dataValid == 1) - mod(length(dataValid),N1*N2);
7 | % matrixExtract = dataOut(dataValid(1:validLength));
8 | % numMatrices = length(matrixExtract)/(N1*N2);
9 | matrixExtract = dataOut(dataValid);
10 | trimLen = mod(length(matrixExtract),N1*N2);
11 | matrixExtract = matrixExtract(1:(length(matrixExtract) - trimLen));
12 | c = reshape(matrixExtract,N2,N1,[]); %<--- note we swap N2 and N1 because this is transposed..
13 |
14 | numMatrices = length(matrixExtract)/(N1*N2);
15 | for ii = 1:numMatrices
16 | diff = double(MatrixInput.') - double(c(:,:,ii));
17 | if ~any(diff(:)~=0)
18 | fprintf('transpose good = %d \n',ii);
19 | else
20 | warning('bad transpose!')
21 | end
22 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/part2_rangedoppler_hdl/writeDopplerInput_fpgaIO.m:
--------------------------------------------------------------------------------
1 | %--------------------------------------------------------------------------
2 | % Constant Design parameters
3 | %
4 | %--------------------------------------------------------------------------
5 |
6 | N1 = 256; % row
7 | N2 = 64; % columns
8 |
9 | enableFullMatrixWrite = true;
10 | debugInputFrame = true;
11 | %--------------------------------------------------------------------------
12 | % Adjustable Design parameters
13 | %
14 | %--------------------------------------------------------------------------
15 |
16 | % init parameters
17 | range_doppler_system_param_init;
18 |
19 | % Number of coherent processing intervals (CPI) to run
20 | NumCPI = 1;
21 |
22 | % Create radar data cube
23 | radarDataCube = createRadarDataCubeMod(...
24 | txSignalFullPeriod,antennaElement,Fs,Fc, ...
25 | targetPos, targetVel, targetRCS, ...
26 | RngMax, RxActiveTime, RngGate, ...
27 | CPILength, NumCPI, CPILength*pulsePeriod);
28 |
29 | %% Create fpga object
30 | hFPGA = fpga("Xilinx");
31 |
32 |
33 |
34 | %% Setup fpga object
35 | % This function configures the "fpga" object with the same interfaces as the generated IP core
36 | if enableFullMatrixWrite
37 | frameLenWrite = 256*64;
38 | frameLenRead = 256*64;
39 | else
40 | frameLenWrite = 256;
41 | frameLenRead = 256*64;
42 | end
43 | setup_fpgaIO(hFPGA,frameLenWrite,frameLenRead);
44 | writePort(hFPGA, "resetIP", true);
45 |
46 | if debugInputFrame
47 | debugRegInput.bypassFFT = true;
48 | debugRegInput.bypassMatchedFilter = true;
49 | writePort(hFPGA, "debugRegInput", debugRegInput);
50 | else
51 | debugRegInput.bypassFFT = false;
52 | debugRegInput.bypassMatchedFilter = false;
53 | writePort(hFPGA, "debugRegInput", debugRegInput);
54 | end
55 |
56 | %% Create frame
57 | radarDataCube_fi = packBits(radarDataCube);
58 | radarDataCube_fi_mat = reshape(radarDataCube_fi,256,64);
59 | radarDataCube_fi_mat = fi(radarDataCube_fi_mat,0,64,0);
60 |
61 | if debugInputFrame
62 | radarDataCube_fi = fi(1:(256*64),0,64,0);
63 | radarDataCube_fi_mat = reshape(radarDataCube_fi,256,64);
64 | end
65 |
66 |
67 | %% Write frame
68 | if ~enableFullMatrixWrite
69 | prevValidCount = 0;
70 | for ii = 1:64
71 | writePort(hFPGA, "axis_mm2s_tdata", radarDataCube_fi_mat(:,ii));
72 | data_debugRead = readPort(hFPGA, "debugRead");
73 | measuredValidCount = data_debugRead.FIFO_ValidWriteCount;
74 | fprintf('valid count diff = %d \n',double(measuredValidCount) - double(prevValidCount));
75 | prevValidCount = measuredValidCount;
76 | end
77 | else
78 | writePort(hFPGA, "axis_mm2s_tdata", radarDataCube_fi(:));
79 | data_debugRead = readPort(hFPGA, "debugRead");
80 | measuredValidCount = data_debugRead.FIFO_ValidWriteCount;
81 | fprintf('valid count diff = %d \n',double(measuredValidCount) - 256*64);
82 |
83 | end
84 | %% read and Unpack
85 | rangeDopplerRead = readPort(hFPGA, "axis_s2mm_tdata");
86 |
87 | data_ddrDoneCounter = readPort(hFPGA, "ddrDoneCounter");
88 | fprintf('DDR4 write count = %d \n', uint32(data_ddrDoneCounter));
89 |
90 | if ~debugInputFrame
91 | re = reinterpretcast(bitsliceget(rangeDopplerRead,32,1),numerictype(1,32,21)) ;
92 | imag = reinterpretcast(bitsliceget(rangeDopplerRead,64,33),numerictype(1,32,21)) ;
93 | rdMat = complex(re,imag);
94 | else
95 | output_data = reshape(rangeDopplerRead,64,256);
96 | expectedTranspose = double(radarDataCube_fi_mat.');
97 | plot(output_data(:) - expectedTranspose(:))
98 | xlabel('Samples')
99 | title('Error for Expected vs Actual BRAM Burst transpose');
100 |
101 | end
102 |
103 | %% AXI4 debug register reads
104 | data_fifo_full_event = readPort(hFPGA, "fifo_full_event");
105 |
106 | fprintf('Number of samples FIFO outputted = %d \n',data_debugRead.FIFO_ValidWriteCount);
107 | fprintf('Number of bursts completed for writes = %d \n',data_debugRead.AXI4M_WrValidCnt);
108 | fprintf('Number of times BRAM FSM paused input FIFO = %d \n',data_debugRead.BRAM_FSM_StoppingFIFO_Counter);
109 | fprintf('Number of lost samples = %d \n',data_debugRead.FIFO_LostSampleCount);
110 | fprintf('Number of times back-pressure applied on MM2s = %d \n',data_debugRead.FIFO_BackPressureAppliedOnMM2S);
111 | fprintf('Number of times FIFO was full = %d \n',data_debugRead.FIFO_FullEventCount);
112 |
113 |
114 | %%
115 | if ~debugInputFrame
116 | img = reshape(double(rdMat),64,256);
117 | cubeOutput = fftshift(transpose(img),2);
118 | cubeOutput = 20*log10(abs(cubeOutput));
119 |
120 | nexttile([1,2]);
121 | imagesc([-VelMax VelMax],[RngMin RngMax],cubeOutput);
122 | title('Range-Doppler');
123 | xlabel('Velocity');
124 | ylabel('Range');
125 | colorbar;
126 | end
127 |
128 |
129 |
130 | %% Release hardware resources
131 | release(hFPGA);
132 |
133 |
134 | %% Helper functions
135 |
136 | function output = packBits(waveformInput)
137 |
138 | waveformInput_fi = fi(waveformInput,1,20,18);
139 | % [real(waveformInput_fi) imag(waveformInput_fi)]
140 | output = bitconcat(real(waveformInput_fi(:)),imag(waveformInput_fi(:)));
141 |
142 | end
143 |
144 |
145 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/-LsZ8HXJj2Q_3Mm_5RR2W21dUukd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/-LsZ8HXJj2Q_3Mm_5RR2W21dUukp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/0avZ0B7B9QBO8c3kVcoPdfvh0a4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/0avZ0B7B9QBO8c3kVcoPdfvh0a4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/4SII37bbmPr-uDt2KwUOF17LD3Md.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/4SII37bbmPr-uDt2KwUOF17LD3Mp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/hVqQ-9HgOfR-miUHZ1Olro2oO1Ed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/hVqQ-9HgOfR-miUHZ1Olro2oO1Ep.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/tKvNkHTpbT6GAm3k-7n7cooRcn0d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/tKvNkHTpbT6GAm3k-7n7cooRcn0p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/ySwxmLB6i3-U3ibpDX9G5VF_qIkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/1AK6k8_2MMsrq1VagZS1umPpphk/ySwxmLB6i3-U3ibpDX9G5VF_qIkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/4SVYQZsILIuEyZXh7AZiBXaAzWId.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/4SVYQZsILIuEyZXh7AZiBXaAzWIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/TDGNiicbXqPcaT25VpzQ4PfNaGEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/TDGNiicbXqPcaT25VpzQ4PfNaGEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/TnMVnPKCYgLFQp-huKXjIUP3g50d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/TnMVnPKCYgLFQp-huKXjIUP3g50p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/XI63F3DpcFZVEmLxabCze_1yGYUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/XI63F3DpcFZVEmLxabCze_1yGYUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/u09gIjf84mrcY04PvVsIqz_A2nId.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/u09gIjf84mrcY04PvVsIqz_A2nIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/ytXa1Px-hQUhxMW6RexuadiW05Md.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/CAsOFWEXbRicMJSXkpnan34QAz4/ytXa1Px-hQUhxMW6RexuadiW05Mp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/EP7gYHkiKJzsbwl1Kmg0OEWqO4od.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/EP7gYHkiKJzsbwl1Kmg0OEWqO4op.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/fSmbuBCUit5i5wOBPuJA2g5w9NId.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/fSmbuBCUit5i5wOBPuJA2g5w9NIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lJnjawKd-WsGvgvgCWqsl0Tg_aUd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/lJnjawKd-WsGvgvgCWqsl0Tg_aUp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/pJPJd6FiWRygNl9o0EVnymaY7Ykd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/pJPJd6FiWRygNl9o0EVnymaY7Ykp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/NwDM1JfMyUKVVWcp71u8HzQ1GJc/ErjdZpt4SMkWn8v-1ahF4A3siMMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/NwDM1JfMyUKVVWcp71u8HzQ1GJc/ErjdZpt4SMkWn8v-1ahF4A3siMMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/NwDM1JfMyUKVVWcp71u8HzQ1GJc/MnQp2l-5jErytlj-zxMUdpGpr5cd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/NwDM1JfMyUKVVWcp71u8HzQ1GJc/MnQp2l-5jErytlj-zxMUdpGpr5cp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Ud.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/66WgGCcF5RIH9MCEgPmgjZK9k3Up.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/WZRuNzqc-Db7NcQAZO8Y-R8U9cc/AtMjXDrOSm8YDv3_4UFXiyrWqNEp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/1AK6k8_2MMsrq1VagZS1umPpphkd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/1AK6k8_2MMsrq1VagZS1umPpphkp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/CAsOFWEXbRicMJSXkpnan34QAz4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/CAsOFWEXbRicMJSXkpnan34QAz4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/NwDM1JfMyUKVVWcp71u8HzQ1GJcd.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/NwDM1JfMyUKVVWcp71u8HzQ1GJcp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/tczr9cMCNMOtxnSsL6yRolFxYBId.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/tczr9cMCNMOtxnSsL6yRolFxYBIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/root/EEtUlUb-dLAdf0KpMVivaUlztwAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/root/WZRuNzqc-Db7NcQAZO8Y-R8U9ccp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/EGS-wA3-Ks6urVqBkUEHtwtFE_Ed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/EGS-wA3-Ks6urVqBkUEHtwtFE_Ep.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/KRklbgq8aG-kfYmOgOLRLkm3QDId.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/KRklbgq8aG-kfYmOgOLRLkm3QDIp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/Q6dDcsN2OKbQzgD58TRr8ONsFJMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/Q6dDcsN2OKbQzgD58TRr8ONsFJMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/WSzvG5f_5Cvt8a1ZYLPc6xfuSq4d.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/WSzvG5f_5Cvt8a1ZYLPc6xfuSq4p.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/Xi_uJVws7Ulmwu5Gll1EDSreybMd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/Xi_uJVws7Ulmwu5Gll1EDSreybMp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/b9vcJ5kLPMvo3kZz_IJEYIN8Z6cd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/b9vcJ5kLPMvo3kZz_IJEYIN8Z6cp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/haKPcoVMP6OfLpW27bivJk-zciAd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/haKPcoVMP6OfLpW27bivJk-zciAp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/rKuGYAHY8-cXC9XRh5EcCRlNuEQd.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/rKuGYAHY8-cXC9XRh5EcCRlNuEQp.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/uPQ5MtfZJq79kMUTlWx4p0q_8hod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/resources/project/tczr9cMCNMOtxnSsL6yRolFxYBI/uPQ5MtfZJq79kMUTlWx4p0q_8hop.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/AXIBusObjects.m:
--------------------------------------------------------------------------------
1 | function AXIBusObjects()
2 | % AXIBUSOBJECTS initializes a set of bus objects in the MATLAB base workspace
3 |
4 | % Bus object: BusAXIWriteCtrlM2S
5 | clear elems;
6 | elems(1) = Simulink.BusElement;
7 | elems(1).Name = 'wr_addr';
8 | elems(1).Dimensions = 1;
9 | elems(1).DimensionsMode = 'Fixed';
10 | elems(1).DataType = 'uint32';
11 | elems(1).SampleTime = -1;
12 | elems(1).Complexity = 'real';
13 | elems(1).Min = [];
14 | elems(1).Max = [];
15 | elems(1).DocUnits = '';
16 | elems(1).Description = '';
17 |
18 | elems(2) = Simulink.BusElement;
19 | elems(2).Name = 'wr_len';
20 | elems(2).Dimensions = 1;
21 | elems(2).DimensionsMode = 'Fixed';
22 | elems(2).DataType = 'uint32';
23 | elems(2).SampleTime = -1;
24 | elems(2).Complexity = 'real';
25 | elems(2).Min = [];
26 | elems(2).Max = [];
27 | elems(2).DocUnits = '';
28 | elems(2).Description = '';
29 |
30 | elems(3) = Simulink.BusElement;
31 | elems(3).Name = 'wr_valid';
32 | elems(3).Dimensions = 1;
33 | elems(3).DimensionsMode = 'Fixed';
34 | elems(3).DataType = 'boolean';
35 | elems(3).SampleTime = -1;
36 | elems(3).Complexity = 'real';
37 | elems(3).Min = [];
38 | elems(3).Max = [];
39 | elems(3).DocUnits = '';
40 | elems(3).Description = '';
41 |
42 | BusAXIWriteCtrlM2S = Simulink.Bus;
43 | BusAXIWriteCtrlM2S.HeaderFile = '';
44 | BusAXIWriteCtrlM2S.Description = '';
45 | BusAXIWriteCtrlM2S.DataScope = 'Auto';
46 | BusAXIWriteCtrlM2S.Alignment = -1;
47 | BusAXIWriteCtrlM2S.Elements = elems;
48 | clear elems;
49 | assignin('base','BusAXIWriteCtrlM2S', BusAXIWriteCtrlM2S);
50 |
51 | % Bus object: BusAXIWriteCtrlS2M
52 | clear elems;
53 | elems(1) = Simulink.BusElement;
54 | elems(1).Name = 'wr_ready';
55 | elems(1).Dimensions = 1;
56 | elems(1).DimensionsMode = 'Fixed';
57 | elems(1).DataType = 'boolean';
58 | elems(1).SampleTime = -1;
59 | elems(1).Complexity = 'real';
60 | elems(1).Min = [];
61 | elems(1).Max = [];
62 | elems(1).DocUnits = '';
63 | elems(1).Description = '';
64 |
65 | elems(2) = Simulink.BusElement;
66 | elems(2).Name = 'wr_complete';
67 | elems(2).Dimensions = 1;
68 | elems(2).DimensionsMode = 'Fixed';
69 | elems(2).DataType = 'boolean';
70 | elems(2).SampleTime = -1;
71 | elems(2).Complexity = 'real';
72 | elems(2).Min = [];
73 | elems(2).Max = [];
74 | elems(2).DocUnits = '';
75 | elems(2).Description = '';
76 |
77 | BusAXIWriteCtrlS2M = Simulink.Bus;
78 | BusAXIWriteCtrlS2M.HeaderFile = '';
79 | BusAXIWriteCtrlS2M.Description = '';
80 | BusAXIWriteCtrlS2M.DataScope = 'Auto';
81 | BusAXIWriteCtrlS2M.Alignment = -1;
82 | BusAXIWriteCtrlS2M.Elements = elems;
83 | clear elems;
84 | assignin('base','BusAXIWriteCtrlS2M', BusAXIWriteCtrlS2M);
85 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/createRadarDataCubeMod.m:
--------------------------------------------------------------------------------
1 | function dataCube = createRadarDataCubeMod(TxWaveform,RxArray,Fs,Fc, ...
2 | TargetPos,TargetVel,TargetRCS,...
3 | RngMax,RngActiveTime,RngGateTime,...
4 | CPILength,NumCPI,CPIDelta)
5 |
6 | rng('default')
7 |
8 | tx = phased.Transmitter('PeakPower',3000,'Gain',50);
9 |
10 | freespaceTx = phased.FreeSpace('SampleRate',Fs,...
11 | 'MaximumDistanceSource','Property',...
12 | 'MaximumDistance',RngMax,...
13 | 'OperatingFrequency',Fc);
14 |
15 | radarTarget = phased.RadarTarget('MeanRCS',TargetRCS,'OperatingFrequency',Fc);
16 |
17 | targetPlatform = phased.Platform('InitialPosition',TargetPos,'Velocity',TargetVel);
18 |
19 | freespaceRx = phased.FreeSpace('SampleRate',Fs,...
20 | 'MaximumDistanceSource','Property',...
21 | 'MaximumDistance',RngMax,...
22 | 'OperatingFrequency',Fc);
23 |
24 | rxCollector = phased.Collector('Sensor',RxArray,'OperatingFrequency',Fc);
25 |
26 | rx = phased.ReceiverPreamp('Gain',80,'NoiseFigure',30,'SampleRate',Fs);
27 |
28 | TxPos = [0;0;0];
29 | TxVel = [0;0;0];
30 | RxPos = [0;0;0];
31 | RxVel = [0;0;0];
32 |
33 | RngActiveSamples = RngActiveTime*Fs;
34 | RngGateSamples = RngGateTime*Fs;
35 | PulsePeriod = length(TxWaveform)/Fs;
36 |
37 | dataCube = complex(zeros(RngActiveSamples,CPILength,NumCPI));
38 |
39 | T = 0;
40 | for nn=1:NumCPI
41 | if nn > 1
42 | targetPlatform(T);
43 | end
44 | for ii=1:CPILength
45 | [TgtPos,TgtVel] = targetPlatform(PulsePeriod);
46 | temp = tx(TxWaveform);
47 | temp = horzcat(temp,temp);
48 | temp = freespaceTx(temp,TxPos,TgtPos,TxVel,TgtVel);
49 | temp = radarTarget(temp);
50 | temp = freespaceRx(temp,TgtPos,RxPos,TgtVel,RxVel);
51 | [~,ang] = rangeangle(TgtPos);
52 | temp = rxCollector(temp,ang);
53 | temp = rx(temp);
54 | dataCube(:,ii,nn) = temp(uint32(RngGateSamples+1):end,:);
55 | end
56 | T = T+CPIDelta;
57 | end
58 |
59 | end
60 |
61 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/getLogged.m:
--------------------------------------------------------------------------------
1 |
2 | function signal_val = getLogged(logsout,signal_name)
3 |
4 | % logsout = simout_obj.logsout;
5 | if isempty(logsout)
6 | error('No logged signal found. Make sure ''%s'' is logged in the model',...
7 | signal_name);
8 | end
9 |
10 | sig = logsout.getElement(signal_name);
11 | if isempty(sig)
12 | error('Signal ''%s'' not found. Make sure it is logged and named correctly.',...
13 | signal_name);
14 | end
15 |
16 | signal_val = squeeze(sig.Values.Data);
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/range_doppler_system_param_init.m:
--------------------------------------------------------------------------------
1 | %% Radar parameters
2 |
3 | % Environment
4 | propSpeed = physconst('LightSpeed'); % Propagation speed
5 | Fc = 10e9; % Operating/carrier frequency
6 | lambda = propSpeed/Fc;
7 |
8 | % Inherit sample rate
9 | if ~exist('Fs','var')
10 | Fs = 250e6;
11 | end
12 | Ts = 1/Fs;
13 |
14 |
15 |
16 |
17 | % Application parameters
18 | pulseWidthSamples = 32;
19 | pulseBw = Fs/2; % Pulse bandwidth
20 |
21 | CPILength = 64; % Number of pulses in a Coherent Processing Interval
22 |
23 | % totalSamplesPulse = Fs/PRF;
24 | % = 4250;
25 | RxActiveSamples = 256;
26 | RngGateSamples = 8346 - RxActiveSamples;
27 |
28 | % Derived params
29 | pulsePeriodSamples = RngGateSamples+RxActiveSamples;
30 | pulseWidth = pulseWidthSamples*Ts; % Pulse width
31 | pulsePeriod = pulsePeriodSamples*Ts; % Pulse repetition period
32 | PRF = 1/pulsePeriod; % Pulse repetition frequency
33 | CPIPeriod = CPILength*pulsePeriod;
34 | RxActiveTime = RxActiveSamples*Ts;
35 |
36 |
37 | %
38 |
39 |
40 | RngGate = RngGateSamples*Ts; % Range gate start
41 | RngMin = propSpeed*RngGate/2;
42 | RngMax = propSpeed/(PRF*2); % Maximum unambiguous range
43 | VelMax = propSpeed*PRF/(Fc*4); % Maximum unambiguous velocity
44 |
45 | RngDimLen = RxActiveSamples;
46 | VelDimLen = CPILength;
47 | RngEstBins = linspace(RngMin,RngMax,RngDimLen);
48 | VelEstBins = linspace(-VelMax,VelMax,VelDimLen);
49 |
50 | % Matched filter parameters
51 | hwav = phased.LinearFMWaveform(...
52 | 'PulseWidth',pulseWidth,...
53 | 'PRF',PRF,...
54 | 'SweepBandwidth',pulseBw,...
55 | 'SampleRate',Fs);
56 | matchingCoeff = getMatchedFilter(hwav);
57 | txSignalFullPeriod = hwav();
58 | txSignal = txSignalFullPeriod(1:pulseWidthSamples);
59 |
60 | %% Target parameters
61 | target1Az = -47;
62 | target1Dist = 4950;
63 | target1Speed = 100;
64 | target1RCS = 2.5;
65 |
66 | target2Az = 50;
67 | target2Dist = 4900;
68 | target2Speed = -150;
69 | target2RCS = 4;
70 |
71 | target1Pos = [target1Dist*cosd(target1Az); target1Dist*sind(target1Az); 0];
72 | target1Vel = [target1Speed*cosd(target1Az); target1Speed*sind(target1Az); 0];
73 | target2Pos = [target2Dist*cosd(target2Az); target2Dist*sind(target2Az); 0];
74 | target2Vel = [target2Speed*cosd(target2Az); target2Speed*sind(target2Az); 0];
75 |
76 | targetPos = [target1Pos target2Pos];
77 | targetVel = [target1Vel target2Vel];
78 | targetRCS = [target1RCS target2RCS];
79 |
80 | %% Rx Array / Beamforming parameters
81 |
82 | numAntennaElements = 1;
83 |
84 | antennaElement = phased.IsotropicAntennaElement(...
85 | 'FrequencyRange',[Fc-1e8 Fc+1e8], 'BackBaffled', true);
86 |
87 |
88 | % Beamforming scan angle
89 | RxScanAngle = target2Az;
90 |
91 |
92 | %% CFAR detection
93 | CFARGuardVel = 1;
94 | CFARGuardRng = 1;
95 | CFARTrainVel = 8;
96 | CFARTrainRng = 4;
97 | CFARGuardRegion = [CFARGuardRng CFARGuardVel];
98 | CFARTrainRegion = [CFARTrainRng CFARTrainVel];
99 | CFARRngPad = CFARGuardRng+CFARTrainRng;
100 | CFARVelPad = CFARGuardVel+CFARTrainVel;
101 | CFARRngIdx = (1+CFARRngPad):(RngDimLen-CFARRngPad);
102 | CFARRngBins = RngEstBins(CFARRngIdx);
103 | CFARRngNumBins = numel(CFARRngIdx);
104 | CFARVelIdx = [(1+CFARVelPad):(VelDimLen/2 - 2) ...
105 | (VelDimLen/2 + 3):(VelDimLen-CFARVelPad)];
106 | CFARVelBins = VelEstBins(CFARVelIdx);
107 | CFARVelNumBins = numel(CFARVelIdx);
108 | CFARProb = 1e-12;
109 | CFARIdx = zeros(2,CFARVelNumBins*CFARRngNumBins);
110 | nn = 1;
111 | for ii=CFARVelIdx
112 | for jj=CFARRngIdx
113 | CFARIdx(:,nn) = [jj;ii];
114 | nn=nn+1;
115 | end
116 | end
--------------------------------------------------------------------------------
/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/window_taper.slx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mathworks/FPGA-Adaptive-Beamforming-and-Radar-Examples/fc4f485755b9486f0b891e46fbf67c1143c8e104/rangedoppler/hw_only/partB_MatchedFilterFFTTranspose/shared_files/window_taper.slx
--------------------------------------------------------------------------------