FPGA----IP核cordic使用

之前说过,使用IP核要先百度,然后看文档,然后再百度最后使用。本篇文章以cord IC核的sin、cos来进行实验(全网最详教程)。

1、定点数、浮点数、反码、补码

首先要明确这几个词的概念。废话不多说,直接上例子:采用32位的有符号定点数表示方法,第一位表示符号位(0是正数,1是负数),因此还剩31个位置来表示数据,具体整数部分与小数部分是几位,看自己设定。我们下面假设整数部分2位(因为-pi~pi=-3.14~3.14,2位可以表示3),29位表示小数。

Exp1:

1.5=1+0.5=>0(符号位)_01(整数位)_0.5*2^29(小数位)=0(符号位)_01(整数位)_1,0000,0000,0000,0000,0000,0000,0000(小数位)=00110000000000000000000000000000=30000000'h('h表示16进制)

②负数是正数的补码,即反码+1:补码=反码(二进制取反即可)+1

由于1.5=0_01_10000000000000000000000000000,所以其反码为1_10_0,1111,1111,1111,1111,1111,1111,1111,所以其补码为1_10_1,0000,0000,0000,0000,0000,0000,0000,所以

-1.5=11010000000000000000000000000000=D0000000'h

Exp2:

120°=120/180*pi=2.094395102393195=2+(0.094395102393195*2^29)=0_10_int(50677984.71016798224384)=0_10_50677985=0_10_0,0011,0000,0101,0100,1000,1110,0001=01000011000001010100100011100001=430548E1'h

-120°=-120/180*pi=-2.094395102393195=1_01_1,1100,1111,1010,1011,0111,0001,1110=10111100111110101011011100011110=BCFAB71E'h

2、了解了编码规则后就开始使用cordic IP核

实验任务:使用IP核cordic的sin/cos功能

实验软硬件:ZCU106、Vivado2019.1

实验过程:

step1:建立test_pl_cordic项目,建立top源文件,并添加Clocking Wizard
与cordic IP核(如果这一步不会请参考前面的文章)

step2:cordic IP核的配置

 

step3:赋值代码,并仿真(因为testbench里设置了时延,因此下面的第三图里面的按钮必须点一下才能看到仿真结果)

`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng
// 
// Create Date: 2021/12/31 14:33:38
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top(
    input   clk_p,
    input   clk_n,
    input   rst,
    output [63:0] data_a,
    output [63:0] data_b,
    output [63:0] data_c
    );
    reg    [31:0]  c_E_PH       [2:0];//A相
    reg            compute_sign =   1'b0;
    clk_wiz_0 uut_clk_wiz_0(
        .clk_out1(clk),
  // Status and control signals
        .reset(~rst),//高电平复位
        .locked(locked),
 // Clock in ports
        .clk_in1_p(clk_p),
        .clk_in1_n(clk_n)
    );
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
        end
        else begin
            c_E_PH[0] <= 32'h00000000;      //A相
            c_E_PH[1] <= 32'hBCFAB71E;      //B相
            c_E_PH[2] <= 32'h430548E1;      //C相
            compute_sign    <= 1'b1;
        end
        
    end
    reg             s_axis_phase_tvalid_a = 1'b0;
    reg     [31:0]  s_axis_phase_tdata_a  = 32'b0; 
    reg             s_axis_phase_tvalid_b = 1'b0;
    reg     [31:0]  s_axis_phase_tdata_b  = 32'b0;
    reg             s_axis_phase_tvalid_c = 1'b0;
    reg     [31:0]  s_axis_phase_tdata_c  = 32'b0;   
    wire    [63:0]  m_axis_dout_tdata_a;
    wire    [63:0]  m_axis_dout_tdata_b;
    wire    [63:0]  m_axis_dout_tdata_c;
    cordic_0 uut_cordic_sin_cos_a(
        .aclk(clk),
        .s_axis_phase_tvalid(s_axis_phase_tvalid_a),
        .s_axis_phase_tdata(s_axis_phase_tdata_a),

        .m_axis_dout_tvalid(m_axis_dout_tvalid_a),
        .m_axis_dout_tdata(m_axis_dout_tdata_a)
    );
    cordic_0 uut_cordic_sin_cos_b(
        .aclk(clk),
        .s_axis_phase_tvalid(s_axis_phase_tvalid_b),
        .s_axis_phase_tdata(s_axis_phase_tdata_b),

        .m_axis_dout_tvalid(m_axis_dout_tvalid_b),
        .m_axis_dout_tdata(m_axis_dout_tdata_b)
    );
    cordic_0 uut_cordic_sin_cos_c(
        .aclk(clk),
        .s_axis_phase_tvalid(s_axis_phase_tvalid_c),
        .s_axis_phase_tdata(s_axis_phase_tdata_c),

        .m_axis_dout_tvalid(m_axis_dout_tvalid_c),
        .m_axis_dout_tdata(m_axis_dout_tdata_c)
    );
    assign  data_a  =   m_axis_dout_tdata_a;
    assign  data_b  =   m_axis_dout_tdata_b;
    assign  data_c  =   m_axis_dout_tdata_c;
    always @(posedge clk or negedge rst) begin
        if (!rst)begin
            //复位
            s_axis_phase_tvalid_a   <=  1'b0;
            s_axis_phase_tvalid_b   <=  1'b0;
            s_axis_phase_tvalid_c   <=  1'b0;
        end
        else if(compute_sign == 1'b1) begin
            //可以开始计算
            s_axis_phase_tvalid_a <= 1'b1;
            s_axis_phase_tdata_a  <= c_E_PH[0];
            s_axis_phase_tvalid_b <= 1'b1;
            s_axis_phase_tdata_b  <= c_E_PH[1];
            s_axis_phase_tvalid_c <= 1'b1;
            s_axis_phase_tdata_c  <= c_E_PH[2];
            compute_sign    <= 1'b0;
        end
        else if(m_axis_dout_tvalid_a  == 1'b1
                && m_axis_dout_tvalid_b  == 1'b1    &&  m_axis_dout_tvalid_c  == 1'b1) begin
            s_axis_phase_tvalid_a   <=  1'b0;
            s_axis_phase_tvalid_b   <=  1'b0;
            s_axis_phase_tvalid_c   <=  1'b0;
        end
    end
endmodule
`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng
// 
// Create Date: 2021/12/31 14:49:12
// Design Name: 
// Module Name: testbench
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module testbench(

    );
    reg clk;
    reg rst;
    wire [63:0] data_a;
    wire [63:0] data_b;
    wire [63:0] data_c;
    always #4 clk=~clk;
    initial begin
        clk = 1'b0;
        rst = 1'b0;
        #10;
        rst = 1'b1;
    end

    top uut_top(
        .clk_p(clk),
        .clk_n(~clk),
        .rst(rst),
        .data_a(data_a),
        .data_b(data_b),
        .data_c(data_c)
    );
endmodule

step4:结果分析

注意:输出是64位的,前32位是sin后32位是cos

 我们把B相与C相的前32位拿来进行验证:

B相:c8930a30=11001000100100110000101000110000=1(符号位)_1(整数位)_00,1000,1001,0011,0000,1010,0011,0000(小数位)=-(1-1).((2^30-001000100100110000101000110000)/2^30)=-0.((2^30-143854128)/2^30)=-0.866

C相:376CF5D0=110111011011001111010111010000=0(符号位)_0(整数位)_11,0111,0110,1100,1111,0101,1101,0000(小数位)=0.(110111011011001111010111010000/2^30)=0.866

----------------------------2023-1-10更新---------------------------------------------------------------------------------

附上所有结果的转换截图,不要再说我代码不对/计算步骤不对了,我文章3000+的阅读量,不可能出错的!!!评论不要误人子弟!!!

1、32位浮点数转fix32_29

reg [31:0] input_data = 32'h3FC00000;//1.5
reg [31:0] input_data = 32'hBFC00000;//-1.5

 

2、32位浮点数转fix32_30

reg [31:0] input_data = 32'h3F5DB22D;//0.866
reg [31:0] input_data = 32'hBF5DB22D;//-0.866

 验证完毕!!!

  • 12
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 22
    评论
下面是一个使用Vivado Cordic IP的简单实例: 假设我们要计算正弦函数sin(x),其中x是输入角度,输出结果是浮点数。我们可以使用Vivado Cordic IP来计算sin(x)的值。 1. 在Vivado设计环境中创建新的IP项目。 2. 在IP目录中搜索Cordic IP核,并将其添加到设计中。 3. 双击Cordic IP核,打开其属性选项卡。在这里,选择计算角度和输出数据类型为浮点数。 4. 将Cordic IP核FPGA的时钟信号和输入角度信号连接起来。 5. 在设计中添加一个AXI GPIO核,用于输入角度值。 6. 在Xilinx SDK中创建一个新的应用程序项目。 7. 编写C代码,从GPIO核读取角度值,并将其作为输入发送到Cordic IP核。然后,从Cordic IP核读取输出值,并将其转换为浮点数格式,最后计算sin(x)的值。 8. 在Vivado中生成比特流文件,将其下载到FPGA设备中进行测试和验证。 下面是C代码示例: ```c #include <stdio.h> #include <math.h> #include "xparameters.h" #include "xil_io.h" #define CORDIC_BASE_ADDR XPAR_CORDIC_IP_0_S00_AXI_BASEADDR #define GPIO_BASE_ADDR XPAR_AXI_GPIO_0_BASEADDR int main() { float x, y, z, sin_z; // 读取输入角度值 xil_printf("Enter the angle in degrees:\n"); scanf("%f", &x); z = x * M_PI / 180.0; // 将输入角度值发送到Cordic IP核 Xil_Out32(CORDIC_BASE_ADDR + 0x00, *(u32*)&z); // 从Cordic IP核读取输出值 y = *(float*)(CORDIC_BASE_ADDR + 0x04); // 计算sin(z)的值 sin_z = y; // 输出结果 xil_printf("sin(%f degrees) = %f\n", x, sin_z); return 0; } ``` 需要注意的是,此示例代码仅用于说明如何使用Vivado Cordic IP,实际应用中可能需要更复杂的硬件设计和软件编程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发光的沙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值