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

Subversion Repositories neorv32

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
-- #################################################################################################
2
-- # << NEORV32 - True Random Number Generator (TRNG) >>                                           #
3
-- # ********************************************************************************************* #
4 68 zero_gravi
-- # This processor module instantiates the "neoTRNG" true random number generator.                #
5
-- # See the neoTRNG's documentation for more information: https://github.com/stnolting/neoTRNG    #
6 2 zero_gravi
-- # ********************************************************************************************* #
7
-- # BSD 3-Clause License                                                                          #
8
-- #                                                                                               #
9 74 zero_gravi
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
10 2 zero_gravi
-- #                                                                                               #
11
-- # Redistribution and use in source and binary forms, with or without modification, are          #
12
-- # permitted provided that the following conditions are met:                                     #
13
-- #                                                                                               #
14
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
15
-- #    conditions and the following disclaimer.                                                   #
16
-- #                                                                                               #
17
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
18
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
19
-- #    provided with the distribution.                                                            #
20
-- #                                                                                               #
21
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
22
-- #    endorse or promote products derived from this software without specific prior written      #
23
-- #    permission.                                                                                #
24
-- #                                                                                               #
25
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
26
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
27
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
28
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
29
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
30
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
31
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
32
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
33
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
34
-- # ********************************************************************************************* #
35
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
36
-- #################################################################################################
37
 
38
library ieee;
39
use ieee.std_logic_1164.all;
40
use ieee.numeric_std.all;
41
 
42
library neorv32;
43
use neorv32.neorv32_package.all;
44
 
45
entity neorv32_trng is
46
  port (
47
    -- host access --
48
    clk_i  : in  std_ulogic; -- global clock line
49
    addr_i : in  std_ulogic_vector(31 downto 0); -- address
50
    rden_i : in  std_ulogic; -- read enable
51
    wren_i : in  std_ulogic; -- write enable
52
    data_i : in  std_ulogic_vector(31 downto 0); -- data in
53
    data_o : out std_ulogic_vector(31 downto 0); -- data out
54
    ack_o  : out std_ulogic  -- transfer acknowledge
55
  );
56
end neorv32_trng;
57
 
58
architecture neorv32_trng_rtl of neorv32_trng is
59
 
60 68 zero_gravi
  -- neoTRNG Configuration -------------------------------------------------------------------------------------------
61
  constant num_cells_c     : natural := 3; -- total number of ring-oscillator cells
62
  constant num_inv_start_c : natural := 3; -- number of inverters in first cell (short path), has to be odd
63
  constant num_inv_inc_c   : natural := 2; -- number of additional inverters in next cell (short path), has to be even
64
  constant num_inv_delay_c : natural := 2; -- additional inverters to form cell's long path, has to be even
65
  -- -----------------------------------------------------------------------------------------------------------------
66 2 zero_gravi
 
67
  -- control register bits --
68 47 zero_gravi
  constant ctrl_data_lsb_c : natural :=  0; -- r/-: Random data byte LSB
69
  constant ctrl_data_msb_c : natural :=  7; -- r/-: Random data byte MSB
70
  constant ctrl_en_c       : natural := 30; -- r/w: TRNG enable
71
  constant ctrl_valid_c    : natural := 31; -- r/-: Output data valid
72 2 zero_gravi
 
73
  -- IO space: module base address --
74
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
75
  constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
76
 
77 68 zero_gravi
  -- access control --
78
  signal acc_en : std_ulogic; -- module access enable
79
  signal wren   : std_ulogic; -- full word write enable
80
  signal rden   : std_ulogic; -- read enable
81
 
82
  -- Component: neoTRNG true random number generator --
83
  component neoTRNG
84 23 zero_gravi
    generic (
85 68 zero_gravi
      NUM_CELLS     : natural; -- total number of ring-oscillator cells
86
      NUM_INV_START : natural; -- number of inverters in first cell (short path), has to be odd
87
      NUM_INV_INC   : natural; -- number of additional inverters in next cell (short path), has to be even
88
      NUM_INV_DELAY : natural  -- additional inverters to form cell's long path, has to be even
89 23 zero_gravi
    );
90
    port (
91 68 zero_gravi
      clk_i    : in  std_ulogic; -- global clock line
92
      enable_i : in  std_ulogic; -- unit enable (high-active), reset unit when low
93
      data_o   : out std_ulogic_vector(7 downto 0); -- random data byte output
94
      valid_o  : out std_ulogic  -- data_o is valid when set
95 23 zero_gravi
    );
96
  end component;
97
 
98 68 zero_gravi
  -- TRNG interface --
99
  signal trng_data  : std_ulogic_vector(7 downto 0);
100
  signal trng_valid : std_ulogic;
101 2 zero_gravi
 
102 68 zero_gravi
  -- arbiter --
103
  signal enable  : std_ulogic;
104
  signal valid   : std_ulogic;
105
  signal rnd_reg : std_ulogic_vector(7 downto 0);
106 2 zero_gravi
 
107
begin
108
 
109
  -- Access Control -------------------------------------------------------------------------
110
  -- -------------------------------------------------------------------------------------------
111
  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';
112
  wren   <= acc_en and wren_i;
113
  rden   <= acc_en and rden_i;
114
 
115
 
116
  -- Read/Write Access ----------------------------------------------------------------------
117
  -- -------------------------------------------------------------------------------------------
118
  rw_access: process(clk_i)
119
  begin
120
    if rising_edge(clk_i) then
121 68 zero_gravi
      -- host bus acknowledge --
122 47 zero_gravi
      ack_o <= wren or rden;
123 68 zero_gravi
 
124 2 zero_gravi
      -- write access --
125
      if (wren = '1') then
126 68 zero_gravi
        enable <= data_i(ctrl_en_c);
127 2 zero_gravi
      end if;
128 68 zero_gravi
 
129 2 zero_gravi
      -- read access --
130
      data_o <= (others => '0');
131
      if (rden = '1') then
132 68 zero_gravi
        data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_reg;
133
        data_o(ctrl_en_c)    <= enable;
134
        data_o(ctrl_valid_c) <= valid;
135 2 zero_gravi
      end if;
136 68 zero_gravi
 
137
      -- sample --
138
      if (trng_valid = '1') then
139
        rnd_reg <= trng_data;
140
      end if;
141
 
142
      -- data valid? --
143
      if (enable = '0') then -- disabled
144
        valid <= '0';
145
      else
146
        if (trng_valid = '1') then
147
          valid <= '1';
148
        elsif (rden = '1') then
149
          valid <= '0';
150
        end if;
151
      end if;
152 2 zero_gravi
    end if;
153
  end process rw_access;
154
 
155
 
156 68 zero_gravi
  -- neoTRNG --------------------------------------------------------------------------------
157
  -- -------------------------------------------------------------------------------------------
158
  neoTRNG_inst: neoTRNG
159
    generic map (
160
      NUM_CELLS     => num_cells_c,
161
      NUM_INV_START => num_inv_start_c,
162
      NUM_INV_INC   => num_inv_inc_c,
163
      NUM_INV_DELAY => num_inv_delay_c
164
    )
165
    port map (
166
      clk_i    => clk_i,
167
      enable_i => enable,
168
      data_o   => trng_data,
169
      valid_o  => trng_valid
170
    );
171
 
172
 
173
end neorv32_trng_rtl;
174
 
175
 
176
-- ############################################################################################################################
177
-- ############################################################################################################################
178
 
179
 
180
-- #################################################################################################
181
-- # << neoTRNG - A Tiny and Platform-Independent True Random Number Generator for any FPGA >>     #
182
-- # ********************************************************************************************* #
183
-- # This generator is based on entropy cells, which implement simple ring-oscillators. Each ring- #
184
-- # oscillator features a short and a long delay path that is dynamically selected defining the   #
185
-- # primary oscillation frequency. The cells are cascaded so that the random data output of a     #
186
-- # cell controls the delay path of the next cell (which has the next-larger inverter chain).     #
187
-- #                                                                                               #
188
-- # The random data outputs of all cells are XOR-ed and de-biased using a von Neumann randomness  #
189
-- # extractor (converting edges into bits). The resulting bit is sampled in chunks of 8 bits to   #
190
-- # provide the final random data output. No further internal post-processing is applied. Hence,  #
191
-- # the TRNG produces simple de-biased *RAW* data.                                                #
192
-- #                                                                                               #
193
-- # The entropy cell architecture uses individually-controlled latches and inverters to create    #
194
-- # the inverter chain in a platform-agnostic style that can be implemented for any FPGA without  #
195
-- # requiring primitive instantiation or technology-specific attributes.                          #
196
-- #                                                                                               #
197
-- # See the neoTRNG's documentation for more information: https://github.com/stnolting/neoTRNG    #
198
-- # ********************************************************************************************* #
199
-- # BSD 3-Clause License                                                                          #
200
-- #                                                                                               #
201 74 zero_gravi
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
202 68 zero_gravi
-- #                                                                                               #
203
-- # Redistribution and use in source and binary forms, with or without modification, are          #
204
-- # permitted provided that the following conditions are met:                                     #
205
-- #                                                                                               #
206
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
207
-- #    conditions and the following disclaimer.                                                   #
208
-- #                                                                                               #
209
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
210
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
211
-- #    provided with the distribution.                                                            #
212
-- #                                                                                               #
213
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
214
-- #    endorse or promote products derived from this software without specific prior written      #
215
-- #    permission.                                                                                #
216
-- #                                                                                               #
217
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
218
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
219
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
220
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
221
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
222
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
223
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
224
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
225
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
226
-- # ********************************************************************************************* #
227
-- # neoTRNG - https://github.com/stnolting/neoTRNG                            (c) Stephan Nolting #
228
-- #################################################################################################
229
 
230
library ieee;
231
use ieee.std_logic_1164.all;
232
use ieee.numeric_std.all;
233
 
234
entity neoTRNG is
235
  generic (
236
    NUM_CELLS     : natural; -- total number of ring-oscillator cells
237
    NUM_INV_START : natural; -- number of inverters in first cell (short path), has to be odd
238
    NUM_INV_INC   : natural; -- number of additional inverters in next cell (short path), has to be even
239
    NUM_INV_DELAY : natural  -- additional inverters to form cell's long path, has to be even
240
  );
241
  port (
242
    clk_i    : in  std_ulogic; -- global clock line
243
    enable_i : in  std_ulogic; -- unit enable (high-active), reset unit when low
244
    data_o   : out std_ulogic_vector(7 downto 0); -- random data byte output
245
    valid_o  : out std_ulogic  -- data_o is valid when set
246
  );
247
end neoTRNG;
248
 
249
architecture neoTRNG_rtl of neoTRNG is
250
 
251
  -- Component: neoTRNG entropy cell --
252
  component neoTRNG_cell
253
    generic (
254
      NUM_INV_S : natural; -- number of inverters in short path
255
      NUM_INV_L : natural  -- number of inverters in long path
256
    );
257
    port (
258
      clk_i    : in  std_ulogic; -- system clock
259
      select_i : in  std_ulogic; -- delay select
260
      enable_i : in  std_ulogic; -- enable chain input
261
      enable_o : out std_ulogic; -- enable chain output
262
      data_o   : out std_ulogic  -- sync random bit
263
    );
264
  end component;
265
 
266
  -- ring-oscillator array interconnect --
267
  type cell_array_t is record
268
    en_in  : std_ulogic_vector(NUM_CELLS-1 downto 0);
269
    en_out : std_ulogic_vector(NUM_CELLS-1 downto 0);
270
    rnd    : std_ulogic_vector(NUM_CELLS-1 downto 0);
271
    sel    : std_ulogic_vector(NUM_CELLS-1 downto 0);
272
  end record;
273
  signal cell_array : cell_array_t;
274
 
275
  -- global cell-XOR --
276
  signal rnd_bit : std_ulogic;
277
 
278
  -- von-Neumann de-biasing --
279
  type debiasing_t is record
280
    sreg  : std_ulogic_vector(1 downto 0);
281
    state : std_ulogic; -- process de-biasing every second cycle
282
    valid : std_ulogic; -- de-biased data
283
    data  : std_ulogic; -- de-biased data valid
284
  end record;
285
  signal deb : debiasing_t;
286
 
287
  -- control unit --
288
  type ctrl_t is record
289
    enable : std_ulogic;
290
    run    : std_ulogic;
291
    cnt    : std_ulogic_vector(2 downto 0); -- bit counter
292
    sreg   : std_ulogic_vector(7 downto 0); -- data shift register
293
  end record;
294
  signal ctrl : ctrl_t;
295
 
296
begin
297
 
298
  -- Sanity Checks --------------------------------------------------------------------------
299
  -- -------------------------------------------------------------------------------------------
300
  assert not (NUM_CELLS < 2) report "neoTRNG config ERROR: Total number of ring-oscillator cells <NUM_CELLS> has to be >= 2." severity error;
301
  assert not ((NUM_INV_START mod 2)  = 0) report "neoTRNG config ERROR: Number of inverters in first cell <NUM_INV_START> has to be odd." severity error;
302
  assert not ((NUM_INV_INC   mod 2) /= 0) report "neoTRNG config ERROR: Inverter increment for each next cell <NUM_INV_INC> has to be even." severity error;
303
  assert not ((NUM_INV_DELAY mod 2) /= 0) report "neoTRNG config ERROR: Inverter increment to form long path <NUM_INV_DELAY> has to be even." severity error;
304
 
305
 
306 23 zero_gravi
  -- Entropy Source -------------------------------------------------------------------------
307 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
308 68 zero_gravi
  neoTRNG_cell_inst:
309
  for i in 0 to NUM_CELLS-1 generate
310
    neoTRNG_cell_inst_i: neoTRNG_cell
311 23 zero_gravi
    generic map (
312 68 zero_gravi
      NUM_INV_S => NUM_INV_START + (i*NUM_INV_INC), -- number of inverters in short chain
313
      NUM_INV_L => NUM_INV_START + (i*NUM_INV_INC) + NUM_INV_DELAY -- number of inverters in long chain
314 23 zero_gravi
    )
315
    port map (
316
      clk_i    => clk_i,
317 68 zero_gravi
      select_i => cell_array.sel(i),
318
      enable_i => cell_array.en_in(i),
319
      enable_o => cell_array.en_out(i),
320
      data_o   => cell_array.rnd(i) -- SYNC data output
321 23 zero_gravi
    );
322
  end generate;
323
 
324 68 zero_gravi
  -- path select chain --
325
  cell_array.sel(0) <= cell_array.rnd(NUM_CELLS-1); -- use output of last cell to select path of first cell
326
  cell_array.sel(NUM_CELLS-1 downto 1) <= cell_array.rnd(NUM_CELLS-2 downto 0); -- i+1 <= i
327
 
328
  -- enable chain --
329
  cell_array.en_in(0) <= ctrl.enable; -- start of chain
330 74 zero_gravi
  cell_array.en_in(NUM_CELLS-1 downto 1) <= cell_array.en_out(NUM_CELLS-2 downto 0); -- i+1 <= i
331 68 zero_gravi
 
332
 
333
  -- XOR All Cell's Outputs -----------------------------------------------------------------
334
  -- -------------------------------------------------------------------------------------------
335
  cell_xor: process(cell_array.rnd)
336
    variable tmp_v : std_ulogic;
337 2 zero_gravi
  begin
338 68 zero_gravi
    tmp_v := '0';
339
    for i in 0 to NUM_CELLS-1 loop
340
      tmp_v := tmp_v xor cell_array.rnd(i);
341 2 zero_gravi
    end loop; -- i
342 68 zero_gravi
    rnd_bit <= tmp_v;
343
  end process cell_xor;
344 2 zero_gravi
 
345 23 zero_gravi
 
346 68 zero_gravi
  -- John von Neumann Randomness Extractor --------------------------------------------------
347 23 zero_gravi
  -- -------------------------------------------------------------------------------------------
348 68 zero_gravi
  debiasing_sync: process(clk_i)
349 2 zero_gravi
  begin
350
    if rising_edge(clk_i) then
351 68 zero_gravi
      deb.sreg <= deb.sreg(0) & rnd_bit;
352
      -- start operation when last cell is enabled and process in every second cycle --
353
      deb.state <= (not deb.state) and cell_array.en_out(NUM_CELLS-1);
354 2 zero_gravi
    end if;
355 68 zero_gravi
  end process debiasing_sync;
356 2 zero_gravi
 
357 68 zero_gravi
  -- edge detector --
358
  debiasing_comb: process(deb)
359 23 zero_gravi
    variable tmp_v : std_ulogic_vector(2 downto 0);
360
  begin
361 68 zero_gravi
    tmp_v := deb.state & deb.sreg(1 downto 0); -- check groups of two non-overlapping bits from the input stream
362 23 zero_gravi
    case tmp_v is
363 68 zero_gravi
      when "101"  => deb.valid <= '1'; deb.data <= '0'; -- rising edge = '0'
364
      when "110"  => deb.valid <= '1'; deb.data <= '1'; -- falling edge = '1'
365
      when others => deb.valid <= '0'; deb.data <= '-'; -- no valid data
366 23 zero_gravi
    end case;
367 68 zero_gravi
  end process debiasing_comb;
368 23 zero_gravi
 
369
 
370 68 zero_gravi
  -- Control Unit ---------------------------------------------------------------------------
371 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
372 68 zero_gravi
  control_unit: process(clk_i)
373 2 zero_gravi
  begin
374
    if rising_edge(clk_i) then
375 68 zero_gravi
      -- make sure enable is sync --
376
      ctrl.enable <= enable_i;
377
 
378
      -- sample chunks of 8 bit --
379
      if (ctrl.enable = '0') then
380
        ctrl.cnt <= (others => '0');
381
        ctrl.run <= '0';
382
      elsif (deb.valid = '1') then -- valid random sample?
383
        ctrl.cnt <= std_ulogic_vector(unsigned(ctrl.cnt) + 1);
384
        ctrl.run <= '1';
385 2 zero_gravi
      end if;
386
 
387 68 zero_gravi
      -- sample shift register --
388
      if (deb.valid = '1') then
389
        ctrl.sreg <= ctrl.sreg(ctrl.sreg'left-1 downto 0) & deb.data;
390 2 zero_gravi
      end if;
391
 
392 74 zero_gravi
      -- data valid? --
393
      if (ctrl.cnt = "000") and (ctrl.run = '1') and (deb.valid = '1') then
394
        valid_o <= '1';
395
      else
396
        valid_o <= '0';
397
      end if;
398 2 zero_gravi
    end if;
399 68 zero_gravi
  end process control_unit;
400 2 zero_gravi
 
401 68 zero_gravi
  -- random byte output --
402
  data_o <= ctrl.sreg;
403 23 zero_gravi
 
404
 
405 68 zero_gravi
end neoTRNG_rtl;
406
 
407
 
408 23 zero_gravi
-- ############################################################################################################################
409
-- ############################################################################################################################
410
 
411
 
412
-- #################################################################################################
413 68 zero_gravi
-- # << neoTRNG - A Tiny and Platform-Independent True Random Number Generator for any FPGA >>     #
414 23 zero_gravi
-- # ********************************************************************************************* #
415 68 zero_gravi
-- # neoTRNG Entropy Cell                                                                          #
416
-- #                                                                                               #
417
-- # The cell consists of two ring-oscillators build from inverter chains. The short chain uses    #
418
-- # NUM_INV_S inverters and oscillates at a "high" frequency and the long chain uses NUM_INV_L    #
419
-- # inverters and oscillates at a "low" frequency. The select_i input selects which chain is      #
420
-- # actually used.                                                                                #
421
-- #                                                                                               #
422
-- # Each inverter chain is constructed as an "asynchronous" shift register. The single inverters  #
423
-- # are connected via latches that are used to enable/disable the TRNG. Also, these latches are   #
424
-- # used as additional delay element. By using unique enable signals for each latch, the          #
425
-- # synthesis tool cannot "optimize" (=remove) any of the inverters out of the design making the  #
426
-- # design platform-agnostic.                                                                     #
427 23 zero_gravi
-- # ********************************************************************************************* #
428
-- # BSD 3-Clause License                                                                          #
429
-- #                                                                                               #
430 47 zero_gravi
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
431 23 zero_gravi
-- #                                                                                               #
432
-- # Redistribution and use in source and binary forms, with or without modification, are          #
433
-- # permitted provided that the following conditions are met:                                     #
434
-- #                                                                                               #
435
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
436
-- #    conditions and the following disclaimer.                                                   #
437
-- #                                                                                               #
438
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
439
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
440
-- #    provided with the distribution.                                                            #
441
-- #                                                                                               #
442
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
443
-- #    endorse or promote products derived from this software without specific prior written      #
444
-- #    permission.                                                                                #
445
-- #                                                                                               #
446
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
447
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
448
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
449
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
450
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
451
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
452
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
453
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
454
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
455
-- # ********************************************************************************************* #
456 68 zero_gravi
-- # neoTRNG - https://github.com/stnolting/neoTRNG                            (c) Stephan Nolting #
457 23 zero_gravi
-- #################################################################################################
458
 
459
library ieee;
460
use ieee.std_logic_1164.all;
461
 
462 68 zero_gravi
entity neoTRNG_cell is
463 23 zero_gravi
  generic (
464 68 zero_gravi
    NUM_INV_S : natural; -- number of inverters in short path
465
    NUM_INV_L : natural  -- number of inverters in long path
466 23 zero_gravi
  );
467
  port (
468 68 zero_gravi
    clk_i    : in  std_ulogic; -- system clock
469
    select_i : in  std_ulogic; -- delay select
470 47 zero_gravi
    enable_i : in  std_ulogic; -- enable chain input
471
    enable_o : out std_ulogic; -- enable chain output
472
    data_o   : out std_ulogic  -- sync random bit
473 23 zero_gravi
  );
474 68 zero_gravi
end neoTRNG_cell;
475 23 zero_gravi
 
476 68 zero_gravi
architecture neoTRNG_cell_rtl of neoTRNG_cell is
477 23 zero_gravi
 
478 68 zero_gravi
  signal inv_chain_s   : std_ulogic_vector(NUM_INV_S-1 downto 0); -- short oscillator chain
479
  signal inv_chain_l   : std_ulogic_vector(NUM_INV_L-1 downto 0); -- long oscillator chain
480
  signal feedback      : std_ulogic; -- cell feedback/output
481
  signal enable_sreg_s : std_ulogic_vector(NUM_INV_S-1 downto 0); -- enable shift register for short chain
482
  signal enable_sreg_l : std_ulogic_vector(NUM_INV_L-1 downto 0); -- enable shift register for long chain
483
  signal sync_ff       : std_ulogic_vector(1 downto 0); -- output signal synchronizer
484 23 zero_gravi
 
485
begin
486
 
487 68 zero_gravi
  -- Ring Oscillators -----------------------------------------------------------------------
488 23 zero_gravi
  -- -------------------------------------------------------------------------------------------
489 68 zero_gravi
  -- Each cell provides a short inverter chain (high frequency) and a long oscillator chain (low frequency).
490
  -- The select_i signals defines which chain is enabled.
491
  -- NOTE: All signals that control a inverter-latch element have to be registered to ensure a single element
492
  -- is mapped to a single LUT (or LUT + FF(latch-mode)).
493
 
494
  -- short oscillator chain --
495
  ring_osc_short: process(enable_i, enable_sreg_s, feedback, inv_chain_s)
496 2 zero_gravi
  begin
497 68 zero_gravi
    for i in 0 to NUM_INV_S-1 loop -- inverters in short chain
498 47 zero_gravi
      if (enable_i = '0') then -- start with a defined state (latch reset)
499 68 zero_gravi
        inv_chain_s(i) <= '0';
500
      elsif (enable_sreg_s(i) = '1') then
501
        if (i = NUM_INV_S-1) then -- left-most inverter?
502
          inv_chain_s(i) <= not feedback;
503 23 zero_gravi
        else
504 68 zero_gravi
          inv_chain_s(i) <= not inv_chain_s(i+1);
505 23 zero_gravi
        end if;
506
      end if;
507 47 zero_gravi
    end loop; -- i
508 68 zero_gravi
  end process ring_osc_short;
509 2 zero_gravi
 
510 68 zero_gravi
  -- long oscillator chain --
511
  ring_osc_long: process(enable_i, enable_sreg_l, feedback, inv_chain_l)
512
  begin
513
    for i in 0 to NUM_INV_L-1 loop -- inverters in long chain
514
      if (enable_i = '0') then -- start with a defined state (latch reset)
515
        inv_chain_l(i) <= '0';
516
      elsif (enable_sreg_l(i) = '1') then
517
        if (i = NUM_INV_L-1) then -- left-most inverter?
518
          inv_chain_l(i) <= not feedback;
519
        else
520
          inv_chain_l(i) <= not inv_chain_l(i+1);
521
        end if;
522
      end if;
523
    end loop; -- i
524
  end process ring_osc_long;
525 2 zero_gravi
 
526 68 zero_gravi
  -- length select --
527
  feedback <= inv_chain_l(0) when (select_i = '0') else inv_chain_s(0);
528
 
529
 
530 23 zero_gravi
  -- Control --------------------------------------------------------------------------------
531
  -- -------------------------------------------------------------------------------------------
532 68 zero_gravi
  -- Using individual enable signals for each inverter from a shift register to prevent the synthesis tool
533
  -- from removing all but one inverter (since they implement "logical identical functions" (='toggle')).
534
  -- This makes the TRNG platform independent (since we do not need to use primitives to ensure a correct architecture).
535 23 zero_gravi
  ctrl_unit: process(clk_i)
536
  begin
537
    if rising_edge(clk_i) then
538 68 zero_gravi
      -- enable sreg --
539
      enable_sreg_s <= enable_sreg_s(enable_sreg_s'left-1 downto 0) & enable_i;
540
      enable_sreg_l <= enable_sreg_l(enable_sreg_l'left-1 downto 0) & enable_sreg_s(enable_sreg_s'left);
541
      -- data output sync - no metastability beyond this point --
542
      sync_ff <= sync_ff(0) & feedback;
543 23 zero_gravi
    end if;
544
  end process ctrl_unit;
545 2 zero_gravi
 
546 23 zero_gravi
  -- output for "enable chain" --
547 68 zero_gravi
  enable_o <= enable_sreg_l(enable_sreg_l'left);
548 23 zero_gravi
 
549 68 zero_gravi
  -- random data output --
550 47 zero_gravi
  data_o <= sync_ff(1);
551 23 zero_gravi
 
552
 
553 68 zero_gravi
end neoTRNG_cell_rtl;

powered by: WebSVN 2.1.0

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