利用查找表来实现三角函数

        首先需要创建一个正弦函数的查找表。我们只需要考虑0到90度的范围,因为正弦函数具有对称性,其他角度的值可以通过简单的数学变换获得。输出的正弦值和余弦值放大了10000倍,这样可以在不失太多精度的情况下,使用整数运算。

下图是计算正弦和余弦值的关键代码。

 

        下图是我经过仿真验证的波形。但是有一个很奇怪的事情就是按照这个时序仿真图来说输入的角度和输出的结果的值与理论值相比是一致的。但是在我的testbench中,如果测试的是一个大于270度的值,在测试的波形中不会出现我设置的角度,而是会随机出现一个数值,并且这个随机出现的数值和它的输出结果还是正确的。

        经过仔细调试我的代码,解决了上述的问题。我一开始认为我的代码是没问题的,但是经过我多次利用testbench调试,我发现我的输入信号最多只能算到255度,原来是在进行设计的过程中,我的输入信号的位数出现了问题,0到359度的位数应该是9位,(即[8:0]),但我一开始设置成了8位所以导致的错误。

        在仿真验证的时候也要对位数进行修改:

         位数正确的仿真验证结果:

        仿真结果与理论相符。

 以下是设计代码:

module trig_lookup(
    input [8:0] angle,  // 输入角度,范围0-359
    output reg signed [15:0] sine_value,  // 输出正弦值,放大10000倍,有符号
    output reg signed [15:0] cosine_value   // 输出余弦值,放大10000倍
);

reg [15:0] sine_table[0:90];


initial begin
    sine_table[0] = 16'd0; sine_table[1] = 16'd175; sine_table[2] = 16'd349; sine_table[3] = 16'd523; sine_table[4] = 16'd698;
    sine_table[5] = 16'd872; sine_table[6] = 16'd1045; sine_table[7] = 16'd1218; sine_table[8] = 16'd1391; sine_table[9] = 16'd1564;
    sine_table[10] = 16'd1736; sine_table[11] = 16'd1908; sine_table[12] = 16'd2079; sine_table[13] = 16'd2249; sine_table[14] = 16'd2419;
    sine_table[15] = 16'd2588; sine_table[16] = 16'd2756; sine_table[17] = 16'd2924; sine_table[18] = 16'd3090; sine_table[19] = 16'd3256;
    sine_table[20] = 16'd3420; sine_table[21] = 16'd3584; sine_table[22] = 16'd3746; sine_table[23] = 16'd3907; sine_table[24] = 16'd4067;
    sine_table[25] = 16'd4226; sine_table[26] = 16'd4384; sine_table[27] = 16'd4540; sine_table[28] = 16'd4695; sine_table[29] = 16'd4848;
    sine_table[30] = 16'd5000; sine_table[31] = 16'd5150; sine_table[32] = 16'd5299; sine_table[33] = 16'd5446; sine_table[34] = 16'd5592;
    sine_table[35] = 16'd5736; sine_table[36] = 16'd5878; sine_table[37] = 16'd6018; sine_table[38] = 16'd6157; sine_table[39] = 16'd6293;
    sine_table[40] = 16'd6428; sine_table[41] = 16'd6561; sine_table[42] = 16'd6691; sine_table[43] = 16'd6820; sine_table[44] = 16'd6947;
    sine_table[45] = 16'd7071; sine_table[46] = 16'd7193; sine_table[47] = 16'd7314; sine_table[48] = 16'd7431; sine_table[49] = 16'd7547;
    sine_table[50] = 16'd7660; sine_table[51] = 16'd7771; sine_table[52] = 16'd7880; sine_table[53] = 16'd7987; sine_table[54] = 16'd8090;
    sine_table[55] = 16'd8192; sine_table[56] = 16'd8290; sine_table[57] = 16'd8387; sine_table[58] = 16'd8480; sine_table[59] = 16'd8572;
    sine_table[60] = 16'd8660; sine_table[61] = 16'd8746; sine_table[62] = 16'd8829; sine_table[63] = 16'd8910; sine_table[64] = 16'd8988;
    sine_table[65] = 16'd9063; sine_table[66] = 16'd9135; sine_table[67] = 16'd9205; sine_table[68] = 16'd9272; sine_table[69] = 16'd9336;
    sine_table[70] = 16'd9397; sine_table[71] = 16'd9455; sine_table[72] = 16'd9511; sine_table[73] = 16'd9563; sine_table[74] = 16'd9613;
    sine_table[75] = 16'd9659; sine_table[76] = 16'd9703; sine_table[77] = 16'd9744; sine_table[78] = 16'd9783; sine_table[79] = 16'd9819;
    sine_table[80] = 16'd9853; sine_table[81] = 16'd9884; sine_table[82] = 16'd9912; sine_table[83] = 16'd9937; sine_table[84] = 16'd9960;
    sine_table[85] = 16'd9980; sine_table[86] = 16'd9997; sine_table[87] = 16'd10011; sine_table[88] = 16'd10023; sine_table[89] = 16'd10031;
    sine_table[90] = 17'd10000;
end

always @(angle) begin
    if (angle <= 90) begin
        sine_value = sine_table[angle];
    end else if (angle <= 180) begin
        sine_value = sine_table[180 - angle];
    end else if (angle <= 270) begin
        sine_value = -sine_table[angle - 180];
    end else begin
        sine_value = -sine_table[360 - angle];
    end

    
    if (angle <= 90) begin
        cosine_value = sine_table[90 - angle];
    end else if (angle <= 180) begin
        cosine_value = -sine_table[angle - 90];
    end else if (angle <= 270) begin
        cosine_value = -sine_table[270 - angle];
    end else begin
        cosine_value = sine_table[angle - 270];
    end
    end
   
endmodule

以下是仿真验证代码:

module trig_lookup_tb();

    reg [8:0] angle;  // 测试输入角度
    wire [15:0] sine_value;  // 正弦输出
    wire [15:0] cosine_value;  // 余弦输出
    
    trig_lookup uut (
        .angle(angle),
        .sine_value(sine_value),
        .cosine_value(cosine_value)
        );
        
    initial begin   
         angle = 8'd0;    // 0°
        #10 angle = 8'd30;   // 30°
        #10 angle = 8'd60;   // 60°
        #10 angle = 8'd90;   // 90°
        #10 angle = 8'd120;  // 120°
        #10 angle = 8'd150;  // 150°
        #10 angle = 8'd180;  // 180°
        #10 angle = 8'd210;  // 210°
        #10 angle = 8'd240;  // 240°
        #10 angle = 8'd250;  // 250°
        #10 angle = 8'd255;  // 255°
        #10 angle = 9'd270;  // 270°
        #10 angle = 9'd285;  // 285°
        #10 angle = 9'd300;  // 300°
        #10 angle = 9'd330;  // 330°
        #10 angle = 9'd360;  // 360°
        #10 $stop;
    end

endmodule
RTL diagram
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值