m序列发生器
什么是m序列发生器
m序列发生器的概念在《数字电路》这门课里讲的比较详细了,这里就不给大家详细复习了。简而言之,长度为 k k k的m序列发生器会产生周期为 2 k − 1 2^k-1 2k−1的序列串,其中任取一个长度为 k k k的序列总是不相同,并且一个周期内长度为 k k k的序列遍历除了(000…0)共k个0以外的全体序列。
如何实现m序列发生器
在Verilog里,我们采用长度为 k k k的移位寄存器来实现m序列的发生,其中 k = 4 k=4 k=4的m序列发生器如下图所示:
可以看出,其反馈方程为 Q 0 = Q 2 ⊕ Q 3 Q_0=Q_2\oplus Q_3 Q0=Q2⊕Q3
如何得到m序列的反馈方程
对于更一般的情形,我们想要找出反馈方程并不是那么平凡的事情。所幸的是,这一问题可以用近世代数里的本原多项式这一概念来解决,前人已经为我们制作出了 k ≤ 25 k\le 25 k≤25的反馈方程的表格(值得注意的是,最小本原多项式并不是唯一的),具体内容可以参考链接1 。由于这并不是我们的重点,此处略去。我们将目光集中在这个图上,下图也是搬运自链接1:
本原多项式可以指导我们构造反馈方程。具体而言,对于长度为 n n n的m序列,除了 x n x^n xn外,只要存在 x p x^p xp系数为1,那么 Q n − 1 − p Q_{n-1-p} Qn−1−p就参与异或。
以 k = 14 k=14 k=14为例,本原多项式为 x 14 + x 10 + x 6 + x + x 0 x^{14}+x^{10}+x^6+x+x^0 x14+x10+x6+x+x0,其中 x 0 x^0 x0代表 Q 13 Q_{13} Q13、 x 1 x^1 x1代表 Q 12 Q_{12} Q12、 x 6 x^6 x6代表 Q 7 Q_{7} Q7、 x 10 x^{10} x10代表 Q 3 Q_{3} Q3, x 14 x^{14} x14丢掉不看。
可以用这段Python小程序校验一下本原多项式是否是正确的:
length = 8 # m序列长度为len,周期为"2^len - 1"
M_poly = [7,5,4,3] # 本原多项式x^3+x+1
M_xor = [0] * length
for i in M_poly:
M_xor[length-1-i] = 1
M_series = [1] * length
ALL_M_series = []
for i in range(2**length-1):
temp = 0
for j in range(length):
temp = temp + M_xor[j]*M_series[j]
M_series.append(temp%2)
del M_series[0]
ALL_M_series.append(''.join([str(i) for i in M_series]))
print(2**length-1)
# print(ALL_M_series)
# print(set(ALL_M_series))
print((len(ALL_M_series)==len(set(ALL_M_series))))
用Verilog写m序列发生器及其testbench
m序列发生器(2-16位)
module M_series#(
parameter len = 4 // parameter range from 2 to 16
)
(
input wire clk,
input wire rst_n,
output wire Q
);
reg[(len-1):0] Q_r;
assign Q = Q_r[(len-1)];
always @(posedge clk or negedge rst_n) begin
if (rst_n == 0) begin // negedge reset
Q_r <= ~(0);
end
else begin
Q_r <= Q_r<<1; // shift reg
case(len)
2 : Q_r[0] <= Q_r[1]^Q_r[0];
3 : Q_r[0] <= Q_r[2]^Q_r[1];
4 : Q_r[0] <= Q_r[3]^Q_r[2];
5 : Q_r[0] <= Q_r[4]^Q_r[2];
6 : Q_r[0] <= Q_r[5]^Q_r[4];
7 : Q_r[0] <= Q_r[6]^Q_r[3];
8 : Q_r[0] <= Q_r[7]^Q_r[5]^Q_r[4]^Q_r[3];
9 : Q_r[0] <= Q_r[8]^Q_r[4];
10: Q_r[0] <= Q_r[9]^Q_r[6];
11: Q_r[0] <= Q_r[10]^Q_r[8];
12: Q_r[0] <= Q_r[11]^Q_r[10]^Q_r[7]^Q_r[5];
13: Q_r[0] <= Q_r[12]^Q_r[11]^Q_r[9]^Q_r[8];
14: Q_r[0] <= Q_r[13]^Q_r[12]^Q_r[7]^Q_r[3];
15: Q_r[0] <= Q_r[14]^Q_r[13];
16: Q_r[0] <= Q_r[15]^Q_r[14]^Q_r[12]^Q_r[3];
default: Q_r[0] <= Q_r[0];
endcase
end
end
endmodule
testbench
//~ `New testbench
`timescale 1ns / 1ns
module tb_M_series;
// M_series Parameters
parameter PERIOD = 10;
parameter M_len = 5;
// M_series Inputs
reg clk = 0 ;
reg rst_n = 1 ;
// M_series Outputs
wire Q ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
M_series #(
.len ( M_len ))
u_M_series (
.clk ( clk ),
.rst_n ( rst_n ),
.Q ( Q )
);
initial
begin
#(PERIOD*2) rst_n = 0;
#(PERIOD*2) rst_n = 1;
#(PERIOD*100)
$finish;
end
endmodule