%% Implement Control Signals Based Mathematical Functions using HDL Coder
% This document gives the overview of the control signal based fixed point
% mathematical functions in HDLMathLib and examples associated with all the blocks present in the HDLMathLib
% by using HDL Coder(TM).
% HDLMathLib includes following blocks with control ports.
%
% # Sqrt
% # Atan2
% # Sin
% # Cos
% # SinCos
% # Cos+jSin
% # Reciprocal
% # Divide
%
% Copyright 2020 The MathWorks, Inc.

%% HDLMathLib Library With Control Ports for Mathematical Functions
% To see all the mathematical function blocks in the HDLMathLib library,
% open the library using following command.
open_system('HDLMathLib')

%%
% You can see various mathematical function blocks with control ports.
% Sqrt, Atan2, SinCos, Reciprocal and Divide blocks are described with
% example in the following sections. You can use sin, cos, Cos+jsin blocks in your model
% same way by referring below sections.

%% Sqrt Block with Control Signals
% Each port of the Sqrt block is as explained below.
%
% <<hdlcoder_sqrtPort.PNG>>

%%
% When you open the Sqrt block, it uses MATLAB Function blocks for the
% data and valid lines. This is as shown below.
open_system('hdlcoder_sqrt_bitset_control')
open_system('hdlcoder_sqrt_bitset_control/Sqrt')

%% Example using Contol Signals based Sqrt Block
% This section shows how to implement an example using control signal based Square root block and generate HDL code
% by using HDL Coder(TM).

%% Open and Run Simulink Model
% Before opening the model, set the input as follows. You can chose to set different input as per your requirement. This example uses following inputs which is linear.
SQRT_input = fi(1/2^17:1/2^17:1,0,18,17)';

%%
% Specify the wordlength for fixed-point datatypes and the pipeline
% latency for the model. Go through the documentation for latency
% calculation.
WL = 18; latency = 20;

%%
% Open the model |hdlcoder_sqrt_bitset_control| and specify sufficient
% stop time that required to process all the input combinations.
stoptime = length(SQRT_input)-1+latency;
open_system('hdlcoder_sqrt_bitset_control')
sim('hdlcoder_sqrt_bitset_control')

%%
% You can see the below waveform when you simulate the above model. You can
% see that dataOut is valid when validOut is high.
%
% <<hdlcoder_sqrt_waveform.PNG>>

%% Validate Simulink Output by Using Reference Output
% To validate the output obtained by simulating the Simulink model, you can
% compare the Simulink output with a reference output. To obtain the
% reference output, use the <docid:matlab_ref#bu57a5h> function.
%
% Compute the reference output by using the |sqrt| function.
ref_SQRT = sqrt(double(SQRT_input));

%%
% Use logical indexing to extract valid output.
implementation_SQRT = simulink_SQRT(valid_output);

%%
% To validate the output, plot the comparison results by using the
% |comparison_plot| function in this example. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_sqrt(ref_SQRT,implementation_SQRT,1,'SQRT linear input');

%% Generate HDL Code for Square Root Implementation
% Before you generate code, you can see the HDL settings saved on the model
% by using the |hdlsaveparams| function.
hdlsaveparams('hdlcoder_sqrt_bitset_control')

%%
% To generate HDL code for the |Sqrt| block in the model, use the |makehdl|
% function.
%
makehdl('hdlcoder_sqrt_bitset_control/Sqrt')
close_system('hdlcoder_sqrt_bitset_control')
close all;

%% Sqrt Block Synthesis Performance
% Following digrams shows the Sqrt block synthesis performance on the
% Xilinx Virtex 7 and intel Stratix V devices.
%
% <<hdlcoder_sqrt_bitset_control_xilinx.PNG>>
%
%%
%
% <<hdlcoder_sqrt_bitset_control_intel.PNG>>
%

%% Atan2 Block with Control Signals
% Each port of the Atan2 block is as explained below.
%
% <<hdlcoder_atan2port.PNG>>
%
%%
% The Atan2 block has number of iterations as mask parameter. The
% default value is 11 and latency depends on this masked parameter.
%
% <<hdlcoder_atan2_mask.PNG>>
%%
% When you open the Atan2 block, it uses MATLAB Function blocks for the
% data and valid lines. This is as shown below.
open_system('hdlcoder_atan2_control')
open_system('hdlcoder_atan2_control/Atan2')
open_system('hdlcoder_atan2_control/Atan2','force')

%% Example using Control Signal based Atan2 Block
% This section shows how to implement an example using control signal based Atan2 block and generate HDL code
% by using HDL Coder(TM).

%% Open and Run Simulink Model
% Before opening the model, set the input as follows. You can chose to set different input as per your requirement. This example uses following inputs which is linear
% and sweep through input values -pi to pi.
input_values = (-pi:.01/(2*pi):pi)';
RADIUS = 10.^(-2.5:.25:0);
%%
% Specify the wordlength for fixed-point datatypes and the pipeline
% latency for the model. Go through the documentation for latency
% calculation. The latency depends up on the number of iterations.
WL_atan2 = 18; latency_atan2 = 14;

%%
% Setup variables for logging input x and y values.
x_log = zeros(length(input_values)*length(RADIUS),1);
y_log = zeros(length(input_values)*length(RADIUS),1);
for outerindex = 0:length(RADIUS)-1
for index = 1:length(input_values)
input = input_values(index); % access current value
y = RADIUS(outerindex+1)*sin(input); % compute y
x = RADIUS(outerindex+1)*cos(input); % compute x
addr = outerindex*length(input_values)+index;
y_log(addr) = y;
x_log(addr) = x;
end
end

%%
% Open the model |hdlcoder_atan2_control| and specify sufficient
% stop time that required to process all the input combinations. The model has Atan2 block that implements the Atan2 using CORDIC
% algorithm for a |validIn| control signal.
stoptime_atan2 = length(x_log)-1+latency_atan2;
close all
open_system('hdlcoder_atan2_control')
sim('hdlcoder_atan2_control')

%%
% You can see the below waveform when you simulate the above model. You can
% see that dataOut is valid when validOut is high.
%
% <<hdl_coder_atan2_waveform.PNG>>

%% Validate Simulink Output By Using Reference Output
% To validate the output obtained by simulating the Simulink model, you can
% compare the Simulink output with a reference output. To obtain the
% reference output, use the atan2 MATLAB function.
%
% Compute the reference output by using the |atan2| function. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_atan2(atan2(y_log,x_log),sim_final_theta(valid_out),3,'theta');

%% Generate HDL Code for Atan2 Implementation
% Before you generate code, you can see the HDL settings saved on the model
% by using the |hdlsaveparams| function.
hdlsaveparams('hdlcoder_atan2_control')

%%
% To generate HDL code for the |Atan2| block in the model, use the |makehdl|
% function.
%
makehdl('hdlcoder_atan2_control/Atan2')
close_system('hdlcoder_atan2_control')
close all;

%% Atan2 Block Synthesis Performance
% Following digrams shows the Atan2 block synthesis performance on the
% Xilinx Virtex 7 and intel Stratix V devices.
%
% <<hdlcoder_atan2_xilinx.PNG>>
%
%%
%
% <<hdlcoder_atan2_intel.PNG>>
%

%% SinCos Block with Control Signals
% Each port of the SinCos block is as explained below.
%
% <<hdlcoder_sincos.PNG>>
%
%%
% The SinCos block has number of iterations as the mask parameter.The
% default value is 11 and latency depends on this masked parameter.
%
% <<hdlcoder_sincos_mask.PNG>>
%%
% When you open the SinCos block, it uses MATLAB Function blocks for the
% data and valid lines. This is as shown below.
open_system('hdlcoder_sincos_control')
open_system('hdlcoder_sincos_control/SinCos')
open_system('hdlcoder_sincos_control/SinCos','force')

%% Example using Control Signal based SinCos Block
% This section shows how to implement an example using control signal based SinCos block and generate HDL code
% by using HDL Coder(TM).

%% Open and Run Simulink Model
% Before opening the model, set the input as follows. You can chose to set different input as per your requirement. This example uses following inputs which is linear
% and sweep through input values -pi to pi.
input_values = (-pi:.01/(2*pi):pi)';

%%
% Specify the wordlength for fixed-point datatypes and the pipeline
% latency for the model. Go through the documentation for latency
% calculation. The latency depends up on the number of iterations
WL_SinCos = 18; latency_SinCos = 12;

%%
% Open the model |hdlcoder_sincos_control| and specify sufficient
% stop time that required to process all the input combinations. The model has SinCos block that implements the SinCos using CORDIC
% algorithm for a |validIn| control signal. The remaining trigonometric function blocks(Sin, Cos and Cos + jSin) use the
% same CORDIC approximation method and the interface ports differs respectively.
stoptime_sincos = length(input_values)-1+latency_SinCos;
open_system('hdlcoder_sincos_control')
sim('hdlcoder_sincos_control')

%%
% You can see the below waveform when you simulate the above model. You can
% see that dataOut is valid when validOut is high.
%
% <<hdlcoder_sincos_waveform.PNG>>

%% Validate Simulink Output By Using Reference Output
% To validate the output obtained by simulating the Simulink model, you can
% compare the Simulink output with a reference output. To obtain the
% reference output, use the sin and cos MATLAB function.
%
% Compute the reference output by using the |sin| function. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_sincos(sin(input_values),sim_final_sintheta(valid_out),5,'sin');

%%
% Compute the reference output by using the |Cos| function. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_sincos(cos(input_values),sim_final_costheta(valid_out),6,'cos');

%% Generate HDL Code for SinCos Implementation
% Before you generate code, you can see the HDL settings saved on the model
% by using the |hdlsaveparams| function.
hdlsaveparams('hdlcoder_sincos_control')

%%
% To generate HDL code for the |SinCos| block in the model, use the |makehdl|
% function.
%
makehdl('hdlcoder_sincos_control/SinCos')
close_system('hdlcoder_sincos_control')
close all;

%% SinCos Block Synthesis Performance
% Following digrams shows the SinCos block synthesis performance on the
% Xilinx Virtex 7 and intel Stratix V devices.
%
% <<hdlcoder_sincos_xilinx.PNG>>
%
%%
%
% <<hdlcoder_sincos_intel.PNG>>
%

%% Reciprocal Block with Control Signals
% Each port of the Reciprocal block is as explained below.
%
% <<hdlcoder_reciprocalport.PNG>>
%
%%
% When you open the Reciprocal block, it uses MATLAB Function blocks for the
% data and valid lines. This is as shown below.
open_system('hdlcoder_reciprocal_shiftadd_control')
open_system('hdlcoder_reciprocal_shiftadd_control/Reciprocal')

%% Example using Control Signal based Reciprocal Block
% This section shows how to implement an example using control signal based Reciprocal block and generate HDL code
% by using HDL Coder(TM).

%% Open and Run Simulink Model
% Before opening the model, set the input as follows. You can chose to set
% different input as per your requirement. This example uses following inputs which is linear.
reciprocal_input = fi(1/2^17:1/2^17:1,0,18,17)';

%%
% Specify the wordlength for fixed-point datatypes and the pipeline
% latency for the model. Go through the documentation for latency
% calculation.
WL_recip = 18; recip_latency = 22;

%%
% Open the model |hdlcoder_reciprocal_shiftadd_control| and specify sufficient
% stop time that required to process all the input combinations.
stoptime_recip = length(reciprocal_input)-1+recip_latency;
open_system('hdlcoder_reciprocal_shiftadd_control')
sim('hdlcoder_reciprocal_shiftadd_control')

%%
% You can see the below waveform when you simulate the above model. You can
% see that dataOut is valid when validOut is high.
%
% <<hdlcoder_reciprocal_waveform.PNG>>
%
%% Validate Simulink Output By Using Reference Output
% To validate the output obtained by simulating the Simulink model, you can
% compare the Simulink output with a reference output. To obtain the
% reference output, use the <docid:matlab_ref#bu57a5h> function.
%
% Compute the reference output by using the |reciprocal| operation.
ref_reciprocal = 1./double(reciprocal_input);

%%
% Use logical indexing to extract valid output.
implementation_reciprocal = simulink_reciprocal(valid_output);

%%
% To validate the output, plot the comparison results by using the
% |comparison_plot_reciprocal| function in this example. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_reciprocal(ref_reciprocal,implementation_reciprocal,9,'reciprocal linear input');

%% Generate HDL Code for Reciprocal Implementation
% Before you generate code, you can see the HDL settings saved on the model
% by using the |hdlsaveparams| function.
hdlsaveparams('hdlcoder_reciprocal_shiftadd_control')
%%
% To generate HDL code for the |Reciprocal| block in the model, use the |makehdl|
% function.
%
makehdl('hdlcoder_reciprocal_shiftadd_control/Reciprocal')
close_system('hdlcoder_reciprocal_shiftadd_control')
close all;

%% Reciprocal Block Synthesis Perfromance
% Following digrams shows the Reciprocal block synthesis performance on the
% Xilinx Virtex 7 and intel Stratix V devices.
%
% <<hdlcoder_reciprocal_xilinx.PNG>>
%
% <<hdlcoder_reciprocal_intel.PNG>>
%
%

%% Divide Block with Control Signals
% Each port of the Divide block is as explained below.
%
% <<hdlcoder_divideport.PNG>>
%
%%
% When you open the Divide block, it uses MATLAB Function blocks for the
% data and valid lines. This is as shown below.
open_system('hdlcoder_divide_shiftadd_control')
open_system('hdlcoder_divide_shiftadd_control/Divide')

%% Example using Control Signal based Divide Block
% This section shows how to implement an example using control signal based Divide block and generate HDL code
% by using HDL Coder(TM).

%% Open and Run Simulink Model
% Before opening the model, set the input as follows. You can chose to set different input as per your requirement. This example uses following inputs which is linear.
dividend_input = fi(1/2^17:1/2^17:1,0,18,17)';
divisor_input = fi(1/2^17:1/2^17:1,0,18,13)';

%%
% Specify the wordlength for fixed-point datatypes and the pipeline
% latency for the model. Go through the documentation for latency
% calculation.
WL_divide = 18; divide_latency = 22;

%%
% Open the model |hdlcoder_divide_shiftadd_control| and specify sufficient
% stop time that required to process all the input combinations.
stoptime_divide = length(dividend_input)-1+divide_latency;
open_system('hdlcoder_divide_shiftadd_control')
sim('hdlcoder_divide_shiftadd_control')

%%
% You can see the below waveform when you simulate the above model. You can
% see that dataOut is valid when validOut is high.
%
% <<hdlcoder_divide_waveform.PNG>>
%
%% Validate Simulink Output By Using Reference Output
% To validate the output obtained by simulating the Simulink model, you can
% compare the Simulink output with a reference output. To obtain the
% reference output, use the <docid:matlab_ref#bu57a5h> function.
%
% Compute the reference output by using the |divide| function.
ref_divide = double(dividend_input)./double(divisor_input);

%%
% Use logical indexing to extract valid output.
implementation_divide = simulink_divide(valid_output);

%%
% To validate the output, plot the comparison results by using the
% |comparison_plot_divide| function in this example. You can see that the maximum error observed from the comparison results is
% quite small.
comparison_plot_divide(ref_divide,implementation_divide,11,'divide linear input');

%% Generate HDL Code for Divide Implementation
% Before you generate code, you can see the HDL settings saved on the model
% by using the |hdlsaveparams| function.
hdlsaveparams('hdlcoder_divide_shiftadd_control')
%%
% To generate HDL code for the |Divide| block in the model, use the |makehdl|
% function.
%
makehdl('hdlcoder_divide_shiftadd_control/Divide')
close_system('hdlcoder_divide_shiftadd_control')
close all;
%% Divide Block Synthesis Performance
% Following digrams shows the Divide block synthesis performance on the
% Xilinx Virtex 7 and intel Stratix V devices.
%
% <<hdlcoder_divide_xilinx.PNG>>
%
%
% <<hdlcoder_divide_intel.PNG>>
%
%