例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设计开发的基本能力。 <<上一节 下一节>> 相关链接
本文档为【基于CORDIC算法的平方根计算模块的Verilog实现】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。