m序列生成器的原理与MATLAB及FPGA实现

来源:互联网 发布:武汉哪里有mac专柜地址 编辑:程序博客网 时间:2024/06/01 14:53

        m序列是最长线性移位寄存器序列的简称,是一种伪随机序列,因其良好的自相关特性和互相关特性,在通信领域有着广泛的应用,例如扩频通信中的扩频码,同步、加扰、误码率测量等方面。

1. 生成原理

      m序列的生成原理较为简单,通过线性反馈移位寄存器实现。线性反馈移位寄存器的结构如下图所示:


        可以看出线性反馈移位寄存器的更新操作为:


        需要注意的是,上面计算中的加法表示模2加,a(n)更新a(n-1),a(n-1)...a(1)右移一位完成更新操作。线性反馈移位寄存器的输出序列与两个因素有关,一个是寄存器的初始值,另一个是寄存器的连接系数c(i)。连接系数c(i)决定了线性反馈移位寄存器的结构,其可由下面的多项式表示:

        上面的多项式为特征多项式,c(i)的值表示了第i个寄存器是否有连接,c(i)只有两个值,0或1,0表示无连接,1表示有连接。从数学上可以证明:若线性反馈移位寄存器的特征多项式为本原多项式,则寄存器产生的序列达到最大周期,即产生m序列。对于包含n个寄存器的线性反馈移位寄存器,其最大周期为2^n-1,所以其产生的m序列的周期也为2^n-1。
        这里,笔者给出了n不同取值下,本原多项式的表达式,具体如下(图片来自网络):

         要是找不到这张表也不要紧,在MATLAB里通过primpoly函数也可以查出n对应的本原多项式,例如要查n=3对应的本原多项式,在MATLAB的命令行直接输入:primpoly(3),输出:D^3+D^1+1,另外需要注意的是,对于一个指定的n,其本原多项式可能不止一种,比如刚才n=3对应的本原多项式就有两种,primpoly(3)只输出了其中一种,我们可以在primpoly命令中加入可选参数,输出所有的可能结果,即primpoly(3,'all'),输出:D^3+D^1+1和D^3+D^2+1。

2. MATLAB实现

function [mseq] = m_sequence(fbconnection, initregister)
%+++++++++++++++++++++++variables++++++++++++++++++++++++++%
% fbconnection: 线性移位寄存器的系数
% initregister: 寄存器的初始值
% mseq: 生成的m序列
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++%

n = length(fbconnection);
N = 2^n-1;
register = initregister; %定义移位寄存器的初始状态
newregister = zeros(1, n);
mseq = zeros(1, N);

for i = 1:N
    mseq(i) = register(n);
    newregister(1)= mod(sum(fbconnection.*register),2);
    newregister(2:n) = register(1:n-1);
    register = newregister;    
end

        这里将m序列生成器封装成了一个函数,供外部调用,调用的输入参数有两个:fbconnection表示线性反馈移位寄存器的连接系数,需要写成二进制向量形式,且左端为最低位,右端为最高位,initregister表示寄存器的初始值,初始值不能取0,否则寄存器的输出一直为0。下面结合具体的例子讲一下,就清楚怎么用了。考虑寄存器级数n=3的情况,采用的本原多项式为D^3+D^2+1,即c(3)=1,c(2)=1,c(1)=0,c(0)=1,则fbconnection为[c(1) c(2) c(3)]=[0 1 1],因为c(0)作为反馈项必须为1,因此无须考虑到连接系数中,initregister不妨设为[1 0 1],输出的m序列为[1 0 1 1 1 0 0]。

3. FPGA实现

        这里采用verilog对m序列的生成进行描述,具体代码如下:
m_sequence(
  input                 clk,
  input                 rst_n,
  output reg        mseq
);

reg [2:0] LFSR;

/*************************************************************/
// 移位寄存器更新
/*************************************************************/
always @(posedge clk)
    begin
        if(!rst_n)
            LFSR <= 3'b101;
        else begin
            LFSR[0] <= LFSR[2] ^ LFSR[1];  //模2加相当于异或操作
            LFSR[2:1] <= LFSR[1:0];
        end
    end

/*************************************************************/
// m序列输出
/*************************************************************/
always @(posedge clk)
    begin
        if(!rst_n)
            mseq <= 1'b0;
        else
            mseq <= LFSR[2];
    end
/*************************************************************/
0 0