我是靠谱客的博主 害羞小蚂蚁,最近开发中收集的这篇文章主要介绍FPGA使用查表法实现正弦和余弦函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、实现思路

  1. 使用matlab生成正弦值和余弦值的coe文件;
  2. coe文件写入ROM核中;
  3. 通过查表得到角度所对应的正弦值和余弦值。

二、实现方法

1、使用matlab生成正弦值和余弦值的coe文件;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Zheng Wei, 2022/12/05
%% 
%% 输入角度范围:[0,2*pi); 输入数据量化位数:10bit;
%% 输出结果范围:[-1,1];   输出数据量化位数:16bit;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clc;        % 清理命令行
close all;  % 关闭所有图形窗口 
clear all;  % 清理所有工作区变量


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 参数定义
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
in_quantify_bit = 10;        % 输入数据量化位数(无符号数)
alpha = 0:(2*pi/2^in_quantify_bit):(2*pi-2*pi/2^in_quantify_bit);  % 弧度

out_quantify_bit = 16;       % 输出数据量化位数(有符号数)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 获取三角函数值
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cos_alpha = cos(alpha);  % 获得cos函数值
sin_alpha = sin(alpha);  % 获得sin函数值
                                                                               
cos_alpha_q = round(cos_alpha *(2^(out_quantify_bit-1)-1));  % 16bit量化
sin_alpha_q = round(sin_alpha *(2^(out_quantify_bit-1)-1));  % 16bit量化

%figure(1); subplot(2,1,1);plot(alpha,cos_alpha);subplot(2,1,2);plot(alpha,cos_alpha_q);
%figure(2); subplot(2,1,1);plot(alpha,sin_alpha);subplot(2,1,2);plot(alpha,sin_alpha_q);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 生成coe文件,第一行定义数据格式, 16代表ROM的数据格式为16进制。
%% 高16bit代表sin值,低16bit代表cos值,各自最高的1bit是符号位。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for i = 1:1:(2^in_quantify_bit)
    if (cos_alpha_q(i)<0)
       cos_alpha_q(i) = cos_alpha_q(i) + 2^(out_quantify_bit); % 负数用补码表示
    else
       cos_alpha_q(i) = cos_alpha_q(i); % 正数的补码为原码
    end
                                                                                         
    if (sin_alpha_q(i)<0)
       sin_alpha_q(i) = sin_alpha_q(i) + 2^(out_quantify_bit); % 负数用补码表示
    else
       sin_alpha_q(i) = sin_alpha_q(i); % 正数的补码为原码
    end
end

cos_alpha_q = dec2hex(cos_alpha_q); % 因为dec2hex只能转换正数,因此先将cos_alpha_q取补码
sin_alpha_q = dec2hex(sin_alpha_q); % 因为dec2hex只能转换正数,因此先将sin_alpha_q取补码

% 将cos和sin拼接为32bit(各自16bit),此数据输出到FPGA
fid=fopen('cos_sin_lut_1.coe','wt');
fprintf( fid, 'MEMORY_INITIALIZATION_RADIX = 16;n');                     
fprintf( fid, 'MEMORY_INITIALIZATION_VECTOR =n');

for i = 1:1:(2^in_quantify_bit)
    s=strcat(sin_alpha_q(i,1),sin_alpha_q(i,2),sin_alpha_q(i,3),sin_alpha_q(i,4),cos_alpha_q(i,1),cos_alpha_q(i,2),cos_alpha_q(i,3),cos_alpha_q(i,4));
    fprintf(fid,'%c%c%c%c%c%c%c%c',s); 
    if (i < 2^in_quantify_bit)
        fprintf(fid,',n'); 
    else
        fprintf(fid,';n');  % 分号(;) 结束标志位
    end    
end
fclose(fid);

2、将coe文件写入ROM核中;

3、通过查表得到角度所对应的正弦值和余弦值。

/*----------------------------------------------------------------------
    Author:  Zheng Wei
    Date:    2022-12-05
    Version: 1.0
    Description: It is a cos_sin_lut_1 testbench.
-----------------------------------------------------------------------*/

`timescale 1ns / 1ps

module tb;
                                                 
                                                  
    reg                         i_sys_clk       ; 
    reg                         i_sys_rst       ;
                                                 
    reg             [09:0]      r_rom_phase     ;
    wire            [15:0]      w_cos_rom_val   ; 
    wire            [15:0]      w_sin_rom_val   ;    
                                                         
                                                          
                                                          
    //  clock generate module
    parameter  period = 6.67;           // 150MHz
    initial begin
        i_sys_clk = 1'b0;
        forever     #(period/2)  i_sys_clk = ~i_sys_clk;
    end
                                                                         
	//-------------------------------------------------------------------
	
	//  system initialization
	task task_sysinit;
		begin		 
            r_rom_phase = 10'd0;
		end
	endtask
	
	//  system reset
	task task_reset;
        begin
            i_sys_rst = 1'b1;
            repeat(20)  @(negedge i_sys_clk);
            i_sys_rst = 1'b0;
        end
    endtask                                                      
                                                          
                                                          
                                                          
    initial begin
        task_sysinit;
	    task_reset  ;
                                            
        repeat(10)  @(posedge i_sys_clk);                                                                            
                                          
                                         
        repeat(100000) @(posedge i_sys_clk);
		                                  
		$stop;                          
    end
                                                                                          
                                                                                         
    always @(posedge i_sys_clk or posedge i_sys_rst) begin
        if (i_sys_rst) begin
            r_rom_phase <= 10'd0;       
        end                  
        else begin           
            r_rom_phase <= r_rom_phase + 10'd1; 
        end
    end        
                                                                                         
                                                                                         
//-----------------------------------------------------------------------------------------------                                                         
                                                            
    cos_sin_lut_1  u_cos_sin_lut_1(
        .clka   ( i_sys_clk                    ),  // input wire clka
        .addra  ( r_rom_phase                  ),  // input wire [9 : 0] addra
        .douta  ({w_sin_rom_val, w_cos_rom_val})   // output wire [31 : 0] douta
    );
                                                                                                 
                                                                                                  
                                                                                                 
endmodule

4、仿真结果

 

最后

以上就是害羞小蚂蚁为你收集整理的FPGA使用查表法实现正弦和余弦函数的全部内容,希望文章能够帮你解决FPGA使用查表法实现正弦和余弦函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部