FPGA生成隨機數的方法,目前有以下幾種:
1、震蕩采樣法
? ? ? ? 實現方式一:通過低頻時鐘作為D觸發器的時鐘輸入端,高頻時鐘作為D觸發器的數據輸入端,使用高頻采樣低頻,利用亞穩態輸出隨機數。
? ? ? ? 實現方式二:使用三個或以上反相器首尾互聯,形成環路振蕩器。使用時鐘采集,得到不穩定的數據,以形成隨機數(其實此種方式與方式一相類似,反相器的組合邏輯相當于高頻時鐘,時鐘信號相當于低頻時鐘,同樣利用亞穩態生成隨機數)。
(直接按照實現方式二,上具體實現代碼)
//反相器環形級聯,組合為振蕩器,利用亞穩態狀態,得到隨機數module random_gen
(input clk,input start, //開始命令output reg random_valid = 0,output reg [7:0] random_data = 0);reg state = 1'b0; //0空閑態 1隨機態(* ALLOW_COMBINATORIAL_LOOPS = "true" *)(*dont_touch = "true" *)reg a = 1'b0;
(* ALLOW_COMBINATORIAL_LOOPS = "true" *)(*dont_touch = "true" *)reg b = 1'b0;
(* ALLOW_COMBINATORIAL_LOOPS = "true" *)(*dont_touch = "true" *)reg c = 1'b0;reg [2:0] bit_cnt = 0; //3個取反器,環形震蕩
//取反器
always@(state)
beginb <= !a;
end//取反器
always@(state)
beginc <= !b;
end//取反器
always@(state)
begina <= !c;
endalways@(posedge clk)
beginif(state == 1'b0) begin //state == 0bit_cnt <= 3'd0;random_valid <= 1'b0;if(start) begin state <= 1'b1;endelse beginstate <= 1'b0;endendelse begin //state == 1bit_cnt <= bit_cnt + 1'b1;if(bit_cnt == 3'b111) beginstate <= 1'b1;random_valid <= 1'b1;endelse beginrandom_valid <= 1'b0; endrandom_data <= {random_data[6:0],c};end
end endmodule
針對于
(* ALLOW_COMBINATORIAL_LOOPS = "true" *)約束,也可以再約束文件中增加約束:
#采用組合邏輯形式的環形震蕩生成隨機數,因此進行約束
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets random_gen/a]
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets random_gen/b]
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets random_gen/c]
2、LFSR偽隨機數
? ? ? ? LFSR(Linear-feedback shift register)是一種特殊的的移位寄存器,他的輸入取決于其先前狀態,其生成的隨機數是一種偽隨機數。其架構如下圖所示:
????????上圖中,gn為反饋系數,取值只能是1或者0,N個D觸發器,可以提供2^(N-1)個輸出狀態,為了保證隨機性,gn的選擇必須滿足一定的條件,不能全部為0,且gn必須等于1。
? ? ? ? 假設輸出的隨機數的位寬為8bits,且取值g0g1g2g3g4g5g6g7g8=101110001,則可以實現如下代碼:
module LFSR #
( parameter [7:0] SEED = 8'h11)
(input rstn, input clk, output reg [7:0] rand_data //隨機數
);always@(posedge clk or negedge rstn)
beginif(!rstn)rand_data <=SEED;else beginrand_data[0] <= rand_data[7];rand_data[1] <= rand_data[0];rand_data[2] <= rand_data[1];rand_data[3] <= rand_data[2];rand_data[4] <= rand_data[3]^rand_data[7];rand_data[5] <= rand_data[4]^rand_data[7];rand_data[6] <= rand_data[5]^rand_data[7];rand_data[7] <= rand_data[6];end
endendmodule
3、使用FLASH或EEPROM生成隨機數
????????讀取FLASH中預存的seed,然后進行相關邏輯運算,得到偽隨機數。同時按照既定的邏輯生成新的seed,寫入到FLASH或者EEPROM中,這樣就可以保證每次輸出的隨機數不同。(此種方式較為復雜,不推薦)
? ? ? ? 此處不進行具體實現。