diff --git a/Makefile b/Makefile index 096be56..b584895 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,8 @@ uart_files = $(wildcard uart16550/*.v) soc_sim_files = $(soc_files) sim_console.vhdl sim_pp_uart.vhdl sim_bram_helpers.vhdl \ sim_bram.vhdl sim_jtag_socket.vhdl sim_jtag.vhdl dmi_dtm_xilinx.vhdl \ - sim_16550_uart.vhdl + sim_16550_uart.vhdl \ + random.vhdl glibc_random.vhdl glibc_random_helpers.vhdl soc_sim_c_files = sim_vhpi_c.c sim_bram_helpers_c.c sim_console_c.c \ sim_jtag_socket_c.c @@ -177,7 +178,8 @@ toplevel=fpga/top-generic.vhdl dmi_dtm=dmi_dtm_dummy.vhdl fpga_files = $(core_files) $(soc_files) fpga/soc_reset.vhdl \ - fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl + fpga/pp_fifo.vhd fpga/pp_soc_uart.vhd fpga/main_bram.vhdl \ + nonrandom.vhdl synth_files = $(core_files) $(soc_files) $(fpga_files) $(clkgen) $(toplevel) $(dmi_dtm) diff --git a/decode1.vhdl b/decode1.vhdl index eceee40..a58525e 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -188,7 +188,7 @@ architecture behaviour of decode1 is 2#0000011010# => (ALU, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- cntlzw 2#1000111010# => (ALU, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- cnttzd 2#1000011010# => (ALU, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- cnttzw - -- 2#1011110011# darn + 2#1011110011# => (ALU, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- darn 2#0001010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbf 2#0000110110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbst 2#0100010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- dcbt diff --git a/execute1.vhdl b/execute1.vhdl index a620a50..a53024f 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -97,6 +97,11 @@ architecture behaviour of execute1 is signal x_to_divider: Execute1ToDividerType; signal divider_to_x: DividerToExecute1Type; + -- random number generator signals + signal random_raw : std_ulogic_vector(63 downto 0); + signal random_cond : std_ulogic_vector(63 downto 0); + signal random_err : std_ulogic; + -- signals for logging signal exception_log : std_ulogic; signal irq_valid_log : std_ulogic; @@ -185,6 +190,11 @@ architecture behaviour of execute1 is return msr_out; end; + -- Tell vivado to keep the hierarchy for the random module so that the + -- net names in the xdc file match. + attribute keep_hierarchy : string; + attribute keep_hierarchy of random_0 : label is "yes"; + begin rotator_0: entity work.rotator @@ -238,6 +248,14 @@ begin d_out => divider_to_x ); + random_0: entity work.random + port map ( + clk => clk, + data => random_cond, + raw => random_raw, + err => random_err + ); + dbg_msr_out <= ctrl.msr; log_rd_addr <= r.log_addr_spr; @@ -776,6 +794,20 @@ begin v.e.write_cr_mask := num_to_fxm(crnum); v.e.write_cr_data := newcrf & newcrf & newcrf & newcrf & newcrf & newcrf & newcrf & newcrf; + when OP_DARN => + if random_err = '0' then + case e_in.insn(17 downto 16) is + when "00" => + result := x"00000000" & random_cond(31 downto 0); + when "10" => + result := random_raw; + when others => + result := random_cond; + end case; + else + result := (others => '1'); + end if; + result_en := '1'; when OP_MFMSR => result := ctrl.msr; result_en := '1'; diff --git a/fpga/fpga-random.vhdl b/fpga/fpga-random.vhdl new file mode 100644 index 0000000..7897c05 --- /dev/null +++ b/fpga/fpga-random.vhdl @@ -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; diff --git a/fpga/fpga-random.xdc b/fpga/fpga-random.xdc new file mode 100644 index 0000000..ba69f87 --- /dev/null +++ b/fpga/fpga-random.xdc @@ -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*] diff --git a/microwatt.core b/microwatt.core index 15786fe..9c91620 100644 --- a/microwatt.core +++ b/microwatt.core @@ -64,6 +64,8 @@ filesets: xilinx_specific: files: - xilinx-mult.vhdl : {file_type : vhdlSource-2008} + - fpga/fpga-random.vhdl : {file_type : vhdlSource-2008} + - fpga/fpga-random.xdc : {file_type : xdc} debug_xilinx: files: diff --git a/nonrandom.vhdl b/nonrandom.vhdl new file mode 100644 index 0000000..16f81da --- /dev/null +++ b/nonrandom.vhdl @@ -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; diff --git a/random.vhdl b/random.vhdl new file mode 100644 index 0000000..063c30e --- /dev/null +++ b/random.vhdl @@ -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;