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

Subversion Repositories neorv32

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

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 47 zero_gravi
-- # This unit implements a *true* random number generator which uses several ring oscillators as  #
5
-- # entropy source. The outputs of all chains are XORed and de-biased using a John von Neumann    #
6
-- # randomness extractor. The de-biased signal is further processed by a simple LFSR for improved #
7
-- # whitening.                                                                                    #
8 2 zero_gravi
-- # ********************************************************************************************* #
9
-- # BSD 3-Clause License                                                                          #
10
-- #                                                                                               #
11 47 zero_gravi
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
12 2 zero_gravi
-- #                                                                                               #
13
-- # Redistribution and use in source and binary forms, with or without modification, are          #
14
-- # permitted provided that the following conditions are met:                                     #
15
-- #                                                                                               #
16
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
17
-- #    conditions and the following disclaimer.                                                   #
18
-- #                                                                                               #
19
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
20
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
21
-- #    provided with the distribution.                                                            #
22
-- #                                                                                               #
23
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
24
-- #    endorse or promote products derived from this software without specific prior written      #
25
-- #    permission.                                                                                #
26
-- #                                                                                               #
27
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
28
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
29
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
30
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
31
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
32
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
33
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
34
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
35
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
36
-- # ********************************************************************************************* #
37
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
38
-- #################################################################################################
39
 
40
library ieee;
41
use ieee.std_logic_1164.all;
42
use ieee.numeric_std.all;
43
 
44
library neorv32;
45
use neorv32.neorv32_package.all;
46
 
47
entity neorv32_trng is
48
  port (
49
    -- host access --
50
    clk_i  : in  std_ulogic; -- global clock line
51
    addr_i : in  std_ulogic_vector(31 downto 0); -- address
52
    rden_i : in  std_ulogic; -- read enable
53
    wren_i : in  std_ulogic; -- write enable
54
    data_i : in  std_ulogic_vector(31 downto 0); -- data in
55
    data_o : out std_ulogic_vector(31 downto 0); -- data out
56
    ack_o  : out std_ulogic  -- transfer acknowledge
57
  );
58
end neorv32_trng;
59
 
60
architecture neorv32_trng_rtl of neorv32_trng is
61
 
62 47 zero_gravi
  -- Advanced Configuration --------------------------------------------------------------------------------
63
  constant num_roscs_c     : natural := 4; -- total number of ring oscillators
64
  constant num_inv_start_c : natural := 5; -- number of inverters in FIRST ring oscillator (has to be odd)
65
  constant num_inv_inc_c   : natural := 2; -- number of inverters increment for each next ring oscillator (has to be even)
66
  constant lfsr_en_c       : boolean := true; -- use LFSR-based post-processing
67
  constant lfsr_taps_c     : std_ulogic_vector(7 downto 0) := "10111000"; -- Fibonacci post-processing LFSR feedback taps
68 2 zero_gravi
  -- -------------------------------------------------------------------------------------------------------
69
 
70
  -- control register bits --
71 47 zero_gravi
  constant ctrl_data_lsb_c : natural :=  0; -- r/-: Random data byte LSB
72
  constant ctrl_data_msb_c : natural :=  7; -- r/-: Random data byte MSB
73
  --
74
  constant ctrl_en_c       : natural := 30; -- r/w: TRNG enable
75
  constant ctrl_valid_c    : natural := 31; -- r/-: Output data valid
76 2 zero_gravi
 
77
  -- IO space: module base address --
78
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
79
  constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
80
 
81 47 zero_gravi
  -- Component: Ring-Oscillator --
82
  component neorv32_trng_ring_osc
83 23 zero_gravi
    generic (
84
      NUM_INV : natural := 16 -- number of inverters in chain
85
    );
86
    port (
87
      clk_i    : in  std_ulogic;
88 47 zero_gravi
      enable_i : in  std_ulogic; -- enable chain input
89
      enable_o : out std_ulogic; -- enable chain output
90
      data_o   : out std_ulogic  -- sync random bit
91 23 zero_gravi
    );
92
  end component;
93
 
94 2 zero_gravi
  -- access control --
95
  signal acc_en : std_ulogic; -- module access enable
96
  signal wren   : std_ulogic; -- full word write enable
97
  signal rden   : std_ulogic; -- read enable
98
 
99 47 zero_gravi
  -- ring-oscillator array --
100
  signal osc_array_en_in  : std_ulogic_vector(num_roscs_c-1 downto 0);
101
  signal osc_array_en_out : std_ulogic_vector(num_roscs_c-1 downto 0);
102
  signal osc_array_data   : std_ulogic_vector(num_roscs_c-1 downto 0);
103 2 zero_gravi
 
104 47 zero_gravi
  -- von-Neumann de-biasing --
105
  type debiasing_t is record
106
    sreg  : std_ulogic_vector(1 downto 0);
107
    state : std_ulogic; -- process de-biasing every second cycle
108
    valid : std_ulogic; -- de-biased data
109
    data  : std_ulogic; -- de-biased data valid
110
  end record;
111
  signal debiasing : debiasing_t;
112 2 zero_gravi
 
113 47 zero_gravi
  -- (post-)processing core --
114
  type processing_t is record
115
    enable : std_ulogic; -- TRNG enable flag
116
    cnt    : std_ulogic_vector(3 downto 0); -- bit counter
117
    sreg   : std_ulogic_vector(7 downto 0); -- data shift register
118
    output : std_ulogic_vector(7 downto 0); -- output register
119
    valid  : std_ulogic; -- data output valid flag
120
  end record;
121
  signal processing : processing_t;
122 23 zero_gravi
 
123 2 zero_gravi
begin
124
 
125 47 zero_gravi
  -- Sanity Checks --------------------------------------------------------------------------
126
  -- -------------------------------------------------------------------------------------------
127
  assert not (num_roscs_c = 0) report "NEORV32 PROCESSOR CONFIG NOTE: TRNG - Total number of ring-oscillators has to be >0." severity error;
128
  assert not ((num_inv_start_c mod 2)  = 0) report "NEORV32 PROCESSOR CONFIG NOTE: TRNG - Number of inverters in fisrt ring has to be odd." severity error;
129
  assert not ((num_inv_inc_c   mod 2) /= 0) report "NEORV32 PROCESSOR CONFIG NOTE: TRNG - Number of inverters increment for each next ring has to be even." severity error;
130
 
131 2 zero_gravi
  -- Access Control -------------------------------------------------------------------------
132
  -- -------------------------------------------------------------------------------------------
133
  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';
134
  wren   <= acc_en and wren_i;
135
  rden   <= acc_en and rden_i;
136
 
137
 
138
  -- Read/Write Access ----------------------------------------------------------------------
139
  -- -------------------------------------------------------------------------------------------
140
  rw_access: process(clk_i)
141
  begin
142
    if rising_edge(clk_i) then
143 47 zero_gravi
      ack_o <= wren or rden;
144 2 zero_gravi
      -- write access --
145
      if (wren = '1') then
146 47 zero_gravi
        processing.enable <= data_i(ctrl_en_c);
147 2 zero_gravi
      end if;
148
      -- read access --
149
      data_o <= (others => '0');
150
      if (rden = '1') then
151 47 zero_gravi
        data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= processing.output;
152
        data_o(ctrl_en_c)                              <= processing.enable;
153
        data_o(ctrl_valid_c)                           <= processing.valid;
154 2 zero_gravi
      end if;
155
    end if;
156
  end process rw_access;
157
 
158
 
159 23 zero_gravi
  -- Entropy Source -------------------------------------------------------------------------
160 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
161 47 zero_gravi
  neorv32_trng_ring_osc_inst:
162
  for i in 0 to num_roscs_c-1 generate
163
    neorv32_trng_ring_osc_inst_i: neorv32_trng_ring_osc
164 23 zero_gravi
    generic map (
165 47 zero_gravi
      NUM_INV => num_inv_start_c + (i*num_inv_inc_c) -- number of inverters in chain
166 23 zero_gravi
    )
167
    port map (
168
      clk_i    => clk_i,
169 47 zero_gravi
      enable_i => osc_array_en_in(i),
170
      enable_o => osc_array_en_out(i),
171
      data_o   => osc_array_data(i)
172 23 zero_gravi
    );
173
  end generate;
174
 
175 47 zero_gravi
  -- RO enable chain --
176
  array_intercon: process(processing.enable, osc_array_en_out)
177 2 zero_gravi
  begin
178 47 zero_gravi
    for i in 0 to num_roscs_c-1 loop
179
      if (i = 0) then -- start of enable chain
180
        osc_array_en_in(i) <= processing.enable;
181 23 zero_gravi
      else
182 47 zero_gravi
        osc_array_en_in(i) <= osc_array_en_out(i-1);
183 2 zero_gravi
      end if;
184
    end loop; -- i
185 47 zero_gravi
  end process array_intercon;
186 2 zero_gravi
 
187 23 zero_gravi
 
188 47 zero_gravi
  -- John von Neumann De-Biasing ------------------------------------------------------------
189 23 zero_gravi
  -- -------------------------------------------------------------------------------------------
190 47 zero_gravi
  neumann_debiasing_sync: process(clk_i)
191 2 zero_gravi
  begin
192
    if rising_edge(clk_i) then
193 47 zero_gravi
      debiasing.sreg  <= debiasing.sreg(debiasing.sreg'left-1 downto 0) & xor_all_f(osc_array_data);
194
      debiasing.state <= (not debiasing.state) and osc_array_en_out(num_roscs_c-1); -- start toggling when last RO is enabled -> process in every second cycle
195 2 zero_gravi
    end if;
196 47 zero_gravi
  end process neumann_debiasing_sync;
197 2 zero_gravi
 
198 47 zero_gravi
  -- Edge detector --
199
  neumann_debiasing_comb: process(debiasing)
200 23 zero_gravi
    variable tmp_v : std_ulogic_vector(2 downto 0);
201
  begin
202
    -- check groups of two non-overlapping bits from the input stream
203 47 zero_gravi
    tmp_v := debiasing.state & debiasing.sreg;
204 23 zero_gravi
    case tmp_v is
205 47 zero_gravi
      when "101"  => debiasing.valid <= '1'; debiasing.data <= '1'; -- rising edge  -> '1'
206
      when "110"  => debiasing.valid <= '1'; debiasing.data <= '0'; -- falling edge -> '0'
207
      when others => debiasing.valid <= '0'; debiasing.data <= '0'; -- no valid data
208 23 zero_gravi
    end case;
209 47 zero_gravi
  end process neumann_debiasing_comb;
210 23 zero_gravi
 
211
 
212 2 zero_gravi
  -- Processing Core ------------------------------------------------------------------------
213
  -- -------------------------------------------------------------------------------------------
214
  processing_core: process(clk_i)
215
  begin
216
    if rising_edge(clk_i) then
217 47 zero_gravi
      -- sample random data bit and apply post-processing --
218
      if (processing.enable = '0') then
219
        processing.cnt  <= (others => '0');
220
        processing.sreg <= (others => '0');
221
      elsif (debiasing.valid = '1') then -- valid random sample?
222
        if (processing.cnt = "1000") then
223
          processing.cnt <= (others => '0');
224 2 zero_gravi
        else
225 47 zero_gravi
          processing.cnt <= std_ulogic_vector(unsigned(processing.cnt) + 1);
226 2 zero_gravi
        end if;
227 23 zero_gravi
        if (lfsr_en_c = true) then -- LFSR post-processing
228 47 zero_gravi
          processing.sreg <= processing.sreg(processing.sreg'left-1 downto 0) & (xnor_all_f(processing.sreg and lfsr_taps_c) xnor debiasing.data);
229 23 zero_gravi
        else -- NO post-processing
230 47 zero_gravi
          processing.sreg <= processing.sreg(processing.sreg'left-1 downto 0) & debiasing.data;
231 23 zero_gravi
        end if;
232 2 zero_gravi
      end if;
233
 
234
      -- data output register --
235 47 zero_gravi
      if (processing.cnt = "1000") then
236
        processing.output <= processing.sreg;
237 2 zero_gravi
      end if;
238
 
239 47 zero_gravi
      -- data ready/valid flag --
240
      if (processing.cnt = "1000") then -- new sample ready?
241
        processing.valid <= '1';
242
      elsif (processing.enable = '0') or (rden = '1') then -- clear when deactivated or on data read
243
        processing.valid <= '0';
244 23 zero_gravi
      end if;
245 2 zero_gravi
    end if;
246
  end process processing_core;
247
 
248 23 zero_gravi
 
249
end neorv32_trng_rtl;
250
 
251
 
252
-- ############################################################################################################################
253
-- ############################################################################################################################
254
 
255
 
256
-- #################################################################################################
257 47 zero_gravi
-- # << NEORV32 - True Random Number Generator (TRNG) - Ring-Oscillator-Based Entropy Source >>    #
258 23 zero_gravi
-- # ********************************************************************************************* #
259 47 zero_gravi
-- # An inverter chain (ring oscillator) is used as entropy source.                                #
260
-- # The inverter chain is constructed as an "asynchronous" LFSR. The single inverters are         #
261
-- # connected via latches that are used to enable/disable the TRNG. Also, these latches are used  #
262
-- # as additional delay element. By using unique enable signals for each latch, the synthesis     #
263
-- # tool cannot "optimize" (=remove) any of the inverters out of the design. Furthermore, the     #
264
-- # latches prevent the synthesis tool from detecting combinatorial loops.                        #
265 23 zero_gravi
-- # ********************************************************************************************* #
266
-- # BSD 3-Clause License                                                                          #
267
-- #                                                                                               #
268 47 zero_gravi
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
269 23 zero_gravi
-- #                                                                                               #
270
-- # Redistribution and use in source and binary forms, with or without modification, are          #
271
-- # permitted provided that the following conditions are met:                                     #
272
-- #                                                                                               #
273
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
274
-- #    conditions and the following disclaimer.                                                   #
275
-- #                                                                                               #
276
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
277
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
278
-- #    provided with the distribution.                                                            #
279
-- #                                                                                               #
280
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
281
-- #    endorse or promote products derived from this software without specific prior written      #
282
-- #    permission.                                                                                #
283
-- #                                                                                               #
284
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
285
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
286
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
287
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
288
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
289
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
290
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
291
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
292
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
293
-- # ********************************************************************************************* #
294
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
295
-- #################################################################################################
296
 
297
library ieee;
298
use ieee.std_logic_1164.all;
299
use ieee.numeric_std.all;
300
 
301
library neorv32;
302
use neorv32.neorv32_package.all;
303
 
304 47 zero_gravi
entity neorv32_trng_ring_osc is
305 23 zero_gravi
  generic (
306
    NUM_INV : natural := 15 -- number of inverters in chain
307
  );
308
  port (
309
    clk_i    : in  std_ulogic;
310 47 zero_gravi
    enable_i : in  std_ulogic; -- enable chain input
311
    enable_o : out std_ulogic; -- enable chain output
312
    data_o   : out std_ulogic  -- sync random bit
313 23 zero_gravi
  );
314 47 zero_gravi
end neorv32_trng_ring_osc;
315 23 zero_gravi
 
316 47 zero_gravi
architecture neorv32_trng_ring_osc_rtl of neorv32_trng_ring_osc is
317 23 zero_gravi
 
318
  signal inv_chain   : std_ulogic_vector(NUM_INV-1 downto 0); -- oscillator chain
319
  signal enable_sreg : std_ulogic_vector(NUM_INV-1 downto 0); -- enable shift register
320 47 zero_gravi
  signal sync_ff     : std_ulogic_vector(1 downto 0); -- output signal synchronizer
321 23 zero_gravi
 
322
begin
323
 
324 47 zero_gravi
  -- Sanity Checks --------------------------------------------------------------------------
325 23 zero_gravi
  -- -------------------------------------------------------------------------------------------
326 47 zero_gravi
  assert not ((NUM_INV mod 2) = 0) report "NEORV32 PROCESSOR CONFIG NOTE: TNRG.ring_oscillator - Number of inverters in ring has to be odd." severity error;
327 23 zero_gravi
 
328
 
329 47 zero_gravi
  -- Ring Oscillator ------------------------------------------------------------------------
330 23 zero_gravi
  -- -------------------------------------------------------------------------------------------
331 47 zero_gravi
  ring_osc: process(enable_i, enable_sreg, inv_chain)
332 2 zero_gravi
  begin
333 47 zero_gravi
    -- Using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
334
    -- from removing all but one inverter (since they implement "logical identical functions").
335
    -- This also allows to make the TRNG platform independent.
336
    for i in 0 to NUM_INV-1 loop -- inverters in chain
337
      if (enable_i = '0') then -- start with a defined state (latch reset)
338
        inv_chain(i) <= '0';
339
      elsif (enable_sreg(i) = '1') then
340
        -- here we have the inverter chain --
341
        if (i = NUM_INV-1) then -- left-most inverter?
342
          inv_chain(i) <= not inv_chain(0);
343 23 zero_gravi
        else
344 47 zero_gravi
          inv_chain(i) <= not inv_chain(i+1);
345 23 zero_gravi
        end if;
346
      end if;
347 47 zero_gravi
    end loop; -- i
348
  end process ring_osc;
349 2 zero_gravi
 
350
 
351 23 zero_gravi
  -- Control --------------------------------------------------------------------------------
352
  -- -------------------------------------------------------------------------------------------
353
  ctrl_unit: process(clk_i)
354
  begin
355
    if rising_edge(clk_i) then
356
      enable_sreg <= enable_sreg(enable_sreg'left-1 downto 0) & enable_i; -- activate right-most inverter first
357 47 zero_gravi
      sync_ff     <= sync_ff(0) & inv_chain(0); -- synchronize to prevent metastability 
358 23 zero_gravi
    end if;
359
  end process ctrl_unit;
360 2 zero_gravi
 
361 23 zero_gravi
  -- output for "enable chain" --
362
  enable_o <= enable_sreg(enable_sreg'left);
363
 
364
  -- rnd output --
365 47 zero_gravi
  data_o <= sync_ff(1);
366 23 zero_gravi
 
367
 
368 47 zero_gravi
end neorv32_trng_ring_osc_rtl;

powered by: WebSVN 2.1.0

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