查看: 1885|回复: 1

FPGA设计信号发生器

[复制链接]
  • TA的每日心情

    2018-11-20 13:41
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2019-9-6 09:56:34 | 显示全部楼层 |阅读模式
    分享到:
    对于信号发生器的设计,不论芯片的类型,只要所设计的逻辑单元够用即可,还有就是内存要够。好了,话不多说。直接来开始FPGA的信号发生器设计吧。

    直接上图:
    该图是quartus的开发环境,大家看下,感觉和你们的也不会有太大的区别。尽管软件的版本一直在升级,可是感觉变化也不会太大。

    继续上图:

    这个是我所建立的文件,大概看了一下,其中.v文件是我建立的一些verilog文件,有几个特殊的文件,比如.bdf文件是顶层文件。因为采用的思想是自顶向下的设计思想。先模块化,然后顶层直接调用即可。.qip文件是调用的是quatus自带的IP核,主要是用来存放波形数据的。.stp文件是signaltep文件,主要是用来硬件仿真观察数据用的,这个很有用哦,和modelsim差不多的功能,主要区别是,一个是硬件仿真,一个是软件仿真。都可以用来分析时序。

    直接上代码:

    module SPI_SLAVE

    #(

        parameterrom_len_width=9,//ROM标的深度,同时也代表了相位控制字的位数

        parameteRFtw_width=21,//频率控制字的位数

        parameter N=8

    )

    (

    input rst,    //复位端口

    input [N-1:0] txdata,    //N位发送数据,CS下降沿把数据存入模块

    input sclk,       //spi时钟

    input cs,     //spi片选

    input mosi,       //从接收端

    input ftw_en, //频率输入控制端使能

    input ptw_en, //相位控制端口使能

    input clk,   //频率>>sclk

    output reg miso,     //从输出端

    output [ftw_width-1:0]    ftw_out, //频率控制字的位数

    output [rom_len_width-1:0] ptw_out//相位控制字输出

    //output [5:0] count,//测试

    //output [23:0] data_temp_done //测试用

    );

    reg [9-1:0] temp_rx,temp_tx;

    reg negedge_cs,temp_cs;

    reg data_done;

    reg [5:0] count_spi;

    reg [24-1:0] data_temp;//24位数据暂存寄存器

    reg [ftw_width-1:0] ftw_last;

    reg [rom_len_width-1:0] ptw_last;

    reg [4:0] i;

    always @(negedge rst or posedge sclk)//mosi receive logic

    begin

    IF(!rst)

        begin

        count_spi<=0;

        temp_rx<=8'd0;

        data_temp<=0;

        ftw_last<=0;

        ptw_last<=0;

        i<=0;

        end

        else if(cs==0)

        begin

        case(i)

        5'd0:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d1

        end

        5'd1:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d2

        end

        5'd2:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d3

        end

        5'd3:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d4

        end

        5'd4:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d5

        end

        5'd5:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d6

        end

        5'd6:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d7

        end

        5'd7:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d8

        end

        5'd8:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d9

        end

        5'd9:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d10

        end

        5'd10:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d11

        end

        5'd11:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d12

        end

        5'd12:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d13

        end

        5'd13:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d14

        end

        5'd14:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d15

        end

        5'd15:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d16

        end

        5'd16:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d17

        end

        5'd17:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d18

        end

        5'd18:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d19

        end

        5'd19:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d20

        end

        5'd20:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d21

        end

        5'd21:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d22

        end

        5'd22:

        begin

        data_temp[24-1:0]<={data_temp[24-2:0],mosi};//串行数据左移输入

        i<=i+1'b1;//翻转到下一个状态5’d23

        end

        5'd23:

        begin

        data_temp[24-1:0]={data_temp[24-2:0],mosi};//串行数据左移输入

        if(!ftw_en)

               begin

               ftw_last[21-1:0]<=data_temp[24-4:0];

               data_temp<=24'd0;

               end

        else if(!ptw_en)

               begin

               ptw_last<=data_temp[8:0];

               data_temp<=24'd0;

               end

        i<=0;//翻转到下一个状态5’d0

        end

    endcase

    end

    /*if(flag==0)

        begin

        count_spi<=0;

        temp_rx<=8'd0;

        data_temp<=0;

        ftw_last<=0;

        ptw_last<=0;

        flag<=1;

        end

        else if(cs==0&&flag==1)

        begin

        count_spi<=count_spi+1'd1;

        temp_rx[N-1:0]<={temp_rx[N-2:0],mosi};//串行数据左移输入

        case(count_spi)

        6'd8:

           begin

           data_temp[24-1:16]<=temp_rx[7:0];//高位在前

           //temp_rx=0;

           end

        6'd16:

           begin

           data_temp[16-1:8]<=temp_rx[7:0];

           //temp_rx=0;

           end

        6'd24:

           begin

           data_temp[7:0]<=temp_rx[7:0];

           //temp_rx=0;

           if(!ftw_en)

               begin

               ftw_last[21-1:0]<=data_temp[24-1:3];

               data_temp<=24'd0;

               count_spi<=0;

               end

           if(!ptw_en)

                  begin

                  ptw_last<=data_temp[8:0];

                  data_temp<=24'd0;

                  end

           flag<=0;

           end

        endcase

        end*/

    end

    /*always @(posedge clk)//cs negedge test

    begin

        if((cs==0)&&(temp_cs==1))

        negedge_cs<=1;

        else

        negedge_cs<=0;

        temp_cs<=cs;

    end*/

    /*always @(negedge sclk or posedge negedge_cs)//miso transmitlogic

    begin

    if(negedge_cs==1)

    temp_tx<=txdata;

    else

    temp_tx[N-2:0]<=temp_tx[N-1:1];

    miso<=temp_tx[0];

    end*/

    assign ftw_out=ftw_last;

    assign ptw_out=ptw_last;

    //assign count=count_spi;//测试用

    //assign data_temp_done=data_temp;//测试用

    Endmodule

        上面的模块代码是用来完成SPI数据的接收,接收数据长度是24位的,这个可以根据自己的需要进行必要的调整。

    module phase_accumulator

    #(

        parameterrom_len_width=9,//ROM标的深度

        parameterphase_acc_width=26,//相位累加器的位数

        parameterftw_width=21//频率控制字的位数

    )

    (

    input rst,

    input [ftw_width-1:0] ftw,

    input [rom_len_width-1:0] ptw,

    input clk,

    output[rom_len_width-1:0] q

    );

    `define ptw_enable 1

    `ifdef ptw_enable

    reg [rom_len_width-1:0] phase;

    reg [phase_acc_width-1:0] phase1;

    always @(negedge rst or posedge clk)

    begin

        if(!rst)

           begin

               phase=1'd0;

               phase1=1'd0;

           end

        else

           begin

               phase1<=phase1+ftw;

               phase<=phase1[phase_acc_width-1:phase_acc_width-rom_len_width]+ptw;

           end

    end

    `else

    `endif

    assign q   =   phase;

    endmodule

    这部分的模块是完成相位累加器的设计,采用的是当今比较流行的DDS设计原理,

    输出的q是rom表的地址,该地址根据相位累加器的累加来驱动地址的递增。不同DDS的建议可以去看下DDS的设计原理。在此,我也不嫌麻烦,将它给贴出来给你们看看。如下:

    令DDS时钟为,相位累加器位数为n,频率控制字的位数为m,ROM表的深度的位宽为D,相位控制字的位数为p。

    再令,,。

    当要设计一个DDS时,应该根据具体的性能指标来设计,从而避免不必要的资源浪费,一般设计给出的具体指标如下:

    指标:频率分辨率为,相位分辨率为,要求产生信号的最高频率为,且最高相位为,每个周期点数不少于N个。

    根据上面的指标,我们要求得具体的DDS时钟为,相位累加器位数为n,频率控制字的位数为m,ROM表的深度的位宽为d。

    (1)其中、n、m是和频率有关的参数,可以先进行求解:

    1  根据要求可以列出以下不等式:
    好了,我们继续:




    回复

    使用道具 举报

    该用户从未签到

    发表于 2020-5-2 22:05:25 来自手机 | 显示全部楼层
    剩下部分怎么查看?
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-28 02:49 , Processed in 0.131763 second(s), 19 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.