forked from cores/microwatt
Add random number generator and implement the darn instruction
This adds a true random number generator for the Xilinx FPGAs which uses a set of chaotic ring oscillators to generate random bits and then passes them through a Linear Hybrid Cellular Automaton (LHCA) to remove bias, as described in "High Speed True Random Number Generators in Xilinx FPGAs" by Catalin Baetoniu of Xilinx Inc., in: https://pdfs.semanticscholar.org/83ac/9e9c1bb3dad5180654984604c8d5d8137412.pdf This requires adding a .xdc file to tell vivado that the combinatorial loops that form the ring oscillators are intentional. The same code should work on other FPGAs as well if their tools can be told to accept the combinatorial loops. For simulation, the random.vhdl module gets compiled in, which uses the pseudorand() function to generate random numbers. Synthesis using yosys uses nonrandom.vhdl, which always signals an error, causing darn to return 0xffff_ffff_ffff_ffff. This adds an implementation of the darn instruction. Darn can return either raw or conditioned random numbers. On Xilinx FPGAs, reading a raw random number gives the output of the ring oscillators, and reading a conditioned random number gives the output of the LHCA. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>jtag-port
parent
290b05f97d
commit
1a7aebeef8
@ -0,0 +1,53 @@
|
||||
-- Random number generator for Microwatt
|
||||
-- Based on https://pdfs.semanticscholar.org/83ac/9e9c1bb3dad5180654984604c8d5d8137412.pdf
|
||||
-- "High Speed True Random Number Generators in Xilinx FPGAs"
|
||||
-- by Catalin Baetoniu, Xilinx Inc.
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
|
||||
entity random is
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
data : out std_ulogic_vector(63 downto 0);
|
||||
raw : out std_ulogic_vector(63 downto 0);
|
||||
err : out std_ulogic
|
||||
);
|
||||
end entity random;
|
||||
|
||||
architecture behaviour of random is
|
||||
signal ringosc : std_ulogic_vector(63 downto 0);
|
||||
signal ro_reg : std_ulogic_vector(63 downto 0);
|
||||
signal lhca : std_ulogic_vector(63 downto 0);
|
||||
|
||||
constant lhca_diag : std_ulogic_vector(63 downto 0) := x"fffffffffffffffb";
|
||||
|
||||
begin
|
||||
random_osc : process(all)
|
||||
begin
|
||||
-- chaotic set of ring oscillators
|
||||
ringosc(0) <= ringosc(63) xor ringosc(0) xor ringosc(1);
|
||||
for i in 1 to 62 loop
|
||||
ringosc(i) <= ringosc(i-1) xor ringosc(i) xor ringosc(i+1);
|
||||
end loop;
|
||||
ringosc(63) <= not (ringosc(62) xor ringosc(63) xor ringosc(0));
|
||||
end process;
|
||||
|
||||
lhca_update : process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
ro_reg <= ringosc;
|
||||
raw <= ro_reg;
|
||||
-- linear hybrid cellular automaton
|
||||
-- used to even out the statistics of the ring oscillators
|
||||
lhca <= ('0' & lhca(63 downto 1)) xor (lhca and lhca_diag) xor
|
||||
(lhca(62 downto 0) & '0') xor ro_reg;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
data <= lhca;
|
||||
err <= '0';
|
||||
end behaviour;
|
@ -0,0 +1,3 @@
|
||||
set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets soc0/processor/execute1_0/random_0/ro_reg*]
|
||||
set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets soc0/processor/execute1_0/random_0/p_*]
|
||||
set_property ALLOW_COMBINATORIAL_LOOPS TRUE [get_nets soc0/processor/execute1_0/random_0/D*]
|
@ -0,0 +1,22 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
|
||||
entity random is
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
data : out std_ulogic_vector(63 downto 0);
|
||||
raw : out std_ulogic_vector(63 downto 0);
|
||||
err : out std_ulogic
|
||||
);
|
||||
end entity random;
|
||||
|
||||
architecture behaviour of random is
|
||||
|
||||
begin
|
||||
data <= (others => '1');
|
||||
raw <= (others => '1');
|
||||
err <= '1';
|
||||
end behaviour;
|
@ -0,0 +1,30 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
library work;
|
||||
use work.glibc_random.all;
|
||||
|
||||
entity random is
|
||||
port (
|
||||
clk : in std_ulogic;
|
||||
data : out std_ulogic_vector(63 downto 0);
|
||||
raw : out std_ulogic_vector(63 downto 0);
|
||||
err : out std_ulogic
|
||||
);
|
||||
end entity random;
|
||||
|
||||
architecture behaviour of random is
|
||||
begin
|
||||
err <= '0';
|
||||
|
||||
process(clk)
|
||||
variable rand : std_ulogic_vector(63 downto 0);
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
rand := pseudorand(64);
|
||||
data <= rand;
|
||||
raw <= rand;
|
||||
end if;
|
||||
end process;
|
||||
end behaviour;
|
Loading…
Reference in New Issue