Using the State Control block to generate more efficient code with HDL Coder™

This example shows how to use the State Control block to generate hardware-friendly HDL code using HDL Coder.

Introduction to the State Control block

The State Control block is a block that modifies the Simulink simulation behavior for its containing subsystem and all subsystems nested beneath it. Its purpose is to more closely model the synchronous behavior of clocked digital hardware, particularly with respect to blocks that have state and use explicit enable and reset signals.

When a State Control block is placed in a subsystem and has its parameter set to ''Synchronous'', the generated HDL code will be more hardware friendly. When a subsystem is in Synchronous mode it is marked with a graphic ''S'' in its lower left corner. A State Control block with its parameter set to ''Classic'' behaves identically to when there is no State Control block in the subsystem.

The simulation behavior difference between the two modes is small, but significant to generating efficient HDL code. The differences focus around the simulation behavior involving explicit reset and enable signals. For example, in Synchronous mode, the explict block reset input has priority over the block enable input signal.

Classic mode behavior for Delay with explicit enable input port

HDL code generated by HDL Coder simulates identically to the model that it is generated from. In Classic State Control mode, the generated code for certain constructs implements sub-optimal hardware due to this requirement. For example, a Delay block with explicit enable input will generate a bypass register, comprised of a register and a mulitplexer, in addition to the modeled register, to capture the Simulink Classic mode behavior.

Examine the contents of Enabled_Delay.vhd to observe the additional register signals and the bypass register.

load_system('hdlcoder_statecontrol_model');
open_system('hdlcoder_statecontrol_model');
set_param('hdlcoder_statecontrol_model', 'SimulationCommand', 'update');
makehdl('hdlcoder_statecontrol_model/MAC FIR Block', 'TargetDirectory', 'hdlsrc_classic');
### Generating HDL for 'hdlcoder_statecontrol_model/MAC FIR Block'.
### Starting HDL check.
### Begin VHDL Code Generation for 'hdlcoder_statecontrol_model'.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/Coeff ROM as hdlsrc_classic/hdlcoder_statecontrol_model/Coeff_ROM.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/Enabled_Delay as hdlsrc_classic/hdlcoder_statecontrol_model/Enabled_Delay.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line/circular buffer logic as hdlsrc_classic/hdlcoder_statecontrol_model/circular_buffer_logic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line/SimpDualPortRAM_Wrapper_generic/SimpleDualPortRAM_generic as hdlsrc_classic/hdlcoder_statecontrol_model/SimpleDualPortRAM_generic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line/SimpDualPortRAM_Wrapper_generic as hdlsrc_classic/hdlcoder_statecontrol_model/SimpDualPortRAM_Wrapper_generic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line as hdlsrc_classic/hdlcoder_statecontrol_model/RAM_delay_line.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block/Switch/Set Complexity as hdlsrc_classic/hdlcoder_statecontrol_model/Set_Complexity.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block as hdlsrc_classic/hdlcoder_statecontrol_model/MAC_FIR_Block.vhd.
### Generating package file hdlsrc_classic/hdlcoder_statecontrol_model/MAC_FIR_Block_pkg.vhd.
### Creating HDL Code Generation Check Report file:///tmp/BR2016bd_418663_21018/publish_examples3/tpad7ded80_4423_490b_af84_8dadc224750c/hdlsrc_classic/hdlcoder_statecontrol_model/MAC_FIR_Block_report.html
### HDL check for 'hdlcoder_statecontrol_model' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

type hdlsrc_classic/hdlcoder_statecontrol_model/Enabled_Delay.vhd
-- -------------------------------------------------------------
-- 
-- File Name: hdlsrc_classic/hdlcoder_statecontrol_model/Enabled_Delay.vhd
-- Created: 2016-07-23 11:40:44
-- 
-- Generated by MATLAB 9.1 and HDL Coder 3.9
-- 
-- -------------------------------------------------------------


-- -------------------------------------------------------------
-- 
-- Module: Enabled_Delay
-- Source Path: hdlcoder_statecontrol_model/MAC FIR Block/Enabled_Delay
-- Hierarchy Level: 1
-- 
-- -------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;

ENTITY Enabled_Delay IS
  PORT( clk                               :   IN    std_logic;
        reset                             :   IN    std_logic;
        enb                               :   IN    std_logic;
        din_re                            :   IN    std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        din_im                            :   IN    std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        LocalEnable                       :   IN    std_logic;
        Out1_re                           :   OUT   std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        Out1_im                           :   OUT   std_logic_vector(33 DOWNTO 0)  -- sfix34_En31
        );
END Enabled_Delay;


ARCHITECTURE rtl OF Enabled_Delay IS

  -- Signals
  SIGNAL din_re_signed                    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL din_im_signed                    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL Enabled_Delay_bypass_delay_re    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL Enabled_Delay_bypass_delay_im    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL Enabled_Delay_reg_re             : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL Enabled_Delay_reg_im             : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL dout_re                          : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL dout_im                          : signed(33 DOWNTO 0);  -- sfix34_En31

BEGIN
  din_re_signed <= signed(din_re);

  din_im_signed <= signed(din_im);

  Enabled_Delay_1_process : PROCESS (clk, reset)
  BEGIN
    IF reset = '1' THEN
      Enabled_Delay_bypass_delay_re <= to_signed(0, 34);
      Enabled_Delay_bypass_delay_im <= to_signed(0, 34);
      Enabled_Delay_reg_re <= to_signed(0, 34);
      Enabled_Delay_reg_im <= to_signed(0, 34);
    ELSIF clk'EVENT AND clk = '1' THEN
      IF enb = '1' AND LocalEnable = '1' THEN
        Enabled_Delay_bypass_delay_im <= Enabled_Delay_reg_im;
        Enabled_Delay_reg_im <= din_im_signed;
        Enabled_Delay_bypass_delay_re <= Enabled_Delay_reg_re;
        Enabled_Delay_reg_re <= din_re_signed;
      END IF;
    END IF;
  END PROCESS Enabled_Delay_1_process;

  
  dout_re <= Enabled_Delay_reg_re WHEN LocalEnable = '1' ELSE
      Enabled_Delay_bypass_delay_re;
  
  dout_im <= Enabled_Delay_reg_im WHEN LocalEnable = '1' ELSE
      Enabled_Delay_bypass_delay_im;

  Out1_re <= std_logic_vector(dout_re);

  Out1_im <= std_logic_vector(dout_im);

END rtl;

Synchronous mode behavior for Delay with explicit enable input port

A Delay block with explict enable in Synchronous State Control mode will generate HDL code that creates more efficient hardware. The implementation does not contain a bypass register.

Examine Enabled_Delay_Sync.vhd and note the improvement in the generated code as compared to the Classic mode output.

makehdl('hdlcoder_statecontrol_model/MAC FIR Block Sync', 'TargetDirectory', 'hdlsrc_sync');
### Generating HDL for 'hdlcoder_statecontrol_model/MAC FIR Block Sync'.
### Starting HDL check.
### Begin VHDL Code Generation for 'hdlcoder_statecontrol_model'.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/Coeff ROM as hdlsrc_sync/hdlcoder_statecontrol_model/Coeff_ROM.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/Enabled Delay Sync as hdlsrc_sync/hdlcoder_statecontrol_model/Enabled_Delay_Sync.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/circular buffer logic as hdlsrc_sync/hdlcoder_statecontrol_model/circular_buffer_logic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/write enable logic as hdlsrc_sync/hdlcoder_statecontrol_model/write_enable_logic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/SimpDualPortRAM_Wrapper_generic/SimpleDualPortRAM_generic as hdlsrc_sync/hdlcoder_statecontrol_model/SimpleDualPortRAM_generic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/SimpDualPortRAM_Wrapper_generic as hdlsrc_sync/hdlcoder_statecontrol_model/SimpDualPortRAM_Wrapper_generic.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line as hdlsrc_sync/hdlcoder_statecontrol_model/RAM_delay_line.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync/Switch/Set Complexity as hdlsrc_sync/hdlcoder_statecontrol_model/Set_Complexity.vhd.
### Working on hdlcoder_statecontrol_model/MAC FIR Block Sync as hdlsrc_sync/hdlcoder_statecontrol_model/MAC_FIR_Block_Sync.vhd.
### Generating package file hdlsrc_sync/hdlcoder_statecontrol_model/MAC_FIR_Block_Sync_pkg.vhd.
### Creating HDL Code Generation Check Report file:///tmp/BR2016bd_418663_21018/publish_examples3/tpad7ded80_4423_490b_af84_8dadc224750c/hdlsrc_sync/hdlcoder_statecontrol_model/MAC_FIR_Block_Sync_report.html
### HDL check for 'hdlcoder_statecontrol_model' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.
type hdlsrc_sync/hdlcoder_statecontrol_model/Enabled_Delay_Sync.vhd
-- -------------------------------------------------------------
-- 
-- File Name: hdlsrc_sync/hdlcoder_statecontrol_model/Enabled_Delay_Sync.vhd
-- Created: 2016-07-23 11:41:22
-- 
-- Generated by MATLAB 9.1 and HDL Coder 3.9
-- 
-- -------------------------------------------------------------


-- -------------------------------------------------------------
-- 
-- Module: Enabled_Delay_Sync
-- Source Path: hdlcoder_statecontrol_model/MAC FIR Block Sync/Enabled Delay Sync
-- Hierarchy Level: 1
-- 
-- -------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;

ENTITY Enabled_Delay_Sync IS
  PORT( clk                               :   IN    std_logic;
        reset                             :   IN    std_logic;
        enb                               :   IN    std_logic;
        din_re                            :   IN    std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        din_im                            :   IN    std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        LocalEnable                       :   IN    std_logic;
        Out1_re                           :   OUT   std_logic_vector(33 DOWNTO 0);  -- sfix34_En31
        Out1_im                           :   OUT   std_logic_vector(33 DOWNTO 0)  -- sfix34_En31
        );
END Enabled_Delay_Sync;


ARCHITECTURE rtl OF Enabled_Delay_Sync IS

  -- Signals
  SIGNAL din_re_signed                    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL din_im_signed                    : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL dout_re                          : signed(33 DOWNTO 0);  -- sfix34_En31
  SIGNAL dout_im                          : signed(33 DOWNTO 0);  -- sfix34_En31

BEGIN
  din_re_signed <= signed(din_re);

  din_im_signed <= signed(din_im);

  Enabled_Delay_process : PROCESS (clk, reset)
  BEGIN
    IF reset = '1' THEN
      dout_re <= to_signed(0, 34);
      dout_im <= to_signed(0, 34);
    ELSIF clk'EVENT AND clk = '1' THEN
      IF enb = '1' AND LocalEnable = '1' THEN
        dout_re <= din_re_signed;
        dout_im <= din_im_signed;
      END IF;
    END IF;
  END PROCESS Enabled_Delay_process;


  Out1_re <= std_logic_vector(dout_re);

  Out1_im <= std_logic_vector(dout_im);

END rtl;

Enabled Subsystems

When a model has an Enabled subsystem in Synchronous mode, the code generated for it will also be improved. A Synchronous mode Enabled subsystem will no longer generate bypass registers on the subsystem outputs. In addition, any registers inside the Enabled subsystem that have explicit enable inputs will also show the same improvements as discussed previously.

MATLAB Function Blocks and Synchronous Mode

MATLAB Function Blocks require more precise configuration in order to be used in Synchronous mode. The block outputs must either be all fully combinatorial, with no persistent variables, or they all must be driven from persistent variables, with no direct feedthrough paths from block input to output.

The Classic mode MATLAB code in this example has both direct feedthrough and registered paths through the code. The output wr_en is generated using direct feedthrough from inputs valid and count. The other two block outputs wr_addr and rd_addr are driven by values stored in the persistent variables newest_loc and rd_addr_reg, respectively.

For more information on configuring blocks so they conform with Synchronous mode, please refer to the documentation.

open_system('hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line')
open_system('hdlcoder_statecontrol_model/MAC FIR Block/RAM delay line/circular buffer logic')

To generate code from this block in Synchronous mode the two sets of outputs must be separated into two MATLAB Function Blocks; one for the purely combinatorial code and one for the state-based code.

open_system('hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line')
open_system('hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/circular buffer logic')
open_system('hdlcoder_statecontrol_model/MAC FIR Block Sync/RAM delay line/write enable logic')

The Edit data menu pick on the MATLAB toolstrip opens the MATLAB Function block Ports and Data Manager. The state-based block must be marked as not allowing direct feedthrough.

For additional information

To learn more about the State Control block, please refer to the block documentation.

Was this topic helpful?