原创 基于FPGA/CPLD的MSK调制解调的工程应用

2008-5-26 07:20 7385 12 14 分类: FPGA/CPLD

基于FPGA/CPLDMSK调制解调的工程应用<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


为了便于信号发射,提高信道利用率、发射功率效率以及改善通信质量,人们研制出各种通信信号的调制样式。尽管调制样式多种多样,但实质上调制不外乎用调制信号去控制载波的某一个(或几个)参数,使这个参数按照调制信号的规律而变化。调制信号可以分别寄生在已调信号的振幅、频率和相位中,相应的调制就是调幅、调频和调相这三大类熟知的调制方式。


 


MSK信号就是调频这一大类中的一种相位连续的移频键控。其主要特点是包络恒定,带外辐射小,实现较简单,可用于移动通信中的数字传输。


 


MSK信号具有如下特点:


1)已调制信号的振幅是恒定的;


2)信号的频率偏移严格地等于正负1/4Ts,相应的调制指数h=(f2f1Ts=1/2


3)以载波相位为基准的信号相位在一个码元期间内准确地线性变化正负Π/2


4)在一个码元期间内,信号应包括四分之一载波周期的整数倍;


5)在码元转换时刻信号的相位是连续的,或者说,信号的波形没有突跳


 


MSK调制方式的突出优点是信号具有


恒定的振幅及信号的功率谱在主瓣以外衰减较快。然而,在一些通信场合,列如移动通信中,对信号带外辐射功率的限制是十分严格的,比如必须衰减70-80db以上。


GMSK是在MSK调制器之前加入一高斯低通滤波器。也就是说,用高斯低通滤波器作为MSK调制的前置滤波器。之前做过了高斯低通滤波器的FPGA设计。这一节做MSK调制的设计,下一节将把二者连接起来成为一个GMSK调制系统。


 


第三路信号source是基带码元,第五和第七路信号分别为IQ两路信号,其与分别与余弦和正弦相乘的波形如qsinpcos所示。


<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />


 


点击看大图


    产生两路正余弦高频调制信号分别为hsinhcos,再将它们与原pq两路信号相乘结果如pmuxqmux


点击看大图


 


    将得到的pmuxqmux信号相加,得到的mskout信号即MSK调制的最后输出。



点击看大图


 

Verilog代码如下:



6ca66c2f-ca91-4d02-adc6-69e1f8eb0935.jpg


 


module msk_top(clk,rst,rfd,pcos,qsin,hcos,hsin,pmux,qmux,mskout);


 


    input clk;        //主时钟信号


    input rst;        //复位信号


    input rfd;


 


//  output[15:0] cos,sin;


    output[15:0] pcos,qsin;


//  output[15:0] p,q;


    output[15:0] hcos,hsin;


    output[31:0] pmux,qmux;


    output[32:0] mskout;


 


   wire clk_500;         //50分频信号


    wire clk_50;         //500分频信号


    wire nd;                 //差分编码输出标志位


    wire rfd;            //差分编码启动位


    wire[15:0] source;   //差分信号


    wire[15:0] p,q;      //pq两路信号


    wire iqen;           //pq两路信号输出标志位


    wire[15:0] phase_in; //输入相位


    wire ce;                 //cossin工作使能信号


    wire csrdy;              //cossin输出使能信号


    wire pqsrdy;         //pcosqsin输出使能信号


    wire[15:0] cos,sin;  //正余弦发生信号


    wire[15:0] pcos,qsin;//输出的IQ两路信号


    wire[15:0] phase_h;  //高频相位


    wire rdyhigh;        //高频相位产生模块输出使能信号


    wire[15:0] hcos,hsin;//高频正余弦输出


    wire[31:0] pmux,qmux;//IQ两路信号的的最后输出


    wire muxprdy,muxqrdy;//IQ两路信号的输出使能信号


    wire[32:0] mskout;   //MSK调制输出


    wire mskrdy;         //MSK调制使出使能信号


 


 


    clkfen        clkfen( .clk(clk), .rst(rst), .clk_500(clk_500), .clk_50(clk_50));


    sent_source       sent_source( .clk_50(clk_50), .rst(rst), .nd(nd), .rfd(rfd), .source(source) );


    pqvalue       pqvalue( .clk(clk_50), .rst(rst), .nd(nd), .signal_in(source), .preg(p), .qreg(q), .rdy(iqen));


    phase_generate phase_generate( .clk(clk_500), .rst(rst), .en(nd), .phase(phase_in), .rdy(ce) );


    cos_sin           cos_sin( .phase_in(phase_in), .clk(clk_500), .ce(ce), .x_out(cos), .y_out(sin), .rdy(csrdy));


    pcosqsin          pcosqsin( .clk(clk), .rst(rst), .en(csrdy), .iqen(iqen), .p(p), .q(q),


                                 .sin(sin), .cos(cos), .qsin(qsin), .pcos(pcos), .rdy(pqsrdy));


    highfre           highfre( .clk(clk_500), .rst(rst), .en(nd), .phase(phase_h), .rdy(rdyhigh));//高频相位产生模块  


    hcossin       hcossin( .phase_in(phase_h), .clk(clk_500), .ce(rdyhigh), .x_out(hcos), .y_out(hsin), .rdy(hfrdy));


    mux           muxp( .clk(clk_500), .a(pcos), .b(hcos), .q(pmux), .nd(hfrdy), .rdy(muxprdy));   


    mux2              muxq( .clk(clk_500), .a(qsin), .b(hsin), .q(qmux), .nd(hfrdy), .rdy(muxqrdy));


    add               add( .clk(clk_500), .rst(rst), .en(muxprdy), .a(pmux), .b(qmux), .sum(mskout), .rdy(mskrdy));   


 


endmodule


 


 


module clkfen(clk,rst,clk_500,clk_50);


 


    input clk;


    input rst;


    output clk_50,clk_500;


 


    reg clk_50,clk_500;


    reg[8:0] num;


 


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           num <= 9'd0; 


           clk_500 <= 0;


           clk_50 <= 0;


           end


       else begin


           num <= num+1;


//         if(num == 9) begin


//            num <= 0;


//            clk_50 <= ~clk_50;


//            end


          case (num)


               9'd49:    clk_500 <= ~clk_500;


               9'd99:    clk_500 <= ~clk_500;


               9'd149:   clk_500 <= ~clk_500;


               9'd199:   clk_500 <= ~clk_500;


               9'd249:   clk_500 <= ~clk_500;


               9'd299:   clk_500 <= ~clk_500;


               9'd349:   clk_500 <= ~clk_500;


                9'd399:   clk_500 <= ~clk_500;


               9'd449:   clk_500 <= ~clk_500;


               9'd499: begin num <= 0;


                                clk_500 <= ~clk_500;


                                clk_50 <= ~clk_50;


                                end


               default: ;


               endcase       


           end


    end


 


endmodule


 


 


module sent_source(clk_50,rst,nd,rfd,source);


 


    input clk_50;     //50KHz时钟信号


    input rst;        //复位信号,高电平有效


    input rfd;


    output[15:0] source;        //1bit基带信号,16bit表示


    output nd;


 


    reg[15:0] source;


    reg[15:0] scode;


    reg[3:0] num;


    reg nd;


 


    always @ (posedge clk_50 or posedge rst) begin


       if(rst) begin


           nd <= 0;


           source <= 16'd0;


           num <= 4'b1111;


           scode <= 16'b1010011010111111;         //1011101001101001;


           end


       else if(rfd) begin


           if(scode[num]) begin


              source <= 16'h7fff;


              end


           else begin


              source <= 16'h8000;


              end


           nd <= 1;


           num <= num-1;


           end


       else nd <= 0;


    end


 


endmodule


 


 


module pqvalue(clk,rst,nd,signal_in,preg,qreg,rdy);


 


    input clk;


    input rst;


    input nd;                       //该模块工作启动信号


    input[15:0] signal_in;      //输入的十六位信号


    output[15:0] preg;


    output[15:0] qreg;


    output rdy;


 


    reg num;


    reg[15:0] signal_reg;


    reg[15:0] p,q;


    reg[15:0] preg,qreg;


    reg rdy;          //输出标志位


    reg rdy0;


 


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           p <= 16'h7fff;           //p的初始值为+1


           q <= 16'h7fff;           //q的初始值为+1


           num <= 1;


           signal_reg <= 0;


           rdy0 <= 0;


           end


       else if(nd)   begin


           rdy0 <= 1;


           num <= ~num;


           signal_reg <= signal_in;


           case( {signal_reg,signal_in} )


              32'h7fff8000:  if(num) q <= ~q;


                               else p <= ~p;     //-1,+1


              32'h80007fff:     if(num) q <= ~q;  


                               else p <= ~p;     //+1,-1


              default: ;        //其它情况pq值保持不变


              endcase


           end


       else begin


           p <= 16'h7fff;           //p的初始值为+1


           q <= 16'h7fff;           //q的初始值为+1


           num <= 1;


           signal_reg <= 0;


           rdy0 <= 0;


           end


    end


 


    always @ (posedge clk) begin       //将数据缓冲一个时钟周期后输出


       if(rst) begin


           preg <= 16'd0;


           qreg <= 16'd0;


           rdy <= 0;


           end


       else if(rdy0) begin


           preg <= p;


           qreg <= q;


           rdy <= 1;


           end


       else begin


           preg <= 16'd0;


           qreg <= 16'd0;


           rdy <= 0;


           end


    end


 


endmodule


 


 


module pqvalue(clk,rst,nd,signal_in,preg,qreg,rdy);


 


    input clk;


    input rst;


    input nd;                       //该模块工作启动信号


    input[15:0] signal_in;      //输入的十六位信号


    output[15:0] preg;


    output[15:0] qreg;


    output rdy;


 


    reg num;


    reg[15:0] signal_reg;


    reg[15:0] p,q;


    reg[15:0] preg,qreg;


    reg rdy;          //输出标志位


    reg rdy0;


 


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           p <= 16'h7fff;           //p的初始值为+1


           q <= 16'h7fff;           //q的初始值为+1


           num <= 1;


           signal_reg <= 0;


           rdy0 <= 0;


           end


       else if(nd)   begin


           rdy0 <= 1;


           num <= ~num;


           signal_reg <= signal_in;


           case( {signal_reg,signal_in} )


              32'h7fff8000:  if(num) q <= ~q;


                               else p <= ~p;     //-1,+1


              32'h80007fff:     if(num) q <= ~q;  


                               else p <= ~p;     //+1,-1


              default: ;        //其它情况pq值保持不变


              endcase


           end


       else begin


           p <= 16'h7fff;           //p的初始值为+1


           q <= 16'h7fff;           //q的初始值为+1


           num <= 1;


           signal_reg <= 0;


           rdy0 <= 0;


           end


    end


 


    always @ (posedge clk) begin       //将数据缓冲一个时钟周期后输出


       if(rst) begin


           preg <= 16'd0;


           qreg <= 16'd0;


           rdy <= 0;


           end


       else if(rdy0) begin


           preg <= p;


           qreg <= q;


           rdy <= 1;


           end


       else begin


           preg <= 16'd0;


           qreg <= 16'd0;


           rdy <= 0;


           end


    end


 


endmodule


 


 


module phase_generate(clk,rst,en,phase,rdy);


 


    input clk;


    input rst;


    input en;


    output[15:0] phase;


    output rdy;


 


    reg[15:0] phase;


    reg rdy;


   


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           phase <= 16'h0000;  


           rdy <= 0;


           end


       else if(en) begin


           rdy <= 1;


           if( (phase < 16'h8000) && (phase > 16'h6087) ) begin


              phase <= 16'h9b82;   //-pi


              end


           else begin


              phase <= phase + 16'h0527;  //0527


              end          


           end


       else begin


           phase <= 16'h0000;


           rdy <= 0;


           end


    end


 


endmodule


 


 


module pcosqsin(clk,rst,en,iqen,p,q,sin,cos,qsin,pcos,rdy);


 


    input clk;


    input rst;


    input en;


    input iqen;


    input[15:0] p,q;


    input[15:0] sin,cos;


    output[15:0] qsin,pcos;


    output rdy;


 


    reg[15:0] qsin,pcos;


    reg rdy;


    reg[15:0] preg,qreg;


 


    always @ (posedge clk) begin


       if(rst) begin


           qsin <= 16'd0;


           pcos <= 16'd0;


           rdy <= 0;


           end


       else if(en) begin


           rdy <= 1;


           case(preg)


              16'h7fff: pcos <= cos;


              16'h8000: pcos <= ~cos + 1;


              default: ;


              endcase


           case(qreg)


              16'h7fff: qsin <= sin;


              16'h8000: qsin <= ~sin + 1;


              default: ;


              endcase


           end


       else begin


           qsin <= 16'd0;


           pcos <= 16'd0;


           rdy <= 0;


           end


    end


 


    always @ (posedge clk) begin         //pq两路信号缓冲一个时钟周期


       if(rst) begin


           preg <= 16'd0;


           qreg <= 16'd0;


           end


       else if(iqen) begin


           preg <= p;


           qreg <= q;


           end


       else begin


           preg <= 16'd0;


           qreg <= 16'd0;


           end


    end


 


endmodule


 


 


module highfre(clk,rst,en,phase,rdy);


 


    input clk;


    input rst;


    input en;


    output[15:0] phase;


    output rdy;


 


    reg[15:0] phase;


    reg rdy;


    reg rdyreg;


   


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           phase <= 16'h0000;  


           rdy <= 0;


           end


       else if(rdyreg) begin


           rdy <= 1;


           if( (phase < 16'h8000) && (phase > 16'h6087) ) begin


              phase <= 16'h9b82;   //-pi


              end


           else begin


              phase <= phase + 16'h3243;  //1657


              end          


           end


       else begin


           phase <= 16'h0000;


           rdy <= 0;


           end


    end


 


    always @ (posedge clk or posedge rst) begin


       if(rst) begin


           rdyreg <= 0;


           end


       else if(en)   begin


           rdyreg <= 1;


          end


       else begin


           rdyreg <= 0;


           end


    end


 


endmodule


 


 


module add(clk,rst,en,a,b,sum,rdy);


 


    input clk;


    input rst;


    input en;


    input[31:0] a,b;


    output[32:0] sum;


    output rdy;


 


    reg[32:0] sum;


    reg rdy;


 


    always @ (posedge clk) begin


       if(rst) begin


           sum <= 33'd0;


           rdy <= 0;


           end


       else if(en) begin


           rdy <= 1;


           sum <= {a[31],a} + {b[31],b};


          end


       else begin


           sum <= 33'd0;


           rdy <= 0;


           end


    end


 


endmodule


 


 


其中用到两个正余弦和两个乘法的IP Core.正所谓用面积换速度吧。


 

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户377235 2013-5-11 17:20

您好,我也是从事相关的工作,想问一下,您的IP核是自己写的吗,我想看看您的这个工程,我的QQ邮箱:305659935@qq.com,希望博主不吝赐教!

用户575829 2010-12-6 16:27

学习!夯实基础!

ilove314_323192455 2010-6-12 11:19

TimeQuest是无法直接使用现有数据分析IO接口时序,但是人可以分析,可以提出IO口约束参数交给TimeQuest分析啊。目前也发现之前的板子闪屏和电源纹波过大有一定关系,改版后由于电源部分也做了一些改进,已经不会出现这个问题了

用户972891 2010-6-11 09:30

建议仔细分析下“IO接口上的VCLK和DB[7:0]”之间的通路延时(PCB板+FPGA内部通路所有延时),防止一定概率的建立/保持时间不满足 不要忽略一点,FPGA无法分析外部的条件的;而且,个人认为,时序分析OK也只是说明了概率问题

ilove314_323192455 2010-5-22 22:52

正常仿真的时候都是没有问题的,而且最终出现状况并不是有规律的,是有一定突发性的,所以我只能推断是误码存在

用户1492539 2010-5-22 15:26

觉得是不是与这个计数器配合的电路有问题?就像博主说的当x_cnt > 10’d799时,计数器是可以继续跑的,直到0,再循环,也就是说这个计数器可以恢复,而与之配合的的那部分电路却没有恢复,所以博主还要看那部分电路是否够健壮。

用户151245 2008-5-30 01:17

我的毕设题目就是基于FPGA的GMSK数字调制器研制,希望博主不吝赐教 QQ 95611302 E-mail jr19861029@163.com
相关推荐阅读
特权ilove314 2016-06-30 21:16
例说FPGA连载6:FPGA开发所需的技能
例说FPGA连载6:FPGA开发所需的技能 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   前面的文字已经做了很多铺垫,相信读...
特权ilove314 2016-06-28 21:09
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-28 21:05
例说FPGA连载5:FPGA的优势与局限性
例说FPGA连载5:FPGA的优势与局限性 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   若要准确评估FPGA技术能否满足开...
特权ilove314 2016-06-26 22:11
例说FPGA连载4:FPGA语言与厂商介绍
例说FPGA连载4:FPGA语言与厂商介绍 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   Verilog与VHDL 说到FP...
特权ilove314 2016-06-23 21:26
例说FPGA连载3:FPGA与其它主流芯片的比较
例说FPGA连载3:FPGA与其它主流芯片的比较 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   FPGA、ASIC和ASSP...
特权ilove314 2016-06-21 20:32
例说FPGA连载2:FPGA是什么
例说FPGA连载2:FPGA是什么 特权同学,版权所有 配套例程和更多资料下载链接: http://pan.baidu.com/s/1c0nf6Qc   2015年伊始,Intel欲出资百亿美金收...
EE直播间
更多
我要评论
2
12
关闭 站长推荐上一条 /3 下一条