Generate Simulink Model from CORDIC Atan2 Verilog Code
This example shows how you can import a file containing Verilog® code and generate the corresponding Simulink® model by using the importhdl function. importhdl imports and parses the specified Verilog files to generate the corresponding Simulink model. The Verilog code in this example contains a CORDIC atan2 algorithm.
CORDIC 2-Argument Arctangent (atan2) Verilog Design
This Verilog input file implements a CORDIC atan2 algorithm.
cordic_atan2_verilog_file = 'cordic_atan2.v';
type(cordic_atan2_verilog_file);
`timescale 1ns / 1ps
module cordic_atan2(
input clk, // clock
input reset, // reset to the system
input enable, // enable
input signed [15:0] x_in, // Input x value
input signed [15:0] y_in, // Input Y value
output reg signed [15:0] theta // Input theta value
);
// Pipeline the input values
reg signed [17:0]x_in_d; reg signed [17:0]y_in_d;
always @(posedge clk)
begin
if(reset) begin
x_in_d <={18{1'b0}};
y_in_d <={18{1'b0}};
end else if(enable) begin
// extend the input values for intermediate calculations
x_in_d <= {{2{x_in[15]}},x_in};
y_in_d <= {{2{y_in[15]}},y_in};
end
end
// pre quad correction logic
reg x_qaud_adjust; reg y_qaud_adjust;
reg y_non_zero; reg signed [17:0]x_pre_quad_out;
reg signed [17:0]y_pre_quad_out;
always @(posedge clk)begin
if(reset)begin
x_pre_quad_out <= {18{1'b0}};
y_pre_quad_out <= {18{1'b0}};
x_qaud_adjust <= 1'b0;
y_qaud_adjust <= 1'b0;
y_non_zero <=1'b0;
end
else if(enable)begin
if(x_in_d[17] == 1'b1)begin
x_pre_quad_out <= -x_in_d;
x_qaud_adjust <= 1'b1;
end
else begin
x_pre_quad_out <= x_in_d;
x_qaud_adjust <= 1'b0;
end
if(y_in_d[17] == 1'b1)begin
y_pre_quad_out <= -y_in_d;
y_qaud_adjust <= 1'b1;
y_non_zero <=1'b1;
end
else begin
y_pre_quad_out <= y_in_d;
y_qaud_adjust <= 1'b0;
y_non_zero <= |y_in_d; // reduction or for test non zero or not
end
end
end
//LOOKUP TABLE FOR THE ANGLES
wire signed [15:0]LUT[0:14];
wire signed [17:0]x_k[0:15];
wire signed [17:0]y_k[0:15];
wire signed [17:0]z_k[0:15];
wire signed [15:0]theta_temp;
parameter PI = 16'sh6488;
assign LUT[0] = 16'h1922;
assign LUT[1] = 16'h0Ed6;
assign LUT[2] = 16'h07D7;
assign LUT[3] = 16'h03FB;
assign LUT[4] = 16'h01FF;
assign LUT[5] = 16'h0100;
assign LUT[6] = 16'h0080;
assign LUT[7] = 16'h0040;
assign LUT[8] = 16'h0020;
assign LUT[9] = 16'h0010;
assign LUT[10] = 16'h0008;
assign LUT[11] = 16'h0004;
assign LUT[12] = 16'h0002;
assign LUT[13] = 16'h0001;
assign LUT[14] = 16'h0000;
assign x_k[0] = x_pre_quad_out;
assign y_k[0] = y_pre_quad_out;
wire signed [17:0]theta_temp0;
assign theta_temp0 = z_k[15];
assign theta_temp = theta_temp0[15:0];
assign z_k[0] = 18'd0;
//cordic iterator
genvar i;
generate
for (i = 0; i<15; i =i+1)
begin
Kernel cordic_iterator (.clk (clk),
.reset(reset),
.enable (enable ),
.itr_num(i),
.x_in(x_k[i]),
.y_in(y_k[i]),
.z_in(z_k[i]),
.lut_constant(LUT[i]),
.x_out(x_k[i+1]),
.y_out(y_k[i+1]),
.z_out(z_k[i+1])
);
end
endgenerate
// matching delays for the control signls of the pre quadrant correction logic
reg x_qaud_adjust_match_delay[0:14];
reg y_qaud_adjust_match_delay[0:14];
reg y_non_zero_match_delay[0:14];
integer k;
always @(posedge clk)begin
if(reset)begin
x_qaud_adjust_match_delay[0] <= 1'b0; y_qaud_adjust_match_delay[0] <= 1'b0;
y_non_zero_match_delay [0] <= 1'b0; x_qaud_adjust_match_delay[1] <= 1'b0;
y_qaud_adjust_match_delay[1] <= 1'b0; y_non_zero_match_delay [1] <= 1'b0;
x_qaud_adjust_match_delay[2] <= 1'b0; y_qaud_adjust_match_delay[2] <= 1'b0;
y_non_zero_match_delay [2] <= 1'b0; x_qaud_adjust_match_delay[3] <= 1'b0;
y_qaud_adjust_match_delay[3] <= 1'b0; y_non_zero_match_delay [3] <= 1'b0;
x_qaud_adjust_match_delay[4] <= 1'b0; y_qaud_adjust_match_delay[4] <= 1'b0;
y_non_zero_match_delay [4] <= 1'b0; x_qaud_adjust_match_delay[5] <= 1'b0;
y_qaud_adjust_match_delay[5] <= 1'b0; y_non_zero_match_delay [5] <= 1'b0;
x_qaud_adjust_match_delay[6] <= 1'b0; y_qaud_adjust_match_delay[6] <= 1'b0;
y_non_zero_match_delay [6] <= 1'b0; x_qaud_adjust_match_delay[7] <= 1'b0;
y_qaud_adjust_match_delay[7] <= 1'b0; y_non_zero_match_delay [7] <= 1'b0;
x_qaud_adjust_match_delay[8] <= 1'b0; y_qaud_adjust_match_delay[8] <= 1'b0;
y_non_zero_match_delay [8] <= 1'b0; x_qaud_adjust_match_delay[9] <= 1'b0;
y_qaud_adjust_match_delay[9] <= 1'b0; y_non_zero_match_delay [9] <= 1'b0;
x_qaud_adjust_match_delay[10] <= 1'b0; y_qaud_adjust_match_delay[10] <= 1'b0;
y_non_zero_match_delay [10] <= 1'b0; x_qaud_adjust_match_delay[11] <= 1'b0;
y_qaud_adjust_match_delay[11] <= 1'b0; y_non_zero_match_delay [11] <= 1'b0;
x_qaud_adjust_match_delay[12] <= 1'b0; y_qaud_adjust_match_delay[12] <= 1'b0;
y_non_zero_match_delay [12] <= 1'b0; x_qaud_adjust_match_delay[13] <= 1'b0;
y_qaud_adjust_match_delay[13] <= 1'b0; y_non_zero_match_delay [13] <= 1'b0;
x_qaud_adjust_match_delay[14] <= 1'b0; y_qaud_adjust_match_delay[14] <= 1'b0;
y_non_zero_match_delay [14] <= 1'b0;
end
else if(enable) begin
x_qaud_adjust_match_delay[0] <=x_qaud_adjust;
y_qaud_adjust_match_delay[0] <=y_qaud_adjust;
y_non_zero_match_delay[0] <=y_non_zero;
for(k =0; k <14 ;k = k+1)begin
x_qaud_adjust_match_delay[k+1] <= x_qaud_adjust_match_delay[k];
y_qaud_adjust_match_delay[k+1] <= y_qaud_adjust_match_delay[k];
y_non_zero_match_delay[k+1] <= y_non_zero_match_delay[k];
end
end
end
// post quadrant correction logic
always @(posedge clk) begin
if(reset)
theta<=16'd0;
else if(enable)begin
if(y_non_zero_match_delay[14])begin
if(x_qaud_adjust_match_delay[14])begin
if(y_qaud_adjust_match_delay[14])
theta <=theta_temp -PI;
else
theta <=PI -theta_temp;
end
else begin
if(y_qaud_adjust_match_delay[14])
theta <= -theta_temp;
else
theta <= theta_temp;
end
end
else if(x_qaud_adjust_match_delay[14])begin
theta <= PI;
end
else begin
theta <= 16'd0;
end
end
end
endmodule
module Kernel(
input clk,
input reset,
input enable,
input signed [17:0]x_in,
input signed [17:0]y_in,
input signed [17:0]z_in,
input [4:0]itr_num,
input signed [15:0]lut_constant,
output reg signed [17:0]x_out,
output reg signed [17:0]y_out,
output reg signed [17:0]z_out);
wire signed [17:0] lut_constant_signExtension = {{2{lut_constant[15]}},lut_constant};
always @(posedge clk)begin
if(reset)begin
x_out <={18{1'b0}};
y_out <={18{1'b0}};
z_out <= {18{1'b0}};
end
else if(enable)begin
if(y_in[17])begin
x_out <= x_in -(y_in>>>itr_num);
y_out <= y_in + (x_in>>>itr_num);
z_out <= z_in - lut_constant_signExtension;
end
else begin
x_out <= x_in +(y_in>>>itr_num);
y_out <= y_in - (x_in>>>itr_num);
z_out <= z_in + lut_constant_signExtension;
end
end
end
endmodule
This Verilog design contains various commonly used Verilog constructs such as:
Continuous assignments
Always blocks
Conditional Statements
Module instantiation
Generate Constructs
For Loop
Import HDL File Containing CORDIC atan2 Algorithm
To import the Verilog file, specify the file name as an argument to the importhdl function.
importhdl(cordic_atan2_verilog_file);
### Parsing <a href="matlab:edit('cordic_atan2.v')">cordic_atan2.v</a>.
### Top Module name: 'cordic_atan2'.
### Identified ClkName::clk.
### Identified RstName::reset.
### Identified ClkEnbName::enable.
Warning: Unused signals detected in the Demux block created for vector index signal 'x_k'. A Demux block created for a vector index signal has all possible output signals based on the size and dimensions provided.
Warning: Unused signals detected in the Demux block created for vector index signal 'y_k'. A Demux block created for a vector index signal has all possible output signals based on the size and dimensions provided.
### Hdl Import parsing done.
### Removing unconnected components.
### Unconnected components detected when importing the HDL code. These components are removed from the generated Simulink model.
### Creating Target model cordic_atan2
### Begin model generation 'cordic_atan2'...
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Start Layout...
### Working on hierarchy at ---> 'cordic_atan2'.
### Laying out components.
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2'.
### Laying out components.
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator1'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator10'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator11'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator12'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator13'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator14'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator2'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator3'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator4'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator5'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator6'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator7'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator8'.
### Laying out components.
### Drawing block edges...
### Working on hierarchy at ---> 'cordic_atan2/cordic_atan2/cordic_iterator9'.
### Laying out components.
### Drawing block edges...
### Drawing block edges...
### Drawing block edges...
### Model generation complete.
### Setting model parameters.
### Generated model file /tmp/Bdoc25b_2988451_710120/tp11ca1a46/hdlcoder-ex38650911/hdlimport/cordic_atan2/cordic_atan2.slx.
### Importhdl completed.
importhdl parses the input file and displays messages of the import process in the MATLAB™ Command Window. The import provides a link to the generated Simulink model cordic_atan2.slx. The generated model uses the same name as the top module in the input Verilog file.
Examine Generated Simulink Model
To open the generated Simulink model, click the link in the Command Window. The model is saved in the hdlimport/cordic_atan2 path relative to the current folder. You can simulate the model and observe the simulation results.
open_system('hdlimport/cordic_atan2/cordic_atan2') Simulink.BlockDiagram.arrangeSystem('cordic_atan2') set_param('cordic_atan2', 'UnconnectedOutputMsg', 'None'); sim('hdlimport/cordic_atan2/cordic_atan2.slx');

Generated Module instances
The Verilog code instantiates 15 kernel modules by using the generate construct. In the generated Simulink model, 15 kernel modules are seen.
generate
for (i = 0; i<15; i =i+1)
begin
Kernel cordic_iterator (.clk(clk),
.reset(reset),
.enable(enable),
.itr_num(i),
.x_in(x_k[i]),
.y_in(y_k[i]),
.z_in(z_k[i]),
.lut_constant(LUT[i]),
.x_out(x_k[i+1]),
.y_out(y_k[i+1]),
.z_out(z_k[i+1]));
end
endgenerate

Simulink model for the Kernel Module
module Kernel( input clk, input reset, input enable, input signed [17:0]x_in, input signed [17:0]y_in, input signed [17:0]z_in, input [4:0]itr_num, input signed [15:0]lut_constant, output reg signed [17:0]x_out, output reg signed [17:0]y_out, output reg signed [17:0]z_out);
wire signed [17:0] lut_constant_signExtension = {{2{lut_constant[15]}},lut_constant};
always @(posedge clk)begin if(reset)begin x_out <={18{1'b0}}; y_out <={18{1'b0}}; z_out <= {18{1'b0}}; end else if(enable)begin if(y_in[17])begin x_out <= x_in -(y_in>>>itr_num); y_out <= y_in + (x_in>>>itr_num); z_out <= z_in - lut_constant_signExtension; end else begin x_out <= x_in +(y_in>>>itr_num); y_out <= y_in - (x_in>>>itr_num); z_out <= z_in + lut_constant_signExtension; end end end
endmodule
