M 序列是一种伪随机序列,常用于保密通信、信道抗干扰测试等,关于生成原理等可见我之前的文章,此处不表。
直接上代码,此模块只需要指定本原多项式,就可以自动生成对应阶数的 M 序列,泛用性比较好。至于本原多项式,可以用 matlab 的 primpoly 函数生成,然后随便选一个,我这里默认的是 10 阶的第一个本原多项式 1033,读者可自行修改为其他值。
/*
* file : M_seq.v
* author : 今朝无言
* date : 2023-05-04
* version : v1.0
* description : M序列发生器
*/
module M_seq(
input clk,
output mg
);
parameter F = 1033; //本原多项式
localparam N = clogb2(F) - 1; //阶数
localparam L = (1 << N) - 1; //M序列周期
reg [N-1:0] a = 1'b1;
wire [N:0] c;
reg an;
assign c = F;
integer i = 0;
always @(posedge clk) begin
an = 0;
for(i = 1; i <= N; i = i+1) begin
an = c[i]? an + a[N-i] : an;
end
a = {an, a[N-1:1]};
end
assign mg = a[0];
//------------------------log2-----------------------------
function integer clogb2 (input integer depth);
begin
for (clogb2 = 0; depth > 0; clogb2 = clogb2 + 1) begin
depth = depth >> 1;
end
end
endfunction
endmodule
仿真文件如下
`timescale 1ns/100ps
module M_seq_tb();
reg clk_100M = 1'b1;
always #5 begin
clk_100M <= ~clk_100M;
end
wire mg;
M_seq #(.F(1033))
M_seq_inst(
.clk (clk_100M),
.mg (mg)
);
//-----------------------仿真结果保存---------------------------------
integer dout_file;
localparam filename = "./m_seq.txt";
initial begin
dout_file = $fopen(filename);
if(dout_file == 0) begin //打开文件失败
$display("can not open the file!");
$finish;
end
end
always @(posedge clk_100M) begin
$fdisplay(dout_file, "%d", mg);
end
initial begin
#(10*1023)
$fclose(dout_file);
$finish;
end
endmodule
仿真结果保存到 m_seq.txt 文件中,然后可以自行与 matlab 的生成结果比对。