FPGA利用查找表实现sin cos函数

1.生成0到360度的sin和 cos函数的coe文件

2.导入ROM里面

3.编写Verilog程序

4.进行仿真或者逻辑分析仪

1.sin函数

clear;
clc;
Quantify_bit=16;      % 量化位数

theta=0:1:360;  % 度
L=length(theta);          % 采样点数
y=sind(theta);
                   
yt=round(y*(2^(Quantify_bit-1)-1));     % 16bit量化

% 在.coe文件中
% 第一行为定义数据格式, 2代表 ROM 的数据格式为二进制。
% 从第 3 行开始到第最后一行,是这个  L(数据长度为1024)* ADC_bit(16bit) 大小 ROM 的初始化数据。
% 第一行到倒数第二行的数字后面用逗号,最后一行数字结束用分号。
fid=fopen('sin1.coe','w');  % w表示write
fprintf(fid,'Memory_Initialization_Radix = 2;\r\n'); % 二进制
fprintf(fid,'Memory_Initialization_Vector = \r\n');
for p=1:L
    B_s=dec2bin(yt(p)+(yt(p)<0)*2^Quantify_bit,Quantify_bit);
    for q=1:Quantify_bit  % 12位,依次判断这12位的数值
        if B_s(q)=='1'
            data=1;
        else
            data=0;
        end
        fprintf(fid,'%d',data);
    end
    
    %  下面if语句的目的
    %  每行数字后面用逗号(,),最后一行数字结束用分号(;)
    if (p

cos函数

clear;
clc;

Quantify_bit=16;      % 量化位数

theta=0:1:360;  % 度
L=length(theta);          % 采样点数
y=cosd(theta);
                   
yt=round(y*(2^(Quantify_bit-1)-1));     % 16bit量化

% 在.coe文件中
% 第一行为定义数据格式, 2代表 ROM 的数据格式为二进制。
% 从第 3 行开始到第最后一行,是这个  L(数据长度为1024)* ADC_bit(16bit) 大小 ROM 的初始化数据。
% 第一行到倒数第二行的数字后面用逗号,最后一行数字结束用分号。
fid=fopen('cos1.coe','w');  % w表示write
fprintf(fid,'Memory_Initialization_Radix = 2;\r\n'); % 二进制
fprintf(fid,'Memory_Initialization_Vector = \r\n');
for p=1:L
    B_s=dec2bin(yt(p)+(yt(p)<0)*2^Quantify_bit,Quantify_bit);
    for q=1:Quantify_bit  % 12位,依次判断这12位的数值
        if B_s(q)=='1'
            data=1;
        else
            data=0;
        end
        fprintf(fid,'%d',data);
    end
    
    %  下面if语句的目的
    %  每行数字后面用逗号(,),最后一行数字结束用分号(;)
    if (p

2.

FPGA利用查找表实现sin cos函数_第1张图片

FPGA利用查找表实现sin cos函数_第2张图片

FPGA利用查找表实现sin cos函数_第3张图片

sin类似

添加ila的IP

FPGA利用查找表实现sin cos函数_第4张图片

FPGA利用查找表实现sin cos函数_第5张图片

 3.

top文件

module top(
    input sys_clk,  //50MHz时钟
    input rst_n     //复位,低电平有效
    );
/*
    函数功能:
    产生余弦值 
*/   
wire [15:0] cos_value; //ROM读出数据  每个数据有12bit
reg  [8:0]  cos_addr; //ROM输入地址 361个数据,需要2^9个地址
   
//产生ROM地址读取数据
always @ (posedge sys_clk or negedge rst_n)
begin
    if(!rst_n)
        cos_addr <= 10'd0;
    else
        cos_addr <= cos_addr+1'b1;
end
//实例化ROM
rom_cos rom_cos_inst
(
    .clka  (sys_clk ),   //inoput clka
    .addra (cos_addr ),  // input wire [8 : 0] addra 361个数据,需要2^9个地址
    .douta (cos_value )  // output wire [15 : 0] douta  
);

/*
    函数功能:
    产生正弦值 
*/   
wire [15:0] sin_value; //ROM读出数据  每个数据有12bit
reg  [8:0]  sin_addr; //ROM输入地址  1024个数据,需要2^10个地址
   
//产生ROM地址读取数据
always @ (posedge sys_clk or negedge rst_n)
begin
    if(!rst_n)
        sin_addr <= 10'd0;
    else
        sin_addr <= sin_addr+1'b1;
end
//实例化ROM
rom_sin rom_sin_inst
(
    .clka  (sys_clk ),   //inoput clka
    .addra (sin_addr ),  // input wire [8 : 0] addra 361个数据,需要2^9个地址
    .douta (sin_value )  // output wire [15 : 0] douta  
);

/*
    函数功能:
    查表计算某角度的正弦值、余弦值
*/   
wire [15:0] data_value_sin;
wire [15:0] data_value_cos;
reg [8:0]       theta;
always @(posedge sys_clk or negedge rst_n) begin// 角度
    if(!rst_n)
        theta <= 9'd60;
    else if(theta < 9'd300)
        theta <= theta + 9'd30;
    else
        theta <= 9'd180;
end


//查表得到余弦值
rom_cos rom_cos_data_inst
(
    .clka  (sys_clk ),   //inoput clka
    .addra (theta ),  // input wire [8 : 0] addra 361个数据,需要2^9个地址
    .douta (data_value_cos )  // output wire [15 : 0] douta  
);
//查表得到正弦值
rom_sin rom_sin_data_inst
(
    .clka  (sys_clk ),   //inoput clka
    .addra (theta ),  // input wire [8 : 0] addra 361个数据,需要2^9个地址
    .douta (data_value_sin )  // output wire [15 : 0] douta  
);



//实例化逻辑分析仪
ila_0 ila_0_inst (
	.clk(sys_clk), // input wire clk


	.probe0(cos_addr ), // input wire [8:0]  probe0  
	.probe1(cos_value), // input wire [15:0]  probe1 
	.probe2(sin_addr ), // input wire [8:0]  probe2 
	.probe3(sin_value), // input wire [15:0]  probe3
    .probe4(data_value_sin), // input wire [`15:0]  probe4
    .probe5(data_value_cos) // input wire [15:0]  probe5
);


endmodule

 top1_tb文件

`timescale 1ns / 1ps

module top1_tb();

reg sys_clk;
reg rst_n;

initial begin
    sys_clk = 1'b0;
    rst_n = 1'b0;
    #20
    rst_n = 1'b1;
end

always #10 sys_clk = ~sys_clk;

top u_top(
    .sys_clk(sys_clk),  //50MHz时钟
    .rst_n(rst_n)     //复位,低电平有效
    ); 
endmodule

 4.

FPGA利用查找表实现sin cos函数_第6张图片

 最后结果,theta=60的时候,data_value_sin = 28377,这是量化后的值,除以2^15 -1=32767,28377/32767=0.866=根号3除以2

FPGA利用查找表实现sin cos函数_第7张图片

 

data_value_cos = 16383,16383/32767=0.49998约等于0.5

你可能感兴趣的:(fpga开发)