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

Subversion Repositories neorv32

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

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 23 zero_gravi
-- # This unit implements a true random number generator which uses several GARO chain as entropy  #
5
-- # source. The outputs of all chains are XORed and de-biased using a John von Neumann randomness #
6
-- # extractor. The de-biased signal is further processed by a simple LFSR for improved whitening. #
7 2 zero_gravi
-- #                                                                                               #
8
-- # Sources:                                                                                      #
9
-- #  - Von Neumann De-Biasing: "Iterating Von Neumann's Post-Processing under Hardware            #
10
-- #    Constraints" by Vladimir Rozic, Bohan Yang, Wim Dehaene and Ingrid Verbauwhede, 2016       #
11
-- # ********************************************************************************************* #
12
-- # BSD 3-Clause License                                                                          #
13
-- #                                                                                               #
14
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
15
-- #                                                                                               #
16
-- # Redistribution and use in source and binary forms, with or without modification, are          #
17
-- # permitted provided that the following conditions are met:                                     #
18
-- #                                                                                               #
19
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
20
-- #    conditions and the following disclaimer.                                                   #
21
-- #                                                                                               #
22
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
23
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
24
-- #    provided with the distribution.                                                            #
25
-- #                                                                                               #
26
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
27
-- #    endorse or promote products derived from this software without specific prior written      #
28
-- #    permission.                                                                                #
29
-- #                                                                                               #
30
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
31
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
32
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
33
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
34
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
35
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
36
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
37
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
38
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
39
-- # ********************************************************************************************* #
40
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
41
-- #################################################################################################
42
 
43
library ieee;
44
use ieee.std_logic_1164.all;
45
use ieee.numeric_std.all;
46
 
47
library neorv32;
48
use neorv32.neorv32_package.all;
49
 
50
entity neorv32_trng is
51
  port (
52
    -- host access --
53
    clk_i  : in  std_ulogic; -- global clock line
54
    addr_i : in  std_ulogic_vector(31 downto 0); -- address
55
    rden_i : in  std_ulogic; -- read enable
56
    wren_i : in  std_ulogic; -- write enable
57
    data_i : in  std_ulogic_vector(31 downto 0); -- data in
58
    data_o : out std_ulogic_vector(31 downto 0); -- data out
59
    ack_o  : out std_ulogic  -- transfer acknowledge
60
  );
61
end neorv32_trng;
62
 
63
architecture neorv32_trng_rtl of neorv32_trng is
64
 
65
  -- advanced configuration --------------------------------------------------------------------------------
66 23 zero_gravi
  constant num_inv_c   : natural := 15; -- length of GARO inverter chain (default=15, has to be odd)
67
  constant num_garos_c : natural := 2; -- number of GARO elements (default=2)
68
  constant lfsr_taps_c : std_ulogic_vector(7 downto 0) := "10111000"; -- Fibonacci post-processing LFSR feedback taps
69
  constant lfsr_en_c   : boolean := true; -- use LFSR-based post-processing
70
  type tap_mask_t is array (0 to num_garos_c-1) of std_ulogic_vector(num_inv_c-2 downto 0);
71
  constant tap_mask : tap_mask_t := ( -- GARO tap masks, sum of set bits has to be even
72
    "11110000000000",
73
    "00000011000000"
74
  );
75 2 zero_gravi
  -- -------------------------------------------------------------------------------------------------------
76
 
77
  -- control register bits --
78 23 zero_gravi
  constant ctrl_data_lsb_c   : natural :=  0; -- r/-: Random data bit LSB
79
  constant ctrl_data_msb_c   : natural :=  7; -- r/-: Random data bit MSB
80
  constant ctrl_data_valid_c : natural := 15; -- r/-: Output data valid
81
  constant ctrl_err_zero_c   : natural := 16; -- r/-: stuck at 0 error
82
  constant ctrl_err_one_c    : natural := 17; -- r/-: stuck at 1 error
83
  constant ctrl_en_c         : natural := 31; -- r/w: TRNG enable
84 2 zero_gravi
 
85
  -- IO space: module base address --
86
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
87
  constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
88
 
89 23 zero_gravi
  -- Component: GARO Element --
90
  component neorv32_trng_garo_element
91
    generic (
92
      NUM_INV : natural := 16 -- number of inverters in chain
93
    );
94
    port (
95
      clk_i    : in  std_ulogic;
96
      enable_i : in  std_ulogic;
97
      enable_o : out std_ulogic;
98
      mask_i   : in  std_ulogic_vector(NUM_INV-2 downto 0);
99
      data_o   : out std_ulogic;
100
      error0_o : out std_ulogic;
101
      error1_o : out std_ulogic
102
    );
103
  end component;
104
 
105 2 zero_gravi
  -- access control --
106
  signal acc_en : std_ulogic; -- module access enable
107
  signal wren   : std_ulogic; -- full word write enable
108
  signal rden   : std_ulogic; -- read enable
109
 
110 23 zero_gravi
  -- garo array --
111
  signal garo_en_in    : std_ulogic_vector(num_garos_c-1 downto 0);
112
  signal garo_en_out   : std_ulogic_vector(num_garos_c-1 downto 0);
113
  signal garo_data     : std_ulogic_vector(num_garos_c-1 downto 0);
114
  signal garo_err_zero : std_ulogic_vector(num_garos_c-1 downto 0);
115
  signal garo_err_one  : std_ulogic_vector(num_garos_c-1 downto 0);
116
  signal garo_res      : std_ulogic;
117
  signal garo_err0     : std_ulogic;
118
  signal garo_err1     : std_ulogic;
119 2 zero_gravi
 
120 23 zero_gravi
  -- de-biasing --
121
  signal db_data     : std_ulogic_vector(2 downto 0);
122
  signal db_state    : std_ulogic; -- process de-biasing every second cycle
123
  signal rnd_valid   : std_ulogic;
124
  signal rnd_data    : std_ulogic;
125 2 zero_gravi
 
126 23 zero_gravi
  -- processing core --
127
  signal rnd_enable : std_ulogic;
128
  signal rnd_cnt    : std_ulogic_vector(3 downto 0);
129
  signal rnd_sreg   : std_ulogic_vector(7 downto 0);
130
  signal rnd_output : std_ulogic_vector(7 downto 0);
131
  signal rnd_ready  : std_ulogic;
132
 
133
  -- health check --
134
  signal rnd_error_zero : std_ulogic; -- stuck at zero
135
  signal rnd_error_one  : std_ulogic; -- stuck at one
136
 
137 2 zero_gravi
begin
138
 
139
  -- Access Control -------------------------------------------------------------------------
140
  -- -------------------------------------------------------------------------------------------
141
  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';
142
  wren   <= acc_en and wren_i;
143
  rden   <= acc_en and rden_i;
144
 
145
 
146
  -- Read/Write Access ----------------------------------------------------------------------
147
  -- -------------------------------------------------------------------------------------------
148
  rw_access: process(clk_i)
149
  begin
150
    if rising_edge(clk_i) then
151
      ack_o <= acc_en and (rden_i or wren_i);
152
      -- write access --
153
      if (wren = '1') then
154 23 zero_gravi
        rnd_enable <= data_i(ctrl_en_c);
155 2 zero_gravi
      end if;
156
      -- read access --
157
      data_o <= (others => '0');
158
      if (rden = '1') then
159 23 zero_gravi
        data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_output;
160
        data_o(ctrl_data_valid_c) <= rnd_ready;
161
        data_o(ctrl_err_zero_c)   <= rnd_error_zero;
162
        data_o(ctrl_err_one_c)    <= rnd_error_one;
163
        data_o(ctrl_en_c)         <= rnd_enable;
164 2 zero_gravi
      end if;
165
    end if;
166
  end process rw_access;
167
 
168
 
169 23 zero_gravi
  -- Entropy Source -------------------------------------------------------------------------
170 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
171 23 zero_gravi
  neorv32_trng_garo_element_inst:
172
  for i in 0 to num_garos_c-1 generate
173
    neorv32_trng_garo_element_inst_i: neorv32_trng_garo_element
174
    generic map (
175
      NUM_INV => num_inv_c -- number of inverters in chain
176
    )
177
    port map (
178
      clk_i    => clk_i,
179
      enable_i => garo_en_in(i),
180
      enable_o => garo_en_out(i),
181
      mask_i   => tap_mask(i),
182
      data_o   => garo_data(i),
183
      error0_o => garo_err_zero(i),
184
      error1_o => garo_err_one(i)
185
    );
186
  end generate;
187
 
188
  -- GARO element connection --
189
  garo_intercon: process(rnd_enable, garo_en_out, garo_data, garo_err_zero, garo_err_one)
190
    variable data_v : std_ulogic;
191
    variable err0_v : std_ulogic;
192
    variable err1_v : std_ulogic;
193 2 zero_gravi
  begin
194 23 zero_gravi
    -- enable chain --
195
    for i in 0 to num_garos_c-1 loop
196
      if (i = 0) then
197
        garo_en_in(i) <= rnd_enable;
198
      else
199
        garo_en_in(i) <= garo_en_out(i-1);
200 2 zero_gravi
      end if;
201
    end loop; -- i
202 23 zero_gravi
    -- data & status --
203
    data_v := garo_data(0);
204
    err0_v := garo_err_zero(0);
205
    err1_v := garo_err_one(0);
206
    for i in 1 to num_garos_c-1 loop
207
      data_v := data_v xor garo_data(i);
208
      err0_v := err0_v or garo_err_zero(i);
209
      err1_v := err1_v or garo_err_one(i);
210
    end loop; -- i
211
    garo_res  <= data_v;
212
    garo_err0 <= err0_v;
213
    garo_err1 <= err1_v;
214
  end process garo_intercon;
215 2 zero_gravi
 
216 23 zero_gravi
 
217
  -- De-Biasing -----------------------------------------------------------------------------
218
  -- -------------------------------------------------------------------------------------------
219
  jvn_debiasing_sync: process(clk_i)
220 2 zero_gravi
  begin
221
    if rising_edge(clk_i) then
222 23 zero_gravi
      db_data  <= db_data(db_data'left-1 downto 0) & garo_res;
223
      db_state <= (not db_state) and rnd_enable; -- just toggle when enabled -> process in every second cycle
224 2 zero_gravi
    end if;
225 23 zero_gravi
  end process jvn_debiasing_sync;
226 2 zero_gravi
 
227
 
228 23 zero_gravi
  -- John von Neumann De-Biasing --
229
  jvn_debiasing: process(db_state, db_data)
230
    variable tmp_v : std_ulogic_vector(2 downto 0);
231
  begin
232
    -- check groups of two non-overlapping bits from the input stream
233
    tmp_v := db_state & db_data(db_data'left downto db_data'left-1);
234
    case tmp_v is
235
      when "101"  => rnd_valid <= '1'; rnd_data <= '1'; -- rising edge -> '1'
236
      when "110"  => rnd_valid <= '1'; rnd_data <= '0'; -- falling edge -> '0'
237
      when others => rnd_valid <= '0'; rnd_data <= '-'; -- invalid
238
    end case;
239
  end process jvn_debiasing;
240
 
241
 
242 2 zero_gravi
  -- Processing Core ------------------------------------------------------------------------
243
  -- -------------------------------------------------------------------------------------------
244
  processing_core: process(clk_i)
245
  begin
246
    if rising_edge(clk_i) then
247 23 zero_gravi
      -- sample random data and apply post-processing --
248 2 zero_gravi
      if (rnd_enable = '0') then
249
        rnd_cnt  <= (others => '0');
250
        rnd_sreg <= (others => '0');
251 23 zero_gravi
      elsif (rnd_valid = '1') and (garo_en_out(garo_en_out'left) = '1') then -- valid random sample and GAROs ready?
252
        if (rnd_cnt = "1000") then
253 2 zero_gravi
          rnd_cnt <= (others => '0');
254
        else
255
          rnd_cnt <= std_ulogic_vector(unsigned(rnd_cnt) + 1);
256
        end if;
257 23 zero_gravi
        if (lfsr_en_c = true) then -- LFSR post-processing
258
          rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & (xnor_all_f(rnd_sreg and lfsr_taps_c) xnor rnd_data);
259
        else -- NO post-processing
260
          rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & rnd_data;
261
        end if;
262 2 zero_gravi
      end if;
263
 
264
      -- data output register --
265 23 zero_gravi
      if (rnd_cnt = "1000") then
266
        rnd_output <= rnd_sreg;
267 2 zero_gravi
      end if;
268
 
269 23 zero_gravi
      -- health check error --
270
      if (rnd_enable = '0') then
271
        rnd_error_zero <= '0';
272
        rnd_error_one  <= '0';
273
      else
274
        rnd_error_zero <= rnd_error_zero or garo_err0;
275
        rnd_error_one  <= rnd_error_one  or garo_err1;
276
      end if;
277
 
278 2 zero_gravi
      -- data ready flag --
279 23 zero_gravi
      if (rnd_cnt = "1000") then -- new sample ready?
280
        rnd_ready <= '1';
281
      elsif (rnd_enable = '0') or (rden = '1') then -- clear when deactivated or on data read
282
        rnd_ready <= '0';
283 2 zero_gravi
      end if;
284
    end if;
285
  end process processing_core;
286
 
287 23 zero_gravi
 
288
end neorv32_trng_rtl;
289
 
290
 
291
-- ############################################################################################################################
292
-- ############################################################################################################################
293
 
294
 
295
-- #################################################################################################
296
-- # << NEORV32 - True Random Number Generator (TRNG) - GARO Chain-Based Entropy Source >>         #
297
-- # ********************************************************************************************* #
298
-- # An inverter chain (ring oscillator) is used as entropy source. The inverter chain is          #
299
-- # constructed as GARO (Galois Ring Oscillator) TRNG, which is an "asynchronous" LFSR. The       #
300
-- # single inverters are connected via latches that are used to enbale/disable the TRNG. Also,    #
301
-- # these latches are used as additional delay element. By using unique enable signals for each   #
302
-- # latch, the synthesis tool cannot "optimize" (=remove) any of the inverters out of the design. #
303
-- # Furthermore, the latches prevent the synthesis tool from detecting combinatorial loops.       #
304
-- #                                                                                               #
305
-- # Sources:                                                                                      #
306
-- #  - GARO: "Experimental Assessment of FIRO- and GARO-based Noise Sources for Digital TRNG      #
307
-- #    Designs on FPGAs" by Martin Schramm, Reiner Dojen and Michael Heigly, 2017                 #
308
-- #  - Latches for platform independence: "Extended Abstract: The Butterfly PUF Protecting IP     #
309
-- #    on every FPGA" by Sandeep S. Kumar, Jorge Guajardo, Roel Maesyz, Geert-Jan Schrijen and    #
310
-- #    Pim Tuyls, Philips Research Europe, 2008                                                   #
311
-- # ********************************************************************************************* #
312
-- # BSD 3-Clause License                                                                          #
313
-- #                                                                                               #
314
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
315
-- #                                                                                               #
316
-- # Redistribution and use in source and binary forms, with or without modification, are          #
317
-- # permitted provided that the following conditions are met:                                     #
318
-- #                                                                                               #
319
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
320
-- #    conditions and the following disclaimer.                                                   #
321
-- #                                                                                               #
322
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
323
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
324
-- #    provided with the distribution.                                                            #
325
-- #                                                                                               #
326
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
327
-- #    endorse or promote products derived from this software without specific prior written      #
328
-- #    permission.                                                                                #
329
-- #                                                                                               #
330
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
331
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
332
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
333
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
334
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
335
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
336
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
337
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
338
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
339
-- # ********************************************************************************************* #
340
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
341
-- #################################################################################################
342
 
343
library ieee;
344
use ieee.std_logic_1164.all;
345
use ieee.numeric_std.all;
346
 
347
library neorv32;
348
use neorv32.neorv32_package.all;
349
 
350
entity neorv32_trng_garo_element is
351
  generic (
352
    NUM_INV : natural := 15 -- number of inverters in chain
353
  );
354
  port (
355
    clk_i    : in  std_ulogic;
356
    enable_i : in  std_ulogic;
357
    enable_o : out std_ulogic;
358
    mask_i   : in  std_ulogic_vector(NUM_INV-2 downto 0);
359
    data_o   : out std_ulogic;
360
    error0_o : out std_ulogic;
361
    error1_o : out std_ulogic
362
  );
363
end neorv32_trng_garo_element;
364
 
365
architecture neorv32_trng_garo_element_rtl of neorv32_trng_garo_element is
366
 
367
  -- debugging --
368
  constant is_sim_c : boolean := false;
369
 
370
  signal inv_chain   : std_ulogic_vector(NUM_INV-1 downto 0); -- oscillator chain
371
  signal enable_sreg : std_ulogic_vector(NUM_INV-1 downto 0); -- enable shift register
372
  signal sync_ff     : std_ulogic_vector(2 downto 0); -- synchronizer
373
 
374
  signal cnt_zero, cnt_one : std_ulogic_vector(5 downto 0); -- stuck-at-0/1 counters
375
 
376
begin
377
 
378
  -- Sanity Check ---------------------------------------------------------------------------
379
  -- -------------------------------------------------------------------------------------------
380
  assert ((NUM_INV mod 2) /= 0) report "NEORV32 TRNG.GARO_element: NUM_INV has to be odd." severity error;
381
 
382
 
383
  -- Entropy Source -------------------------------------------------------------------------
384
  -- -------------------------------------------------------------------------------------------
385
  garo_chain: process(clk_i, enable_i, enable_sreg, mask_i, inv_chain)
386 2 zero_gravi
  begin
387 23 zero_gravi
    if (is_sim_c = false) then
388
      for i in 0 to NUM_INV-1 loop -- inverters in chain
389
        if (enable_i = '0') then -- start with a defined state (latch reset)
390
          inv_chain(i) <= '0';
391
        -- Using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
392
        -- from removing all but one inverter (since they implement "logical identical functions").
393
        -- This also allows to make the TRNG platform independent.
394
        elsif (enable_sreg(i) = '1') then
395
          -- here we have the inverter chain --
396
          if (i = NUM_INV-1) then -- left-most inverter?
397
            inv_chain(i) <= not inv_chain(0); -- direct input of right most inverter (= output signal)
398
          else
399
            -- if tap switch is ON:  use final output XORed with previous inverter's output
400
            -- if tap switch is OFF: just use previous inverter's output
401
            inv_chain(i) <= not (inv_chain(i+1) xor (inv_chain(0) and mask_i(i)));
402
          end if;
403
        end if;
404
      end loop; -- i
405
    else -- simulate as simple LFSR
406
      if rising_edge(clk_i) then
407
        if (enable_i = '0') then
408
          inv_chain <= (others => '0');
409
        else
410
          inv_chain(NUM_INV-1 downto 0) <= inv_chain(inv_chain'left-1 downto 0) & xnor_all_f(inv_chain(NUM_INV-2 downto 0) and mask_i);
411
        end if;
412
      end if;
413
    end if;
414
  end process garo_chain;
415 2 zero_gravi
 
416
 
417 23 zero_gravi
  -- Control --------------------------------------------------------------------------------
418
  -- -------------------------------------------------------------------------------------------
419
  ctrl_unit: process(clk_i)
420
  begin
421
    if rising_edge(clk_i) then
422
      enable_sreg <= enable_sreg(enable_sreg'left-1 downto 0) & enable_i; -- activate right-most inverter first
423
      sync_ff     <= sync_ff(sync_ff'left-1 downto 0) & inv_chain(0); -- synchronize to prevent metastability 
424
    end if;
425
  end process ctrl_unit;
426 2 zero_gravi
 
427 23 zero_gravi
  -- output for "enable chain" --
428
  enable_o <= enable_sreg(enable_sreg'left);
429
 
430
  -- rnd output --
431
  data_o <= sync_ff(sync_ff'left);
432
 
433
 
434
  -- Health Check ---------------------------------------------------------------------------
435
  -- -------------------------------------------------------------------------------------------
436
  health_check: process(clk_i)
437
  begin
438
    if rising_edge(clk_i) then
439
      if (enable_sreg(enable_sreg'left) = '0') then
440
        cnt_zero <= (others => '0');
441
        cnt_one  <= (others => '0');
442
      else
443
        -- stuck-at-zero --
444
        if (and_all_f(cnt_zero) = '0') then -- max not reached yet
445
          error0_o <= '0';
446
          if (sync_ff(sync_ff'left) = '0') then
447
            cnt_zero <= std_ulogic_vector(unsigned(cnt_zero) + 1);
448
          else
449
            cnt_zero <= (others => '0');
450
          end if;
451
        else
452
          error0_o <= '1';
453
        end if;
454
        -- stuck-at-one --
455
        if (and_all_f(cnt_one) = '0') then -- max not reached yet
456
          error1_o <= '0';
457
          if (sync_ff(sync_ff'left) = '1') then
458
            cnt_one <= std_ulogic_vector(unsigned(cnt_one) + 1);
459
          else
460
            cnt_one <= (others => '0');
461
          end if;
462
        else
463
          error1_o <= '1';
464
        end if;
465
      end if;
466
    end if;
467
  end process health_check;
468
 
469
 
470
end neorv32_trng_garo_element_rtl;

powered by: WebSVN 2.1.0

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