在数字信号处理系统中经常需要计算arctan函数,比如在解调系统中由DDC得到复基带信号q和i支路计算arctan(q/i)即可得到基带信号的相位。在FPGA设计中可以使用CORDIC算法来实现arctan。
本文将介绍在Vivado开发环境下如何使用Xilinx提供的Cordic(6.0) IP核计算arctan。该IP核还可以实现其它CORDIC算法可实现的功能,将在后面的文章中介绍。
Xilinx的CORDIC IP核属于收费IP,但是不需要像 Quartus那样通过修改license文件来破解。如果是个人学习,现在网络上流传的license破解文件在破解Vivado的同时也破解了绝大多数可以破解的IP核。只要在IP Catalog界面中CORDIC的License状态为“Included”即可正常使用。
在IP Catalog中打开CORDIC,主界面如下:
左边的Tab可以切换看到CORDIC的模块图(IP Symbol)、实现细节(Implementation Details)。其中最重要的信息就是Latency,由这个值可以知道得到输出结果需要多少个时钟。右边的Tab是对CORDIC进行配置。
Functional Selection选择为“Arc Tan”,结构默认为并行结构。Pipelining Mode可以设置为最大值(Maximum)、最优值(Optimal)和不设置流水线(No pipelining即纯组合逻辑实现)。增加流水线级数可以提高计算速度。计算arctan时Data Format固定为带符号小数(SignedFraction)。Phase Format可以设置为Radians(以pi为单位)或Scaled Radians(将单位pi归一化到-1~1范围内)。
Input/Output Options中设置输入数据位宽和输出数据位宽,以及舍位的模式,这里选择为Nearest Even,表示最接近的值(可以理解为四舍五入)。
另外值得注意的一个参数是“Coarse Rotation”,默认为勾选。选中此值时,CORDIC的输出范围是-pi~pi;没有选中时,CORDIC的输出范围是-1/4pi~1/4pi。前者通常更符合我们的需要。
Vivado的很多IP核采用的是AXI4接口,主要有数据(tdata)、准备好(tready)、有效(tvalid)几种信号,还有主机(m)和从机(s)之分。另外在AXI4 Stream Options这个Tab还可以配置使用更多辅助的AXI4接口信号。
接下来介绍几个主要的接口:
上表中的接口在计算arctan时所需。其它接口在后面的设计中使用到CORDIC的其它功能时,再做介绍。需要注意,AXI4接口位宽是以字节为单位,即只会是8的倍数,因此需要结合设计的实际位宽做相应处理。
IP核的接口在Verilog HDL中进行设计时,一定要参考官方文档中给出的索命。在IP核的配置界面点击“documentation”,可以找到IP核的user guide。 也可以在Xilinx官网或DocNav工具中搜索pg105,查阅CORDIC IP核的说明。
计算arctan的CORDIC接口时序非常简单,Verilog HDL示例代码如下所示:
`timescale 1ns / 1ps
//----------------------------------------------------
// CORDIC IP核计算arctan
//----------------------------------------------------
module arctan_cul
(
input clk, //系统时钟
input rst_n,
input signed [15:0] i,q, //复基带信号
output signed out_valid, //输出有效信号
output signed [15:0] theta //arctan计算结果
);
//输入y和x,out=arctan(y/x);
//tdata端口,yin在前,xin在后
cordic_0 cordic1
(
.aclk (clk),
.aresetn (rst_n),
.s_axis_cartesian_tvalid (1'b1),
.s_axis_cartesian_tdata ({q[15],q[15:1],i[15],i[15:1]}),
.m_axis_dout_tvalid (out_valid),
.m_axis_dout_tdata (theta)
);
endmodule
CORDIC的IP核包括Y和X两个数据输入,共同占用tdata总线,Y占用高字节部分,X占用低字节部分。比如输入数据位宽为16Bits时,15~8位为Y,7~0位为X。CORDIC计算arctan(Y/X),输出计算结果。
根据pg105的介绍,CORDIC的输入数据范围应限制在-1~1(否则会出错),输出数据范围为(-pi~pi,选中Coarse Rotation)。且数据格式为带符号小数,输入数据整数位有2bit;输出数据整数位有3bit。这是pg105给出的实例:
代码中一定能要保证输入数据的范围限定在-1~1之间。如果不能确定上级模块向CORDIC中输入数据的范围,可以先仿真,确定数据的最大值和最小值是否超出了该范围。如果超过可以用类似“{q[15],q[15:1],i[15],i[15:1]}”这样的移位除法,缩小输入数据范围。由于是带符号数二进制补码,移位时注意高位补符号位。
另外需要知道的是,其实定点数(二进制)的运算规则其实与小数点定在哪一位是无关的,这个定点数值具体是多少,取决于你在看待这个数时,人为的认为小数点在哪一位。比如1100这个数,认为小数点在最后时,则为12;认为小数点在第3bit后面时,则为3.0。在看待CORDIC的输入输出数据的值时,要清楚这一点。
使用CORDIC计算DDC输出的i和q支路,arctan(q/i),得到基带信号的相位。在Vivado中进行仿真,如下图所示:
可以看到同相支路i和正交支路q经过计算后得到基带信号的相位theta,表明功能正确。具体实例情况可参考“FPGA综合系统设计(七)DDC相位差检测https://blog.csdn.net/FPGADesigner/article/details/80785174 ”。