基于FPGA的复指数转换模块设计设计()
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于FPGA的复指数转换模块设计设计()
毕业设计论文
基于FPGA 的复指数转换模块设计
摘要:复指数运算会运用在许多通信数字处理领域中,例如ofdm 系统的调制、
加扰等。
CORDIC 算法是在许多角度计算方面有着广泛应用的经典算法,本文通过考虑FPGA 的结构、精度局限和速度要求,采用流水线技术(pipeline),在FPGA 上用CORDIC 算法实现对复数处理。
关键词: 坐标旋转数字计算; FPGA; 复指数
1 引言
FPGA 以其灵活性和使用方便在现今的数字领域已经得到了广泛的应用。
但FPGA 实现数字系统也有其自身的局限性,其一是器件资源的门阵列规模的限制,其二是单元延迟限制。
所以,这就需要设计者充分考虑器件的实际工作能力。
复数的计算在数字领域尤其是数字通信领域是一种应用非常广泛的计算,如果用传统的除法器、乘法器等计算方法,需要占用大量的FPGA 资源,这样就不能满足设计者的要求,需要设计者考虑其他的算法实现这种类型的计算。
CORDIC 算法在硬件电路的实现上只用到了加法器和移位器,这样就大大节约了FPGA 的资源,从而可以满足设计者的要求。
2 CORDIC 算法简介
CORDIC(CoordinateRotationDigital Computer),又名:坐标旋转数字计算,是J. Voider 等人于1959年在设计美国航空导航控制系统的过程中提出来的一种算法。
下面就简要地介绍一下CORDIC 算法的基本数学思想。
如图1所示,将向量),Y (X i i 旋转θ角,得到一个新的向量),Y (X j j ,那么有:
θ
Y θX β)(θR Y θ
Y θX β)(θR X i i j i i j cos sin sin sin cos cos -=+=-=+= (1)
式中R 为圆周的半径,θ为旋转角度。
写成矩阵形式:
⎥⎦⎤⎢⎣⎡⎥⎦⎤⎢⎣⎡-=⎥⎦⎤⎢⎣⎡⎥⎦⎤⎢⎣
⎡-=⎥⎦⎤⎢⎣⎡i i i i j j Y X θθθY X θθθθY X 1tan tan 1cos cos sin sin cos (2)
如果假设θ是由n 个n θ角度叠加而成的,那么根据式(2)得出每一步的叠加操作需要按照式(3)操作。
⎥⎦
⎤
⎢⎣⎡⎥⎦⎤⎢⎣⎡-=⎥⎦⎤⎢⎣⎡++n n n n n n n Y X θ
θθY X 1tan tan 1
cos 11 (3) 利用式子(3)经过n 步叠加可以表示由向量),Y (X i i 旋转到向量),Y (X j j ,如下表示:
⎥⎦
⎤
⎢⎣⎡⎥⎦⎤⎢⎣⎡-⎥⎦⎤⎢
⎣⎡-=⎥⎦⎤⎢⎣⎡i i n n n j j Y X θθ...θθθ...θθY X 1tan tan 1
1tan tan 1
cos cos cos 0010 (4) 由于计算机进行计算采用二进制形式,所以我们选取⎪⎭
⎫
⎝⎛=n n θ21arctan ,这样
选取n θ方便了n θtan 的计算,即n n n S -=2tan θ,式(4)前面的n θcos 可以去累积乘的极限即:
∏∏∞
=∞
=≈⎥⎦⎤⎢⎣⎡
==0
n 0n 607253.0)21arctan(co cos K n n s θ
如果我们在设计的系统中提前计算K ,那么当抛开K 不算时,式(3)就可以表示成式(5):
⎥⎦
⎤
⎢⎣⎡⎥⎦⎤⎢⎣⎡-=⎥⎦⎤⎢⎣⎡--++n n n n n n n n Y X S S Y X 12
21
11 {}()110,S θS θi n
i i
i -==∑= (5)
至此,我们可以得出结论,由向量),Y (X i i ,在先计算K 的情况下,我们可以由式(5)逐步的计算旋转角度后得出向量),Y (X j j 。
计算的精度由n 的大小决定,式(5)中的n S 由每一步的具体情况而定。
3 CORDIC 算法的复数计算应用
复指数可以表示为θj e ,由欧拉恒等式θθθcos sin e j j +=知,只要知道角度
θ,就可以计算正余弦的值来表示这个复数。
已知角度,如何求:θsin 、θcos 。
这个问题我们可以转换为利用CORDIC 这种向量旋转的思想进行解析,建模如下(见图2):
),A(01
图2 向量旋转坐标图
起始向量→
OA 为[][]0,0,1,,i =θi i Y X ,终止向量→
OB 为[][]θθθθ,sin ,cos ,,=j j j Y X ,由→OA 经过n 步旋转到→
OB ,即可得到θsin 、θcos 。
设:Zn 表示经过n 步旋转后,得到的结果与θ的差值,即:∑=-=n
i i Z 0n θθ,
通过这样的假设,就可以得到:
⎩⎨
⎧<-≥=0
n 10
n 1Z Z Sn (6) 将(5)和(6)式结合,就可以得到它的逻辑表述:
)(Z(n))Z(n X(n)*Y(n))Y(n Y(n)*X(n))X(n Z(n)IF n n
n
----=++=+-=+≥2arctan 121210
)
(Z(n))Z(n X(n)*Y(n))Y(n Y(n)*X(n))X(n ELSE
n n
n
---+=+-=++=+2arctan 12121 计算所得的)1(+n X 、)1(+n Y 即为所求的θsin 、θcos 。
θ)
4 复指数转换模块的FPGA 实现
4.1 关键问题分析
(1) 复数θθθcos sin e j j +=,其中πθ20<≤。
由下列变换关系
α
)π(ααπ)(αα
)π(αα
π)(αsin 2
cos cos cos cos 2
sin sin sin -=+-=+=+=+
计算θsin 、θcos 时采用将θ转换成锐角α计算,然后在根据θ是第几象限来确定αsin 、αcos 的正负。
关系如表1: 表1
(2) 采用锐角的形式后,有2
0α<≤,在fpga 的实现中,角度
α我们采用比例
缩放变换成2
1
0<
≤π
α。
我们用16位二进制数表示这个角度,最高两位表示象限,其余14位表示相位值。
第几象限(2bit) 相位值(14bit) 我们知道,用二进制表示2
1
0<
≤π
α
的小数点后第1为0,所以我们表示相位值时从小数点第2位开始表示,这样可以提高表示精度。
(3) 由前面规定我们选取⎪⎭
⎫
⎝⎛=n n θ21arctan ,那么n n n S -=2tan θ。
Fpga 实现中,我
们采用13级迭代,我们可以得表2: 表2
图3 复数转换模块框图4.3 端口定义说明
phase_in input 输入相位,高两位表示在第几象限,低14位表示相位角中pi的系数的第二位小数开
始的数。
sin_out output 输出正弦值
cos_out output 输出余弦值
eps output 表示第i次旋转后剩余未旋转的角度
p_flag output 正余弦值输出标志
4.4 模块详细流程图
5 仿真验证
根据以上分析编写cos_sin_value.v 模块代码,见附件。
然后建立向量波形文件
cos_sin_value.vwf (见工程),根据要求在cos_sin_value.vwf 文件中编辑激励信号。
仿真一:
当输入相位角为30°时,即
6
π
,系数为1/6=0.0010101010101010,那么输入的16位相位角phase_in = 0001_0101_0101_0101。
仿真结果得:
sin_out = 0011_1111_1111_1110,cos_out = 0110_1110_1101_1100 仿真结果如下图
图5 仿真结果图
表3 仿真结果分析
6
π
θ=
理论值(第1位表示正负) 仿真结果 误差
θin s
0100_0000_0000_0000
(1/2=0.50) 0011_1111_1111_1110
(0.4999) -0.0001
θcos
0110_1110_1101_1001
(0.8660523=)
0110_1110_1101_1100
(
0.86608)
0.00003
仿真二:
当输入相位角为135°时,即
43π,变换成第一象限角为4
π
,系数为1/4=0.0100000000000,那么输入的
16位相位角phase_in =
0110_0000_0000_0000。
仿真结果得:
sin_out = 0101_1010_0000_0100,cos_out = 1010_0101_1111_1111 仿真结果如下图
图6 仿真结果图
表4 仿真结果分析
4
3πθ=
理论值(第1位表示正负) 仿真结果 误差
θin s
0101_1010_1000_0010
(0.707122=) 0101_1010_0000_0100
(0.7032) -0.0039
θcos
1010_0101_0111_1101 (0.70712
2
-=-)
1010_0101_1111_1111
(-
0.7031)
-0.0040
由上实验结果可知:仿真结果与理论结果基本一致,误差还是比较小的;如果想进一步缩小误差,可以增加迭代次数。
附件:
模块名:cos_sin_value.v 模块代码:
`timescale 1ns / 100ps
////////////////////////////////////////////////////////////////////////////////// // Company:
// Engineer:
// Create Date: 17/01/2013
// Design Name:
// Module Name:
// Project Name:
// Target Devices:
// Tool versions:
// Description:
// Dependencies:
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
////////////////////////////////////////////////////////////////////////////////// module cos_sin_value(
clk,
rst_n,
ena,
phase_in,
sin_out,
cos_out,
eps,
puc_zc_cordic_flag
);
parameter DATA_WIDTH=16; //定义数据位宽为16
parameter PIPELINE=16; //流水线级数为16
input clk;
input rst_n;
input ena;
input [DATA_WIDTH-1:0] phase_in; //输入相位
output [DATA_WIDTH-1:0] sin_out; //输出正弦值
output [DATA_WIDTH-1:0] cos_out; //输出余弦值
output [DATA_WIDTH-1:0] eps; //表示第i次旋转后剩余未旋转的角度
output puc_zc_cordic_flag; //正余弦值输出标志
reg [DATA_WIDTH-1:0] sin_out;
reg [DATA_WIDTH-1:0] cos_out;
reg [DATA_WIDTH-1:0] eps;
reg puc_zc_cordic_flag;
reg [DATA_WIDTH-1:0] phase_in_reg; //输入相位缓存
//这里的相位表示是这样的:最高位和次高位这两位表示象限
//(如00代表的第一象限,01代表的第二象限,10代表的第三象限,11代表的第四象限)
//,剩下的低十四位代表相位值(这里一个单位代表的度数是90/16384=0.005493)
// 矩阵相乘中间寄存器变量,用于13次迭代计算
reg [DATA_WIDTH-1:0] x0,y0,z0;
reg [DATA_WIDTH-1:0] x1,y1,z1;
reg [DATA_WIDTH-1:0] x2,y2,z2;
reg [DATA_WIDTH-1:0] x3,y3,z3;
reg [DATA_WIDTH-1:0] x4,y4,z4;
reg [DATA_WIDTH-1:0] x5,y5,z5;
reg [DATA_WIDTH-1:0] x6,y6,z6;
reg [DATA_WIDTH-1:0] x7,y7,z7;
reg [DATA_WIDTH-1:0] x8,y8,z8;
reg [DATA_WIDTH-1:0] x9,y9,z9;
reg [DATA_WIDTH-1:0] x10,y10,z10;
reg [DATA_WIDTH-1:0] x11,y11,z11;
reg [DATA_WIDTH-1:0] x12,y12,z12;
reg [DATA_WIDTH-1:0] x13,y13,z13;
reg [1:0] quadrant[PIPELINE:0]; //定义象限定义变量
reg [3:0] count; //时钟计数
integer i; //整型变量
always @(posedge clk or negedge rst_n) //正余弦值输出标志控制(在使能信号拉高的第16个时钟后)
begin
if(!rst_n)
begin
count<=4'b0000;
puc_zc_cordic_flag<=1'b0;
end
else
if(ena==1'b1)
begin
if(count==4'b1111)
begin
puc_zc_cordic_flag<=1'b1; //正余弦值输出标志置1 end
else begin
puc_zc_cordic_flag<=1'b0;
count<=count+1'b1;
end
end
else begin
puc_zc_cordic_flag<=1'bz;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
phase_in_reg<=16'h0000;
else
if(ena==1'b1)
begin
case(phase_in[15:14])
2'b00:phase_in_reg<=phase_in; //当前输入为第一象限的相位角
2'b01:phase_in_reg<=phase_in - 16'h4000; //-pi/2(当前输入为第二象限的相位角,故要减去pi/2)
2'b10:phase_in_reg<=phase_in - 16'h8000; //-pi(当前输入为第三象限的相位角,故要减去pi)
2'b11:phase_in_reg<=phase_in - 16'hC000; //-3pi/2(当前输入为第四象限的相位角,故要减去3pi/2)
default:;
endcase
end
else begin
phase_in_reg<=16'h0000;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x0<=16'h0000;
y0<=16'h0000;
z0<=16'h0000;
end
else
if(ena==1'b1)
begin
//m=1,旋转模式(这种模式可以用来计算一个输入角的正弦值和余弦值)
//x0=k,模校正因子的值
//y0=0
//z0=phase_in
x0 <= 16'h4DBA; //define aggregate constant
Xi=1/P=1/1.6467=0.60725(Xi=2^7*P=16'h4DBA)
y0 <= 16'h0000;
z0 <= phase_in_reg;
end
else begin
x0<=16'hzzzz;
y0<=16'hzzzz;
z0<=16'hzzzz;
end
end
//level_1(第一级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x1<=16'h0000;
y1<=16'h0000;
z1<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z0[15]==1'b0) //当前的相位值是正的
begin
x1 <= x0 - y0;
y1 <= y0 + x0;
z1 <= z0 - 16'h2000; //45deg
end
else //当前的相位值是负的
begin
x1 <= x0 + y0;
y1 <= y0 - x0;
z1 <= z0 + 16'h2000; //45deg
end
end
else begin
x1<=16'hzzzz;
y1<=16'hzzzz;
z1<=16'hzzzz;
end
end
//level_2(第二级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x2<=16'h0000;
y2<=16'h0000;
z2<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z1[15]==1'b0) //当前的相位值是正的
begin
x2 <= x1 -
{y1[DATA_WIDTH-1],y1[DATA_WIDTH-2:1]};//y1向右移一位且最高位不变
y2 <= y1 +
{x1[DATA_WIDTH-1],x1[DATA_WIDTH-2:1]};//x1向右移一位且最高位不变
z2 <= z1 - 16'h12E4; //26.565deg
end
else //当前的相位值是负的
begin
x2 <= x1 + {y1[DATA_WIDTH-1],y1[DATA_WIDTH-2:1]};
y2 <= y1 - {x1[DATA_WIDTH-1],x1[DATA_WIDTH-2:1]};
z2 <= z1 + 16'h12E4; //26.565deg
end
end
else begin
x2<=16'hzzzz;
y2<=16'hzzzz;
z2<=16'hzzzz;
end
end
//level_3(第三级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x3<=16'h0000;
y3<=16'h0000;
z3<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z2[15]==1'b0)
begin
x3 <= x2 -
{{2{y2[DATA_WIDTH-1]}},y2[DATA_WIDTH-2:2]};
y3 <= y2 +
{{2{x2[DATA_WIDTH-1]}},x2[DATA_WIDTH-2:2]};
z3 <= z2 - 16'h09FB; //14.036deg
end
else
begin
x3 <= x2 +
y3 <= y2 -
{{2{x2[DATA_WIDTH-1]}},x2[DATA_WIDTH-2:2]};
z3 <= z2 + 16'h09FB; //14.036deg
end
end
else begin
x3<=16'hzzzz;
y3<=16'hzzzz;
z3<=16'hzzzz;
end
end
//level_4(第四级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x4<=16'h0000;
y4<=16'h0000;
z4<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z3[15]==1'b0)
begin
x4 <= x3 -
{{3{y3[DATA_WIDTH-1]}},y3[DATA_WIDTH-2:3]};
y4 <= y3 +
z4 <= z3 - 16'h0511; //7.125deg
end
else
begin
x4 <= x3 +
{{3{y3[DATA_WIDTH-1]}},y3[DATA_WIDTH-2:3]};
y4 <= y3 -
{{3{x3[DATA_WIDTH-1]}},x3[DATA_WIDTH-2:3]};
z4 <= z3 + 16'h0511; //7.125deg
end
end
else begin
x4<=16'hzzzz;
y4<=16'hzzzz;
z4<=16'hzzzz;
end
end
//level_5(第五级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x5<=16'h0000;
y5<=16'h0000;
z5<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z4[15]==1'b0)
begin
x5 <= x4 -
{{4{y4[DATA_WIDTH-1]}},y4[DATA_WIDTH-2:4]};
y5 <= y4 +
{{4{x4[DATA_WIDTH-1]}},x4[DATA_WIDTH-2:4]};
z5 <= z4 - 16'h028B; //3.576deg
end
else
begin
x5 <= x4 +
{{4{y4[DATA_WIDTH-1]}},y4[DATA_WIDTH-2:4]};
y5 <= y4 -
{{4{x4[DATA_WIDTH-1]}},x4[DATA_WIDTH-2:4]};
z5 <= z4 + 16'h028B; //3.576deg
end
end
else begin
x5<=16'hzzzz;
y5<=16'hzzzz;
z5<=16'hzzzz;
end
end
//level_6(第六级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x6<=16'h0000;
y6<=16'h0000;
z6<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z5[15]==1'b0)
begin
x6 <= x5 -
{{5{y5[DATA_WIDTH-1]}},y5[DATA_WIDTH-2:5]};
y6 <= y5 +
{{5{x5[DATA_WIDTH-1]}},x5[DATA_WIDTH-2:5]};
z6 <= z5 - 16'h0145; //1.789deg
end
else
begin
x6 <= x5 +
{{5{y5[DATA_WIDTH-1]}},y5[DATA_WIDTH-2:5]};
y6 <= y5 -
{{5{x5[DATA_WIDTH-1]}},x5[DATA_WIDTH-2:5]};
z6 <= z5 + 16'h0145; //1.789deg
end
end
else begin
x6<=16'hzzzz;
y6<=16'hzzzz;
z6<=16'hzzzz;
end
end
//level_7(第七级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x7<=16'h0000;
y7<=16'h0000;
z7<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z6[15]==1'b0)
begin
x7 <= x6 -
{{6{y6[DATA_WIDTH-1]}},y6[DATA_WIDTH-2:6]};
y7 <= y6 +
{{6{x6[DATA_WIDTH-1]}},x6[DATA_WIDTH-2:6]};
z7 <= z6 - 16'h00A2; //0.895deg
end
else
begin
x7 <= x6 +
{{6{y6[DATA_WIDTH-1]}},y6[DATA_WIDTH-2:6]};
y7 <= y6 -
{{6{x6[DATA_WIDTH-1]}},x6[DATA_WIDTH-2:6]};
z7 <= z6 + 16'h00A2; //0.895deg
end
end
else begin
x7<=16'hzzzz;
y7<=16'hzzzz;
z7<=16'hzzzz;
end
end
//level_8(第八级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x8<=16'h0000;
y8<=16'h0000;
z8<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z7[15]==1'b0)
begin
x8 <= x7 -
{{7{y7[DATA_WIDTH-1]}},y7[DATA_WIDTH-2:7]};
y8 <= y7 +
{{7{x7[DATA_WIDTH-1]}},x7[DATA_WIDTH-2:7]};
z8 <= z7 - 16'h0051; //0.447deg
end
else
begin
x8 <= x7 +
y8 <= y7 -
{{7{x7[DATA_WIDTH-1]}},x7[DATA_WIDTH-2:7]};
z8 <= z7 + 16'h0051; //0.447deg
end
end
else begin
x8<=16'hzzzz;
y8<=16'hzzzz;
z8<=16'hzzzz;
end
end
//level_9(第九级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x9<=16'h0000;
y9<=16'h0000;
z9<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z8[15]==1'b0)
begin
x9 <= x8 -
{{8{y8[DATA_WIDTH-1]}},y8[DATA_WIDTH-2:8]};
y9 <= y8 +
z9 <= z8 - 16'h0028; //0.223deg
end
else
begin
x9 <= x8 +
{{8{y8[DATA_WIDTH-1]}},y8[DATA_WIDTH-2:8]};
y9 <= y8 -
{{8{x8[DATA_WIDTH-1]}},x8[DATA_WIDTH-2:8]};
z9 <= z8 + 16'h0028; //0.223deg
end
end
else begin
x9<=16'hzzzz;
y9<=16'hzzzz;
z9<=16'hzzzz;
end
end
//level_10(第十级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x10<=16'h0000;
y10<=16'h0000;
z10<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z9[15]==1'b0)
begin
x10 <= x9 -
{{9{y9[DATA_WIDTH-1]}},y9[DATA_WIDTH-2:9]};
y10 <= y9 +
{{9{x9[DATA_WIDTH-1]}},x9[DATA_WIDTH-2:9]};
z10 <= z9 - 16'h0014; //0.112deg
end
else
begin
x10 <= x9 +
{{9{y9[DATA_WIDTH-1]}},y9[DATA_WIDTH-2:9]};
y10 <= y9 -
{{9{x9[DATA_WIDTH-1]}},x9[DATA_WIDTH-2:9]};
z10 <= z9 + 16'h0014; //0.112deg
end
end
else begin
x10<=16'hzzzz;
y10<=16'hzzzz;
z10<=16'hzzzz;
end
end
//level_11(第十一级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x11<=16'h0000;
y11<=16'h0000;
z11<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z10[15]==1'b0)
begin
x11 <= x10 -
{{10{y10[DATA_WIDTH-1]}},y10[DATA_WIDTH-2:10]};
y11 <= y10 +
{{10{x10[DATA_WIDTH-1]}},x10[DATA_WIDTH-2:10]};
z11 <= z10 - 16'h000A; //0.056deg
end
else
begin
x11 <= x10 +
{{10{y10[DATA_WIDTH-1]}},y10[DATA_WIDTH-2:10]};
y11 <= y10 -
{{10{x10[DATA_WIDTH-1]}},x10[DATA_WIDTH-2:10]};
z11 <= z10 + 16'h000A; //0.056deg
end
end
else begin
x11<=16'hzzzz;
y11<=16'hzzzz;
z11<=16'hzzzz;
end
end
//level_12(第十二级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x12<=16'h0000;
y12<=16'h0000;
z12<=16'h0000;
end
else if(ena==1'b1)
begin
if(z11[15]==1'b0)
begin
x12 <= x11 -
{{11{y10[DATA_WIDTH-1]}},y11[DATA_WIDTH-2:11]};
y12 <= y11 +
{{11{x10[DATA_WIDTH-1]}},x11[DATA_WIDTH-2:11]};
z12 <= z11 - 16'h0005; //0.028deg
end
else
begin
x12 <= x11 +
{{11{y10[DATA_WIDTH-1]}},y11[DATA_WIDTH-2:11]};
y12 <= y11 -
{{11{x10[DATA_WIDTH-1]}},x11[DATA_WIDTH-2:11]};
z12 <= z11 + 16'h0005; //0.028deg
end
end
else begin
x12<=16'hzzzz;
y12<=16'hzzzz;
z12<=16'hzzzz;
end
end
//level_13(第十三级迭代)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x13<=16'h0000;
y13<=16'h0000;
z13<=16'h0000;
end
else
if(ena==1'b1)
begin
if(z12[15]==1'b0)
begin
x13 <= x12 -
{{12{y10[DATA_WIDTH-1]}},y12[DATA_WIDTH-2:12]};
y13 <= y12 +
{{12{x10[DATA_WIDTH-1]}},x12[DATA_WIDTH-2:12]};
z13 <= z12 - 16'h0002; //0.014deg
end
else
begin
x13 <= x12 +
{{12{y10[DATA_WIDTH-1]}},y12[DATA_WIDTH-2:12]};
y13 <= y12 -
{{12{x10[DATA_WIDTH-1]}},x11[DATA_WIDTH-2:12]};
z13 <= z12 + 16'h0002; //0.014deg
end
end
else begin
x13<=16'hzzzz;
y13<=16'hzzzz;
z13<=16'hzzzz;
end
end
//为了对齐数据,保留相位信息
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
for(i=0; i<=PIPELINE; i=i+1)
quadrant[i]<=2'b00;
else
if(ena==1'b1)
begin
for(i=0; i<PIPELINE; i=i+1)
quadrant[i+1]<=quadrant[i];
quadrant[0]<=phase_in[15:14];
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sin_out <= 16'h0000;
cos_out <= 16'h0000;
eps <= 16'h0000;
end
else
if(ena==1'b1)
case(quadrant[14]) //前面13级迭代完成
2'b00:begin //输入的是第一相位的相位角的正余弦输出
sin_out <= y13;
cos_out <= x13;
eps <= z13;
end
2'b01:begin //输入的是第二相位的相位角的正余弦输出
sin_out <= x13; //由于是第二象限的相位角,故正弦输出为正
cos_out <= ~(y13) + 1'b1; //由于是第二象限的相位角,故余弦输出为负
//(这个时候的输出要用补码表示,即对y13进行取反加1操作)
eps <= z13;
end
2'b10:begin //输入的是第三相位的相位角的正余弦输出
sin_out <= ~(y13) + 1'b1; //由于是第三象限的相位角,故正弦弦输出为负
//(这个时候的输出要用补码表示,即对y13进行取反加1操作)
cos_out <= ~(x13) + 1'b1; //由于是第三象限的相位角,故余弦输出为负
//(这个时候的输出要用补码表示,即对x13进行取反加1操作)
eps <= z13;
end
2'b11:begin //输入的是第四相位的相位角的正余弦输出
sin_out <= ~(x13) + 1'b1; //由于是第四象限的相位角,故正弦弦输出为负
//(这个时候的输出要用补码表示,即对x13进行取反加1操作)
cos_out <= y13;
eps <= z13; //表示第13次旋转后剩余未旋转角度
end
endcase
end
endmodule。