当前位置:   article > 正文

FPGA实战--2FSK调制_2fsk输入最大跳频

2fsk输入最大跳频

首先了解一下2FSK的百度百科:(2ASK请直接看结尾)

FSK是信息传输中使用得较早的一种调制方式,它的主要优点是: 实现起来较容易,抗噪声与抗衰减的性能较好。在中低速数据传输中得到了广泛的应用。所谓FSK就是用数字信号去调制载波的频率。如果是采用二进制调制信号,则称为2FSK;采用多进制调制信号,则称为MFSK。
l 调制方法:2FSK可看作是两个不同载波频率的ASK已调信号之和。
l 解调方法:相干法和非相干法。
l 类型: 二进制移频键控( 2FSK), 多进制移频键控(MFSK)。
在上述三种基本的调制方法之外,随着大容量和远距离 数字通信技术的发展,出现了一些新的问题,主要是信道的带宽限制和非线性对传输信号的影响。在这种情况下,传统的数字调制方式已不能满足应用的需求,需要采用新的数字调制方式以减小信道对所传信号的影响,以便在有限的带宽资源条件下获得更高的传输速率。这些技术的研究,主要是围绕充分节省频谱和高效率的利用频带展开的。多进制调制,是提高 频谱利用率的有效方法,恒包络技术能适应信道的非线性,并且保持较小的频谱占用率。
从传统数字调制技术扩展的技术有 最小移频键控MSK)、 高斯滤波最小移频键控GMSK)、 正交幅度调制QAM)、 正交频分复用调制OFDM)等等。
我们需要怎么做
本次实战中,我们选用二进制频移键控,原理和方法比较简单粗暴,我们用一个伪随机序列(M序列)来假装按键,然后生成2个不同频率正弦波,通过一个选通开关并口输出,在使用并转串芯片转换实现2FSK的简单实践,下面我们来记录实践流程。

        首先是顶层文件(实践中就是原理草图,大概的实现原理)

从左到右分别是时钟接口->分频器->正弦波发生器/M序列发生器->开关选通(实验中时钟为20M),下面是各个模块代码:

分频器:(N代表分频数,为了让结果清晰,所以M序列的分频数很高,因为要让一个上升沿有好几个周期才行)

  1. module fenpin(clk_out,clk_in);
  2. output clk_out;
  3. input clk_in;
  4. reg[13:0] cnt;
  5. reg clk_out;
  6. parameter N=1024;
  7. always@(posedge clk_in)
  8. begin
  9. begin
  10. if(cnt==N/2-1)
  11. begin clk_out<=!clk_out;
  12. cnt<=0;
  13. end else
  14. cnt<=cnt+1;
  15. end
  16. end
  17. endmodule

仿真结果:


M序列发生器:

  1. module MXL(clk ,out);
  2. input clk;
  3. output out;
  4. reg[3:0] tmp=4'b0;
  5. reg out;
  6. always @(posedge clk )
  7. begin
  8. if(tmp > 4'd15)
  9. tmp=4'd0;
  10. else tmp=tmp+1'b1;
  11. case(tmp)
  12. 4'd0:out<=0;
  13. 4'd1:out<=1;
  14. 4'd2:out<=0;
  15. 4'd3:out<=0;
  16. 4'd4:out<=1;
  17. 4'd5:out<=1;
  18. 4'd6:out<=0;
  19. 4'd7:out<=1;
  20. 4'd8:out<=1;
  21. 4'd9:out<=0;
  22. 4'd10:out<=1;
  23. 4'd11:out<=0;
  24. 4'd12:out<=0;
  25. 4'd13:out<=0;
  26. 4'd14:out<=0;
  27. 4'd15:out<=0;
  28. endcase
  29. end
  30. endmodule

仿真结果:



重点,正弦波发生器:(这是这个实验难点,需要使用IP,所谓正弦波发生器,就是计数器+ram核,将正弦波抽样128个点,然后随着计数器计数逐个输出,ps,并口),调用IP核流程和mif文件的参数设置参考TOP文件,就是顶层文件图。mif文件导入在ram核的创建中。下面也带上C语言产生mif文件(也就是正弦波的序列)

内部结构图:


C语言mif文件代码(用VC或者devc++运行即可,摘自:点击打开链接)这个代码浅显易懂,读懂为好。

  1. #include <stdio.h>
  2. #include <math.h>
  3. #define PI 3.141592
  4. #define DEPTH 128 /*数据深度,即存储单元的个数*/
  5. #define WIDTH 8 /*存储单元的宽度*/
  6. int main(void)
  7. {
  8. int i,temp;
  9. float s;
  10. FILE *fp;
  11. fp = fopen("TestMif.mif","w"); /*文件名随意,但扩展名必须为.mif*/
  12. if(NULL==fp)
  13. printf("Can not creat file!\r\n");
  14. else
  15. {
  16. printf("File created successfully!\n");
  17. /*
  18. * 生成文件头:注意不要忘了“;”
  19. */
  20. fprintf(fp,"DEPTH = %d;\n",DEPTH);
  21. fprintf(fp,"WIDTH = %d;\n",WIDTH);
  22. fprintf(fp,"ADDRESS_RADIX = HEX;\n");
  23. fprintf(fp,"DATA_RADIX = HEX;\n");
  24. fprintf(fp,"CONTENT\n");
  25. fprintf(fp,"BEGIN\n");
  26. /*
  27. * 以十六进制输出地址和数据
  28. */
  29. for(i=0;i<DEPTH;i++)
  30. {
  31. /*周期为128个点的正弦波*/
  32. s = sin(PI*i/64);
  33. /*将-1~1之间的正弦波的值扩展到0-255之间*/
  34. temp = (int)((s+1)*255/2);
  35. /*以十六进制输出地址和数据*/
  36. fprintf(fp,"%x\t:\t%x;\n",i,temp);
  37. }//end for
  38. fprintf(fp,"END;\n");
  39. fclose(fp);
  40. }
  41. }

仿真结果:

选通开关代码:

  1. module KAIGUAN(din0,dout,din1,sel);
  2. parameter N=12;
  3. input[N-1:0] din0;
  4. output[N-1:0] dout;
  5. input[N-1:0] din1;
  6. input sel;
  7. wire[N-1:0] MW_din0l;
  8. wire[N-1:0] MW_din1l;
  9. reg[N-1:0] MW_dtempl;
  10. always@(MW_din0l or MW_din1l or sel)
  11. begin
  12. case(sel)
  13. 1'd0:MW_dtempl=MW_din0l;
  14. default:MW_dtempl=MW_din1l;
  15. endcase
  16. end
  17. assign dout=MW_dtempl;
  18. assign MW_din0l=din0;
  19. assign MW_din1l=din1;
  20. endmodule

整体系统的仿真结果:

仿真成功!

下载到FPGA中接上示波器:(FFT中有两个高峰,实验成功,具体速率大家可以自己算哦)


2ASK比较简单,至于要信号发生器的分频器分频数目一致,然后改任意一个波形发生器的mif文件(中心范围缩小,可改代码得,记得有个直流偏置),其他不用变。

过程写的比较简单粗暴,有问题可留言或者私信,我都会看的!





声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/482377
推荐阅读
相关标签
  

闽ICP备14008679号