特权同学

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

0
阅读(3648)

基于FPGA/CPLDMSK调制解调的工程应用

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

 

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

 

MSK信号具有如下特点:

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

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

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

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

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

 

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

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

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

 

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

 产生两路正余弦高频调制信号分别为hsin和hcos,再将它们与原pq两路信号相乘结果如pmux和qmux。

 

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

 

 

Verilog代码如下:

 

 

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;                 //cos和sin工作使能信号

    wire csrdy;              //cos和sin输出使能信号

    wire pqsrdy;         //pcos和qsin输出使能信号

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

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

    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: ;        //其它情况p和q值保持不变

              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: ;        //其它情况p和q值保持不变

              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.正所谓用面积换速度吧。