Products & Services Solutions Academia Support User Community Company

Using Complex Signals

Introduction

This section describes Embedded MATLAB Function block support for complex data types for HDL code generation. See also the eml_hdl_design_patterns library for numerous examples showing HDL related applications of complex arithmetic in Embedded MATLAB Function blocks.

Declaring Complex Signals

The following Embedded MATLAB Function block code declares several local complex variables. x and y are declared by complex constant assignment; z is created using the using the complex() function.

function [x,y,z] = fcn

% create 8 bit complex constants
x = uint8(1 + 2i);
y = uint8(3 + 4j);
z = uint8(complex(5, 6));

The following code example shows VHDL code generated from the previous Embedded MATLAB Function block code.

ENTITY complex_decl IS
    PORT (
        clk : IN std_logic; 
        clk_enable : IN std_logic; 
        reset : IN std_logic;
        x_re : OUT std_logic_vector(7 DOWNTO 0);
        x_im : OUT std_logic_vector(7 DOWNTO 0);
        y_re : OUT std_logic_vector(7 DOWNTO 0);
        y_im : OUT std_logic_vector(7 DOWNTO 0);
        z_re : OUT std_logic_vector(7 DOWNTO 0);
        z_im : OUT std_logic_vector(7 DOWNTO 0));
END complex_decl;
 
 
ARCHITECTURE fsm_SFHDL OF complex_decl IS
 
BEGIN
    x_re <= std_logic_vector(to_unsigned(1, 8));
    x_im <= std_logic_vector(to_unsigned(2, 8));
    y_re <= std_logic_vector(to_unsigned(3, 8));
    y_im <= std_logic_vector(to_unsigned(4, 8));
    z_re <= std_logic_vector(to_unsigned(5, 8));
    z_im <= std_logic_vector(to_unsigned(6, 8));
END fsm_SFHDL;

As shown in the example, all complex inputs, outputs and local variables declared in Embedded MATLAB code expand into real and imaginary signals. The naming conventions for these derived signals are:

A complex variable declared in an Embedded MATLAB Function block remains complex during the entire length of the program, following Embedded MATLAB Function block language rules.

Conversion Between Complex and Real Signals

The Embedded MATLAB Function block provides access to the fields of a complex signal via the real() and imag() functions, as shown in the following code.

function [Re_part, Im_part]= fcn(c)
% Output real and imaginary parts of complex input signal
 
Re_part = real(c);
Im_part = imag(c);

The coder supports these constructs, accessing the corresponding real and imaginary signal components in generated HDL code. In the following Verilog code example, the Embedded MATLAB Function block complex signal variable c is flattened into the signals c_re and c_im. Each of these signals is assigned to the output variables Re_part and Im_part, respectively.

module Complex_To_Real_Imag (clk, clk_enable, reset, c_re, c_im, Re_part, Im_part );

    input clk;
    input clk_enable;
    input reset;
    input [3:0] c_re;
    input [3:0] c_im;
    output [3:0] Re_part;
    output [3:0] Im_part;

    // Output real and imaginary parts of complex input signal
    assign Re_part = c_re;
    assign Im_part = c_im;

Arithmetic Operations on Complex Numbers

When generating HDL code for the Embedded MATLAB Function Block, the coder supports the following arithmetic operators for complex numbers composed of all base types (integer, fixed-point, double):

The coder supports division only for the Fixed-Point Toolbox divide function (see divide in the Fixed-Point Toolbox documentation). The divide function is supported only if the base type of both complex operands is fixed-point.

As shown in the following example, the default sum and product mode for fixed-point objects is FullPrecsion, and the CastBeforeSum property defaults to true.

fm = hdlfimath
 
fm =
 

             RoundMode: floor
          OverflowMode: wrap
           ProductMode: FullPrecision
  MaxProductWordLength: 128
               SumMode: FullPrecision
      MaxSumWordLength: 128
         CastBeforeSum: true

Given fixed-point operands, the coder follows full-precision cast before sum semantics. Each addition or subtraction increases the result width by one bit. Further casting is necessary to bring the results back to a smaller bit width.

In the following example function, two complex operands (with real and imaginary ufix4 components) are summed, with a complex result having real and imaginary ufix5 components. The result is then cast back to the original bit width.

function z = fcn(x, y)
% addition of two complex numbers x,y of type 'ufix4'
 
% x+y will have'ufix5' type
z = x+y;
 
% to cast the result back to 'ufix4'
% z = fi(x + y, numerictype(x), fimath(x));

The following example shows VHDL code generated from this function.

ENTITY complex_add_entity IS
    PORT (
        clk : IN std_logic; 
        clk_enable : IN std_logic; 
        reset : IN std_logic;
        x_re : IN std_logic_vector(3 DOWNTO 0);
        x_im : IN std_logic_vector(3 DOWNTO 0);
        y_re : IN std_logic_vector(3 DOWNTO 0);
        y_im : IN std_logic_vector(3 DOWNTO 0);
        z_re : OUT std_logic_vector(4 DOWNTO 0);
        z_im : OUT std_logic_vector(4 DOWNTO 0));
END complex_add_entity;
 
ARCHITECTURE fsm_SFHDL OF complex_add_entity IS
 
BEGIN
    -- addition of two complex numbers x,y of type 'ufix4'
    -- x+y will have'ufix5' type
    z_re <= std_logic_vector(resize(unsigned(x_re), 5) +   
                             resize(unsigned(y_re), 5));

    z_im <= std_logic_vector(resize(unsigned(x_im), 5) + 
                             resize(unsigned(y_im), 5));

    -- to cast the result back to 'ufix4' use
    -- z = fi(x + y, numerictype(x), fimath(x));

END fsm_SFHDL;

Similarly, for the product operation in FullPrecision mode, the result bit width increases to the sum of the lengths of the individual operands. Further casting is necessary to bring the results back to a smaller bit width.

The following example function shows how the product of two complex operands (with real and imaginary ufix4 components) can be cast back to the original bit width.

function z = fcn(x, y)
% Multiplication of two complex numbers x,y of type 'ufix4'
 
% x*y will have'ufix8' type
z = x * y;
 
% to cast the result back to 'ufix4'
% z = fi(x * y, numerictype(x), fimath(x));

The following example shows VHDL code generated from this function.

ENTITY complex_mul IS
    PORT (
        clk : IN std_logic; 
        clk_enable : IN std_logic; 
        reset : IN std_logic;
        x_re : IN std_logic_vector(3 DOWNTO 0);
        x_im : IN std_logic_vector(3 DOWNTO 0);
        y_re : IN std_logic_vector(3 DOWNTO 0);
        y_im : IN std_logic_vector(3 DOWNTO 0);
        z_re : OUT std_logic_vector(8 DOWNTO 0);
        z_im : OUT std_logic_vector(8 DOWNTO 0));
END complex_mul;
 
 
ARCHITECTURE fsm_SFHDL OF complex_mul IS
 
    SIGNAL pr1 : unsigned(7 DOWNTO 0);
    SIGNAL pr2 : unsigned(7 DOWNTO 0);
    SIGNAL pr1in : unsigned(8 DOWNTO 0);
    SIGNAL pr2in : unsigned(8 DOWNTO 0);
    SIGNAL pre : unsigned(8 DOWNTO 0);
    SIGNAL pi1 : unsigned(7 DOWNTO 0);
    SIGNAL pi2 : unsigned(7 DOWNTO 0);
    SIGNAL pi1in : unsigned(8 DOWNTO 0);
    SIGNAL pi2in : unsigned(8 DOWNTO 0);
    SIGNAL pim : unsigned(8 DOWNTO 0);
 
BEGIN
 -- addition of two complex numbers x,y of type 'ufix4'
    -- x*y will have'ufix8' type
    pr1 <= unsigned(x_re) * unsigned(y_re);
    pr2 <= unsigned(x_im) * unsigned(y_im);
    pr1in <= resize(pr1, 9);
    pr2in <= resize(pr2, 9);
    pre <= pr1in - pr2in;
    pi1 <= unsigned(x_re) * unsigned(y_im);
    pi2 <= unsigned(x_im) * unsigned(y_re);
    pi1in <= resize(pi1, 9);
    pi2in <= resize(pi2, 9);
    pim <= pi1in + pi2in;
    z_re <= std_logic_vector(pre);
    z_im <= std_logic_vector(pim);
    -- to cast the result back to 'ufix4'
    -- z = fi(x * y, numerictype(x), fimath(x));
END fsm_SFHDL;

Support for Vectors of Complex Numbers

Embedded MATLAB Function Block supports HDL code generation for vectors of complex numbers. Like scalar complex numbers, vectors of complex numbers are flattened down to vectors of real and imaginary parts in generated HDL code.

For example in the following script t is a complex vector variable of base type ufix4 and size [1,2].

function y = fcn(u1, u2)
 
t = [u1 u2];
y = t+1;

In the generated HDL code the variable t is broken down into real and imaginary parts with the same two-element array. .

VARIABLE t_re : vector_of_unsigned4(0 TO 3);
VARIABLE t_im : vector_of_unsigned4(0 TO 3);

The real and imaginary parts of the complex number have the same vector of type ufix4, as shown in the following code.

TYPE vector_of_unsigned4 IS ARRAY (NATURAL RANGE <>) OF unsigned(3 DOWNTO 0);

All complex vector-based operations (+,-,* etc.,) are similarly broken down to vectors of real and imaginary parts. Operations are performed independently on all the elements of such vectors, following Embedded MATLAB semantics for vectors of complex numbers.

In both VHDL and Verilog code generated for the Embedded MATLAB Function Block, complex vector ports are always flattened. If complex vector variables appear on inputs and outputs, real and imaginary vector components are further flattened to scalars.

In the following Embedded MATLAB Function Block code, u1 and u2 are scalar complex numbers and y is a vector of complex numbers.

function y = fcn(u1, u2)
 
t = [u1 u2];
y = t+1;

This generates the following port declarations in a VHDL entity definition.

ENTITY Embedded_MATLAB_Function IS
    PORT (
        clk : IN std_logic; 
        clk_enable : IN std_logic; 
        reset : IN std_logic;
        u1_re : IN vector_of_std_logic_vector4(0 TO 1);
        u1_im : IN vector_of_std_logic_vector4(0 TO 1);
        u2_re : IN vector_of_std_logic_vector4(0 TO 1);
        u2_im : IN vector_of_std_logic_vector4(0 TO 1);
        y_re : OUT vector_of_std_logic_vector32(0 TO 3);
        y_im : OUT vector_of_std_logic_vector32(0 TO 3));
END Embedded_MATLAB_Function;

Other Operations on Complex Numbers

The coder supports the following functions with complex operands:

The isreal function, which always returns 0 for complex numbers, is particularly useful for writing Embedded MATLAB algorithms that behave differently based on whether the input is a complex or real signal.

function y = fcn(u)

% output is same as input if 'u' is real 
% output is  conjugate of input if 'u' is complex

if isreal(u)
    y = u;
else
    y = conj(u);
end

For detailed information on these functions, see Supported Functions and Limitations of the Fixed-Point Embedded MATLAB Subset in the Fixed-Point Toolbox documentation.

  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

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