第6节 Verilog常用程序示例3
推荐给好友
打印
加入收藏
更新于2008-05-28 12:43:03

例2-28 基于CORDIC算法的平方根计算模块的Verilog实现。

① MATLAB代码

为了便于读者理解,首先用MATLAB实现计算sqrt(x2+y2)的Cordic算法,代码如下:

function Xout = mysqrt (x, y);
K = 8;
An = 1;
for i =1: K
        a(i) = 1/(2^(i));
        An =An*sqrt(1+1/(4^i));
end
%anger = atan(a); %计算出的角度
theta = 0;

for i = 1:K
       sigma = -sign(y);
       x = x - sigma*y/(2^i);
       y = y + sigma*x/(2^i);
  % z = z - sigma*a(i);
end

Xout= x/An;

经过测试,上述程序可利用Cordic算法来计算输入数据平方和的根。

② Verilog代码

module mysqrt(clk, x, y, fout, fy);
       input              clk;
input [15:0] x;
input [15:0] y;
output [15:0] fout;
output [15:0] fy;
reg [15:0] fout;
reg [15:0] fy;

//采用8级流水线来实现

wire [15:0] x1, y1 ,x2, y2, x3, y3, x4, y4, x5, y5;
wire [15:0] x6, y6 ,x7, y7, x8, y8;

//
reg [15:0] xtemp, ytemp;
reg addx1, addx2, addx3, addx4, addx5, addx6, addx7, addx8;
reg addy1, addy2, addy3, addy4, addy5, addy6, addy7, addy8;

always @(posedge clk) begin 
      xtemp <= x;
          ytemp <= y;

          fout <= x8;
          fy <= y8;

          if(ytemp[15] == 0) begin
                   addx1 <= 1; 
                   addy1 <= 0; 
          end 
          else begin
                   addx1 <= 0; 
                   addy1 <= 1; 
          end 
               if(y1[15] == 0) begin
                   addx2 <= 1; 
                   addy2 <= 0; 
          end 
          else begin 
                   addx2 <= 0; 
                   addy2 <= 1; 
          end 
             if(y2[15] == 0) begin 
                   addx3 <= 1; 
                   addy3 <= 0; 
          end 
          else begin 
                  addx3 <= 0; 
                  addy3 <= 1; 
          end 
             if(y3[15] == 0) begin 
                  addx4 <= 1; 
                  addy4 <= 0; 
          end 
          else begin 
                   addx4 <= 0; 
                   addy4 <= 1; 
          end 
              if(y4[15] == 0) begin 
                   addx5 <= 1; 
                   addy5 <= 0; 
          end 
          else begin 
                   addx5 <= 0; 
                   addy5 <= 1; 
         end 
             if(y5[15] == 0) begin 
                   addx6 <= 1; 
                   addy6 <= 0;
          end
          else begin 
                  addx6 <= 0; 
                  addy6 <= 1;
          end
              if(y6[15] == 0) begin
                  addx7 <= 1; 
                  addy7 <= 0; 
          end
          else begin
                  addx7 <= 0; 
                  addy7 <= 1;
          end 
             if(y7[15] == 0) begin 
                   addx8 <= 1;
                   addy8 <= 0;
          end
          else begin
                  addx8 <= 0;
                  addy8 <= 1;
          end
end

//第1次迭代模块
addandsub addandsub1x(
.A(xtemp),
.B({ytemp[15],ytemp[15:1]}),
.ADD(addx1),
.Q(x1),
.CLK(clk));

addandsub addandsub1y(
.A(ytemp),
.B({xtemp[15],xtemp[15:1]}),
.ADD(addy1),
.Q(y1),
.CLK(clk));

//第2次迭代模块
addandsub addandsub2x(
.A(x1),
.B({{2{y1[15]}},y1[15:2]}),
.ADD(addx2),
.Q(x2),
.CLK(clk));

addandsub addandsub2y(
.A(y1),
.B({{2{x1[15]}},x1[15:2]}),
.ADD(addy2),
.Q(y2),
.CLK(clk));

//第3次迭代模块
addandsub addandsub3x(
.A(x2),
.B({{3{y2[15]}},y2[15:3]}),
.ADD(addx3),
.Q(x3),
.CLK(clk));

addandsub addandsub3y(
.A(y2),
.B({{3{x2[15]}},x2[15:3]}),
.ADD(addy3),
.Q(y3),
.CLK(clk));

//第4次迭代模块
addandsub addandsub4x(
.A(x3),
.B({{4{y3[15]}},y3[15:4]}),
.ADD(addx4),
.Q(x4),
.CLK(clk));

addandsub addandsub4y(
.A(y3),
.B({{4{x3[15]}},x3[15:4]}),
.ADD(addy4),
.Q(y4),
.CLK(clk));

//第5次迭代模块
addandsub addandsub5x(
.A(x4),
.B({{5{y4[15]}},y4[15:5]}),
.ADD(addx5),
.Q(x5),
.CLK(clk));

addandsub addandsub5y(
.A(y4),
.B({{5{x4[15]}},x4[15:5]}),
.ADD(addy5),
.Q(y5),
.CLK(clk));

//第6次迭代模块
addandsub addandsub6x(
.A(x5),
.B({{6{y5[15]}},y5[15:6]}),
.ADD(addx6),
.Q(x6),
.CLK(clk));

addandsub addandsub6y(
.A(y5),
.B({{6{x5[15]}},x5[15:6]}),
.ADD(addy6),
.Q(y6),
.CLK(clk));

//第7次迭代模块
addandsub addandsub7x(
.A(x6),
.B({{7{y6[15]}},y6[15:7]}),
.ADD(addx7),
.Q(x7),
.CLK(clk));

addandsub addandsub7y(
.A(y6),
.B({{7{x6[15]}},x6[15:7]}),
.ADD(addy7),
.Q(y7),
.CLK(clk));

//第8次迭代
addandsub addandsub8x(
.A(x7),
.B({{8{y7[15]}},y7[15:8]}),
.ADD(addx8),
.Q(x8),
.CLK(clk));

addandsub addandsub8y(
.A(y7),
.B({{8{x7[15]}},x7[15:8]}),
.ADD(addy8),
.Q(y8),
.CLK(clk));

endmodule

上述程序的RTL级结构如图比较复杂,这里就不再给出。在ModelSim 6.2b中完成仿真,其结果如图2-35所示,如竖线所标,输入为170、170时,经过8个时钟周期,输出248,近似等于 ,如果对输出计算精度有更高的要求,则可加大迭代次数。

 

图2-35 Cordic算法的仿真结果示意图

2.7 本章小结

本章简要介绍了Verilog硬件描述语言的发展历史和技术特点;然后介绍了相关的基本语法,这是进行FPGA设计所必须的基础知识。读者如果想要了解Verilog语言更多的细节,可参考关于Verilog语言的专著。最后给出了典型的Verilog实例,包括基本的触发器、译码器设计,常用的算术运算模块以及高级的Cordic算法模块,希望读者从中体会到Verilog的开发技巧,初步具备Verilog设计开发的基本能力。

 

<<上一节    下一节>>




 
关于我们 | 诚邀加盟 | 客户服务 | 相关法律 | 网站地图 | 友情链接 | 服务信箱:service@eefocus.com
© 2006 与非门科技信息咨询(北京)有限公司 All Rights Reserved.