OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_trng.vhd] - Blame information for rev 22

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
-- #################################################################################################
2
-- # << NEORV32 - True Random Number Generator (TRNG) >>                                           #
3
-- # ********************************************************************************************* #
4
-- # This unit implements a true random number generator which uses an inverter chain as entropy   #
5
-- # source. The inverter chain is constructed as GARO (Galois Ring Oscillator) TRNG. The single   #
6
-- # inverters are connected via simple latches that are used to enbale/disable the TRNG. Also,    #
7
-- # these latches are used as additional delay element. By using unique enable signals for each   #
8
-- # latch, the synthesis tool cannot "optimize" one of the inverters out of the design. Further-  #
9
-- # more, the latches prevent the synthesis tool from detecting combinatorial loops.              #
10
-- # The output of the GARO is de-biased by a simple von Neuman random extractor and is further    #
11
-- # post-processed by a 16-bit LFSR for improved whitening.                                       #
12
-- #                                                                                               #
13
-- # Sources:                                                                                      #
14
-- #  - GARO: "Experimental Assessment of FIRO- and GARO-based Noise Sources for Digital TRNG      #
15
-- #    Designs on FPGAs" by Martin Schramm, Reiner Dojen and Michael Heigly, 2017                 #
16
-- #  - Latches for platform independence: "Extended Abstract: The Butterfly PUF Protecting IP     #
17
-- #    on every FPGA" by Sandeep S. Kumar, Jorge Guajardo, Roel Maesyz, Geert-Jan Schrijen and    #
18
-- #    Pim Tuyls, Philips Research Europe, 2008                                                   #
19
-- #  - Von Neumann De-Biasing: "Iterating Von Neumann's Post-Processing under Hardware            #
20
-- #    Constraints" by Vladimir Rozic, Bohan Yang, Wim Dehaene and Ingrid Verbauwhede, 2016       #
21
-- # ********************************************************************************************* #
22
-- # BSD 3-Clause License                                                                          #
23
-- #                                                                                               #
24
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
25
-- #                                                                                               #
26
-- # Redistribution and use in source and binary forms, with or without modification, are          #
27
-- # permitted provided that the following conditions are met:                                     #
28
-- #                                                                                               #
29
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
30
-- #    conditions and the following disclaimer.                                                   #
31
-- #                                                                                               #
32
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
33
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
34
-- #    provided with the distribution.                                                            #
35
-- #                                                                                               #
36
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
37
-- #    endorse or promote products derived from this software without specific prior written      #
38
-- #    permission.                                                                                #
39
-- #                                                                                               #
40
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
41
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
42
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
43
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
44
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
45
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
46
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
47
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
48
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
49
-- # ********************************************************************************************* #
50
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
51
-- #################################################################################################
52
 
53
library ieee;
54
use ieee.std_logic_1164.all;
55
use ieee.numeric_std.all;
56
 
57
library neorv32;
58
use neorv32.neorv32_package.all;
59
 
60
entity neorv32_trng is
61
  port (
62
    -- host access --
63
    clk_i  : in  std_ulogic; -- global clock line
64
    addr_i : in  std_ulogic_vector(31 downto 0); -- address
65
    rden_i : in  std_ulogic; -- read enable
66
    wren_i : in  std_ulogic; -- write enable
67
    data_i : in  std_ulogic_vector(31 downto 0); -- data in
68
    data_o : out std_ulogic_vector(31 downto 0); -- data out
69
    ack_o  : out std_ulogic  -- transfer acknowledge
70
  );
71
end neorv32_trng;
72
 
73
architecture neorv32_trng_rtl of neorv32_trng is
74
 
75
  -- advanced configuration --------------------------------------------------------------------------------
76
  constant num_inv_c   : natural := 16; -- length of GARO inverter chain (default=16, max=16)
77
  constant lfsr_taps_c : std_ulogic_vector(15 downto 0) := "1101000000001000"; -- Fibonacci LFSR feedback taps
78
  -- -------------------------------------------------------------------------------------------------------
79
 
80
  -- control register bits --
81
  constant ctrl_taps_lsb_c  : natural :=  0; -- -/w: TAP 0 enable
82
  constant ctrl_taps_msb_c  : natural := 15; -- -/w: TAP 15 enable
83
  constant ctrl_en_c        : natural := 31; -- r/w: TRNG enable
84
 
85
  -- data register bits --
86
  constant ctrl_data_lsb_c  : natural :=  0; -- r/-: Random data bit 0
87
  constant ctrl_data_msb_c  : natural := 15; -- r/-: Random data bit 15
88
  constant ctrl_rnd_valid_c : natural := 31; -- r/-: Output byte valid
89
 
90
  -- IO space: module base address --
91
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
92
  constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
93
 
94
  -- access control --
95
  signal acc_en : std_ulogic; -- module access enable
96
  signal addr   : std_ulogic_vector(31 downto 0); -- access address
97
  signal wren   : std_ulogic; -- full word write enable
98
  signal rden   : std_ulogic; -- read enable
99
 
100
  -- random number generator --
101
  signal rnd_inv         : std_ulogic_vector(num_inv_c-1 downto 0); -- inverter chain
102
  signal rnd_enable_sreg : std_ulogic_vector(num_inv_c-1 downto 0); -- enable shift register
103
  signal rnd_enable      : std_ulogic;
104
  signal tap_config      : std_ulogic_vector(15 downto 0);
105
  signal rnd_sync        : std_ulogic_vector(02 downto 0); -- metastability filter & de-biasing
106
  signal ready_ff        : std_ulogic; -- new random data available
107
  signal rnd_sreg        : std_ulogic_vector(15 downto 0); -- sample shift reg
108
  signal rnd_cnt         : std_ulogic_vector(04 downto 0);
109
  signal new_sample      : std_ulogic; -- new output byte ready
110
  signal rnd_data        : std_ulogic_vector(15 downto 0); -- random data register (read-only)
111
 
112
  -- Randomness extractor (von Neumann De-Biasing) --
113
  signal db_state  : std_ulogic;
114
  signal db_enable : std_ulogic; -- valid data from de-biasing
115
  signal db_data   : std_ulogic; -- actual data from de-biasing
116
 
117
begin
118
 
119
  -- Access Control -------------------------------------------------------------------------
120
  -- -------------------------------------------------------------------------------------------
121
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = trng_base_c(hi_abb_c downto lo_abb_c)) else '0';
122
  addr   <= trng_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
123
  wren   <= acc_en and wren_i;
124
  rden   <= acc_en and rden_i;
125
 
126
 
127
  -- Read/Write Access ----------------------------------------------------------------------
128
  -- -------------------------------------------------------------------------------------------
129
  rw_access: process(clk_i)
130
  begin
131
    if rising_edge(clk_i) then
132
      ack_o <= acc_en and (rden_i or wren_i);
133
      -- write access --
134
      if (wren = '1') then
135
        if (addr = trng_ctrl_addr_c) then
136 22 zero_gravi
          tap_config <= data_i(tap_config'left downto 0);
137
          rnd_enable <= data_i(ctrl_en_c);
138 2 zero_gravi
        end if;
139
      end if;
140
      -- read access --
141
      data_o <= (others => '0');
142
      if (rden = '1') then
143
        if (addr = trng_ctrl_addr_c) then
144
          data_o(ctrl_taps_msb_c downto ctrl_taps_lsb_c) <= tap_config;
145
          data_o(ctrl_en_c) <= rnd_enable;
146
        else -- trng_data_addr_c
147
          data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_data;
148
          data_o(ctrl_rnd_valid_c) <= ready_ff;
149
        end if;
150
      end if;
151
    end if;
152
  end process rw_access;
153
 
154
 
155
  -- True Random Generator ------------------------------------------------------------------
156
  -- -------------------------------------------------------------------------------------------
157
  entropy_source: process(rnd_enable_sreg, rnd_enable, rnd_inv, tap_config)
158
  begin
159
    for i in 0 to num_inv_c-1 loop
160
      if (rnd_enable = '0') then -- start with a defined state (latch reset)
161
        rnd_inv(i) <= '0';
162
      -- uniquely enable latches to prevent synthesis from removing chain elements
163
      elsif (rnd_enable_sreg(i) = '1') then -- latch enable
164
        -- here we have the inverter chain --
165
        if (i = num_inv_c-1) then -- left most inverter?
166
          if (tap_config(i) = '1') then
167
            rnd_inv(i) <= not rnd_inv(0); -- direct input of right most inverter (= output signal)
168
          else
169
            rnd_inv(i) <= '0';
170
          end if;
171
        else
172
          if (tap_config(i) = '1') then
173
            rnd_inv(i) <= not (rnd_inv(i+1) xor rnd_inv(0)); -- use final output as feedback
174
          else
175
            rnd_inv(i) <= not rnd_inv(i+1); -- normal chain: use previous inverter's output as input
176
          end if;
177
        end if;
178
      end if;
179
    end loop; -- i
180
  end process entropy_source;
181
 
182
  -- unique enable signals for each inverter latch --
183
  inv_enable: process(clk_i)
184
  begin
185
    if rising_edge(clk_i) then
186
      -- using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
187
      -- from removing all but one inverter (since they implement "logical identical functions")
188
      -- this also allows to make the trng platform independent
189
      rnd_enable_sreg <= rnd_enable_sreg(num_inv_c-2 downto 0) & rnd_enable; -- activate right most inverter first
190
    end if;
191
  end process inv_enable;
192
 
193
 
194
  -- Processing Core ------------------------------------------------------------------------
195
  -- -------------------------------------------------------------------------------------------
196
  processing_core: process(clk_i)
197
  begin
198
    if rising_edge(clk_i) then
199
      -- synchronize output of GARO --
200
      rnd_sync <= rnd_sync(1 downto 0) & rnd_inv(0); -- no more metastability
201
 
202
      -- von Neumann De-Biasing state --
203
      db_state <= (not db_state) and rnd_enable; -- just toggle -> process in every second cycle
204
 
205
      -- sample random data & post-processing --
206
      if (rnd_enable = '0') then
207
        rnd_cnt  <= (others => '0');
208
        rnd_sreg <= (others => '0');
209
      elsif (db_enable = '1') then -- valid de-biased output?
210
        if (rnd_cnt = "10000") then
211
          rnd_cnt <= (others => '0');
212
        else
213
          rnd_cnt <= std_ulogic_vector(unsigned(rnd_cnt) + 1);
214
        end if;
215
        rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & (xnor_all_f(rnd_sreg and lfsr_taps_c) xor db_data); -- LFSR post-processing
216
--      rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & db_data; -- LFSR post-processing
217
      end if;
218
 
219
      -- data output register --
220
      if (new_sample = '1') then
221
        rnd_data <= rnd_sreg;
222
      end if;
223
 
224
      -- data ready flag --
225
      if (rnd_enable = '0') or (rden = '1') then -- clear when deactivated or on data read
226
        ready_ff <= '0';
227
      elsif (new_sample = '1') then
228
        ready_ff <= '1';
229
      end if;
230
    end if;
231
  end process processing_core;
232
 
233
  -- John von Neumann De-Biasing --
234
  debiasing: process(db_state, rnd_sync)
235
    variable tmp_v : std_ulogic_vector(2 downto 0);
236
  begin
237
    -- check groups of two non-overlapping bits from the input stream
238
    tmp_v := db_state & rnd_sync(2 downto 1);
239
    case tmp_v is
240
      when "101"  => db_enable <= '1'; db_data <= '1'; -- rising edge  -> '1'
241
      when "110"  => db_enable <= '1'; db_data <= '0'; -- falling edge -> '0'
242 3 zero_gravi
      when others => db_enable <= '0'; db_data <= '0'; -- invalid
243 2 zero_gravi
    end case;
244
  end process debiasing;
245
 
246
  -- new valid byte available? --
247
  new_sample <= '1' when (rnd_cnt = "10000") and (rnd_enable = '1') and (db_enable = '1') else '0';
248
 
249
 
250
end neorv32_trng_rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.