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

该博客介绍了如何生成0到360度的正余弦函数16位量化coe文件,并将其导入ROM,然后使用Verilog编写程序进行仿真。在仿真过程中,通过ILA(逻辑分析仪)IP进行信号观测,展示了当角度为60度时,正弦值和余弦值的量化结果,并解释了这些数值的含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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<L)
        fprintf(fid,',\r\n'); 
    else
        fprintf(fid,';\r\n');    % 分号(;)  结束标志位
    end
   
end
fclose(fid);

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<L)
        fprintf(fid,',\r\n'); 
    else
        fprintf(fid,';\r\n');    % 分号(;)  结束标志位
    end
   
end
fclose(fid);

2.

sin类似

添加ila的IP

 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.

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

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值