CORDIC算法[VHDL]

目录

1.实验要求

2.系统设计方案

2.1 算法基本思想:

2.2  算法选择

3.系统总体设计方案

4.主要代码

4.1:设计流水线和主要算法部分

 5.管脚锁定及硬件现象;

5.1 编译效果

 5.2 管脚锁定

5.3 硬件现象

6.自主学习评价报告

1.实验要求

        设计一个应用CORDIC算法求解正弦函数 和余弦函数 的VHDL程序,CORDIC算法能够包含圆周系统,线性系统,双曲线系统三种旋转系统,将旋转的角度通过统一的硬件实现多功能

2.系统设计方案

2.1 算法基本思想:

        CORDIC算法的基本思想是通过一系列固定的、与运算基数相关的角度偏摆来逼近所需的旋转角度。可通过该算法的圆周模式、双曲线模式、线性模式等不同的实现模式,来计算乘除、平方根、正弦、余弦、反正切向量旋转以及指数运算等,可见图1.1所示;

由于基本运算单元只有移位与加减法,这就为CORDIC算法的FPGA实现打下了良好的基础。

CORDIC算法包含圆周系统、线性系统、双曲系统三种旋转系统。

图1.1  坐标旋转图

2.2  算法选择

        CORDIC算法的实现有两种结构方案:迭代结构和流水线结构。

        基于迭代结构的CORDIC算法实现方案只需要一组移位及加减运算的单元,硬件开销很小,但控制比较复杂,而且完成一次CORDIC运算需要多个时钟周期,当对速度要求较高时很难满足要求。  基于流水线结构的实现方案,每级CORDIC迭代运算都使用单独的一套运算单元,与基于迭代结构的实现方案相比,流水线结构的处理速度非常快,当流水线填满之后每个时钟周期就会计算出一组结果。本设计采用流水线结构进行设计:

 图1.2 CORDIC算法的流水线结构

         如图1.2所示,是基于流水线技术的CORDIC硬件实现架构。架构由控制单元,选择器,移位寄存器,ROM,加法器组成。ROM中存放的是预先计算好的数据值(弧度数表示),供处理器运算中调用。从架构中可以看出只有移位和加减法操作,因此特别适合于可编程逻辑器件。每次计算之前要对角度值Z进行判断,根据Z的符号来决定图2.2中的加减运算,得到的结果再通过寄存器保存中间变量供下级流水线使用。

这种设计采用的流水线技术,是以面积换取速度的一种方式,通过增加硬件资源来提高计算速度,使CORDIC的每一级都同时工作,能够连续的输出结果。

3.系统总体设计方案

          先设计一个根据已知的( Xn-1,Yn-1,Zn-)求解( Xn,Yn ,Zn )的通用流水单元电路程序CORDICPIPE.VHD,再利用N个单元电路构成流水线,实现由(X0,Y0 ,Z0 )求解( Xn,Yn ,Zn )的CORDIC算法实现电路程序CORDIC.VHD,最后给CORDIC算法实现电路赋予确定的初值(0.60725,0,角度 ),构建一个求解正弦和余弦函数的顶层电路程序SINANDCOS_CORDIC.VHD见图1.3所示;总体RTL图见图1.4所示;

图1.3     总体结构图

图1.4 系统RTL图 

4.主要代码

4.1:设计流水线和主要算法部分

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY CORDICPIPE IS
 GENERIC(WIDTH:NATURAL:= 16;  --类属表
 PIPEID:NATURAL:=1);
 PORT(CLK:IN STD_LOGIC;
 ENA:IN STD_LOGIC;
 XI:IN SIGNED(WIDTH-1 DOWNTO 0);
 YI:IN SIGNED(WIDTH-1 DOWNTO 0);
 ZI:IN SIGNED(19 DOWNTO 0);
 XO:OUT SIGNED(WIDTH-1 DOWNTO 0);
 YO:OUT SIGNED(WIDTH-1 DOWNTO 0);
 ZO:OUT SIGNED(19 DOWNTO 0));
 END ENTITY CORDICPIPE;
 ARCHITECTURE ART OF CORDICPIPE IS
 --FUNCTION CATAN (CONSTANTE ARC-TANGENT).
 --THIS IS A LOOKUP TABLE CONTAINING PRE-CALCULATED ARC-TANGENTS.   
 --N IS THE NUMBER OF THE PIPE,RETURNED IS A20BIT ARC-TANGENT VALUE.
 --THE NUMBERS ARE CALCULATED AS FOLLOWS:Z(N)=ATAN(I/2^N)
 --EXAMPLES:
 --20BIT VALUES=>2~20=2PI(RAD)
 --1(RAD)=2~20/2PI=166886.053...
 --N:O,ATAN(I/1)=0.7853..(RAD)
 --0.7853..*166886.053..=131072(DEC)=20000(HEX)
 --N:1,ATAN(I/2)=0.4636.(RAD)
 --0.4636..*166886.053..=77376.32(DEC)= 12E40(HEX)
 --N:2,ATAN(1/4)=0.2449.(RAD)
 --0.2449..*166886.053.=40883.52(DEC)= 9FB3(HEX)
 --N:3,ATAN(1/8)=0.1243..(RAD)
 --0.1243..*166886.053..=20753.1I(DEC)=5111(HEX)
 FUNCTION CATAN(N:NATURAL) RETURN INTEGER IS
 VARIABLE RESULT:INTEGER;           --根据迭代步骤N的值求解该步需要旋转的角度,提高一个预计算的CASE查表
 BEGIN
 CASE N IS
 WHEN 0=> RESULT:=16#020000#;
 WHEN 1=> RESULT:=16#012E40#;
 WHEN 2=> RESULT:=16#09FB4#;
 WHEN 3=> RESULT:=16#05111#;
 WHEN 4=> RESULT:=16#028B1#;
 WHEN 5=> RESULT:=16#0145D#;
 WHEN 6=> RESULT:=16#0A2F#;
 WHEN 7=> RESULT:=16#0518#;
 WHEN 8=> RESULT:=16#028C#;
 WHEN 9=> RESULT:=16#0146#;
 WHEN 10=> RESULT:=16#0A3#;
 WHEN 11=> RESULT:=16#051#;
 WHEN 12=> RESULT:=16#029#;
 WHEN 13=> RESULT:=16#014#;
 WHEN 14=> RESULT:=16#0A#;
 WHEN 15=> RESULT:=16#05#;
 WHEN 16=> RESULT:=16#03#;
 WHEN 17=> RESULT:=16#01#;
 WHEN OTHERS=>RESULT:=16#0#;
 END CASE;
 RETURN RESULT;
 END CATAN;
 --FUNCTION DELTA IS ACTUALLY AN ARITHMATIC SHIFT RIGHT
 FUNCTION DELTA(ARG:SIGNED;CNT:NATURAL)RETURN SIGNED IS   --根据输入ARG和CNT求解ARG/2^CNT  
 VARIABLE TMP:SIGNED(ARG'RANGE);
 CONSTANT LO:INTEGER:=ARG'HIGH-CNT+1;
 BEGIN
 FOR N IN ARG'HIGH DOWNTO LO LOOP
 TMP(N):=ARG(ARG'HIGH);    --将右移后空余各位补符号位
 END LOOP;
 FOR N IN ARG'HIGH-CNT DOWNTO 0 LOOP
 TMP(N):=ARG(N+CNT);       --TMP的数据右移的CNT位
 END LOOP;
 RETURN TMP;
 END FUNCTION DELTA;
 FUNCTION ADDSUB(DATAA,DATAB:IN SIGNED;ADD_SUB:IN STD_LOGIC)  --根据信号的不同将DATAA和DATAB做加法和减法
 RETURN SIGNED IS
 BEGIN
 IF(ADD_SUB='1')THEN
 RETURN DATAA+DATAB;
ELSE
 RETURN DATAA-DATAB;
 END IF;
 END FUNCTION ADDSUB;
 SIGNAL DX,XRESULT:SIGNED(WIDTH-1 DOWNTO 0);
 SIGNAL DY,YRESULT:SIGNED(WIDTH-1 DOWNTO 0);
 SIGNAL ATAN,ZRESULT:SIGNED(19 DOWNTO 0);
 SIGNAL ZNEG,ZPOS:STD_LOGIC;
 
 --开始真正的计算所需要的
 BEGIN
 DX<=DELTA(XI,PIPEID);  --调用函数求出2^-nXN并将函数的返回值赋值给DX
 DY<=DELTA(YI,PIPEID);    --调用函数求出2^-nYN并将函数的返回值赋值给DY
 ATAN<=CONV_SIGNED(CATAN(PIPEID),20);  --实际就是调用函数求出弧度数并转换成20位有符号数
 --GENERATE ADDER STRUCTURES
 ZNEG<=ZI(19);
 ZPOS<=NOT ZI(19);  --将符号位给他,即是旋转的方向
 --XADD
 XRESULT<=ADDSUB(XI,DY,ZNEG);  --求出Xn+1
 --YADD
 YRESULT<=ADDSUB(YI,DX,ZPOS);--求出Yn+1
 --ZADD
 ZRESULT<=ADDSUB(ZI,ATAN,ZNEG);  --求出Zn+1
 GEN_REGS:PROCESS(CLK)IS
 BEGIN
 IF(CLK'EVENT AND CLK='1')THEN
 IF(ENA='1')THEN
 XO<=XRESULT;
 YO<=YRESULT;
 ZO<=ZRESULT;
 END IF;
 END IF;
 END PROCESS GEN_REGS;
 END ARCHITECTURE ART;
 
 --基于流水线实现算法的电路设计
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
 ENTITY CORDIC IS
 GENERIC(PIPELINE:INTEGER:=15;
         WIDTH:INTEGER:=16);
PORT(CLK:IN STD_LOGIC;
ENA:IN STD_LOGIC;
XI:IN SIGNED(WIDTH-1 DOWNTO 0);
YI:IN SIGNED(WIDTH-1 DOWNTO 0):=(OTHERS=>'0');
ZI:IN SIGNED(WIDTH-1 DOWNTO 0);
XO:OUT SIGNED(WIDTH-1 DOWNTO 0);
YO: OUT SIGNED(WIDTH-1 DOWNTO 0));
END ENTITY CORDIC;
ARCHITECTURE ART OF CORDIC IS
 TYPE XYVECTOR IS ARRAY(PIPELINE DOWNTO 0)OF
 SIGNED(WIDTH-1 DOWNTO 0);
 TYPE ZVECTOR IS ARRAY(PIPELINE DOWNTO 0)OF
 SIGNED(19 DOWNTO 0);
 COMPONENT CORDICPIPE
 GENERIC(WIDTH:NATURAL:=16;
         PIPEID:NATURAL:=1);
 PORT(CLK:IN STD_LOGIC;
 ENA:IN STD_LOGIC;
 XI:IN SIGNED(WIDTH-1 DOWNTO 0);
 YI:IN SIGNED(WIDTH-1 DOWNTO 0);
 ZI:IN SIGNED(19 DOWNTO 0);
 XO: OUT SIGNED(WIDTH-1 DOWNTO 0);
 YO:OUT SIGNED(WIDTH-1 DOWNTO 0);
 ZO:OUT SIGNED(19 DOWNTO 0));
 END COMPONENT CORDICPIPE;
 SIGNAL X,Y:XYVECTOR;--定义模块间连接信号,用于16个流水线单元电路的级联
 SIGNAL Z:ZVECTOR;
 BEGIN
 --FILL FIRST NODES
 --FILLX
 X(0)<=XI;  --将外部输入xi赋值给第一级流水线单元的输入X(0)
 --FILL Y
 Y(0)<=YI;--将外部输入Yi赋值给第一级流水线单元的输入Y(0)
 --FILLZ
 Z(0)(19 DOWNTO 4)<=ZI;
 --把外部输入赋值给第一级流水线单元的输入
 Z(0)(3 DOWNTO 0)<=(OTHERS=>'0');
 --GENERATE PIPELINE
 GEN_PIPE: FOR N IN 1 TO PIPELINE GENERATE
 PIPE:CORDICPIPE
 GENERIC MAP(WIDTH=>WIDTH,PIPEID=>N-1)
 PORT MAP(CLK,ENA,X(N-1),Y(N-1),Z(N-1),X(N),Y(N),Z(N));
 END GENERATE GEN_PIPE;
 --ASSIGN OUTPUTS
 XO<=X(PIPELINE);
 --复制了16个相同的单元电路,并且各个单元首尾相接,构成流水线结构
 YO<=Y(PIPELINE);
 END ARCHITECTURE ART;

 5.管脚锁定及硬件现象;

5.1 编译效果

        具体程序编译所用资源见图5.1所示;

 图5.1  编译系统资源展示

 5.2 管脚锁定

        为了能够将计算结果显示至数码管,进行相关的引脚锁定,具体引脚锁定见图5.2所示;

 图5.2 管脚锁定

5.3 硬件现象

         将输入角度设置为0度,30度,45度,60度进行算法,其对比数据见图5.3所示,将计算结果显示至数码管上,硬件显示见图5.4,图5.5,图5.6,图5.7,图5.8所示;

 图5.3   正弦和余弦函数求解过程中有关参数及量化值对照表

 图5.4 输入0度计算输出

 图5.5 输入30度计算输出

  图5.6 输入45度计算输出

  图5.7  输入60度计算输出

6.自主学习评价报告

本次实验为自主研究性项目,为了能够更加深入了解VHDL语言的应用方面,我通过自主学习和同学探讨的方式完成了这次实验。

1.对CORDIC算法的深入了解,在实验开始前,通过自己的自主学习,寻找相关资料,了解到本算法主要功能为计算旋转角度的正余弦值从而能够更加快速的得到一些日常难以求正余弦的角度。

2.了解到CORDIC分为迭代结构和流水线结构,迭代结构硬件要求较低,但是对于速度较高时很难满足要求,流水线结构硬件较复杂但是处理速度非常快,为了达到速度要求选择用流水线结构设计。

3.在查看相关资料时候,存在一些问题,例如如何将每个角度和二进制数一一对应起来,通过和同学探讨知道,其正余弦函数的图像性质,将输入输出转换为16位二进制的数字与之一一对应起来,那么通过算法计算得出来的结果便和我们正确的正余弦角度一一对应。

4.在程序中本次实验使用了多个函数,利用调用函数来计算相关数据从而大达到算法的作用,其中利用到了量化计算,将角度DEG的度数与量化后的16位弧度数进行对应的换算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Esaki diode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值