N 通常是为 LFSR 的状态保留的,M 可以很好地用于我们希望生成的随机位数。
标准 LFSR 生成 1 位随机数据,如果使用 LFSR 的连续位,它们可以高度相关,尤其是在每个时钟周期取多位值时。为了消除这种相关性,我们可以对 lfsr 进行超频,例如 4 次以生成 4 位。对此的替代方法是计算您将为每个位获得的方程(反馈多项式)。对于每个时钟,其内部状态(由 LFSR 的 N 位表示)将向前移动 4 步。超频或创建反馈抽头以将状态向前移动超过 1 步的两种技术都称为跃进。
问题中的代码示例取自a previous question and answer,这是一个为跨越式lfsr手动创建额外反馈的示例。
可以通过生成转移矩阵并提高我们希望前进的步数的幂来完成此操作。
快速 4 位 LFRS 示例:使用转换矩阵 a:
a =
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 1
反馈是矩阵的最后一行看到的第一位和最后一位的异或。所有其他行只是一个班次。这个 LFSR 的输出是好的一位。两位将受到高度相关性的影响,除非超频。
>> a^2
ans =
0 0 1 0
0 0 0 1
1 0 0 1
1 1 0 1
如果我们想要两个位,我们需要对转换矩阵求平方。可以看出,前两行是两个位置的移位,我们需要两个位置的反馈,即我们每时钟将LFSR向前移动两个状态。
只是为了确认我们是否需要三个位:
a^3
ans =
0 0 0 1
1 0 0 1
1 1 0 1
1 1 1 1
上一个问题中的第二个代码示例继续对代码进行参数化,因此不必手动创建跨越式计算,跳过所有可爱的数学!然而,所使用的方法意味着它不能完全参数化。因此,我想重新审视我为该问题提供的示例:
module fibonacci_lfsr(
input clk,
input rst_n,
output [4:0] data
);
wire feedback = data[4] ^ data[1] ;
always @(posedge clk or negedge rst_n)
if (~rst_n)
data <= 4'hf;
else
data <= {data[3:0], feedback} ;
endmodule
现在我们要对其进行参数化:
module fibonacci_lfsr#(
parameter POLYNOMIAL = 4'h9
)(
input clk,
input rst_n,
output [4:0] data
);
//AND data with POLYNOMIAL this
// selects only the taps in the polynomial to be used.
// ^( ) performs a XOR reduction to 1 bit
always @* begin
feedback = ^( POLYNOMIAL & data);
end
//Reseting to 0 is easier
// Invert feedback, all 1's state is banned instead of all 0's
always @(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= {data[3:0], ~feedback};
endmodule
现在是一小步,只需将移位移到同步循环之外以帮助执行后面的步骤。
always @* begin
data_next = data;
feedback = ^( POLYNOMIAL & data);
data_next = {data_next[3:0], ~feedback} ; //<- Shift and feedback
end
always @(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= data_next;
TL;DR
现在要控制跳跃式迭代,让工具完成乘以转移矩阵的繁重工作。
module fibonacci_lfsr#(
parameter POLYNOMIAL = 4'h9,
parameter N = 4,
parameter BITS = 2
)(
input clk,
input rst_n,
output [BITS-1:0] random
);
reg [N-1:0] data;
reg [N-1:0] data_next;
reg feedback;
assign random = data[N-1:N-BITS];
always @* begin
data_next = data;
// Compiler unrolls the loop, calculating the transition matrix
for (int i=0; i<BITS; i++) begin
feedback = ^( POLYNOMIAL & data_next);
data_next = {data_next[N-2:0], ~feedback} ;
end
end
always @(posedge clk or negedge rst_n)
if (~rst_n)
data <= 'b0;
else
data <= data_next;
endmodule
EDA Playground 上的示例。
i++ 是 SystemVerilog 的一部分。如果您只能合成普通(2009 年之前)Verilog,那么您需要将 i 声明为整数并在 for 循环中使用 i =i+1。