Products & Services Solutions Academia Support User Community Company

Learn more about Filter Design HDL Coder   

Customizing the HDL Code

Specifying a Header Comment

The coder includes a header comment block, such as the following, at the top of the files it generates:

-- -------------------------------------------------------------
--
-- Module: filter_tb_pkg
--
-- Generated by MATLAB(R) 7.9 and the Filter Design HDL Coder 2.5.
--
-- Generated on: 2009-05-11 15:34:30
-- -------------------------------------------------------------

You can use the Comment in header option to add a comment string, to the end of the header comment block in each generated file. For example, you might use this option to add the commentThis module was automatically generated.. With this change, the preceding header comment block would appear as follows:

-- -------------------------------------------------------------
--
-- Module: filter_tb_pkg
--
-- Generated by MATLAB(R) 7.9 and the Filter Design HDL Coder 2.5.
--
-- Generated on: 2009-05-11 15:34:30
--
-- This module was automatically generated.
--
-- -------------------------------------------------------------

To add a header comment,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Type the comment string in the Comment in header field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property UserComment to add a comment string to the end of the header comment block in each generated HDL file.

Specifying a Prefix for Filter Coefficients

The coder declares a filter's coefficients as constants within an rtl architecture. The coder derives the constant names adding the prefix coeff to the following:

For...The Prefix Is Concatenated with...
FIR filters

Each coefficient number, starting with 1.

Examples: coeff1, coeff22

IIR filters

An underscore (_) and an a or b coefficient name (for example, _a2, _b1, or _b2) followed by the string _sectionn, where n is the section number.

Example: coeff_b1_section3 (first numerator coefficient of the third section)

For example:

ARCHITECTURE rtl OF Hd IS
  -- Type Definitions
  TYPE delay_pipeline_type IS ARRAY(NATURAL range <>) OF signed(15 DOWNTO 0);-- sfix16_En15
  CONSTANT coeff1               : signed(15 DOWNTO 0) := to_signed(-30, 16); -- sfix16_En15
  CONSTANT coeff2               : signed(15 DOWNTO 0) := to_signed(-89, 16); -- sfix16_En15
  CONSTANT coeff3               : signed(15 DOWNTO 0) := to_signed(-81, 16); -- sfix16_En15
  CONSTANT coeff4               : signed(15 DOWNTO 0) := to_signed(120, 16); -- sfix16_En15

To use a prefix other than coeff,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Coefficient prefix field, as shown in the following figure.

    The string that you specify

    • Must start with a letter

    • Cannot end with an underscore (_)

    • Cannot include a double underscore (__)

      Note   If you specify a VHDL or Verilog reserved word, the coder appends a reserved word postfix to the string to form a valid identifier. If you specify a prefix that ends with an underscore, the coder replaces the underscore character with under. For example, if you specify coef_, the coder generates coefficient names such as coefunder1.

Command Line Alternative: Use the generatehdl and generatetb functions with the property CoeffPrefix to change the base name for filter coefficients.

Setting the Postfix String for Resolving Entity or Module Name Conflicts

The coder checks whether multiple entities in VHDL or multiple modules in Verilog share the same name. If a name conflict exists, the coder appends the postfix _block to the second of the two matching strings.

To change the postfix string:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Entity conflict postfix field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property EntityConflictPostfix to change the entity or module conflict postfix string.

Setting the Postfix String for Resolving HDL Reserved Word Conflicts

The coder checks whether any strings that you specify as names, postfix values, or labels are VHDL or Verilog reserved words. See Reserved Word Tables for listings of all VHDL and Verilog reserved words.

If you specify a reserved word, the coder appends the postfix _rsvd to the string. For example, if you try to name your filter mod, for VHDL code, the coder adds the postfix _rsvd to form the name mod_rsvd.

To change the postfix string:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Reserved word postfix field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property ReservedWordPostfix to change the reserved word postfix string.

Reserved Word Tables

The following tables list all VHDL and Verilog reserved words.

VHDL Reserved Words

absaccessafteraliasall
andarchitecturearray assertattribute
beginblockbodybufferbus
casecomponentconfiguration constantdisconnect
downtoelseelsifendentity
exitfileforfunctiongenerate
genericgroupguardedifimpure
ininertialinoutislabel
librarylinkageliteralloopmap
modnandnewnextnor
notnullofonopen
orothersoutpackageport
postponedprocedureprocesspurerange
recordregisterrejectremreport
returnrolrorselectseverity
signalsharedslasllsra
srlsubtypethen totransport
typeunaffectedunitsuntiluse
variablewaitwhenwhilewith
xnorxor   

Verilog Reserved Words

alwaysandassignautomaticbegin
bufbufif0bufif1casecasex
casezcellcmosconfigdeassign
defaultdefparamdesigndisableedge
elseendendcaseendconfigendfunction
endgenerateendmoduleendprimitiveendspecifyendtable
endtaskeventforforceforever
forkfunctiongenerategenvarhighz0
highz1ififnoneincdirinclude
initialinoutinputinstanceinteger
joinlargeliblistlibrarylocalparam
macromodulemediummodulenandnegedge
nmosnornoshowcancellednotnotif0
notif1oroutputparameterpmos
posedgeprimitivepull0pull1pulldown
pulluppulsestyle_oneventpulsestyle_ondetectrcmosreal
realtimeregreleaserepeatrnmos
rpmosrtranrtranif0rtranif1scalared
showcancelledsignedsmallspecifyspecparam
strong0strong1supply0supply1table
tasktimetrantranif0tranif1
tritri0tri1triandtrior
triregunsignedusevectoredwait
wandweak0weak1whilewire
worxnorxor

Setting the Postfix String for Process Block Labels

The coder generates process blocks to modify the content of a filter's registers. The label for each of these blocks is derived from a register name and the postfix _process. For example, the coder derives the label delay_pipeline_process in the following block from the register name delay_pipeline and the postfix string _process.

delay_pipeline_process : PROCESS (clk, reset)
BEGIN
  IF reset = '1' THEN
    delay_pipeline (0 To 50) <= (OTHERS => (OTHERS => '0'));
  ELSIF clk'event AND clk = '1' THEN
    IF clk_enable = '1' THEN
      delay_pipeline(0) <= signed(filter_in)
      delay_pipeline(1 TO 50) <= delay_pipeline(0 TO 49);
    END IF;
  END IF;
END PROCESS delay_pipeline_process;

You can of set the postfix string to a value other than _process. For example, you might change it to _clkproc. To change the string,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Clocked process postfix field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property ClockProcessPostfix to change the postfix string appended to process labels.

Setting a Prefix for Component Instance Names

Instance prefix specifies a string to be prefixed to component instance names in generated code. The default string is u_.

You can of set the postfix string to a value other than u_. To change the string:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Instance prefix field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property InstancePrefix to change the instance prefix string.

Setting a Prefix for Vector Names

Vector prefix specifies a string to be prefixed to vector names in generated VHDL code. The default string is vector_of_.

You can set the prefix string to a value other than vector_of_. To change the string:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the General tab in the Additional settings pane.

  3. Enter a new string in the Vector prefix field, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property VectorPrefixto change the instance prefix string.

Naming HDL Ports

The default names for filter HDL ports are as follows:

HDL PortDefault Port Name
Input portfilter_in
Output portfilter_out
Clock portclk
Clock enable portclk_enable
Reset portreset
Fractional delay port (Farrow filters only)filter_fd

For example, the default VHDL declaration for entity Hd looks like the following.

ENTITYHd IS
   PORT( clk               :     IN    std_logic;
         clk_enable        :     IN    std_logic;
         reset             :     IN    std_logic;
         filter_in         :     IN    std_logic_vector (15 DOWNTO 0); -- sfix16_En15
         filter_out        :     OUT   std_logic_vector (15 DOWNTO 0); -- sfix16_En15
         );
ENDHd;

To change any of the port names,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Ports tab in the Additional settings pane. The following figure highlights the port name fields for Input port, Output port, Clock input port, Reset input port, and Clock enable output port.

  3. Enter new strings in the port name fields, as necessary

Command Line Alternative: Use the generatehdl and generatetb functions with the properties InputPort, OutputPort, ClockInputPort, ClockEnableInputPort, and ResetInputPort to change the names of a filter's VHDL ports.

Specifying the HDL Data Type for Data Ports

By default, filter input and output data ports have data type std_logic_vector in VHDL and type wire in Verilog. If you are generating VHDL code, alternatively, you can specify signed/unsigned, and for output data ports, Same as input data type. The coder applies type SIGNED or UNSIGNED based on the data type specified in the filter design.

To change the VHDL data type setting for the input and output data ports,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Ports tab in the Additional settings pane.

  3. Select a data type from the Input data type or Output data type menu identified in the following figure.

    By default, the output data type is the same as the input data type.

    The type for Verilog ports is always wire, and cannot be changed.

      Note   The setting of Input data type does not affect double-precision input, which is always generated as type REAL for VHDL and wire[63:0] for Verilog.

Command Line Alternative: Use the generatehdl and generatetb functions with the properties InputType and OutputType to change the VHDL data type for a filter's input and output ports.

Suppressing Extra Input and Output Registers

The coder adds an extra input register (input_register) and an extra output register (output_register) during HDL code generation. These extra registers can be useful for timing purposes, but they add to the filter's overall latency. The following process block writes to extra output register output_register when a clock event occurs and clk is active high (1):

Output_Register_Process : PROCESS (clk, reset)
BEGIN
  IF reset = '1' THEN
    output_register <= (OTHERS => '0');
  ELSIF clk'event AND clk = '1' THEN
    IF clk_enable = '1' THEN
      output_register <= output_typeconvert;
    END IF;
  END IF;
END PROCESS Output_Register_Process;

If overall latency is a concern for your application and you have no timing requirements, you can suppress generation of the extra registers as follows:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Ports tab in the Additional settings pane.

  3. Clear Add input register and Add output register as required. The following figure shows the setting for suppressing the generation of an extra input register.

Command Line Alternative: Use the generatehdl and generatetb functions with the properties AddInputRegister and AddOutputRegister to add an extra input or output register.

Representing Constants with Aggregates

By default, the coder represents constants as scalars or aggregates depending on the size and type of the data. The coder represents values that are less than 232 – 1 as integers and values greater than or equal to 232 – 1 as aggregates. The following VHDL constant declarations are examples of declarations generated by default for values less than 32 bits:

CONSTANT coeff1: signed(15 DOWNTO 0) := to_signed(-60, 16); -- sfix16_En16
CONSTANT coeff2: signed(15 DOWNTO 0) := to_signed(-178, 16); -- sfix16_En16

If you prefer that all constant values be represented as aggregates, set the Represent constant values by aggregates as follows:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab.

  3. Select Represent constant values by aggregates, as shown the following figure.

The preceding constant declarations would now appear as follows:

CONSTANT coeff1: signed(15 DOWNTO 0) := (5 DOWNTO 3 => '0',1 DOWNTO 0 => '0,OTHERS =>'1');
CONSTANT coeff2: signed(15 DOWNTO 0) := (7 => '0',5 DOWNTO 4 => '0',0 => '0',OTHERS =>'1');

Command Line Alternative: Use the generatehdl and generatetb functions with the property UseAggregatesForConst to represent all constants in the HDL code as aggregates.

Unrolling and Removing VHDL Loops

By default, the coder supports VHDL loops. However, some EDA tools do not support them. If you are using such a tool along with VHDL, you might need to unroll and remove FOR and GENERATE loops from your filter's generated VHDL code. Verilog code is always unrolled.

To unroll and remove FOR and GENERATE loops,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Select Loop unrolling, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property LoopUnrolling to unroll and remove loops from generated VHDL code.

Using the VHDL rising_edge Function

The coder can generate two styles of VHDL code for checking for rising edges when the filter operates on registers. By default, the generated code checks for a clock event, as shown in the ELSIF statement of the following VHDL process block.

Delay_Pipeline_Process : PROCESS (clk, reset)
BEGIN
  IF reset = '1' THEN
    delay_pipeline(0 TO 50) <= (OTHERS => (OTHERS => '0'));
  ELSEIF clk'event AND clk = '1' THEN
    IF clk_enable = '1' THEN
      delay_pipeline(0) <= signed(filter_in);
		delay_pipeline(1 TO 50) <= delay_pipeline(0 TO 49);
    END IF;
  END IF;
END PROCESS Delay_Pipeline_Process ;

If you prefer, the coder can produce VHDL code that applies the VHDL rising_edge function instead. For example, the ELSIF statement in the preceding process block would be replaced with the following statement:

  ELSIF rising_edge(clk) THEN

To use the rising_edge function,

  1. Click Global Settings in the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Select Use 'rising_edge' for registers, as shown in the following dialog box.

Command Line Alternative: Use the generatehdl and generatetb functions with the property UseRisingEdge to use the VHDL rising_edge function to check for rising edges during register operations.

Suppressing the Generation of VHDL Inline Configurations

VHDL configurations can be either inline with the rest of the VHDL code for an entity or external in separate VHDL source files. By default, the coder includes configurations for a filter within the generated VHDL code. If you are creating your own VHDL configuration files, you should suppress the generation of inline configurations.

To suppress the generation of inline configurations,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Clear Inline VHDL configuration, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property InlineConfigurations to suppress the generation of inline configurations.

Specifying VHDL Syntax for Concatenated Zeros

In VHDL, the concatenation of zeros can be represented in two syntax forms. One form, '0' & '0', is type safe. This is the default. The alternative syntax, "000000...", can be easier to read and is more compact, but can lead to ambiguous types.

To use the syntax "000000..." for concatenated zeros,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Clear Concatenate type safe zeros, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property SafeZeroConcat to use the syntax "000000...", for concatenated zeros.

Suppressing Verilog Time Scale Directives

In Verilog, the coder generates time scale directives (ˋtimescale) , as appropriate, by default. This compiler directive provides a way of specifying different delay values for multiple modules in a Verilog file.

To suppress the use of ˋtimescale directives,

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Clear Use Verilog ˋtimescale directives, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property UseVerilogTimescale to suppress the use of time scale directives.

Specifying Input Type Treatment for Addition and Subtraction Operations

By default, generated HDL code operates on input data using data types as specified by the filter design, and then converts the result to the specified result type.

Typical DSP processors type cast input data to the result type before operating on the data. Depending on the operation, the results can be very different. If you want generated HDL code to handle result typing in this way, use the Cast before sum option as follows:

  1. Select the Global Settings tab on the Generate HDL dialog box.

  2. Select the Advanced tab. The Advanced pane appears.

  3. Select Cast before sum, as shown in the following figure.

Command Line Alternative: Use the generatehdl and generatetb functions with the property CastBeforeSum to cast input values to the result type for addition and subtraction operations.

Relationship Between Cast Before Sum and Cast Before Accum.

The Cast before sum property is related to the FDATool setting for the quantization property Cast signals before accum. as follows:

Using Complex Data and Coefficients

The coder supports use of complex coefficients and complex input signals for fully parallel FIR, CIC, and some other filter structures. In many cases, you can use complex data and complex coefficients in combination. The following table shows the filter structures that support complex data and/or coefficients, and the permitted combinations.

Filter StructureComplex
Data
Complex
Coefficients
Both Complex Data
and Coefficients
dfilt.dffirYYY
dfilt.dfsymfirYYY
dfilt.dfasymfirYYY
dfilt.dffirtYYY
dfilt.scalarYYY
dfilt.delayYN/AN/A
mfilt.cicdecimYN/AN/A
mfilt.cicinterpYN/AN/A
mfilt.firdecimYYY
mfilt.firinterpYYY
mfilt.firsrcYYY
mfilt.firtdecimYYY
mfilt.linearinterpYN/AN/A
mfilt.holdinterpYYN/A
dfilt.df1sosYYY
dfilt.df1tsosYYY
dfilt.df2sosYYY
dfilt.df2tsosYYY

Enabling Code Generation for Complex Data

The option you choose from the Input complexity menu instructs the coder whether or not to generate the appropriate ports and signal paths for the real and imaginary components of a complex signal. The default setting for Input complexity is Real, disabling generation of ports for complex input data. To enable generation of ports for complex input data, set Input complexity to Complex.

The corresponding command line property is InputComplex. By default, InputComplex is set to 'off', disabling generation of ports for complex input data. To enable generation of ports for complex input data, set InputComplex to 'on', as in the following code example:

Hd = design(fdesign.lowpass,'equiripple','Filterstructure','dffir');
generatehdl(Hd, 'InputComplex', 'on');

The following VHDL code excerpt shows the entity definition generated by the preceding commands:

ENTITY Hd IS
   PORT( clk                             :   IN    std_logic; 
         clk_enable                      :   IN    std_logic; 
         reset                           :   IN    std_logic; 
         filter_in_re                    :   IN    real; -- double
         filter_in_im                    :   IN    real; -- double
         filter_out_re                   :   OUT   real; -- double
         filter_out_im                   :   OUT   real  -- double
         );

END Hd;

In the code excerpt, the port names generated for the real components of complex signals are identified by the default postfix string'_re', and port names generated for the imaginary components of complex signals are identified by the default postfix string '_im'.

Setting the Port Name Postfix for Complex Ports

Two code generation properties let you customize naming conventions for the real and imaginary components of complex signals in generated HDL code. These properties are:

Specifying Programmable Filter Coefficients for FIR Filters

By default, the coder obtains filter coefficients from a filter object and hard-codes them into the generated code. An HDL filter realization generated in this way cannot be used with a different set of coefficients.

For direct-form FIR filters, the coder provides GUI options and corresponding command-line properties that let you:

To use programmable coefficients, a port interface (referred to as a processor interface) is generated for the filter entity or module. Coefficient loading is assumed to be under the control of a microprocessor that is external to the generated filter. The filter uses the loaded coefficients for processing input samples.

If you choose one of the serial FIR filter architectures, you can also specify storage of programmable coefficients in your choice of RAM (dual-port or single-port) or register file ( See Using Programmable Coefficients with Serial FIR Filter Architectures).

Supported FIR Filter Types

Programmable filter coefficients are supported for the following direct-form FIR filter types:

Supported Parallel and Serial FIR Filter Architectures

Programmable filter coefficients are supported for the following FIR filter architectures:

If you choose one of the serial filter architectures, see Using Programmable Coefficients with Serial FIR Filter Architectures for special considerations that apply to these architectures.

Generating a Port Interface for Programmable FIR Coefficients

This section describes how to use the CoefficientSource property to specify that a processor interface for loading coefficients is generated. You can also use the Coefficient source list on the Generate HDL dialog box for this purpose.

The valid value strings for the property are:

When you specify 'ProcessorInterface', the generated entity or module definition for the filter includes the following port definitions:

Example.  In the following command-line example, a processor interface is generated in VHDL code for a direct-form symmetric FIR filter with fully parallel (default) architecture.

Hd = design(fdesign.lowpass, 'equiripple', 'FilterStructure', 'dfsymfir');
generatehdl(Hd, 'CoefficientSource', 'ProcessorInterface');

The following listing shows the VHDL entity definition generated for the filter object Hd.

ENTITY Hd IS
   PORT( clk                   :   IN    std_logic; 
         clk_enable            :   IN    std_logic; 
         reset                 :   IN    std_logic; 
         filter_in             :   IN    real; -- double
         write_enable          :   IN    std_logic; 
         write_done            :   IN    std_logic; 
         write_address         :   IN    real; -- double
         coeffs_in             :   IN    real; -- double
         filter_out            :   OUT   real  -- double
         );

END Hd;

Generating a Test Bench for Programmable FIR Coefficients

This section describes how to use the TestbenchCoeffStimulus property to specify how the test bench drives the coefficient ports. You can also use the Coefficient stimulus option for this purpose.

When a coefficient memory interface has been generated for a filter, all coefficient ports have associated test vectors. The TestbenchCoeffStimulus property determines how the test bench drives the coefficient ports.

The TestBenchStimulus property determines the filter input stimuli, as with any filter.

The TestbenchCoeffStimulus property selects from two types of test benches. TestbenchCoeffStimulus takes a vector argument. The valid values are:

Example.  In the following example, a processor interface is generated for a direct-form symmetric FIR filter with fully parallel (default) architecture. The coefficients for the filter object are defined in the vector b. Test bench code is then generated, using a second set of coefficients defined in the vector c. Note that c is trimmed to the effective length of the filter.

b = [-0.01 0.1 0.8 0.1 -0.01];
c = [-0.03 0.5 0.7 0.5 -0.03];
c = c(1:ceil(length(c)/2));
hd = dfilt.dfsymfir(b);
generatehdl(hd, 'CoefficientSource', 'ProcessorInterface');
generatetb(hd,'VHDL', 'TestbenchCoeffStimulus', c);

GUI Options for Programmable Coefficients

The following GUI options let you specify programmable coefficients:

Using Programmable Coefficients with Serial FIR Filter Architectures

This section discusses special considerations for using programmable filter coefficients with FIR filters that have one of the following serial architectures:

Specifying Memory for Programmable Coefficients.  

By default, the processor interface for programmable coefficients loads the coefficients from a register file. The Coefficient memory pulldown menu lets you specify alternative RAM-based storage for programmable coefficients.

Coefficient memory displays for FIR filters, when both the following conditions are met:

The following figure shows the Coefficient memory options for a fully serial FIR filter.

The following table summarizes the Coefficient memory options.

Coefficient Memory Pulldown SelectionDescription
Registersdefault: Store programmable coefficients in a register file.
Single Port RAMs

Store programmable coefficients in single-port RAM.

The coder writes RAM interface code to one or more separate files, depending on the filter partitioning.

Dual Port RAMs

Store programmable coefficients in dual-port RAM.

The coder writes RAM interface code to one or more separate files, depending on the filter partitioning.

You can also use the CoefficientMemory command-line property to specify alternative RAM-based storage for programmable coefficients. The following table summarizes the options.

CoefficientMemory SettingDescription
'CoefficientMemory', 'Registers'default: Store programmable coefficients in a register file.
'CoefficientMemory', 'SinglePortRAMs'

Store programmable coefficients in single-port RAM.

The coder writes RAM interface code to one or more separate files, depending on the filter partitioning.

'CoefficientMemory', 'DualPortRAMs'

Store programmable coefficients in dual-port RAM.

The coder writes RAM interface code to one or more separate files, depending on the filter partitioning.

The commands in the following example create an asymmetric filter Hd, and generate VHDL code for the filter using a partly serial architecture, with a dual-port RAM interface for programmable coefficients.

coeffs = fir1(22,0.45);
Hd = dfilt.dfasymfir(coeffs);
Hd.arithmetic = 'fixed';
generatehdl(Hd,'SerialPartition',[7 4],'CoefficientSource',...
'ProcessorInterface','CoefficientMemory','DualPortRAMs');

Timing Considerations.  In a serial implementation for a FIR filter, the rate of the system clock (clk) is generally a multiple of the filter's input data rate (i.e., the nominal sample rate of the filter). The exact relationship between the clock rate and the filter's data rate is determined by the choice of serial architecture and partitioning.

Programmable coefficients load into the coeffs_in port at either the system clock rate (faster) or the input data (slower) rate. If your design requires loading of coefficients at the faster rate, observe the following points:

The next two code generation examples illustrate how serial partitioning affects the timing of coefficient loading. Both examples generate code for a filter Hd. Hd is an asymmetric filter that requires 11 coefficients. The following code creates the filter Hd:

 rand('state',13893);
 b = rand(1,23);
 Hd = dfilt.dfasymfir(b);
 Hd.Arithmetic='fixed';

The following command generates VHDL code for Hd, using a partly serial architecture with the serial partition [7 4]. CoefficientSource specifies that a processor interface is generated, with the default CoefficientStimulus.

generatehdl(Hd,'SerialPartition',[7 4],'CoefficientSource', 'ProcessorInterface');
...
### Clock rate is 7 times the input sample rate for this architecture.
### HDL latency is 2 samples

As reported by the coder, this partitioning results in a clock rate that is 7 times the input sample rate.

The following timing diagram illustrates the timing of coefficient loading relative to the timing of input data samples. While write_enable is asserted, 11 coefficient values are loaded, via coeffs_in, to 11 sequential memory addresses. On the next clk cycle, write_enable is deasserted and write_done is asserted for one clock period. The coefficient loading operation is completed within 2 cycles of data input, allowing 2 clk cycles to elapse before the arrival of the data value 07FFF. Therefore the newly loaded coefficients are applied to that data sample.

The following code generation example defines a serial partition of [6 5] for the same filter. This results in a slower clock rate, 6 times the input sample rate.

 generatehdl(Hd,'SerialPartition',[6 5],'CoefficientSource', 'ProcessorInterface');
...
### Clock rate is 6 times the input sample rate for this architecture.
### HDL latency is 2 samples

The following timing diagram illustrates that write_done deasserts too late for the coefficients to be applied to the arriving data value 278E. They are applied instead to the next sample, 7FFF.

Specifying Programmable Filter Coefficients for IIR Filters

By default, the coder obtains filter coefficients from a filter object and hard-codes them into the generated code. An HDL filter realization generated in this way cannot be used with a different set of coefficients.

For IIR filters, the coder provides GUI options and corresponding command-line properties that let you:

To use programmable coefficients, a port interface (referred to as a processor interface) is generated for the filter entity or module. Coefficient loading is assumed to be under the control of a microprocessor that is external to the generated filter. The filter uses the loaded coefficients for processing input samples.

For IIR filters, the current release supports programmable coefficients that are stored in a register file.

Supported IIR Filter Types

The following IIR filter types support programmable filter coefficients:

Generating a Port Interface for Programmable IIR Filter Coefficients

This section describes how to use the CoefficientSource property to specify that a processor interface for loading coefficients is generated. You can also use the Coefficient source menu on the Generate HDL dialog box for this purpose.

The valid value strings for the property are:

When you specify 'ProcessorInterface', the generated entity or module definition for the filter includes the following port definitions:

Example.  In the following command-line example, a processor interface is generated in VHDL code for an SOS IIR Direct Form II filter.

Fs = 48e3;             % Sampling frequency
Fc = 10.8e3;           % Cut-off frequency
N = 5;                 % Filter Order
f_lp = fdesign.lowpass('n,f3db',N,Fc,Fs);
Hd = design(f_lp,'butter','FilterStructure','df2sos');
Hd.arithmetic = 'fixed';
generatehdl(Hd, 'CoefficientSource', 'ProcessorInterface')

The following listing shows the VHDL entity definition generated for the filter object Hd.

ENTITY Hd IS
PORT( clk              :   IN    std_logic; 
      clk_enable       :   IN    std_logic; 
      reset            :   IN    std_logic; 
      filter_in        :   IN    std_logic_vector(15 DOWNTO 0); -- sfix16_En15
      write_enable     :   IN    std_logic; 
      write_done       :   IN    std_logic; 
      write_address    :   IN    std_logic_vector(4 DOWNTO 0); -- ufix5
      coeffs_in        :   IN    std_logic_vector(15 DOWNTO 0); -- sfix16
      filter_out       :   OUT   std_logic_vector(15 DOWNTO 0)  -- sfix16_En12
      );

END Hd;

Generating a Test Bench for Programmable IIR Coefficients

This section describes how to use the TestbenchCoeffStimulus property to specify how the test bench drives the coefficient ports. You can also use the Coefficient stimulus option for this purpose.

When a coefficient memory interface has been generated for a filter, all coefficient ports have associated test vectors. The TestbenchCoeffStimulus property determines how the test bench drives the coefficient ports.

The TestBenchStimulus property determines the filter input stimuli, as with any filter.

The TestbenchCoeffStimulus specified the source of coefficients used for the test bench. The valid values for TestbenchCoeffStimulus are:

Addressing Scheme for Loading IIR Coefficients

The following table gives the address generation scheme for the write_address port when loading IIR coefficients into memory. This addressing scheme allows all types of coefficients (scale values, numerator coefficients, and denominator coefficients) to be loaded via a single port (coeffs_in).

Note that all types of coefficients have the same word length, but may have different fractional lengths.

The address for each coefficient is divided into two fields:

The total width of the write_address port is therefore ceil(log2N) + 3bits.

Section AddressCoefficient Address Description
S S ... S000Section scale value
S S ... S001Numerator coefficient: b1
S S ... S011Numerator coefficient: b2
S S ... S100Numerator coefficient: b3
S S ... S101Denominator coefficient: a2
S S ... S110Denominator coefficient: a3 (if order = 2; otherwise unused)
S S ... S110Unused
0 0 ... 0111Last scale value

GUI Options for Programmable Coefficients

The following GUI options let you specify programmable coefficients:

  


Recommended Products

Includes the most popular MATLAB recorded presentations with Q&A sessions led by MATLAB experts.

 © 1984-2010- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS