Pulse Detector HDL Workflow Tutorial
R2024a - R2024b
MathWorks Application Engineering
© 2025 The MathWorks, Inc.
1
Example Overview
In this tutorial, you are provided the MATLAB® reference of a pulse detection algorithm. The
algorithm detects a known waveform in a received signal using a matched filter, and finding
the resulting peak. It is a commonly used technique in radar or wireless communication
systems.
2
Example Overview
This tutorial will guide you through the steps necessary to implement the algorithm in FPGA
hardware, including:
▪ Create a Simulink® model for the algorithm
▪ Implement the hardware architecture
▪ Convert the design to fixed-point
▪ Generate and synthesize the HDL code
3
Software Requirements
▪ You will need the following MathWorks products:
– MATLAB (R2024a or R2024b)
– Simulink
– Fixed-Point DesignerTM
– MATLAB CoderTM
– HDL CoderTM
– Signal Processing ToolboxTM
– DSP System ToolboxTM
– DSP HDL ToolboxTM
▪ AMD VivadoTM 2023.1 is used for the last step (step 4)
– Other Vivado versions typically work, but synthesis results may be different.
4
Preparation
▪ You should be familiar with MATLAB and have basic knowledge of Simulink such as:
– Creating Simulink models (adding & connecting blocks, creating subsystem, etc)
– Setting block and model-level parameters
– Updating, simulating model and viewing simulation results
– Interacting with MATLAB using workspace variables and signal logging
– Using fixed-point data type in Simulink
▪ Use the following resources as needed to prepare for this tutorial:
– MATLAB Onramp
– Simulink Onramp
– HDL Coder Tutorial Overview (video series)
– HDL Coder Evaluation Reference Guide
▪ Locate the example files in the folder: /pulse_detector/work
5
Step 1: Streaming Simulink model
In this step, you will:
▪ Create a Simulink model with streaming input
▪ Implement a hardware-friendly peak finder
▪ Compare the Simulink pulse detector to the MATLAB golden reference
6
Step 1.1: Stream and filter input signal
1. Run pulse_detector_reference.mlx to initialize
parameters needed in this step.
2. Create a new Simulink model and name it
pulse_detector_v1.slx
3. Add a Signal From Workspace block, and enter
RxSignal for Signal on the block dialog. This will
stream the vector RxSignal one sample at a time.
4. Implement the filter function using a Discrete FIR
Filter block from the Simulink library. Enter
CorrFilter for Coefficients.
5. Name the filter block output signal filter_out, and
enable data logging for the signal.
6. Enter SimTime for simulation stop time.
Tip: Make sure to choose the right blocks
7
Step 1.1: Stream and filter input signal
7. Compare the Simulink filter output against the MATLAB reference. Verifying your Simulink model
incrementally helps catch mistakes early on.
• Run the test bench script pulse_detector_v1_tb.mlx. An error is expected at line 16 as the model is incomplete.
• Verify the Simulink filter output matches the MATLAB reference (max error ~ 1e-16 ).
8
Step 1.2: Hardware-friendly peak finder (magnitude-squared)
1. Review the section Hardware friendly implementation of
peak finder in pulse_detector_reference.mlx.
2. At the filter block output, implement magnitude-squared
using the following blocks:
3. Group the blocks in a subsystem and name it Compute
Power. Log the subsystem output as mag_sq_out.
Tip: Enable Signal Dimensions
& Alias Data Types displays to
visualize signal properties.
9
Step 1.3: Hardware-friendly peak finder (local peak)
1. Connect mag_sq_out to a Tapped
Delay block for the sliding window
buffer. Set Number of delays to
WindowLen.
2. Implement the rest of the
hardware-friendly peak finder
using a MATLAB Function block.
Copy and paste the code from
pulse_detector_reference.mlx
(line 42 to the end) to the block,
and modify it to match the
screenshot.
3. Click on Edit Data to open the
Symbols pane and the Property
Inspector. Select WindowLen,
change its Scope to Parameter
and uncheck Tunable.
10
Step 1.3: Hardware-friendly peak finder (local peak)
4. Navigate back to the top-level model. Add a
Constant block and enter threshold for Constant
value.
5. Connect the constant, tapped delay and MATLAB
function blocks as shown. Group the 3 blocks in a
subsystem named Local Peak.
6. Connect Local Peak to a Unit Delay Enabled
Synchronous (UDES) block; log and name the
connecting signals mid_sample and detected as
shown.
7. Finally, connect the UDES block to a Display
block. The UDES block will keep the detected
peak value on display at the end of the simulation.
8. Save the model.
11
Step 1.4: Compare model to MATLAB reference
Run pulse_detector_v1_tb.mlx to simulate the model, and
compare the Simulink outputs to the MATLAB reference.
▪ Maximum error for the correlator, magnitude-squared
and peak value should be in the range of floating-point
eps (e-16).
▪ Peak location is randomized for each run.
▪ The Simulink model implements a detected output
instead of an index for the peak location, as the
algorithm is often used to determine the beginning of a
data frame, where a detected signal is sufficient.
12
Step 2: Hardware micro architecture
In this step, you will:
▪ Prepare the model for HDL code generation
▪ Add data valid control signal
▪ Use hardware-efficient blocks and pipeline the data path
▪ Compare the Simulink architecture model to the MATLAB golden reference
13
Step 2.1: HDL model configurations
1. Save the Simulink model as pulse_detector_v2.slx.
2. Run the MATLAB command
hdlsetup('pulse_detector_v2'). This will configure the
model settings to be compatible with HDL code
generation.
3. Group the filter block, the Compute Power and Local
Peak subsystems into a top-level subsystem named
Pulse Detector. This top-level subsystem will be referred
to as the DUT (Design Under Test) – i.e. the portion of the
model that will generate HDL.
DUT
Note: hdlsetup enables sample time color display for the
model. The next time you update/simulate the model, blocks
will appear red as they operate at the fastest sample rate.
14
Step 2.2: Implement data valid interface
1. Add a data valid input using a Signal From Workspace block;
enter true(size(RxSignal)) for the Signal parameter. This enables
the design to interface with a non-continuous data source,
although the example uses continuous input data for simplicity.
2. Connect the block to the DUT subsystem as a second input.
3. Inside the DUT subsystem, name the first input port data_in, and
the new input port valid_in.
4. Add a new Output port and name it valid_out.
15
Step 2.3: HDL optimized FIR filter
FIR systolic cells
1. Replace the current FIR filter with a Discrete FIR Filter block from the
DSP HDL Toolbox library. This block offers systolic filter architectures
and pipeline register placements that are designed to use FPGA DSP
resources efficiently. It also provides control signals for common data
interfaces.
2. Again, enter CorrFilter for Coefficients, name the data output signal
filter_out, and log the signal.
3. Connect the valid_in port to the FIR valid input, and the FIR valid
output to the valid_out port. Log the FIR valid out as filter_valid.
16
Step 2.4: Insert pipeline registers
1. Pipeline the data input & output using Delay blocks as shown. Add matching delays to the valid
signal path.
2. The FIR filter from DSP HDL Toolbox already contains pipeline registers. No action is required.
1 Modeled 4 Enable Adaptive Pipelining to 1 Modeled
Pipelining
explicitly using pipeline multipliers in the HDL code explicitly using
options:
delay blocks based on target device setting delay blocks
Delay Balancing automatically match
parallel path latency resulting from
2 Provided by block Adaptive Pipelining in the HDL code
17
Step 2.4: Insert pipeline registers
3. Open the HDL Code Toolstrip under
Apps > Code Generation > HDL Coder.
4. Select the Compute Power subsystem and open its HDL
Property Inspector / HDL Block Properties dialog
using the HDL Code Toolstrip. Set AdaptivePipelining
to on, then close the HDL properties dialog.
R2024b R2024a
18
Step 2.5: Compare architecture model to MATLAB reference
1. In the top-level model, terminate the DUT output port valid_out
by connecting it to a Terminator block. Save the model.
2. Run pulse_detector_v2_tb.mlx to simulate the model, and
compare the Simulink outputs to the MATLAB reference.
▪ This test bench uses the new filter_valid signal to qualify
the logged filter & magnitude-squared outputs:
▪ Maximum error for all outputs should be similar to that of
step 1.
Question: What’s wrong with the valid signal implementation?
Answer: The valid signal should also be connected to the sliding window buffer, to prevent invalid samples
from entering the delay line. The simulation is only correct in this example because valid_in is always high.
19
Step 3: Fixed-point conversion
In this step, you will:
▪ Convert the model to fixed-point
▪ Compare the Simulink fixed-point model to the MATLAB golden reference
20
Step 3.1: Define input and filter fixed-point data types
1. Save the Simulink model as pulse_detector_v3.slx.
2. At the top-level model, add a Data Type Conversion block
at the output of RxSignal. Set Output data type to
DT_input, which is defined as fixdt(1,16,14) in the test
bench script to fully represent -1 to 1.
3. Inside the DUT, set Coefficients Data Type on the FIR
filter block to DT_coeff, which is defined as fixdt(1,18).
Fraction length of a constant can be automatically
determined when it is left unspecified.
4. The filter is set up to perform multiply & add using full-
precision fixed-point. Run pulse_detector_v3_tb.mlx to
update the filter output data type (error is expected as the
model is partially converted to fixed-point).
21
Step 3.2: Define magnitude-squared data types
1. In the Compute Power subsystem, add a Data Type Conversion block
after the input port; set Output data type to DT_filter. This reduces the
data word length to 18-bit while maintaining the integer range.
2. Update the model to examine the data types through the subsystem
(error is still okay).
3. Reduce the final adder output to DT_power using another Data Type
Conversion block, and update the model once more (error is still okay).
Tip: 18-bit inputs and full-precision fixed-point allow multiply-add operations (including those
within the FIR filter in the previous step) to be implemented using DSP blocks in most FPGAs.
22
Step 3.3: Define peak picker data types
1. In the Local Peak subsystem, add a Data Type Duplicate
block. Connect one port to the threshold constant block
output, and another to the tapped delay block output.
2. Set Output data type of the threshold constant to
Inherit via back propagation.
These 2 steps allow the threshold constant to take on the
same data type used by the input data.
3. In the MATLAB function block, change the detected value
to true/false.
4. Update and save the model. It should be error-free at this
point. This warning message can be
safely ignored or suppressed.
23
Step 3.4: Compare fixed-point model to MATLAB reference
Run pulse_detector_v3_tb.mlx to simulate the model,
and compare the Simulink fixed-point outputs to the
MATLAB floating-point reference.
▪ Note the increase in error due to quantization.
▪ You may switch between fixed-point and floating-
point using the following flag in the test bench.
Tip: Doing hardware architecture design before
fixed-point conversion prevents quantization noise
from obscuring design errors.
24
Step 4: HDL code generation & synthesis
In this step, you will:
▪ Check the model for HDL compatibility
▪ Generate HDL code and reports
▪ Synthesize the generated design using AMD Vivado
25
Step 4.1: Check model for HDL compatibility
1. Save the Simulink model as pulse_detector_v4.slx.
2. Set the Pulse Detector subsystem as DUT using the
HDL Code Toolstrip (click to unlock; select the
subsystem in the model; click again to lock).
3. Check HDL Compatibility for the DUT subsystem
using HDL Code Advisor. Besides incompatibility,
the tool also checks for settings that may result in
inefficient hardware. In many cases, a shortcut is
provided to modify those settings.
4. De-select the groups Industry standard checks
and Native Floating Point checks – they are not
applicable for this example. Highlight the top folder
named HDL Code Advisor, then click Run Selected
Checks.
26
Step 4.1: Check model for HDL compatibility
5. HDL Code Advisor identifies 3 warnings that are explained below.
For this exercise, you may ignore the warnings and close the UI.
▪ Check for MATLAB Function block settings reports
the use of saturation and rounding logic, which consumes
extra hardware resources. If your design works with floor
rounding and wrap on overflow, you may click Modify
Settings to apply them automatically.
▪ Check for infinite and continuous sample time
sources reports the use of inf sample time in the model,
which may inhibit some optimization features. If that is
the case, you may click Modify Settings to replace all
such instances with back propagation (-1).
▪ Check for model parameters suited for HDL code
generation recommends Simulink diagnostics settings
that may help identify code generation issues, such as
warnings for unconnected signals.
27
Step 4.2: Generate HDL code and reports
1. In MATLAB, run the following command to add AMD Vivado 2023.1 to the system path:
hdlsetuptoolpath('ToolName','Xilinx Vivado','ToolPath','C:\Xilinx\Vivado\2023.1\bin');
2. Launch HDL Workflow Advisor for the DUT subsystem
(HDL Code Toolstrip > Workflow Advisor).
3. Configure the target settings as shown on the right in
step 1. Click Apply at each step to save the changes.
4. Open HDL Code Generation Settings… in step 3.1.
28
Step 4.2: Generate HDL code and reports
5. Change Reset type to Synchronous (under HDL Code Generation > Global Settings), then click OK
to close the Configuration Parameters dialog.
6. Back in HDL Workflow Advisor, run through steps 1 to 3 (right-click on step 3.2 > Run to Selected Task).
Tip: Choose the appropriate global reset type for your FPGA target
to ensure multipliers & pre/post adders are mapped to DSP blocks.
29
Step 4.2: Generate HDL code and reports
7. Review the results of Adaptive Pipelining and
Delay Balancing in the generated optimization
report. Open the generated model using the
provided link to visualize the added latency.
8. Review resource usage in the high-level
resource report.
Note: The generated model is
bit-true & cycle-accurate to the
generated HDL. It is used to
verify the generated code.
30
Step 4.3: Synthesize the generated design
1. Run step 4.1 to create a Vivado project. You may open the project using the provided link and continue
synthesis in Vivado, especially if you expect it to take a long time.
2. Run step 4.2.1 to synthesize the design without launching Vivado.
MATLAB is blocked while synthesis is run in the background.
31
Summary
This completes the tutorial. Compare your work to the solution models in the folder
/pulse_detector/solution.
For more information:
▪ Visit our FPGA and SoC design website
▪ Explore MathWorks Training on HDL code generation and FPGA signal processing
▪ Contact us on File Exchange for additional questions
32