ngu*_*rie 11
正如Morgan的回答所指出的,这只会产生一个随机位.LFSR中的位数仅设置序列重复之前获得的值.如果你想要一个N位随机数,你必须运行LFSR N个周期.但是,如果您希望每个时钟周期都有一个新数字,则另一个选项是展开循环并预测N个循环中的数字.重复下面的Morgan示例,但每个周期得到一个5位数:
module fibonacci_lfsr_5bit(
input clk,
input rst_n,
output reg [4:0] data
);
reg [4:0] data_next;
always @* begin
data_next[4] = data[4]^data[1];
data_next[3] = data[3]^data[0];
data_next[2] = data[2]^data_next[4];
data_next[1] = data[1]^data_next[3];
data_next[0] = data[0]^data_next[2];
end
always @(posedge clk or negedge rst_n)
if(!rst_n)
data <= 5'h1f;
else
data <= data_next;
endmodule
Run Code Online (Sandbox Code Playgroud)
编辑:在下面添加了一个新版本,不需要您进行数学计算.只需将其置于循环中,让综合工具找出逻辑:
module fibonacci_lfsr_nbit
#(parameter BITS = 5)
(
input clk,
input rst_n,
output reg [4:0] data
);
reg [4:0] data_next;
always_comb begin
data_next = data;
repeat(BITS) begin
data_next = {(data_next[4]^data_next[1]), data_next[4:1]};
end
end
always_ff @(posedge clk or negedge reset) begin
if(!rst_n)
data <= 5'h1f;
else
data <= data_next;
end
end
endmodule
Run Code Online (Sandbox Code Playgroud)
我想使LFSR长度也可参数化,但由于反馈抽头不遵循简单模式,因此更加困难.
Sta*_*low 10
这是一个在FPGA上工作的TRNG(真随机数发生器).它基本上是没有触发器的LFSR类型结构,因此它是一个连续运行的组合循环.当你将这些模块中的几个和XOR位组合在一起时,你会得到一个真正随机的位,因为每个组合的抖动都会导致信号混乱.您可以运行的最大时钟速率取决于您的FPGA,您应该使用像diehard,dieharder,STS或TestU01这样的测试套件测试随机性.
这些被称为伽罗瓦环振荡器(GARO).还有其他TRNG使用较少的功率和面积,但它们操作和写入很琐碎,通常依靠调谐延迟使触发器变为亚稳态.
module GARO (input stop,clk, reset, output random);
(* OPTIMIZE="OFF" *) //stop *xilinx* tools optimizing this away
wire [31:1] stage /* synthesis keep */; //stop *altera* tools optimizing this away
reg meta1, meta2;
assign random = meta2;
always@(posedge clk or negedge reset)
if(!reset)
begin
meta1 <= 1'b0;
meta2 <= 1'b0;
end
else if(clk)
begin
meta1 <= stage[1];
meta2 <= meta1;
end
assign stage[1] = ~&{stage[2] ^ stage[1],stop};
assign stage[2] = !stage[3];
assign stage[3] = !stage[4] ^ stage[1];
assign stage[4] = !stage[5] ^ stage[1];
assign stage[5] = !stage[6] ^ stage[1];
assign stage[6] = !stage[7] ^ stage[1];
assign stage[7] = !stage[8];
assign stage[8] = !stage[9] ^ stage[1];
assign stage[9] = !stage[10] ^ stage[1];
assign stage[10] = !stage[11];
assign stage[11] = !stage[12];
assign stage[12] = !stage[13] ^ stage[1];
assign stage[13] = !stage[14];
assign stage[14] = !stage[15] ^ stage[1];
assign stage[15] = !stage[16] ^ stage[1];
assign stage[16] = !stage[17] ^ stage[1];
assign stage[17] = !stage[18];
assign stage[18] = !stage[19];
assign stage[19] = !stage[20] ^ stage[1];
assign stage[20] = !stage[21] ^ stage[1];
assign stage[21] = !stage[22];
assign stage[22] = !stage[23];
assign stage[23] = !stage[24];
assign stage[24] = !stage[25];
assign stage[25] = !stage[26];
assign stage[26] = !stage[27] ^ stage[1];
assign stage[27] = !stage[28];
assign stage[28] = !stage[29];
assign stage[29] = !stage[30];
assign stage[30] = !stage[31];
assign stage[31] = !stage[1];
endmodule
Run Code Online (Sandbox Code Playgroud)
一个LFSR往往是呼叫的第一站.实现相对简单,移位寄存器与多个术语XORd一起创建反馈术语.
在考虑LFSR的实现时,需要考虑随机数的位宽和数量的可重复性.对于N位,最大LFSR将具有(2**N) - 1
状态.所有零状态不能与其他硬件一起使用.
一个示例4位LFSR,点击0位和4位:
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
Run Code Online (Sandbox Code Playgroud)
选择分接点并找出序列长度(重复前的数字数)可以在此表中找到.
例如,17,820,000,30位宽的序列可以使用以下的抽头:
0x20000029 => bits "100000000000000000000000101001"
0x2000005E => bits "100000000000000000000001011110"
0x20000089 => bits "100000000000000000000010001001"
Run Code Online (Sandbox Code Playgroud)
第一个将有一个反馈术语:
feedback = data[29] ^ data[5] ^ data[3] ^ data[0];
Run Code Online (Sandbox Code Playgroud)
如果您不确定水龙头的顺序,请记住MSB将始终是一个反馈点.Last(tap)反馈点定义了LFSR的有效长度,之后它只是一个移位寄存器,与反馈序列无关.
如果需要序列69,273,666,则必须实现31位LFSR并为随机数选择30位.
LFSR是创建1位随机数流的好方法,但如果要连续多个位,则值之间存在相关性,则它是相同的数字移位加抖动位.如果该数字被用作抖动流,您可能需要引入映射层,例如每隔一位交换一次.或者,对每个位使用不同长度的LFSR或抽头点.
高效移位寄存器,LFSR计数器和长伪随机序列发生器,
Peter Alfke的Xilinx应用笔记.
Virtex器件中的线性反馈移位寄存器,
由Maria George和Peter Alfke撰写的Xilinx应用笔记.