概述
FPGA利用查找表实现sin正弦函数
最近在看《基于FPGA的数字图像处理原理及应用》这本书,准备利用FPGA实现一些简单的数字图像处理。想把学习过程中遇到的一些问题以及解决方法与大家分享。
1.查找表的定义
在计算机科学中,查找表使用简单的查询操作替换运行时计算的数组或者associative array这样的数据结构。由于从内存中提取数值经常要比复杂的计算速度快很多,因此这样得到的速度提升是很显著的。
一个经典的例子就是三角表。每次计算所需的正弦值在一些应用中可能会慢的无法忍受,为了避免这种情况,应用程序可以在刚开始的一段时间计算一定数量的角度正弦值,譬如计算每个整数角度的正弦值,在后面的程序需要正弦值的时候,使用查找表从内存中提取临近角度的正弦值而不是使用数学公式进行计算。
由于查找表的高效率与方便易用性,它在实时性要求比较高的嵌入式系统中得到了广泛的应用。在FPGA中,主要是以下两种情况会用到查找表:一种是逻辑的时序要求非常高,例如,若用Cordic计算或是其他计算方式,则其延时不能满足要求时;另一种是计算的复杂度非常高,需要消耗相当一部分逻辑资源,而查找表只需建立一块的存储器,这可以用FPGA的片内存储器来构建,仅仅消耗一小部分逻辑资源。
2.利用查找表实现正弦函数
下面是一个用查找表来实现正弦函数sinx的示例。
①利用MATLAB生成mif文件
mif文件存放sinx的变量和函数值,在程序运行之前利用mif文件对ROM初始化。下面是生成sin函数查找表的MATLAB程序。
用MATLAB运行该程序会生成一个mif文件,文件内容如下。
该mif文件里存放了sinx函数扩大了2^14的901个0-90°步长为0.1°的函数值
用quartus软件打开该mif文件:
可以发现mif文件就是一个表格,对应的内容是地址位和十进制值,所以mif文件头一定不能写错。否则会在下一步初始化ROM时发生错误。
②FPGA例化一个ROM来实现查找表的存放
下面是调用quartus的IP核生成ROM的步骤。
数据位宽和地址位宽根据前面生成的mif决定,这里选取数据位宽为14,地址位宽为10。
‘q’ output port一般不必勾选
在这里点击browse选择mif文件对ROM进行初始化,最后finish即可。
③利用modelsim进行仿真
下面是仿真测试程序
`timescale 1ns/1ns
module tb_top;
//=====================================================================
// ********** Define Parameter and Internal Signals *************
//=====================================================================/
parameter DW = 15 ;
parameter AW = 10 ;
parameter ADDR_MAX = 900 ;
parameter const_half_pi = ADDR_MAX-1 ;
parameter const_pi = ADDR_MAX*2-1;
parameter const_double_pi = ADDR_MAX*4-1;
reg clk ;
reg rst_n ;
reg [AW+2-1:0] address_tmp ;
reg [AW-1:0] address ;
wire [DW-1:0] q_tmp ;
reg [DW+1-1:0] q_tmp1 ;
wire [DW-1:0] q ;
//======================================================================
// *************** Main Code ****************
//======================================================================
always #5 clk = ~clk;
initial begin
clk <= 0;
rst_n <= 0;
address_tmp <= {AW+2{1'b0}};
#100
rst_n <= 1;
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
address_tmp <= {AW+2{1'b0}};
end
else if(address_tmp == const_double_pi)begin
address_tmp <= {AW+2{1'b0}};
end
else begin
address_tmp <= address_tmp + 1'b1;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
address <= {AW{1'b0}};
end
else if(address_tmp == const_double_pi)begin
address <= {AW{1'b0}};
end
else if(address_tmp <= const_half_pi)begin
address <= address_tmp[AW-1:0];
end
else if(address_tmp <= const_pi)begin
address <= const_pi - address_tmp;
end
else if(address_tmp <= const_half_pi+const_pi)begin
address <= address_tmp - const_pi;
end
else begin
address <= const_double_pi - address_tmp;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
q_tmp1 <= {DW+1{1'b0}};
end
else if(address_tmp <= const_pi)begin
q_tmp1 <= {1'b0, q_tmp};
end
else begin
q_tmp1 <= {DW+1{1'b0}} - {1'b0, q_tmp};
end
end
assign q = q_tmp1[DW-1:0] ;
//例化
sin_lut sin_lut_inst(
.address(address),
.clock(clk),
.q(q_tmp)
);
endmodule
仿真结果如下图所示。
以上就是通过FPGA利用查找表实现正弦函数的全部内容。
最后
以上就是无奈镜子为你收集整理的FPGA利用查找表实现sin正弦函数FPGA利用查找表实现sin正弦函数的全部内容,希望文章能够帮你解决FPGA利用查找表实现sin正弦函数FPGA利用查找表实现sin正弦函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复