В этом примере показано, как можно импортировать файл, содержащий код Verilog, и сгенерировать соответствующую модель Simulink при помощи importhdl функция. importhdl импорт и синтаксические анализы заданные файлы Verilog, чтобы сгенерировать соответствующую модель Simulink. Код Verilog в этом примере содержит алгоритм CORDIC atan2.
Этот файл входа Verilog реализует алгоритм CORDIC atan2.
cordic_atan2_verilog_file = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', '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
Этот проект Verilog содержит различные обычно используемые построения Verilog, такие как:
Непрерывные присвоения
Всегда блоки
Условные операторы
Инстанцирование модуля
Сгенерируйте построения
Цикл for
Чтобы импортировать файл Verilog, задайте имя файла в качестве аргумента к importhdl функция.
importhdl(cordic_atan2_verilog_file);
### Parsing <a href="matlab:edit('/mathworks/devel/bat/BR2021ad/build/matlab/toolbox/hdlcoder/hdlcoderdemos/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.
### Begin model generation.
### Creating Target model cordic_atan2
### 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/BR2021ad_1584584_202060/publish_examples2/tp4385e7eb/hdlimport/cordic_atan2/cordic_atan2.slx.
### Importhdl completed.
importhdl анализирует входной файл и отображает сообщения процесса импорта в Командном окне MATLAB™. Импорт обеспечивает ссылку на сгенерированную модель Simulink cordic_atan2.slx. Сгенерированная модель использует то же имя в качестве главного модуля в файле входа Verilog.
Чтобы открыть сгенерированную модель Simulink, щелкните по ссылке в Командном окне. Модель сохранена в hdlimport/cordic_atan2 путь относительно текущей папки. Можно симулировать модель и наблюдать результаты симуляции.
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');

Код Verilog инстанцирует 15 модули ядра при помощи сгенерировать построения. В сгенерированной модели Simulink, 15 модули ядра замечены.
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

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
