Как реализовать аппаратный генератор случайных чисел на HDL (verilog)?
Какие варианты необходимо рассмотреть?
Этот вопрос соответствует формату самостоятельного ответа. Дополнительные ответы и обновления приветствуются.
Как реализовать аппаратный генератор случайных чисел на HDL (verilog)?
Какие варианты необходимо рассмотреть?
Этот вопрос соответствует формату самостоятельного ответа. Дополнительные ответы и обновления приветствуются.
Как отмечено в ответе Моргана, это даст только один случайный бит. Количество битов в LFSR определяет только то, сколько значений вы получите до повторения последовательности. Если вам нужно N-битное случайное число, вам нужно запустить LFSR для N циклов. Однако, если вам нужно новое число каждый такт, другой вариант — развернуть цикл и предсказать, каким будет число за 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, но это намного сложнее, поскольку отводы обратной связи не следуют простой схеме.
Это TRNG (генератор истинных случайных чисел), который работает на FPGA. Это в основном структура типа LFSR без триггеров, поэтому это комбинаторный цикл, который работает непрерывно. Сигнал колеблется хаотично, при объединении нескольких таких модулей и битов XOR получается действительно случайный бит, так как джиттер от каждого комбинируется. Максимальная тактовая частота, с которой вы можете запустить это, зависит от вашей FPGA, вы должны проверить случайность с помощью набора тестов, такого как твердолобый, несгибаемый, 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 разной длины или точки ответвления для каждого бита.
data <= {data[2:0], feedback} ;
вы хотели написать data <= {data[3:0], feedback} ;
. Кроме того, поскольку я публикую, не могли бы вы указать, имеет ли значение, смещаюсь ли я влево или вправо. Я думаю, что здесь вы смещаетесь влево, какая причина для этого? Спасибо
- person ipunished; 26.01.2013
reg [1:0] meta; always @(posedge clk ... meta[1:0] <= {meta[0], inp};
- person Morgan; 26.01.2013