weiqi7777的个人空间 https://blog.eetop.cn/952026 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

cordic 三角函数的硬件实现(二) 组合逻辑实现

已有 1883 次阅读| 2013-12-26 17:15 |个人分类:设计心得

   
   接着上篇的分析。
   接下来就是编写代码:
   module cdcd
  #(
    //输出cos和sin的位宽
//最高位为符号位,剩下6位为数据位
       parameter W   = 17,        
//输入的角度采用16位表示
//最高位表示符号位,1为负数。0为正数
//接下来的7位,表示角度的整数,可表示范围为0--127
//最后的8位,表示小数。可表示范围为0--1
  parameter N_Z = 16         //输入角度phi的位宽
  
)
   (
         input    clk,
input [N_Z-1:0]  phi,
 
output  [W-1:0]    cos,
output  [W-1:0]    sin
    );
//定义中间保存迭代的寄存器值
reg [W-1:0]    x [7:0];
reg [W-1:0]    y [7:0];
reg [N_Z-1:0]  z [7:0];

    always@( posedge clk ) begin
  x[0] = 17'd39797; //0.60725 
  y[0] = 0;
  z[0] = phi;
  //迭代第一次,角度偏移45° 
  if(z[0][N_Z-1])   
     begin
    x[1] = x[0] + y[0];
y[1] = y[0] - x[0];
z[1] = z[0] + 16'd11520;  //45° = 0_0101101_00000000 = 11520
 end
  else
     begin
    x[1] = x[0] - y[0];
y[1] = y[0] + x[0];
z[1] = z[0] - 16'd11520;
 end
 //迭代第二次,角度偏移26.56° 
 if(z[1][N_Z-1])  
     begin
    x[2] = x[1] + {{1{y[1][W-1]}},y[1][W-1:1]};
y[2] = y[1] - {{1{x[1][W-1]}},x[1][W-1:1]};
z[2] = z[1] + 16'd6799;  //25.56° = 0_0011010_10001111 = 6799
 end
  else
     begin
    x[2] = x[1] - {{1{y[1][W-1]}},y[1][W-1:1]};
y[2] = y[1] + {{1{x[1][W-1]}},x[1][W-1:1]};
z[2] = z[1] - 16'd6799;
 end
//迭代第三次,角度偏移14.04° 
  if(z[2][N_Z-1])   
     begin
    x[3] = x[2] + {{2{y[2][W-1]}},y[2][W-1:2]};
y[3] = y[2] - {{2{x[2][W-1]}},x[2][W-1:2]};
z[3] = z[2] + 16'd3594;  //14.04° = 0_0001110_00001010 = 3594
 end
  else
     begin
    x[3] = x[2] - {{2{y[2][W-1]}},y[2][W-1:2]};
y[3] = y[2] + {{2{x[2][W-1]}},x[2][W-1:2]};
z[3] = z[2] - 16'd3594;
 end
 //迭代第四次,角度偏移7.13° 
  if(z[3][N_Z-1])  
     begin
    x[4] = x[3] + {{3{y[3][W-1]}},y[3][W-1:3]};
y[4] = y[3] - {{3{x[3][W-1]}},x[3][W-1:3]};
z[4] = z[3] + 16'd1825;  //7.13° = 0_0000111_00100001 = 1825
 end
  else
     begin
    x[4] = x[3] - {{3{y[3][W-1]}},y[3][W-1:3]};
y[4] = y[3] + {{3{x[3][W-1]}},x[3][W-1:3]};
z[4] = z[3] - 16'd1825;
 end
 //迭代第五次,角度偏移3.58° 
  if(z[4][N_Z-1])   
     begin
    x[5] = x[4] + {{4{y[4][W-1]}},y[2][W-1:4]};
y[5] = y[4] - {{4{x[4][W-1]}},x[2][W-1:4]};
z[5] = z[4] + 16'd916;  //3.58° = 0_0000011_10010100 = 916
 end
  else
     begin
    x[5] = x[4] - {{4{y[4][W-1]}},y[4][W-1:4]};
y[5] = y[4] + {{4{x[4][W-1]}},x[4][W-1:4]};
z[5] = z[4] - 16'd916;
 end
 //迭代第六次,角度偏移1.79° 
  if(z[5][N_Z-1])  
     begin
    x[6] = x[5] + {{5{y[5][W-1]}},y[5][W-1:5]};
y[6] = y[5] - {{5{x[5][W-1]}},x[5][W-1:5]};
z[6] = z[5] + 16'd458;  //1.79° = 0_0000001_11001010 = 458
 end
  else
     begin
    x[6] = x[5] - {{5{y[5][W-1]}},y[5][W-1:5]};
y[6] = y[5] + {{5{x[5][W-1]}},x[5][W-1:5]};
z[6] = z[5] - 16'd458;
 end
 //迭代第七次,角度偏移0.9° 
  if(z[6][N_Z-1])   
     begin
    x[7] = x[6] + {{6{y[6][W-1]}},y[6][W-1:6]};
y[7] = y[6] - {{6{x[6][W-1]}},x[6][W-1:6]};
z[7] = z[6] + 16'd230;  //0.9° = 0_0000000_11100110 = 230
 end
  else
     begin
    x[7] = x[6] - {{6{y[6][W-1]}},y[6][W-1:6]};
y[7] = y[6] + {{6{x[6][W-1]}},x[6][W-1:6]};
z[7] = z[6] - 16'd230;
 end
end
   assign cos = x[7];
   assign sin = y[7];
endmodule

   理解cordic后,编写代码还是比较容易的。编写测试代码,测试该程序:

module cdcd_tb;

         // Inputs

         reg clk;

         reg [15:0] phi;

         // Outputs

         wire [16:0] cos;

         wire [16:0] sin;

         // Instantiate the Unit Under Test (UUT)

         cdcd uut (

                   .clk(clk),

                   .phi(phi),

                   .cos(cos),

                   .sin(sin)

         );

         always #5 clk = ~clk;

         initial begin

                   // Initialize Inputs

                   clk = 0;

                   phi = 0; 

           while(1)

            begin

                   @(negedge clk)

                      phi = (phi + (5<<8));

                     if( 90 <= (phi>>8))

                      phi = 0;

            end     

     endmodule

ISE自带的ISIM仿真,如下图所示:

选取一个值来检查:

选取,输入的角度为7680。。这是二进制显示,实际的角度为7680/256= 30°。

运算得出的结果

 X = cos30°) = 56858/65536 = 0.867484

 Y = sin30°) = 32585/65536 = 0.497208

与实际值相比较:

 cos30°) =   0.866025403784439

sin30°) =   0.5

 

   可看出,相比较,运算出来的结果还是有一定误差的。不过在允许的误差内,还是可以用的。当然可以增加迭代次数,这样可以减小误差。

以上实现,可看出,在一个时钟周期内,就可以算出结果了。但是因为这是功能仿真,没有考虑到计算的延时。如果是用时序仿真的话,就可以看出,输出结果和输入结果有一定的延时。由于中间的运算是采用组合逻辑实现的,因此运算的延时还是挺大的,这样的话,就会影响系统运行的最大频率了。

因此,在实际中,这样是不实用的。因此,后面可以采用流水线的结构,来进行运算,这样可以使系统的运行最大频率提高,还能在一个周期内算出结果。

以上,就是我对cordic算法的硬件实现的分析了。下次,分析采用流水线结构来实现三角函数。



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 1

    关注
  • 1

    粉丝
  • 1

    好友
  • 0

    获赞
  • 5

    评论
  • 542

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-6 22:59 , Processed in 0.029194 second(s), 14 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部