Cordic IP核使用说明以及避坑记录

Cordic IP核使用说明以及避坑记录

参考文章:(140条消息) Vivado cordic IP核rotate和translate使用详解(附有代码)_cordic ip核 rotate_迎风打盹儿的博客-CSDN博客
(140条消息) VIVADO cordic IP核_卡布奇诺加勺糖的博客-CSDN博客


文章目录

  • Cordic IP核使用说明以及避坑记录
  • 前言
  • 一、cordic算法的原理
  • 二、cordic IP核主要功能:
    • 1.translate模式IP核配置和踩坑记录
    • 2. rotate模式IP核配置和踩坑记录
    • 3. 代码参考


前言

项目需求使用了cordicIP核取相位然后旋转,这篇文章主要是记录一下学习IP核以及使用IP核过程中遇到的问题。


一、cordic算法的原理

推荐学习视频:FPGA:Cordic算法介绍与实现_哔哩哔哩_bilibili
视频清晰的讲述了cordic算法的原理以及硬件实现,视频下方还提供了代码和资料,其中有一份XILINX-CORDIC算法文档非常推荐一看。

二、cordic IP核主要功能:

CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法。该算法通过基本的加和移位运算代替乘法运算,使得矢量的旋转和定向的计算不再需要三角函数、乘法、开方、反三角、指数等函数。有以下功能模式:

  • rotate 旋转
  • translate 变换 ——直角坐标转极坐标
  • sin/cos
  • arctan
  • sinh/cosh
  • arc tanh
  • square root 平方根

这次实现主要关注的是:rotate、 translate

1.translate模式IP核配置和踩坑记录

Cordic IP核使用说明以及避坑记录_第1张图片

  1. Functional Selection: 模式选择,此处选择Translate
  2. Architectural Configuration: CORDIC核心有两种架构配置,并行和串行。
  3. Pipelining Mode: CORDIC核心提供了三种流水线模式:无、最优和最大。流水线模式的选择基于功能配置和体系结构配置的选择。

None: CORDIC核心在没有流水线的情况下实现。
优化: CORDIC核心实现了尽可能多的流水线阶段,而不使用任何额外的lut。 最大:CORDIC核心在每个shift-add子阶段之后都有一个管道实现。 此处选择优化。

  1. Phase Format:

radians格式下就是输入正常的弧度制,输入范围是(-π,π) scale
radians则是输入归一化的弧度值,输入范围是(-1,1) 说明白点,radians格式下,你的输入就相当于在scale radians下输入再乘π。 此处选择Radians。

  1. Round Mode: CORDIC核心提供四种舍入模式。

Truncate截断: The X_OUT, Y_OUT, and PHASE_OUT outputs are truncated.

Positive Infinity向上取整: The X_OUT, Y_OUT, and PHASE_OUT outputs are
rounded such that 1/2 is rounded up (towards positive infinity). It is
equivalent to the MATLAB function floor(x + 0.5).

Pos Neg Infinity四舍五入: The outputs X_OUT, Y_OUT, and PHASE_OUT are rounded such that 1/2 is rounded up (towards positive infinity) and -1/2 is rounded down (towards negative infinity). It is equivalent to the MATLAB function round(x).

Nearest Even最近偶数: The X_OUT, Y_OUT, and PHASE_OUT outputs are rounded toward the nearest even number such that a 1/2 is rounded down and 3/2 is rounded up.
根据需要选择Round Pos Neg Inf。

  1. Iterations和 Precision: 不选设为0 IP核根据其他设置默认设置。
  2. Coarse Rotation:如果关闭粗旋转,输入/输出范围将限制在第一象限(-Pi/4,+ Pi/4)。所以应该勾上。
  3. 【坑】Compensation Scaling:补偿方式。cordic这个IP核在使用的时候他的输出是乘了倍数Z的,第一次用的时候没有勾选补偿方式,发现输出结果角度是对的,但是模值不正确,勾选补偿方式后cordic会自己把输出再乘一个Z的倒数,这样就对了。

No Scale Compensation: 输出X和Y没有补偿,并生成,按比例Z缩放。
LUT Based:输出X和Y补偿使用基于LUT的常系数乘法器。
BRAM: 输出X和Y使用块ram为基础的常系数乘法器进行补偿。
Embedded Multiplier: 输出X和Y使用DSP Slice进行补偿。
此处如果选No,不会补偿,输出结果不对。以保证结果正确,必须选择一项补偿方式。此处默认选LUT Based。

  1. 数据范围 需要注意,否则输出可能出错
    Cordic IP核使用说明以及避坑记录_第2张图片
    Cordic IP核使用说明以及避坑记录_第3张图片
    Translation的数据范围,fix格式下数据范围不能超过±1,此外要注意输出的模值会不会超位宽的问题,如果有超需要扩展位宽!!!Fix16_14实际上就是(signed [15:0])/2^14

    Fix16_14: 1(符号位)+1(整数位)+14(小数位)
    仿真器显示定点小数:
    【技巧】Vivado 仿真器simulation显示定点小数_LiangWF22的博客-CSDN博客
    Cordic IP核使用说明以及避坑记录_第4张图片

  2. 输入PADDING:具体是否有补零和补零位数根据IP核配置页面为准。另外如果输入X/Y_IN位宽和IP核位宽不一致需要补符号位。

在这里插入图片描述

第二页不用修改使用默认值即可:
Cordic IP核使用说明以及避坑记录_第5张图片

2. rotate模式IP核配置和踩坑记录

配置和translate模式基本一致,这里我采的一个坑是,我是把translate的输出模值和相位经过一定处理后送到rotate里面,translate的输出位宽是16位,相位是fix16_13,但是我的rotate的输入phase是fix17_14(为了避免rotate输出的模值溢出多给了一位)我刚开始是直接补的符号位,这样子==实际上rotate收到的phase变成原来的一半了!!!==导致一个数据也不对,后来改成低位补一个0就解决了。

Cordic IP核使用说明以及避坑记录_第6张图片


3. 代码参考

参考: (140条消息) Vivado cordic IP核rotate和translate使用详解(附有代码)_cordic ip核 rotate_迎风打盹儿的博客-CSDN博客

1.	`timescale 1ns / 1ps
2.	
3.	 
4.	module cordic_test_tb();
5.	 
6.	// cordic_translate_test Parameters
7.	parameter PERIOD  = 2;
8.	 
9.	// cordic_translate_test Inputs
10.	reg   clk                                  = 0 ;
11.	reg   start                                = 0 ;
12.	reg   [15:0]  x_in                         = 0 ;
13.	reg   [15:0]  y_in                         = 0 ;
14.	reg   [15:0]  pha_in                       = 0 ;
15.	 
16.	// cordic_translate_test Outputs
17.	wire  over1                                 ;
18.	wire  over2                                 ;
19.	wire  [15:0]  x_out1                        ;
20.	wire  [16:0]  x_out2                        ;
21.	wire  [16:0]  y_out2                        ;
22.	wire  [15:0]  pha_out                      ;
23.	 
28.	 
29.	cordic_translate_test  u_cordic_translate_test (
30.	    .clk                     ( clk             ),
31.	    .start                   ( start           ),
32.	    .x_in                    ( x_in     [15:0] ),
33.	    .y_in                    ( y_in     [15:0] ),
34.	 
35.	    .over                    ( over1            ),
36.	    .x_out                   ( x_out1    [15:0] ),
37.	    .pha_out                 ( pha_out   [15:0] )
38.	);
39.	 
40.	 
41.	initial
42.	begin
43.		forever #(PERIOD/2)  clk=~clk;
44.	    #5  start<=1;
45.	    x_in<=16'b0011000000000000;
46.	    y_in<=16'b0011000000000000;
47.	    pha_in<=16'b0011001001000011;
48.	    #2     
49.	    x_in<=16'b1110000000000000;
50.	    y_in<=16'b1110000000000000;
51.	    pha_in<=16'b1001101101111000;
52.	    
53.	    #10
54.	    x_in<=16'b0110000000000000;
55.	    y_in<=16'b1010000000000000;
56.	    pha_in<=16'b0110010010000111;
57.	end
58.	
59.	
60.	
61.	cordic_rotate_test  u_cordic_rotate_test (
62.	    .clk                     ( clk            ),
63.	    .start                   ( start          ),
64.	    .x_in                    ( x_in           ),
65.	    .y_in                    ( y_in           ),
66.	    .pha_in                  ( pha_in         ),
67.	 
68.	    .over                    ( over2           ),
69.	    .x_out                   ( x_out2          ),
70.	    .y_out                   ( y_out2          )
71.	);
72.	 
73.	
74.	
75.	 
76.	endmodule

module cordic_rotate_test(
input clk,                    //输入时钟信号
input start,                  //输入开始计算信号
input [15:0] x_in,            //输入坐标x
input [15:0] y_in,            //输入坐标y
input [15:0] pha_in,          //输入相角
output wire over,             //输出计算完成标志
output wire [16:0] x_out,     //输出坐标x
output wire [16:0] y_out      //输出坐标y
    );
wire [16:0]phase ;
wire [40:0] rotate_out;
//assign phase = {pha_in[15],pha_in};
assign phase = {pha_in,1'b0};
wire [16:0] x_in_1;
wire [16:0] y_in_1;
assign y_in_1 = {y_in[15],y_in};
assign x_in_1 = {x_in[15],x_in};
cordic_rotate u_cordic_rotate_ip (
  .aclk(clk),                                        // input wire aclk
  .s_axis_phase_tvalid(start),          // input wire s_axis_phase_tvalid
  .s_axis_phase_tdata(phase),            // input wire [17 : 0] s_axis_phase_tdata
  .s_axis_cartesian_tvalid(start),  // input wire s_axis_cartesian_tvalid
  .s_axis_cartesian_tdata({y_in_1,7'b0000000,x_in_1}),    // input wire [41 : 0] s_axis_cartesian_tdata
  .m_axis_dout_tvalid(over),            // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata(rotate_out)              // output wire [41 : 0] m_axis_dout_tdata
);
assign  x_out = rotate_out[16:0];
assign  y_out = rotate_out[40:24];
endmodule
module cordic_translate_test(
input clk,                    //输入时钟信号
input start,                  //输入开始计算信号
input [15:0] x_in,            //输入坐标x
input [15:0] y_in,            //输入坐标y
output wire over,              //输出计算完成标志
output wire [15:0] x_out,      //输出坐标x
output wire [15:0] pha_out     //输出相角
);
 
 
cordic_translate cordic_translate_inst(
  .aclk(clk),                                        // input wire aclk
  .s_axis_cartesian_tvalid(start),  // input wire s_axis_cartesian_tvalid
  .s_axis_cartesian_tdata({y_in,x_in}),    // input wire [63 : 0] s_axis_cartesian_tdata
  .m_axis_dout_tvalid(over),            // output wire m_axis_dout_tvalid
  .m_axis_dout_tdata({pha_out,x_out})              // output wire [63 : 0] m_axis_dout_tdata
  
);
 
endmodule

你可能感兴趣的:(FPGA,fpga开发)