资源描述
数字系统设计课程设计
总结报告
学 院 电子与信息学院
班 级 09级信工二班
组 员 李叙琼,王 烁,秦子然,
基于FPGA流水线结构的cordic算法实现
一, 背景
当前最基本的运算就是加法,减法,乘法,除法。但那是随之数字化时代的来临,机器需要处理的数据运算不再仅仅是加减乘除了,会更多涉及到例如正弦,余弦,对数,方根倒数等超越函数(不能用有限的加减乘除开方乘方来表示的函数),例如游戏《雷神之锤iii》用到的快速平方根倒数运算就是一个复杂运算的应用,这些运算不像加减乘除那么简单,那么具有绝对的精度,计算的过程涉及到多次乘除加减,移位,或者近似取值,而如何利用不同的算法来实现这些复杂运算,让其能够在合理的资源占有率的基础上以最快的时间完成运算呢?就成了当前研究的重要课题。Cpu运算器速度上面的不断升级要求普通运算的所用时间减少,从而减少功耗提高速度。对与FPGA来说,如何利用硬件的优势来实现这些复杂的运算?就是我们这次课程设计需要探讨的话题。
超越函数的应用领域已经十分广泛,涉及到航空航天,机器人技术,实时语音,图像处理,滤波技术,FFT变换等多个领域,随着各个领域的深入研究,画面及精度的要求提高务必要求运算器的速度和精度随着提高。当前硬件实现超越函数的算法有多种,按照数学公式一斤对应的实现方式的不同,可以分为查找表,多项式近似法,基于查找表的多项式结合方法,有理数近似和逐位法五种方法。经过对不同算法的分析和比较,我们小组采用cordic算法作为研究对象,主要利用altera公司的cyclone ii 器件以及quartusii集成开发平台实现正余弦的运算。
二, IEEE 754单精度浮点数运算标准
IEEE754规定,单精度浮点数基数为2,由数符、阶码和尾数构成,各部分所占位数如下:
尾数中隐含存储着一个1,因此在计算尾数的真值时比一般形式要多一个整数1。阶码E的存储形式是127的偏移。例如:将数值-0.5按IEEE754单精度格式存储,先将-0.5换成二进制并写成标准形式:-0.5(10进制)=-0.1(2进制)=-1.0×2-1(2进制,-1是指数),这里s=1,M为全0,E-127=-1,E=126(10进制)=01111110(2进制),则存储形式为:
1 01111110 000000000000000000000000=BF000000(16进制)
浮点运算过程中会出现多种特殊值,陈列如下:
1. 零值:指数部分全部为0,并且尾数全部为0,则表示为浮点0.0,并且规定-0 = +0
2. 非规格化值:指数全部为0,尾数非0,则表示非规格化的值,16进制看到的就是[80xxxxxx]h或者[00xxxxxx]h
3. 无穷值:指数全部为1,尾数全部为0,则根据符号位分别表示正无穷大和负无穷大,16进制看到的就是[FF800000]h或者[7F800000]h
4. NAN:指数全部为1,尾数非0,则表示这个值不是一个真正的值(Not A Number)。NAN又分成两类:QNAN(Quiet NAN)和SNAN(Singaling NAN)。QNAN的尾数部分最高位定义为1,SNAN最高位定义为0;QNAN一般表示未定义的算术运算结果,例如除0运算;SNAN一般被用于标记未初始化的值,以此来捕获异常。
三, Cordic算法简介
Cordic算法(The Coordinate Rotational Digital Computer)是一种用于计算一些常用基本运算函数和算术操作的迭代算法。从广义上来讲是一种数值计算逼近的方法,其基本思想是通过不断的偏移角度从而逼近所需旋转角度的一种方法,由于这些固定的角度与计算的基数相关,所以运算只需进行移位及加减操作,不用进行传统计算中所用到的乘法器及除法器,从而节省了大量的硬件资源,同时节省很多的时间,众所周知,浮点乘法器及除法器所需要用到的硬件资源是很大的,在quartus ii中浮点的加法器IP核都至少需要用到八个时钟才能完成一次运算,如果是乘法运算则需要更多时钟周期。从而说明,利用cordic算法来做FPGA的硬件实现有利于节省空间及时间的资源,接下来介绍cordic算法的基本原理及算法的实现可行性。
(1)、cordic算法原理
CORDIC算法包含圆周系统,线性系统,双曲系统三种旋转系统。本文仅以圆周系统推导如下。该系统完成的是一个平面坐标旋转如图1所示,可以看出,将向量( Xi, Yi) 旋转θ角,得到一个新的向量( Xi, Yi) ,那么有:
Xj=Rcos(θ+β)=Xicosθ-Yisinθ
Yj=Rsin(θ+β)=Xisinθ + Yicosθ
式中R为圆周的半径,θ为旋转角度。写成矩阵形式:
Xj Yj=cosθ-sinθsinθcosθXi Yi
使用迭代的方法,旋转的角度可以在多步之内完成,每一步的旋转完成其中的一小部分,多步之后将会完成一个平面旋转。旋转等式由公式(2) 定义,消除cosθn因子得到单步旋转等式[1- 2]为
Xn+1 Yn+1=cosθn-sinθnsinθncosθnXn Yn
=cosθn1-tanθntanθn1Xn Yn (3)
公式(3) 中每一步的旋转角度为:θn=Snarctan12n,其中n=0∞Snθn=θ,即所有迭代角之
和必须等于旋转角度。Sn={ - 1; +1}, Sn的符号决定了向量的旋转方向,对于每一步旋转角Zn如下:
Zn=θ-i=0n-1Siθi (4)
其中Sn为Zn的符号函数,Sn=-1, Zn<0+1, &Zn≥0 (5) 因为cosθn=cos(arctan12n),随着迭代次数
的增加,它将收敛于一个常数K,即
K=1P=n=0Ncosarctan12n=n=0N11+2-2n (6)
暂不考虑这个常数增益,由公式(3) 、公式(4) 和公式(5) 得到:
Xn+1 Yn+1=cosθn1-Sn2-2nSn2-2n1Xn Yn (7)
再通过N次迭代后,提取常数增益K则有:
Xj Yj=n=0Ncosθn1-Sn2-2nSn2-2n1Xi Yi=K*n=0N1-Sn2-2nSn2-2n1Xi Yi (8)
K取决于迭代次数N。对于所有的初始向量和所有的旋转角度而言, K是一个常数。通常把K称作聚焦常数。
(2)、算法可行性
CORDIC算法有旋转模式和向量模式两种计算模式,这里只介绍旋转模式。在旋转模式中,Z为初始化需要旋转的角,当Z旋转变为0时,公式变化如下:
Xn+1=Xn-SnYn2-n
Yn+1=Yn+SnXn2-n
Zn+1=Zn-Sntan-1(2-n)
经过N次迭代后,CORDIC公式的输出变为:
Xn+1=P[X0cosZ0-Y0sinZ0]
Yn+1=P[Y0cosZ0+X0sinZ0]
其中P=n=0N1+2-2n
Zn+1=0 (10)
如果X0=1P,Y0=0,Z0=α,那么N次迭代后CORDIC公式的输出变为:
Xn+1,Yn+1,Zn+1=cosα,sinα,0 (11)
由公式(11)的分析可以看出,CORDIC算法在圆周系统的旋转模式可以用来计算一个输入角的正弦、余弦等。
四, FPGA流水线结构
迭代结构是直接从CORDIC方程转换过来的,其结构如图2所示。从图中可以看到,初始值通过多路进入到寄存器中,当时钟到来时,a,b寄存器中的数据分成两路,一路送到移位器,一路直接送到加(减)法器,与从另一移位器来的数据做运算后,经过多路器又送回到寄存器。移位器随着迭代次数的增加,其移位数也随之增加。c寄存器中的数据则直接送到加(减)法器中,与来自查表中的数据进行运算,随着迭代次数增加,其查找表的地址随之增加,计算的精度逐步提高,当然耗费的资源也就越多。因此,在设计中应根据需要,合理确定迭代次数。
五, Cordic算法的硬件实现方案(代码详见附录)
利用IEEE 754标准固然可以达到很高的精度,但是如果作为工程应用来说,某些精度又是可以忽略的,本设计是基于工程应用的,在牺牲一定精度的基础上做到尽量与单精度浮点数系统进行兼容,也就是说,在经过cordic运算之前的数据是IEEE 754格式的,但是cordic运算器是定点数运算的,首先将单精度浮点数转化为定点数,之后进行正余弦运算,最终得出结果。这样子舍弃精度的可行性来自于两个方面:第一,该cordic算法可支持角度输入范围为(-90°—+90°),所以理论上可以忽略输入值大小问题:第二,正余弦结果都是取近似结果,通过验证,14位定点数可以达到工程要求的精度标准。故采用上述设计方法。设计过程分为两个模块,一个是将IEEE754单精度浮点数转化为定点数的函数,另一个cordic的定点运算。下面对两个函数进行详细的分析。
1) IEEE 754 转定点数
模块名:ieee7542point(clk,rst_n,inp,pointdata);
出入参数说明:clk:时钟。
rst_n : 异步复位信号输入。
Inp:三十二位浮点数输入,规定为ieee754格式,切指数范围为0——127,因为为了配合之前cordic算法的±90的输入。
Pointdata:输出数据,为14位的定点数,一个符号位,一个整数位,五个预留扩展位,八个小数位。格式如下:
符号位1位
预留位5位
整数1位
小数位7位
模块说明:模块将输入的32位ieee754浮点数转化为补码的形式,仅取浮点数的尾数高七位作为转化后计算的精度,精度不高,这受到定点数本身的精度不高所限制,也出于与cordic模块的兼容考虑,cordic是通过迭代次数来实现精度的,当迭代的次数仅为9次,七位小数位已经足够。如果想要增加迭代次数,可以通过预留的位数继续增加。
2) Cordic算法的定点实现
模块名:cordic_test
模块结构:全流水线并行结构。
延迟:第一个结果有九个时钟的延迟,cordic算法是通过迭代来提高精度的,出于速度和资源,精度多方面考虑,该模块折中选择迭代九次。
端口参数说明:cordic_test(clk,rst_n,inp,res_sin,res_cos);
clk : 时钟信号输入端,一位。
rst_n : 异步复位输入端,一位。
inp : 十四位定点数输入端,采用补码形式输入,输入范围±90度,采用弧度形式输入。
res_sin,res_cos : 十三位输出端,也是带符号补码形式。
所有过程变量:均未补码形式。
六, 实验结果
本设计采用Synplify Pro 9.6.2进行综合,采用modelsim 6.5进行仿真,仿真结果如下所示:
1、 IEEE 754 转定点数的综合结果
2、 Cordic算法的综合结果
3、仿真结果
对其中几组数据进行详细分析得到下表:
Inp
Res_sin
Res_cos
0度(14'h00)
0.0078(0x0001)
0.9843(0x7e)
30度(14’h0043)
0.4922(0x003f)
0.8679(0x006f)
-30度(14’h3fbd)
-0.5000(0x1fc0)
0.8750(0x0070)
90度(14’h00C9)
0.9843(0x7e)
0.0078(0x0001)
-90度(14’h3f37)
-1.000(0x1f80)
0.0000(0x0000)
结果分析:设计中采用流水线结构,第九个时钟以后,每个时钟都会产生一个结果,是一种高速度的运算器,从综合的结果看,运算器的运算速度可以达到200M以上,满足一般工程应用的需求。从采样出来的几组经典数据来看,也能够充分验证该运算器的精度,同时证明该设计的合理性和正确性。
七, 实验感想
一周的数字系统课程设计到今天就要告一段落了。总体给人的感觉还是挺难得。平时做实验的时候,并没有很多的实验原理需要我们自己去了解,而且也都是课本上的东西。而这次的课程设计,我们则是要对Cordic算法了解一二,这样才能进行下面的编程设计和后续作业。在这次课设中,算法的理解对我来说是最难的。有很多的公式需要我们自己去理解清楚,在推导公式的过程中,碰了很多的壁,可以说是步步维艰。不过,虽然到现在还是有些一知半解的,但是还是从中学到了一些新思路和处理问题的方式,也是我收获比较大的地方。总之,在以后的学习过程中,还是要踏踏实实,开放思维,这样才能取得更好的学习效果。
秦子然
经过一周的奋斗课程设计也暂时告一个段落,虽然因为管脚太多无法进行板极调试更加因为该运算器本来就仅仅作为系统的内部运算器使用,在开发板上面的结果并没有必然的重要性,主要以仿真为主,需要其他模块进行配合使用,因此没有独立运行的必要性。故我们小组不采用板极调试。仅仅注重算法的设计和实现。对我们的数学和verilog的硬件设计提出了很大的要求,但是我们还是克服了多种困难,最终完成任务。
李叙琼
浮点数运算在现代计算机处理器中起着十分重要的作用,其占用的的时间资源和空间资源对于处理器的设计至关重要。本次实验中所做的,是用移位和加减运算来代替乘除,计算某些超越函数,相比过去利用乘法除法器的做法,这将大大提高运算的速度,的确是一个很大的进步。本次实验过程中,首先是资料收集,在充分理解资料内容的基础上,在进行具体的设计,虽然自己做的工作相对较少,但对于浮点数运算的认识还是加深了很多。
王烁
八, 附录
1, ieee754topoint源代码:
module ieee7542point(clk,rst_n,inp,pointdata);
parameterDataWidth = 32;
parameterEbits = 8 ;
parameterFbits = 23 ;
parameterSbits = 1 ;
parameterDataWidth_point = 14 ;
parameterFraWidth = 8 ;
inputclk,rst_n;
input [DataWidth-1:0] inp ;
output [DataWidth_point-1:0] pointdata ;
reg [FraWidth-1:0] temp;
reg [FraWidth-1:0] Fra;
wire [Ebits-1:0] Edata ;
regSdata ;
//assign Fra = {1'b1,inp[Fbits-1:Fbits-7]};
assignEdata = inp[DataWidth-2:DataWidth-9];
//assign Sdata = inp[DataWidth-1] ;
reg [FraWidth-1:0] shift;
always@(posedgeclk , negedgerst_n)
begin
if(!rst_n)
begin
shift<= 8 ;
end
else
begin
if(Edata<8'h77)
begin
shift<= 8'h08 ;
Sdata<= inp[DataWidth-1] ;
Fra <= {1'b1,inp[Fbits-1:Fbits-7]};
end
else
begin
shift<= 8'h7f - Edata ;
Sdata<= inp[DataWidth-1] ;
Fra <= {1'b1,inp[Fbits-1:Fbits-7]};
end
end
end
reg [DataWidth_point-1:0] pointdata;
always @(posedgeclk , negedgerst_n)
begin
if(!rst_n)
begin
pointdata<= 14'b0 ;
end
else
begin
if(shift==8'h08)
begin
pointdata<= 14'b0;
end
else
begin
if (Sdata==1)
begin
case(shift)
8'h07 :pointdata<= {{13{1'b1}},Fra[Ebits-1]};
8'h06 :pointdata<= {{12{1'b1}},~Fra[Ebits-1],Fra[Ebits-2]};
8'h05 :pointdata<= {{11{1'b1}},~Fra[Ebits-1:Ebits-2],Fra[Ebits-3]};
8'h04 :pointdata<= {{10{1'b1}},~Fra[Ebits-1:Ebits-3],Fra[Ebits-4]};
8'h03 :pointdata<= {{ 9{1'b1}},~Fra[Ebits-1:Ebits-4],Fra[Ebits-5]};
8'h02 :pointdata<= {{ 8{1'b1}},~Fra[Ebits-1:Ebits-5],Fra[Ebits-6]};
8'h01 :pointdata<= {{ 7{1'b1}},~Fra[Ebits-1:Ebits-6],Fra[Ebits-7]};
8'h00 :pointdata<= {{ 6{1'b1}},~Fra[Ebits-1:Ebits-7],Fra[0]};
default :pointdata<= 14'b0;
endcase
end
else
begin
case(shift)
8'h07 :pointdata<= {{13{1'b0}},Fra[Ebits-1]};
8'h06 :pointdata<= {{12{1'b0}},Fra[Ebits-1:Ebits-2]};
8'h05 :pointdata<= {{11{1'b0}},Fra[Ebits-1:Ebits-3]};
8'h04 :pointdata<= {{10{1'b0}},Fra[Ebits-1:Ebits-4]};
8'h03 :pointdata<= {{ 9{1'b0}},Fra[Ebits-1:Ebits-5]};
8'h02 :pointdata<= {{ 8{1'b0}},Fra[Ebits-1:Ebits-6]};
8'h01 :pointdata<= {{ 7{1'b0}},Fra[Ebits-1:Ebits-7]};
8'h00 :pointdata<= {{ 6{1'b0}},Fra[Ebits-1:0]};
default :pointdata<= 14'b0;
endcase
end
end
end
end
endmodule
2, cordic_test源代码:
modulecordic_test(clk,rst_n,inp,res_sin,res_cos);
parameterDataWidth = 13;
parameterDataWidth_Z = 14;
inputclk;
inputrst_n;
input [DataWidth_Z-1:0] inp ;
output [DataWidth-1:0] res_sin,res_cos ;
// regclk,rst_n;
reg [DataWidth-1:0] res_sin,res_cos ;
// reg [DataWidth_Z-1:0] inp ;
//???x0?y0?z0
reg [DataWidth-1:0] x0,y0;
reg [DataWidth_Z-1:0] z0 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x0 = {(DataWidth){1'b0}};
y0 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
z0 <= inp ;
x0<= 13'h4d ;
y0 <= 13'h00;
end
end
//?????45?
reg [DataWidth-1:0] x1,y1;
reg [DataWidth_Z-1:0] z1 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x1 = {(DataWidth){1'b0}};
y1 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z0[DataWidth-1])
begin
x1<= x0+y0;
y1 <= y0-x0;
z1 <= z0+14'h65;
end
else
begin
x1<= x0-y0;
y1 <= y0+x0;
z1 <= z0-14'h65;
end
end
end
//?????26.5?
reg [DataWidth-1:0] x2,y2;
reg [DataWidth_Z-1:0] z2 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x2 = {(DataWidth){1'b0}};
y2 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z1[DataWidth-1])
begin
x2<= x1 + {{1{y1[DataWidth-1]}},y1[DataWidth-1:1]};
y2 <= y1 - {{1{x1[DataWidth-1]}},x1[DataWidth-1:1]};
z2 <= z1 + 14'h3b ;
end
else
begin
x2<= x1 - {{1{y1[DataWidth-1]}},y1[DataWidth-1:1]};
y2 <= y1 + {{1{x1[DataWidth-1]}},x1[DataWidth-1:1]};
z2 <= z1 - 14'h3b ;
end
end
end
//?????14.04?
reg [DataWidth-1:0] x3,y3;
reg [DataWidth_Z-1:0] z3 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x3 = {(DataWidth){1'b0}};
y3 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z2[DataWidth-1])
begin
x3<= x2 + {{2{y2[DataWidth-1]}},y2[DataWidth-1:2]};
y3 <= y2 - {{2{x2[DataWidth-1]}},x2[DataWidth-1:2]};
z3 <= z2 + 14'h1f ;
end
else
begin
x3<= x2 - {{2{y2[DataWidth-1]}},y2[DataWidth-1:2]};
y3 <= y2 + {{2{x2[DataWidth-1]}},x2[DataWidth-1:2]};
z3 <= z2 - 14'h1f ;
end
end
end
//?????7.13?
reg [DataWidth-1:0] x4,y4;
reg [DataWidth_Z-1:0] z4 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x4 = {(DataWidth){1'b0}};
y4 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z3[DataWidth-1])
begin
x4<= x3 + {{3{y3[DataWidth-1]}},y3[DataWidth-1:3]};
y4 <= y3 - {{3{x3[DataWidth-1]}},x3[DataWidth-1:3]};
z4 <= z3 + 14'h10 ;
end
else
begin
x4<= x3 - {{3{y3[DataWidth-1]}},y3[DataWidth-1:3]};
y4 <= y3 + {{3{x3[DataWidth-1]}},x3[DataWidth-1:3]};
z4 <= z3 - 14'h10 ;
end
end
end
//?????3.58?
reg [DataWidth-1:0] x5,y5;
reg [DataWidth_Z-1:0] z5 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x5 = {(DataWidth){1'b0}};
y5 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z4[DataWidth-1])
begin
x5<= x4 + {{4{y4[DataWidth-1]}},y4[DataWidth-1:4]};
y5 <= y4 - {{4{x4[DataWidth-1]}},x4[DataWidth-1:4]};
z5 <= z4 + 14'h8 ;
end
else
begin
x5<= x4 - {{4{y4[DataWidth-1]}},y4[DataWidth-1:4]};
y5 <= y4 + {{4{x4[DataWidth-1]}},x4[DataWidth-1:4]};
z5 <= z4 - 14'h8 ;
end
end
end
//?????1.79?
reg [DataWidth-1:0] x6,y6;
reg [DataWidth_Z-1:0] z6 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x6 = {(DataWidth){1'b0}};
y6 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z5[DataWidth-1])
begin
x6<= x5 + {{5{y5[DataWidth-1]}},y5[DataWidth-1:5]};
y6 <= y5 - {{5{x5[DataWidth-1]}},x5[DataWidth-1:5]};
z6 <= z5 + 14'h4 ;
end
else
begin
x6<= x5 - {{5{y5[DataWidth-1]}},y5[DataWidth-1:5]};
y6 <= y5 + {{5{x5[DataWidth-1]}},x5[DataWidth-1:5]};
z6 <= z5 - 14'h4 ;
end
end
end
//?????0.90?
reg [DataWidth-1:0] x7,y7;
reg [DataWidth_Z-1:0] z7 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
x7 = {(DataWidth){1'b0}};
y7 = {(DataWidth){1'b0}};
// res_cos<= {(DataWidth){1'b0}};
// res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z6[DataWidth-1])
begin
x7<= x6 + {{6{y6[DataWidth-1]}},y6[DataWidth-1:6]};
y7 <= y6 - {{6{x6[DataWidth-1]}},x6[DataWidth-1:6]};
z7 <= z6 + 14'h2 ;
end
else
begin
x7<= x6 - {{6{y6[DataWidth-1]}},y6[DataWidth-1:6]};
y7 <= y6 + {{6{x6[DataWidth-1]}},x6[DataWidth-1:6]};
z7 <= z6 - 14'h2 ;
end
end
end
//?????0.45?
reg [DataWidth-1:0] x8,y8;
reg [DataWidth_Z-1:0] z8 ;
always @(posedgeclk , negedgerst_n )
begin
if (!rst_n)
begin
res_cos<= {(DataWidth){1'b0}};
res_sin<= {(DataWidth){1'b0}};
end
else
begin
if(z7[DataWidth-1])
begin
res_cos<= x7 + {{7{y7[DataWidth-1]}},y7[DataWidth-1:7]};
res_sin<= y7 - {{7{x7[DataWidth-1]}},x7[DataWidth-1:7]};
end
else
begin
res_cos<= x7 - {{7{y7[DataWidth-1]}},y7[DataWidth-1:7]};
res_sin<= y7 + {{7{x7[DataWidth-1]}},x7[DataWidth-1:7]};
end
end
end
endmodule
3, testbench
`timescale 1ns/1ns
modulecordic_test_tb;
parameterDataWidth = 13 ;
parameterDataWidth_Z = 14 ;
regclk , rst_n;
reg [DataWidth_Z-1:0] inp ;
wire [DataWidth-1:0] res_sin,res_cos;
cordic_testM0(clk,rst_n,inp,res_sin,res_cos);
always #5 clk = ~clk ;
initial
begin
inp = 14'b0;
clk = 0;
rst_n = 0;
end
initial
begin
#5 rst_n=1;inp = 14'b0000_0000_0000_00;
#20 rst_n=1;inp = 14'hc9;
#20 rst_n=1;inp = 14'h86 ;
#20 rst_n=1;inp = 14'h65 ;
#20 rst_n=1;inp = 14'h43 ;
#20 rst_n=1;inp = 14'h00 ;
#20 rst_n=1;inp = 14'h3fbd;
#20 rst_n=1;inp = 14'h3f9b ;
#20 rst_n=1;inp = 14'h3f7a ;
#20 rst_n=1;inp = 14'h3f37 ;
#500 $stop ;
end
endmodule
展开阅读全文