毕业设计论文
基于FPGA复指数转换模块设计
摘要:复指数运算会利用在很多通信数字处理领域中,比如ofdm系统调制、
加扰等。CORDIC算法是在很多角度计算方面有着广泛应用经典算法,
本文经过考虑FPGA结构、精度局限和速度要求,采取流水线技术(pipeline),
在FPGA上用CORDIC算法实现对复数处理。
关键词:坐标旋转数字计算;FPGA; 复指数
1 引言
FPGA以其灵活性和使用方便在现今数字领域已经得到了广泛应用。
但FPGA实现数字系统也有其本身不足,其一是器件资源门阵列规模限制,
其二是单元延迟限制。所以,这就需要设计者充足考虑器件实际工作能力。
假如用传统除法器、乘法器等计算方法,需要占用大量FPGA资源,
复数计算在数字领域尤其是数字通信领域是一个应用很广泛计算,
这么就大大节省了FPGA资源,从而能够满足设计者要求。
2 CORDIC算法介绍
CORDIC(CoordinateRotationDigitalComputer), 又名:坐标旋转数字计算,是J.
Voider等人于1959年在设计美国航空导航控制系统过程中提出来一个算法。
下面就简明地介绍一下CORDIC算法基础数学思想。
图1所表示,将向量(Xi,Yi)旋转角,得到一个新向量(Xj,Yj),那么有:
XjRcos(θβ)XicosθYisinθ
YjRsin(θβ)XisinθYicosθ (1)
式中R为圆周半径,为旋转角度。写成矩阵形式:
X
Yj
j
cos
sinθ
θ
cos
sin
θ
θ
X
Yi
i
cosθ
tan
1
θ
1
Y
(2)
假 | 如 | 假 | 设 | 是 | 由 | n个 | n | 角 | 度 | 叠 | 加 | 而 | 成 | , |
那么依据式(2)得出每一步叠加操作需要根据式(3)操作。
X
Yn
n
1
1
cosθn
tan
1
θn
tan
1
θn
X
Yn
n
(3)
利用式子(3)经过n步叠加能够表示由向量
X 1 tanθ 1 (X
tan
j,Y
θ
j)
,以下表示:
X
这么选择n方便了 tann计算,即 tannSn2n,式(4)前面 cosn
能够去累积乘极限即:
K | | | cos | | co s | | arctan( | 1 | ) | | | 0 . 607253 | |||||||
| |
| n |
| | | | 2 | n | | | | |
假如我们在设计系统中提前计算K,那么当抛开K不算时,
式(3)就能够表示成式(5):
X
Yn
n
1
1
Sn
1
2n
S
1
n2n
X
Yn
n
n
θ
i0 S iθiS i 1 , 1 (5)
至此, 我们能够得出结论,由向量(X i ,Y i ) , 在先计算K情况下,
我们能够由式(5)逐步计算旋转角度后得出向量 | (X | j | ,Y | j | ) | 。 | |||
计算精度由n大小决定,式(5)中 | S | n | 由每一步具体情况而定。 |
3 CORDIC算法复数计算应用
复指数能够表示为ej,由欧拉恒等式ejsinjcos知,只要知道角度,
就能够计算正余弦值来表示这个复数。已知角度,怎样求:sin、 cos。
这个问题我们能够转换为利用CORDIC这种向量旋转思想进行解析,
建模以下(见图2):
Y
B( | cos | θ, | sin | θ) |
θ
O A( 0 )
图2 向量旋转坐标图
由OA经过n步旋转到OB,即可得到sin、cos。
n
设:Zn表示经过n步旋转后,得到结果和差值,即:Zni,
i0
经过这么假设,就能够得到:
Sn | | 1 1 | Z | n | | 0 | (6) |
Z | n | | 0 |
将(5)和(6)式结合,就能够得到它逻辑表述:
IF | Z(n) | | 0 | ) |
| ||||||||||||||||
X(n | | 1 | ) | | X(n) | | Y(n)* | 2 | | n | |||||||||||
Y(n | | 1 | ) | | Y(n) | | X(n)* | 2 | | n | |||||||||||
Z(n | | 1 | ) | | Z(n) | | arctan | ( | 2 | | n |
ELSE
X(n | | 1 | ) | | X(n) | | Y(n)* | 2 | | n | ) | 即为所求 | sin | 、 | cos。 | |||||||
Y(n | | 1 | ) | | Y(n) | | X(n)* | 2 | | n | ||||||||||||
Z(n | | 1 | ) | | Z(n) | | arctan | ( | 2 | | n | |||||||||||
计算所得 | X | ( | 1 ) | 、 | Y | ( | 1 ) |
4 复指数转换模块FPGA实现
4.1关键问题分析
(1) 复数 | e | j | | sin | | j | cos, 其中 | 0 | | | 2。由下列变换关系 | ||||||||||||||||||||||
sin | (α | | π) | | sin | α | sin (απ 2 cos (απ 2 | ) | | cos | α | ||||||||||||||||||||||
cos | (α | | π) | | | cos | α | ) | | | sin | α | |||||||||||||||||||||
计算 | sin | 、 | cos时采取将 | 转换成锐角 | 计算, 然后在依据 | | |||||||||||||||||||||||||||
是第几象限来确定sin、cos正负。关系如表1: | |||||||||||||||||||||||||||||||||
(2) 采取锐角形式后, 有 | 0 | | | | , 在fpga实现中, 角度 | | |||||||||||||||||||||||||||
2 | |||||||||||||||||||||||||||||||||
我们采取百分比缩放变换成 | 0 | | | | 1 | 。我们用16位二进制数表示这个角度, | |||||||||||||||||||||||||||
2 |
最高两位表示象限,其它14位表示相位值。
0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
第几象限(2bit) 相位值(14bit)
我们知道,用二进制表示0 1 2 小数点后第1为0,
所以我们表示相位值时从小数点第2位开始表示,这么能够提升表示精度。
(3) 由前面要求我们选择 | θ | | | arctan | | 1 | | , 那么 | tan | | S |
| 2 | | n | 。 Fpga实现中, | |
| | n | | | | 2 | n | | | n | | | n | |
| | |
我们采取13级迭代,我们能够得表2:
表2
n | 实际角度n | n | 相位值十六进制表示 | ||
1 | 45deg |
| 16'h | ||
2 | 26.565deg |
| 16'h12E4 | ||
3 | 14.036deg |
| 16'h09FB | ||
4 | 7.125deg | 1 | 16'h0511 | ||
5 | 3.576deg |
| 16'h0511 | ||
6 | 1.789deg | 1 | 16'h0145 | ||
7 | 0.895deg | 豆 | 网16'h00A2 | ||
| | | | ||
| | | | ||
10 | 0.112deg | 1 | 16'h0014 | ||
11 | 0.056deg |
| 16'h000A | ||
12 | 0.028deg |
| 16'h0005 | ||
13 | 0.014deg |
| 16'h0002 |
4.2复数转换模块框图
[15:0]phase_in [15:0]sin_out
Clk复数 [15:0]cos_out
ena 符号
转换
Rst_n
模块 p_flag
图3复数转换模块框图
4.3端口定义说明
|
4.4模块具体步骤图
5 仿真验证
依据以上分析编写cos_sin_value.v模块代码,见附件。然后建立向量波形文件cos_sin_value.vwf(见工程),依据要求在cos_sin_value.vwf文件中编辑激励信号。
仿真一:
当输入相位角为30° 时, 即
| , 系数为1/6=0.1010, |
6 | |
那么输入16位相位角phase_in= 0001_0101_0101_0101。仿真结果得: sin_out= 0011_1111_1111_1110, cos_out = 0110_1110_1101_1100仿真结果以下图
图5仿真结果图
表3仿真结果分析
|
仿真二:
当输入相位角为135°时, 即 | 3 | , 变换成第一象限角为 | | , 系数为1/4=0.0, |
| 4 | | 4 | |
那么输入16位相位角phase_in= 0110_0000_0000_0000。仿真结果得: sin_out= 0101_1010_0000_0100, cos_out = 1010_0101_1111_1111仿真结果以下图
图6仿真结果图
表4仿真结果分析
|
附件:
模块名: cos_sin_value.v 模块代码:
`timescale 1ns / 100ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Create Date: 17/01/
// Design Name:
// Module Name:
// Project Name:
// Target Devices:
// Tool versions:
//Description:
// Revision: // Additional Comments:
//////////////////////////////////////////////////////////////////////////////////
module cos_sin_value(
clk,
rst_n,
ena,
phase_in,
sin_out,
eps, | cos_out, |
|
|
puc_zc_cordic_flag
);
parameter DATA_WIDTH=16; parameter PIPELINE=16;
input clk;
input rst_n;
input ena;
//定义数据位宽为16
//流水线级数为16
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次旋转后剩下未旋转角度
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 [3:0] count; //时钟计数
integeri; //整型变量
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
elsebegin
puc_zc_cordic_flag<=1'b0; count<=count+1'b1;
end
else begin 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
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
x0<=16'h0000;
y0<=16'h0000;
z0<=16'h0000;
end | if(ena==1'b1) |
|
else | ||
|
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;
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'h; //45deg
end
else //目前相位值是负
begin
x1 <= x0 + y0;
y1 <= y0 - x0;
end
x1<=16'hzzzz;
y1<=16'hzzzz;
z1<=16'hzzzz;
end
end
//level_2(第二级迭代)
always@(posedge clk or negedge 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
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;
else end
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 + {{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
end
else begin
x3<=16'hzzzz;
y3<=16'hzzzz;
z3<=16'hzzzz;
end
end
//level_4(第四级迭代)
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 + {{3{x3[DATA_WIDTH-1]}},x3[DATA_WIDTH-2:3]};
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]};
end z4 <= z3 + 16'h0511; //7.125deg
x4<=16'hzzzz;
y4<=16'hzzzz;
z4<=16'hzzzz;
end
end
//level_5(第五级迭代)
always@(posedge clk or negedge 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
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;
else end
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(第七级迭代)
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]};
end z7 <= z6 + 16'h00A2; //0.895deg
x7<=16'hzzzz;
y7<=16'hzzzz;
z7<=16'hzzzz;
end
end
//level_8(第八级迭代)
always@(posedge clk or negedge 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
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
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;
else end
if(z8[15]==1'b0)
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
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(第十级迭代)
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]};
end z10 <=z9 + 16'h0014; //0.112deg
x10<=16'hzzzz;
y10<=16'hzzzz;
z10<=16'hzzzz;
end
end
//level_11(第十一级迭代)
always@(posedge clk or negedge 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
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;
else if(ena==1'b1) end
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
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
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)
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操作)
故余弦输出为负
//(这个时候输出要用补码表示, 即对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