Model States and Delays in HDL Code by Using Persistent Variables and System Objects
R2026bThis example shows how to model state and delays in a MATLAB® design for HDL code generation by using persistent variables and System objects™. In this example, you use two versions of the same Sobel edge-detection algorithm to compare both approaches and examine the resulting hardware resources in the code generation report.
Examine Persistent-Variable Delays in mlhdlc_sobel Function
Open the mlhdlc_sobel function. This function uses persistent variables to implement hardware delays. Because persistent variables share a single register when the same function is called multiple times, mlhdlc_sobel includes a separate copy of each delay function to create independent hardware delays.
For example, the filterdelay1 function implements a single-pixel delay.
function y = filterdelay1(u) persistent u_d; if isempty(u_d) u_d = 0; end y = u_d; u_d = u; end
To reuse filterdelay while keeping the generated delays independent, the function includes multiple copies with different names, filterdelay1 through filterdelay6, so that each maps to an independent register in the generated HDL. To ensure that the code generator infers persistent variables as registers, each function reads the variables before writing to them.
For longer delays, such as line buffers, mlhdlc_sobel uses circular buffers implemented with persistent arrays and counters. For example, the line_buffer1 function models a delay of one image row of 80 pixels.
function y = line_buffer1(u) persistent u_d ctr; if isempty(u_d) u_d = zeros(1,80); ctr = uint8(1); end y = u_d(ctr); u_d(ctr) = u;
if ctr == uint8(80)
ctr = uint8(1);
else
ctr = ctr + 1;
end
endAs with the single-pixel delays, the function includes a separate copy of the line buffer function, line_buffer1 and line_buffer2, for each independent line buffer delay.
Examine System Object Delays in mlhdlc_sysobj_sobel Function
Open the mlhdlc_sysobj_sobel function. This function uses dsp.Delay System objects to implement hardware delays. Unlike persistent variables, each dsp.Delay object instance is a distinct state holder, so multiple delays are independent without requiring duplicate functions.
For example, this code creates a single-pixel delay.
h1 = dsp.Delay; y = step(h1, u);
This code creates two line-buffer delays. The Length property of the dsp.Delay System object specifies the delay length.
persistent buf1 buf2; if isempty(buf1) buf1 = dsp.Delay('Length', numCols); buf2 = dsp.Delay('Length', numCols); end
lb1 = step(buf1, u); lb2 = step(buf2, lb1);
Each dsp.Delay object corresponds to a distinct delay element. The code generator maps these objects directly to registers without requiring additional logic or duplicate functions.
Generate HDL Code
Generate HDL code for both the mlhdlc_sobel and mlhdlc_sysobj_sobel functions. The code generation runs the test bench for each design to infer types, performs float-to-fixed-point conversion, and generates VHDL code and a resource utilization report.
hdlcfg = coder.config("hdl"); hdlcfg.TestBenchName = "mlhdlc_sobel_tb"; hdlcfg.EnableTraceability = true; fixptcfg = coder.config("fixpt"); fixptcfg.TestBenchName = "mlhdlc_sobel_tb"; codegen -float2fixed fixptcfg -config hdlcfg mlhdlc_sobel hdlcfg.TestBenchName = "mlhdlc_sysobj_sobel_tb"; fixptcfg.TestBenchName = "mlhdlc_sysobj_sobel_tb"; codegen -float2fixed fixptcfg -config hdlcfg mlhdlc_sysobj_sobel
===================================================
Design Name: <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/mlhdlc_sobel.m')">mlhdlc_sobel</a>
Test Bench Name: <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/mlhdlc_sobel_tb.m')">mlhdlc_sobel_tb</a>
===================================================
Input types not specified for design(s) 'mlhdlc_sobel', inferring types by simulating the first test bench: 'mlhdlc_sobel_tb' in the base workspace.
============= Step1: Analyze Floating-Point Code ==============
Code generation successful.
============= Step1a: Verify Floating-Point Code ==============
### Analyzing the design 'mlhdlc_sobel'
### Analyzing the test bench(es) 'mlhdlc_sobel_tb'
### Begin Floating-Point Simulation (Instrumented)
### Floating-Point Simulation Completed in 2.3791 sec(s)
### Elapsed Time: 3.1482 sec(s)
============= Step2: Propose Types Based on Range Information ==============
============= Step3: Generate Fixed-Point Code ==============
### Generating Fixed-Point MATLAB Code <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/fixpt/mlhdlc_sobel_fixpt.m')">mlhdlc_sobel_fixpt</a> Using Proposed Types
### Generating Fixed-Point MATLAB Design Wrapper <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/fixpt/mlhdlc_sobel_wrapper_fixpt.m')">mlhdlc_sobel_wrapper_fixpt</a>
### Generating Mex file for ' mlhdlc_sobel_wrapper_fixpt '
Code generation successful: <a href="matlab: emlcprivate('emcOpenReport','/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/fixpt/reports/mlhdlc_sobel_wrapper_fixpt_mex/html/report.mldatx');">View report</a>
### Generating Type Proposal Report for 'mlhdlc_sobel' <a href="matlab:web('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/fixpt/mlhdlc_sobel_report.html', '-new')">mlhdlc_sobel_report.html</a>
===================================================
Code generation successful.
### Begin MATLAB to HDL Code Generation...
### Working on DUT: mlhdlc_sobel_fixpt.
### Using TestBench: mlhdlc_sobel_tb.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 1: 2 cycles.
### Output port 2: 2 cycles.
### Output port 3: 2 cycles.
### Output port 4: 2 cycles.
### Begin VHDL Code Generation
### Working on mlhdlc_sobel_fixpt/SimpleDualPortRAM_generic as <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/SimpleDualPortRAM_generic.vhd')">SimpleDualPortRAM_generic.vhd</a>.
### Working on mlhdlc_sobel_fixpt as <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/mlhdlc_sobel_fixpt.vhd')">mlhdlc_sobel_fixpt.vhd</a>.
### Generating package file <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/mlhdlc_sobel_fixpt_pkg.vhd')">mlhdlc_sobel_fixpt_pkg.vhd</a>.
### Generating Resource Utilization Report <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/resource_report.html')">resource_report.html</a>.
### Generating Optimization report
### To rerun codegen evaluate the following commands...
---------------------
cgi = load('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/codegen_info.mat');
cfg = cgi.CodeGenInfo.codegenSettings;
fxpCfg = cgi.CodeGenInfo.fxpCfg;
codegen -float2fixed fxpCfg -config cfg -report
---------------------
### Generating HDL Conformance Report <a href="matlab:web('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sobel/hdlsrc/mlhdlc_sobel_fixpt_hdl_conformance_report.html')">mlhdlc_sobel_fixpt_hdl_conformance_report.html</a>.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
### Code generation successful: To view the report, open('codegen/mlhdlc_sobel/hdlsrc/html/report.mldatx')
===================================================
Design Name: <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/mlhdlc_sysobj_sobel.m')">mlhdlc_sysobj_sobel</a>
Test Bench Name: <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/mlhdlc_sysobj_sobel_tb.m')">mlhdlc_sysobj_sobel_tb</a>
===================================================
Input types not specified for design(s) 'mlhdlc_sysobj_sobel', inferring types by simulating the first test bench: 'mlhdlc_sysobj_sobel_tb' in the base workspace.
============= Step1: Analyze Floating-Point Code ==============
Code generation successful.
============= Step1a: Verify Floating-Point Code ==============
### Analyzing the design 'mlhdlc_sysobj_sobel'
### Analyzing the test bench(es) 'mlhdlc_sysobj_sobel_tb'
### Begin Floating-Point Simulation (Instrumented)
### Floating-Point Simulation Completed in 1.9078 sec(s)
### Elapsed Time: 2.6390 sec(s)
============= Step2: Propose Types Based on Range Information ==============
============= Step3: Generate Fixed-Point Code ==============
### Generating Fixed-Point MATLAB Code <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/fixpt/mlhdlc_sysobj_sobel_fixpt.m')">mlhdlc_sysobj_sobel_fixpt</a> Using Proposed Types
### Generating Fixed-Point MATLAB Design Wrapper <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/fixpt/mlhdlc_sysobj_sobel_wrapper_fixpt.m')">mlhdlc_sysobj_sobel_wrapper_fixpt</a>
### Generating Mex file for ' mlhdlc_sysobj_sobel_wrapper_fixpt '
Code generation successful: <a href="matlab: emlcprivate('emcOpenReport','/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/fixpt/reports/mlhdlc_sysobj_sobel_wrapper_fixpt_mex/html/report.mldatx');">View report</a>
### Generating Type Proposal Report for 'mlhdlc_sysobj_sobel' <a href="matlab:web('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/fixpt/mlhdlc_sysobj_sobel_report.html', '-new')">mlhdlc_sysobj_sobel_report.html</a>
===================================================
Code generation successful.
### Begin MATLAB to HDL Code Generation...
### Working on DUT: mlhdlc_sysobj_sobel_fixpt.
### Using TestBench: mlhdlc_sysobj_sobel_tb.
### Begin VHDL Code Generation
### Working on mlhdlc_sysobj_sobel_fixpt/SimpleDualPortRAM_generic as <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/hdlsrc/SimpleDualPortRAM_generic.vhd')">SimpleDualPortRAM_generic.vhd</a>.
### Working on mlhdlc_sysobj_sobel_fixpt as <a href="matlab:edit('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/hdlsrc/mlhdlc_sysobj_sobel_fixpt.vhd')">mlhdlc_sysobj_sobel_fixpt.vhd</a>.
### Generating Resource Utilization Report <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/hdlsrc/resource_report.html')">resource_report.html</a>.
### Generating Optimization report
### To rerun codegen evaluate the following commands...
---------------------
cgi = load('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/hdlsrc/codegen_info.mat');
cfg = cgi.CodeGenInfo.codegenSettings;
fxpCfg = cgi.CodeGenInfo.fxpCfg;
codegen -float2fixed fxpCfg -config cfg -report
---------------------
### Generating HDL Conformance Report <a href="matlab:web('/tmp/Bdoc26b_3351752_3479428/tp06870610/hdlcoder-ex49439323/codegen/mlhdlc_sysobj_sobel/hdlsrc/mlhdlc_sysobj_sobel_fixpt_hdl_conformance_report.html')">mlhdlc_sysobj_sobel_fixpt_hdl_conformance_report.html</a>.
### HDL Conformance check complete with 0 errors, 0 warnings, and 0 messages.
### Code generation successful: To view the report, open('codegen/mlhdlc_sysobj_sobel/hdlsrc/html/report.mldatx')




Compare the Delay Implementations in the Generated Code
After code generation completes, in the Command Window, click the resource_report.html link for mlhdlc_sobel to open its HDL Resource Utilization Report window.
For the mlhdlc_sobel function, the code generator produces two RAM instances, one for each line_buffer function. Each RAM is 128 by 14 bits, which corresponds to a power-of-two implementation of the 80-pixel circular line buffer that stores the 14-bit pixel data.
Then click the resource_report.html link for mlhdlc_sysobj_sobel. In this function, the code generator merges the two dsp.Delay line buffers into a single RAM-based shift register that is 128 by 16 bits. The dsp.Delay System object does not require duplicate functions for each delay, which simplifies the source code while achieving similar hardware resources.
See Also
dsp.Delay (DSP System Toolbox) | hdl.Delay