[英]How to implement a (pseudo) hardware random number generator
正如摩根的回答中所指出的,這只會產生一個隨機位。 LFSR 中的位數僅設置您在序列重復之前獲得的值的數量。 如果你想要一個 N 位的隨機數,你必須運行 N 個周期的 LFSR。 但是,如果您希望每個時鍾周期都有一個新數字,另一種選擇是展開循環並預測 N 個周期中的數字。 重復下面摩根的例子,但每個周期得到一個 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
編輯:在下面添加了一個不需要您進行數學計算的新版本。 把它放在一個循環中,讓綜合工具找出邏輯:
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
我也想讓 LFSR 長度參數化,但這要困難得多,因為反饋抽頭不遵循簡單的模式。
這是一個在 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
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
選擇抽頭點並找出序列長度(重復之前的數字數)可以從該表中找到。
例如,一個 17,820,000、30 位寬的序列可以使用以下抽頭:
0x20000029 => bits "100000000000000000000000101001"
0x2000005E => bits "100000000000000000000001011110"
0x20000089 => bits "100000000000000000000010001001"
第一個將具有以下反饋項:
feedback = data[29] ^ data[5] ^ data[3] ^ data[0];
如果您不確定抽頭的順序,請記住 MSB 將始終是一個反饋點。 最后(抽頭)反饋點定義了 LFSR 的有效長度,之后它只是一個移位寄存器,與反饋序列無關。
如果您需要 69,273,666 的序列,則必須實現 31 位 LFSR 並為您的隨機數選擇 30 位。
LFSR 是創建 1 位隨機數流的好方法,但如果您采用多個連續位,這些位之間存在相關性,則它是相同的數字移位加上抖動位。 如果數字被用作抖動流,您可能需要引入一個映射層,例如每隔一位交換一次。 或者,為每個位使用不同長度的 LFSR 或抽頭點。
高效的移位寄存器、LFSR 計數器和長偽隨機序列發生器,
Peter Alfke 的 Xilinx 應用筆記。
Virtex 器件中的線性反饋移位寄存器,
由 Maria George 和 Peter Alfke 撰寫的 Xilinx 應用筆記。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.