1
0
mirror of synced 2026-04-06 13:11:22 +00:00

commit the neorv32trgn-based trng

This commit is contained in:
Romain Dolbeau
2021-07-20 07:45:51 -04:00
parent c258b75c57
commit aea1865b7b
10 changed files with 877 additions and 49 deletions

View File

@@ -55,6 +55,8 @@ __KERNEL_RCSID(0, "$NetBSD$");
#include <machine/param.h>
#include <uvm/uvm_extern.h>
int sbusfpga_sdram_match(device_t, cfdata_t, void *);
void sbusfpga_sdram_attach(device_t, device_t, void *);
@@ -446,6 +448,30 @@ sbusfpga_sdram_diskstart(device_t self, struct buf *bp)
goto done;
}
/*
{
paddr_t pap;
pmap_t pk = pmap_kernel();
if (pmap_extract(pk, (vaddr_t)bp->b_data, &pap)) {
aprint_normal_dev(sc->dk.sc_dev, "KVA %p mapped to PA 0x%08lx\n", bp->b_data, pap);
if (bp->b_bcount > 4096) {
u_int32_t np = (bp->b_bcount + 4095) / 4096;
u_int32_t pn;
for (pn = 1 ; pn < np ; pn ++) {
paddr_t papn;
if (pmap_extract(pk, (vaddr_t)bp->b_data + pn * 4096, &papn)) {
if (papn != (pap + pn * 4096))
break;
} else break;
}
aprint_normal_dev(sc->dk.sc_dev, "And we have %u out %u consecutive PA pages\n", pn, np);
}
} else {
aprint_normal_dev(sc->dk.sc_dev, "KVA %p not mapped\n", bp->b_data);
}
}
*/
if (bp->b_flags & B_READ) {
unsigned char* data = bp->b_data;
daddr_t blk = bp->b_rawblkno;
@@ -527,18 +553,31 @@ sbusfpga_sdram_diskstart(device_t self, struct buf *bp)
#define CONFIG_CSR_DATA_WIDTH 32
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
#define CSR_LEDS_BASE
//#define CSR_DDRPHY_BASE
//#define CSR_SDRAM_BASE
//#define CSR_EXCHANGE_WITH_MEM_BASE
#define CSR_SDBLOCK2MEM_BASE
#define CSR_SDCORE_BASE
#define CSR_SDIRQ_BASE
#define CSR_SDMEM2BLOCK_BASE
#define CSR_SDPHY_BASE
#define CSR_TRNG_BASE
/* grrr */
#define sbusfpga_exchange_with_mem_softc sbusfpga_sdram_softc
#define sbusfpga_ddrphy_softc sbusfpga_sdram_softc
#include "dev/sbus/litex_csr.h"
#undef CSR_LEDS_BASE
//#undef CSR_DDRPHY_BASE
//#undef CSR_SDRAM_BASE
//#undef CSR_EXCHANGE_WITH_MEM_BASE
#undef CSR_SDBLOCK2MEM_BASE
#undef CSR_SDCORE_BASE
#undef CSR_SDIRQ_BASE
#undef CSR_SDMEM2BLOCK_BASE
#undef CSR_SDPHY_BASE
#undef CSR_TRNG_BASE
int
dma_init(struct sbusfpga_sdram_softc *sc) {

View File

@@ -0,0 +1,207 @@
/* $NetBSD$ */
/*-
* Copyright (c) 2020 Romain Dolbeau <romain@dolbeau.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <machine/autoconf.h>
#include <sys/cpu.h>
#include <sys/conf.h>
#include <sys/rndsource.h>
#include <dev/sbus/sbusvar.h>
#include <dev/sbus/sbusfpga_trng.h>
#include <machine/param.h>
int sbusfpga_trng_print(void *, const char *);
int sbusfpga_trng_match(device_t, cfdata_t, void *);
void sbusfpga_trng_attach(device_t, device_t, void *);
CFATTACH_DECL_NEW(sbusfpga_trng, sizeof(struct sbusfpga_trng_softc),
sbusfpga_trng_match, sbusfpga_trng_attach, NULL, NULL);
dev_type_open(sbusfpga_trng_open);
dev_type_close(sbusfpga_trng_close);
dev_type_ioctl(sbusfpga_trng_ioctl);
const struct cdevsw sbusfpga_trng_cdevsw = {
.d_open = sbusfpga_trng_open,
.d_close = sbusfpga_trng_close,
.d_read = noread,
.d_write = nowrite,
.d_ioctl = noioctl,
.d_stop = nostop,
.d_tty = notty,
.d_poll = nopoll,
.d_mmap = nommap,
.d_kqfilter = nokqfilter,
.d_discard = nodiscard,
.d_flag = 0
};
extern struct cfdriver sbusfpga_trng_cd;
int
sbusfpga_trng_open(dev_t dev, int flags, int mode, struct lwp *l)
{
return (0);
}
int
sbusfpga_trng_close(dev_t dev, int flags, int mode, struct lwp *l)
{
return (0);
}
int
sbusfpga_trng_print(void *aux, const char *busname)
{
sbus_print(aux, busname);
return (UNCONF);
}
int
sbusfpga_trng_match(device_t parent, cfdata_t cf, void *aux)
{
struct sbus_attach_args *sa = (struct sbus_attach_args *)aux;
return (strcmp("RDOL,neorv32trng", sa->sa_name) == 0);
}
#define CONFIG_CSR_DATA_WIDTH 32
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
#define CSR_LEDS_BASE
#define CSR_DDRPHY_BASE
#define CSR_EXCHANGE_WITH_MEM_BASE
#define CSR_SDRAM_BASE
#define CSR_SDBLOCK2MEM_BASE
#define CSR_SDCORE_BASE
#define CSR_SDIRQ_BASE
#define CSR_SDMEM2BLOCK_BASE
#define CSR_SDPHY_BASE
//#define CSR_TRNG_BASE
#include "dev/sbus/litex_csr.h"
#undef CSR_LEDS_BASE
#undef CSR_DDRPHY_BASE
#undef CSR_EXCHANGE_WITH_MEM_BASE
#undef CSR_SDRAM_BASE
#undef CSR_SDBLOCK2MEM_BASE
#undef CSR_SDCORE_BASE
#undef CSR_SDIRQ_BASE
#undef CSR_SDMEM2BLOCK_BASE
#undef CSR_SDPHY_BASE
//#undef CSR_TRNG_BASE
static void
sbusfpga_trng_getentropy(size_t nbytes, void *cookie) {
struct sbusfpga_trng_softc *sc = cookie;
size_t dbytes = 0;
int failure = 0;
while ((nbytes - dbytes) > 0) {
u_int32_t data = trng_data_read(sc);
if (data) {
rnd_add_data_sync(&sc->sc_rndsource, &data, 4, 32); // 32 is perhaps optimistic
dbytes += 4;
} else {
failure ++;
if (failure > (1+(dbytes/4))) { // something going on
aprint_normal_dev(sc->sc_dev, "out of entropy after %zd / %zd bytes\n", dbytes, nbytes);
return;
}
delay(1);
}
}
aprint_normal_dev(sc->sc_dev, "gathered %zd bytes\n", dbytes);
}
/*
* Attach all the sub-devices we can find
*/
void
sbusfpga_trng_attach(device_t parent, device_t self, void *aux)
{
struct sbus_attach_args *sa = aux;
struct sbusfpga_trng_softc *sc = device_private(self);
struct sbus_softc *sbsc = device_private(parent);
int node;
int sbusburst;
sc->sc_bustag = sa->sa_bustag;
sc->sc_dev = self;
if (sbus_bus_map(sc->sc_bustag, sa->sa_slot, sa->sa_offset, sa->sa_size,
BUS_SPACE_MAP_LINEAR, &sc->sc_bhregs_trng) != 0) {
aprint_error(": cannot map registers\n");
return;
}
//sc->sc_buffer = bus_space_vaddr(sc->sc_bustag, sc->sc_bhregs_trng);
sc->sc_bufsiz = sa->sa_size;
node = sc->sc_node = sa->sa_node;
/*
* Get transfer burst size from PROM
*/
sbusburst = sbsc->sc_burst;
if (sbusburst == 0)
sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
sc->sc_burst = prom_getpropint(node, "burst-sizes", -1);
if (sc->sc_burst == -1)
/* take SBus burst sizes */
sc->sc_burst = sbusburst;
/* Clamp at parent's burst sizes */
sc->sc_burst &= sbusburst;
aprint_normal("\n");
aprint_normal_dev(self, "nid 0x%x, bustag %p, burst 0x%x (parent 0x%0x)\n",
sc->sc_node,
sc->sc_bustag,
sc->sc_burst,
sbsc->sc_burst);
trng_ctrl_write(sc, 0x02); // start the TRNG
rndsource_setcb(&sc->sc_rndsource, sbusfpga_trng_getentropy, sc);
rnd_attach_source(&sc->sc_rndsource, device_xname(self), RND_TYPE_RNG, RND_FLAG_HASCB | RND_FLAG_COLLECT_VALUE);
}

View File

@@ -0,0 +1,43 @@
/* $NetBSD$ */
/*-
* Copyright (c) 2020 Romain Dolbeau <romain@dolbeau.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _RDFPGA_TRNG_H_
#define _RDFPGA_TRNG_H_
struct sbusfpga_trng_softc {
device_t sc_dev; /* us as a device */
u_int sc_rev; /* revision */
int sc_node; /* PROM node ID */
int sc_burst; /* DVMA burst size in effect */
bus_space_tag_t sc_bustag; /* bus tag */
bus_space_handle_t sc_bhregs_trng; /* bus handle */
int sc_bufsiz; /* Size of buffer */
struct krndsource sc_rndsource;
};
#endif /* _RDFPGA_TRNG_H_ */

View File

@@ -0,0 +1,382 @@
-- # THIS IS NOT THE ORIGINAL FILE
-- # THIS WAS MODIFIED TO EXPOSE THE TRNG IN LITEX
-- # See the link in the copyright header to find the original file
--
--
-- #################################################################################################
-- # << NEORV32 - True Random Number Generator (TRNG) >> #
-- # ********************************************************************************************* #
-- # This unit implements a *true* random number generator which uses several ring oscillators as #
-- # entropy source. The outputs of all chains are XORed and de-biased using a John von Neumann #
-- # randomness extractor. The de-biased signal is further processed by a simple LFSR for improved #
-- # whitening. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
-- use neorv32.neorv32_package.all;
entity neorv32_trng is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
-- addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0)--; -- data out
-- ack_o : out std_ulogic -- transfer acknowledge
);
end neorv32_trng;
architecture neorv32_trng_rtl of neorv32_trng is
-- Advanced Configuration --------------------------------------------------------------------------------
constant num_roscs_c : natural := 4; -- total number of ring oscillators
constant num_inv_start_c : natural := 5; -- number of inverters in FIRST ring oscillator (has to be odd)
constant num_inv_inc_c : natural := 2; -- number of inverters increment for each next ring oscillator (has to be even)
constant lfsr_en_c : boolean := true; -- use LFSR-based post-processing
constant lfsr_taps_c : std_ulogic_vector(7 downto 0) := "10111000"; -- Fibonacci post-processing LFSR feedback taps
-- -------------------------------------------------------------------------------------------------------
-- control register bits --
constant ctrl_data_lsb_c : natural := 0; -- r/-: Random data byte LSB
constant ctrl_data_msb_c : natural := 7; -- r/-: Random data byte MSB
--
constant ctrl_en_c : natural := 30; -- r/w: TRNG enable
constant ctrl_valid_c : natural := 31; -- r/-: Output data valid
-- IO space: module base address --
-- constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
-- constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
-- copy/pasted from the rtl/core/neorv32_package.vhd file
function xor_reduce_f(a : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
if (a'low < a'high) then -- not null range?
for i in a'low to a'high loop
tmp_v := tmp_v xor a(i);
end loop; -- i
end if;
return tmp_v;
end function xor_reduce_f;
-- Component: Ring-Oscillator --
component neorv32_trng_ring_osc
generic (
NUM_INV : natural := 16 -- number of inverters in chain
);
port (
clk_i : in std_ulogic;
enable_i : in std_ulogic; -- enable chain input
enable_o : out std_ulogic; -- enable chain output
data_o : out std_ulogic -- sync random bit
);
end component;
-- access control --
signal acc_en : std_ulogic; -- module access enable
-- signal wren : std_ulogic; -- full word write enable
-- signal rden : std_ulogic; -- read enable
-- ring-oscillator array --
signal osc_array_en_in : std_ulogic_vector(num_roscs_c-1 downto 0);
signal osc_array_en_out : std_ulogic_vector(num_roscs_c-1 downto 0);
signal osc_array_data : std_ulogic_vector(num_roscs_c-1 downto 0);
-- von-Neumann de-biasing --
type debiasing_t is record
sreg : std_ulogic_vector(1 downto 0);
state : std_ulogic; -- process de-biasing every second cycle
valid : std_ulogic; -- de-biased data
data : std_ulogic; -- de-biased data valid
end record;
signal debiasing : debiasing_t;
-- (post-)processing core --
type processing_t is record
enable : std_ulogic; -- TRNG enable flag
cnt : std_ulogic_vector(3 downto 0); -- bit counter
sreg : std_ulogic_vector(7 downto 0); -- data shift register
output : std_ulogic_vector(7 downto 0); -- output register
valid : std_ulogic; -- data output valid flag
end record;
signal processing : processing_t;
begin
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not (num_roscs_c = 0) report "NEORV32 PROCESSOR CONFIG ERROR: TRNG - Total number of ring-oscillators has to be >0." severity error;
assert not ((num_inv_start_c mod 2) = 0) report "NEORV32 PROCESSOR CONFIG ERROR: TRNG - Number of inverters in fisrt ring has to be odd." severity error;
assert not ((num_inv_inc_c mod 2) /= 0) report "NEORV32 PROCESSOR CONFIG ERROR: TRNG - Number of inverters increment for each next ring has to be even." severity error;
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- 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';
-- wren <= acc_en and wren_i;
-- rden <= acc_en and rden_i;
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- ack_o <= wren_i or rden_i;
-- write access --
if (wren_i = '1') then
processing.enable <= data_i(ctrl_en_c);
end if;
-- read access --
-- data_o <= (others => '0');
if (rden_i = '1') then
data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= processing.output;
data_o(ctrl_en_c) <= processing.enable;
data_o(ctrl_valid_c) <= processing.valid;
end if;
end if;
end process rw_access;
-- Entropy Source -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_trng_ring_osc_inst:
for i in 0 to num_roscs_c-1 generate
neorv32_trng_ring_osc_inst_i: neorv32_trng_ring_osc
generic map (
NUM_INV => num_inv_start_c + (i*num_inv_inc_c) -- number of inverters in chain
)
port map (
clk_i => clk_i,
enable_i => osc_array_en_in(i),
enable_o => osc_array_en_out(i),
data_o => osc_array_data(i)
);
end generate;
-- RO enable chain --
array_intercon: process(processing.enable, osc_array_en_out)
begin
for i in 0 to num_roscs_c-1 loop
if (i = 0) then -- start of enable chain
osc_array_en_in(i) <= processing.enable;
else
osc_array_en_in(i) <= osc_array_en_out(i-1);
end if;
end loop; -- i
end process array_intercon;
-- John von Neumann De-Biasing ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neumann_debiasing_sync: process(clk_i)
begin
if rising_edge(clk_i) then
debiasing.sreg <= debiasing.sreg(debiasing.sreg'left-1 downto 0) & xor_reduce_f(osc_array_data);
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
end if;
end process neumann_debiasing_sync;
-- Edge detector --
neumann_debiasing_comb: process(debiasing)
variable tmp_v : std_ulogic_vector(2 downto 0);
begin
-- check groups of two non-overlapping bits from the input stream
tmp_v := debiasing.state & debiasing.sreg;
case tmp_v is
when "101" => debiasing.valid <= '1'; debiasing.data <= '1'; -- rising edge -> '1'
when "110" => debiasing.valid <= '1'; debiasing.data <= '0'; -- falling edge -> '0'
when others => debiasing.valid <= '0'; debiasing.data <= '0'; -- no valid data
end case;
end process neumann_debiasing_comb;
-- Processing Core ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
processing_core: process(clk_i)
begin
if rising_edge(clk_i) then
-- sample random data bit and apply post-processing --
if (processing.enable = '0') then
processing.cnt <= (others => '0');
processing.sreg <= (others => '0');
elsif (debiasing.valid = '1') then -- valid random sample?
if (processing.cnt = "1000") then
processing.cnt <= (others => '0');
else
processing.cnt <= std_ulogic_vector(unsigned(processing.cnt) + 1);
end if;
if (lfsr_en_c = true) then -- LFSR post-processing
processing.sreg <= processing.sreg(processing.sreg'left-1 downto 0) & ((not xor_reduce_f(processing.sreg and lfsr_taps_c)) xnor debiasing.data);
else -- NO post-processing
processing.sreg <= processing.sreg(processing.sreg'left-1 downto 0) & debiasing.data;
end if;
end if;
-- data output register --
if (processing.cnt = "1000") then
processing.output <= processing.sreg;
end if;
-- data ready/valid flag --
if (processing.cnt = "1000") then -- new sample ready?
processing.valid <= '1';
elsif (processing.enable = '0') or (rden_i = '1') then -- clear when deactivated or on data read
processing.valid <= '0';
end if;
end if;
end process processing_core;
end neorv32_trng_rtl;
-- ############################################################################################################################
-- ############################################################################################################################
-- #################################################################################################
-- # << NEORV32 - True Random Number Generator (TRNG) - Ring-Oscillator-Based Entropy Source >> #
-- # ********************************************************************************************* #
-- # An inverter chain (ring oscillator) is used as entropy source. #
-- # The inverter chain is constructed as an "asynchronous" LFSR. The single inverters are #
-- # connected via latches that are used to enable/disable the TRNG. Also, these latches are used #
-- # as additional delay element. By using unique enable signals for each latch, the synthesis #
-- # tool cannot "optimize" (=remove) any of the inverters out of the design. Furthermore, the #
-- # latches prevent the synthesis tool from detecting combinatorial loops. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neorv32;
-- use neorv32.neorv32_package.all;
entity neorv32_trng_ring_osc is
generic (
NUM_INV : natural := 15 -- number of inverters in chain
);
port (
clk_i : in std_ulogic;
enable_i : in std_ulogic; -- enable chain input
enable_o : out std_ulogic; -- enable chain output
data_o : out std_ulogic -- sync random bit
);
end neorv32_trng_ring_osc;
architecture neorv32_trng_ring_osc_rtl of neorv32_trng_ring_osc is
signal inv_chain : std_ulogic_vector(NUM_INV-1 downto 0); -- oscillator chain
signal enable_sreg : std_ulogic_vector(NUM_INV-1 downto 0); -- enable shift register
signal sync_ff : std_ulogic_vector(1 downto 0); -- output signal synchronizer
begin
-- Ring Oscillator ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ring_osc: process(enable_i, enable_sreg, inv_chain)
begin
-- Using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
-- from removing all but one inverter (since they implement "logical identical functions").
-- This also allows to make the TRNG platform independent.
for i in 0 to NUM_INV-1 loop -- inverters in chain
if (enable_i = '0') then -- start with a defined state (latch reset)
inv_chain(i) <= '0';
elsif (enable_sreg(i) = '1') then
-- here we have the inverter chain --
if (i = NUM_INV-1) then -- left-most inverter?
inv_chain(i) <= not inv_chain(0);
else
inv_chain(i) <= not inv_chain(i+1);
end if;
end if;
end loop; -- i
end process ring_osc;
-- Control --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_unit: process(clk_i)
begin
if rising_edge(clk_i) then
enable_sreg <= enable_sreg(enable_sreg'left-1 downto 0) & enable_i; -- activate right-most inverter first
sync_ff <= sync_ff(0) & inv_chain(0); -- synchronize to prevent metastability
end if;
end process ctrl_unit;
-- output for "enable chain" --
enable_o <= enable_sreg(enable_sreg'left);
-- rnd output --
data_o <= sync_ff(1);
end neorv32_trng_ring_osc_rtl;

View File

@@ -1,5 +1,5 @@
//--------------------------------------------------------------------------------
// Auto-generated by Migen (3ffd64c) & LiteX (8a644c90) on 2021-07-18 12:35:05
// Auto-generated by Migen (3ffd64c) & LiteX (8a644c90) on 2021-07-20 07:32:43
//--------------------------------------------------------------------------------
#ifndef __GENERATED_CSR_H
#define __GENERATED_CSR_H
@@ -12,10 +12,10 @@
#define CSR_LEDS_BASE (CSR_BASE + 0x0L)
#define CSR_LEDS_OUT_ADDR (CSR_LEDS_BASE + 0x0L)
#define CSR_LEDS_OUT_SIZE 1
static inline uint32_t leds_out_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t leds_out_read(struct sbusfpga_leds_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_leds, 0x0L);
}
static inline void leds_out_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void leds_out_write(struct sbusfpga_leds_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_leds, 0x0L, v);
}
#endif // CSR_LEDS_BASE
@@ -25,106 +25,106 @@ static inline void leds_out_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
#define CSR_DDRPHY_BASE (CSR_BASE + 0x1000L)
#define CSR_DDRPHY_RST_ADDR (CSR_DDRPHY_BASE + 0x0L)
#define CSR_DDRPHY_RST_SIZE 1
static inline uint32_t ddrphy_rst_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rst_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x0L);
}
static inline void ddrphy_rst_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rst_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x0L, v);
}
#define CSR_DDRPHY_HALF_SYS8X_TAPS_ADDR (CSR_DDRPHY_BASE + 0x4L)
#define CSR_DDRPHY_HALF_SYS8X_TAPS_SIZE 1
static inline uint32_t ddrphy_half_sys8x_taps_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_half_sys8x_taps_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x4L);
}
static inline void ddrphy_half_sys8x_taps_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_half_sys8x_taps_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x4L, v);
}
#define CSR_DDRPHY_WLEVEL_EN_ADDR (CSR_DDRPHY_BASE + 0x8L)
#define CSR_DDRPHY_WLEVEL_EN_SIZE 1
static inline uint32_t ddrphy_wlevel_en_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_wlevel_en_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x8L);
}
static inline void ddrphy_wlevel_en_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_wlevel_en_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x8L, v);
}
#define CSR_DDRPHY_WLEVEL_STROBE_ADDR (CSR_DDRPHY_BASE + 0xcL)
#define CSR_DDRPHY_WLEVEL_STROBE_SIZE 1
static inline uint32_t ddrphy_wlevel_strobe_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_wlevel_strobe_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0xcL);
}
static inline void ddrphy_wlevel_strobe_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_wlevel_strobe_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0xcL, v);
}
#define CSR_DDRPHY_DLY_SEL_ADDR (CSR_DDRPHY_BASE + 0x10L)
#define CSR_DDRPHY_DLY_SEL_SIZE 1
static inline uint32_t ddrphy_dly_sel_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_dly_sel_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x10L);
}
static inline void ddrphy_dly_sel_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_dly_sel_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x10L, v);
}
#define CSR_DDRPHY_RDLY_DQ_RST_ADDR (CSR_DDRPHY_BASE + 0x14L)
#define CSR_DDRPHY_RDLY_DQ_RST_SIZE 1
static inline uint32_t ddrphy_rdly_dq_rst_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rdly_dq_rst_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x14L);
}
static inline void ddrphy_rdly_dq_rst_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rdly_dq_rst_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x14L, v);
}
#define CSR_DDRPHY_RDLY_DQ_INC_ADDR (CSR_DDRPHY_BASE + 0x18L)
#define CSR_DDRPHY_RDLY_DQ_INC_SIZE 1
static inline uint32_t ddrphy_rdly_dq_inc_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rdly_dq_inc_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x18L);
}
static inline void ddrphy_rdly_dq_inc_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rdly_dq_inc_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x18L, v);
}
#define CSR_DDRPHY_RDLY_DQ_BITSLIP_RST_ADDR (CSR_DDRPHY_BASE + 0x1cL)
#define CSR_DDRPHY_RDLY_DQ_BITSLIP_RST_SIZE 1
static inline uint32_t ddrphy_rdly_dq_bitslip_rst_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rdly_dq_bitslip_rst_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x1cL);
}
static inline void ddrphy_rdly_dq_bitslip_rst_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rdly_dq_bitslip_rst_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x1cL, v);
}
#define CSR_DDRPHY_RDLY_DQ_BITSLIP_ADDR (CSR_DDRPHY_BASE + 0x20L)
#define CSR_DDRPHY_RDLY_DQ_BITSLIP_SIZE 1
static inline uint32_t ddrphy_rdly_dq_bitslip_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rdly_dq_bitslip_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x20L);
}
static inline void ddrphy_rdly_dq_bitslip_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rdly_dq_bitslip_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x20L, v);
}
#define CSR_DDRPHY_WDLY_DQ_BITSLIP_RST_ADDR (CSR_DDRPHY_BASE + 0x24L)
#define CSR_DDRPHY_WDLY_DQ_BITSLIP_RST_SIZE 1
static inline uint32_t ddrphy_wdly_dq_bitslip_rst_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_wdly_dq_bitslip_rst_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x24L);
}
static inline void ddrphy_wdly_dq_bitslip_rst_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_wdly_dq_bitslip_rst_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x24L, v);
}
#define CSR_DDRPHY_WDLY_DQ_BITSLIP_ADDR (CSR_DDRPHY_BASE + 0x28L)
#define CSR_DDRPHY_WDLY_DQ_BITSLIP_SIZE 1
static inline uint32_t ddrphy_wdly_dq_bitslip_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_wdly_dq_bitslip_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x28L);
}
static inline void ddrphy_wdly_dq_bitslip_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_wdly_dq_bitslip_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x28L, v);
}
#define CSR_DDRPHY_RDPHASE_ADDR (CSR_DDRPHY_BASE + 0x2cL)
#define CSR_DDRPHY_RDPHASE_SIZE 1
static inline uint32_t ddrphy_rdphase_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_rdphase_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x2cL);
}
static inline void ddrphy_rdphase_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_rdphase_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x2cL, v);
}
#define CSR_DDRPHY_WRPHASE_ADDR (CSR_DDRPHY_BASE + 0x30L)
#define CSR_DDRPHY_WRPHASE_SIZE 1
static inline uint32_t ddrphy_wrphase_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t ddrphy_wrphase_read(struct sbusfpga_ddrphy_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x30L);
}
static inline void ddrphy_wrphase_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void ddrphy_wrphase_write(struct sbusfpga_ddrphy_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_ddrphy, 0x30L, v);
}
#endif // CSR_DDRPHY_BASE
@@ -134,66 +134,66 @@ static inline void ddrphy_wrphase_write(struct sbusfpga_sdram_softc *sc, uint32_
#define CSR_EXCHANGE_WITH_MEM_BASE (CSR_BASE + 0x2000L)
#define CSR_EXCHANGE_WITH_MEM_BLK_SIZE_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x0L)
#define CSR_EXCHANGE_WITH_MEM_BLK_SIZE_SIZE 1
static inline uint32_t exchange_with_mem_blk_size_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_blk_size_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x0L);
}
#define CSR_EXCHANGE_WITH_MEM_BLK_BASE_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x4L)
#define CSR_EXCHANGE_WITH_MEM_BLK_BASE_SIZE 1
static inline uint32_t exchange_with_mem_blk_base_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_blk_base_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x4L);
}
#define CSR_EXCHANGE_WITH_MEM_MEM_SIZE_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x8L)
#define CSR_EXCHANGE_WITH_MEM_MEM_SIZE_SIZE 1
static inline uint32_t exchange_with_mem_mem_size_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_mem_size_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x8L);
}
#define CSR_EXCHANGE_WITH_MEM_BLK_ADDR_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0xcL)
#define CSR_EXCHANGE_WITH_MEM_BLK_ADDR_SIZE 1
static inline uint32_t exchange_with_mem_blk_addr_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_blk_addr_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0xcL);
}
static inline void exchange_with_mem_blk_addr_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void exchange_with_mem_blk_addr_write(struct sbusfpga_exchange_with_mem_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0xcL, v);
}
#define CSR_EXCHANGE_WITH_MEM_DMA_ADDR_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x10L)
#define CSR_EXCHANGE_WITH_MEM_DMA_ADDR_SIZE 1
static inline uint32_t exchange_with_mem_dma_addr_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_dma_addr_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x10L);
}
static inline void exchange_with_mem_dma_addr_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void exchange_with_mem_dma_addr_write(struct sbusfpga_exchange_with_mem_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x10L, v);
}
#define CSR_EXCHANGE_WITH_MEM_BLK_CNT_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x14L)
#define CSR_EXCHANGE_WITH_MEM_BLK_CNT_SIZE 1
static inline uint32_t exchange_with_mem_blk_cnt_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_blk_cnt_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x14L);
}
static inline void exchange_with_mem_blk_cnt_write(struct sbusfpga_sdram_softc *sc, uint32_t v) {
static inline void exchange_with_mem_blk_cnt_write(struct sbusfpga_exchange_with_mem_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x14L, v);
}
#define CSR_EXCHANGE_WITH_MEM_LAST_BLK_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x18L)
#define CSR_EXCHANGE_WITH_MEM_LAST_BLK_SIZE 1
static inline uint32_t exchange_with_mem_last_blk_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_last_blk_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x18L);
}
#define CSR_EXCHANGE_WITH_MEM_LAST_DMA_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x1cL)
#define CSR_EXCHANGE_WITH_MEM_LAST_DMA_SIZE 1
static inline uint32_t exchange_with_mem_last_dma_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_last_dma_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x1cL);
}
#define CSR_EXCHANGE_WITH_MEM_BLK_REM_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x20L)
#define CSR_EXCHANGE_WITH_MEM_BLK_REM_SIZE 1
static inline uint32_t exchange_with_mem_blk_rem_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_blk_rem_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x20L);
}
#define CSR_EXCHANGE_WITH_MEM_DMA_STATUS_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x24L)
#define CSR_EXCHANGE_WITH_MEM_DMA_STATUS_SIZE 1
static inline uint32_t exchange_with_mem_dma_status_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_dma_status_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x24L);
}
#define CSR_EXCHANGE_WITH_MEM_WR_TOSDRAM_ADDR (CSR_EXCHANGE_WITH_MEM_BASE + 0x28L)
#define CSR_EXCHANGE_WITH_MEM_WR_TOSDRAM_SIZE 1
static inline uint32_t exchange_with_mem_wr_tosdram_read(struct sbusfpga_sdram_softc *sc) {
static inline uint32_t exchange_with_mem_wr_tosdram_read(struct sbusfpga_exchange_with_mem_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_exchange_with_mem, 0x28L);
}
#endif // CSR_EXCHANGE_WITH_MEM_BASE
@@ -467,4 +467,22 @@ static inline uint32_t sdram_dfii_pi3_rddata_read(struct sbusfpga_sdram_softc *s
}
#endif // CSR_SDRAM_BASE
/* trng */
#ifndef CSR_TRNG_BASE
#define CSR_TRNG_BASE (CSR_BASE + 0x4000L)
#define CSR_TRNG_CTRL_ADDR (CSR_TRNG_BASE + 0x0L)
#define CSR_TRNG_CTRL_SIZE 1
static inline uint32_t trng_ctrl_read(struct sbusfpga_trng_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_trng, 0x0L);
}
static inline void trng_ctrl_write(struct sbusfpga_trng_softc *sc, uint32_t v) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_trng, 0x0L, v);
}
#define CSR_TRNG_DATA_ADDR (CSR_TRNG_BASE + 0x4L)
#define CSR_TRNG_DATA_SIZE 1
static inline uint32_t trng_data_read(struct sbusfpga_trng_softc *sc) {
return bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_trng, 0x4L);
}
#endif // CSR_TRNG_BASE
#endif

View File

@@ -3,6 +3,7 @@ h# 40000 constant sbusfpga_csraddr_leds
h# 41000 constant sbusfpga_csraddr_ddrphy
h# 42000 constant sbusfpga_csraddr_exchange_with_mem
h# 43000 constant sbusfpga_csraddr_sdram
h# 44000 constant sbusfpga_csraddr_trng
h# 80000 constant sbusfpga_regionaddr_usb_host_ctrl
h# 0 constant sbusfpga_regionaddr_prom
h# 80000000 constant sbusfpga_regionaddr_main_ram

View File

@@ -5,6 +5,7 @@ fload prom_csr.fth
\ fload v2compat.fth
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ LEDs
\ Absolute minimal stuff; name & registers def.
" RDOL,led" device-name
my-address sbusfpga_csraddr_leds + my-space h# 4 reg
@@ -38,6 +39,7 @@ my-space constant my-sbus-space
\ tokenizer[ 01 emit-byte h# 27 emit-byte h# 01 emit-byte h# 1f emit-byte ]tokenizer
\ The OpenFirmware tokenizer does accept the 'clean' syntax
finish-device
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ USB OHCI
new-device
\ Absolute minimal stuff; name & registers def.
@@ -86,6 +88,7 @@ my-reset!
\ tokenizer[ 01 emit-byte h# 27 emit-byte h# 01 emit-byte h# 1f emit-byte ]tokenizer
\ The OpenFirmware tokenizer does accept the 'clean' syntax
finish-device
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ SDRAM
new-device
\ Absolute minimal stuff; name & registers def.
@@ -129,4 +132,42 @@ my-space constant my-sbus-space
\ init!
\ OpenBIOS tokenizer won't accept finish-device without new-device
\ Cheat by using the tokenizer so we can do OpenBoot 2.x siblings
\ tokenizer[ 01 emit-byte h# 27 emit-byte h# 01 emit-byte h# 1f emit-byte ]tokenizer
\ The OpenFirmware tokenizer does accept the 'clean' syntax
finish-device
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ TRNG
new-device
\ Absolute minimal stuff; name & registers def.
" RDOL,neorv32trng" device-name
my-address sbusfpga_csraddr_trng + my-space h# 8 reg
\ we don't support ET or HWORD
h# 7d xdrint " slave-burst-sizes" attribute
h# 7d xdrint " burst-sizes" attribute
headers
-1 instance value trng-virt
my-address constant my-sbus-address
my-space constant my-sbus-space
: map-in ( adr space size -- virt ) " map-in" $call-parent ;
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-trng ( -- ) my-sbus-address sbusfpga_csraddr_trng + my-sbus-space h# 8 map-in is trng-virt ;
: map-out-trng ( -- ) trng-virt h# 8 map-out ;
\ external
: disabletrng! ( -- )
map-in-trng
1 trng-virt l! ( pattern virt -- )
map-out-trng
;
disabletrng!
end0

View File

@@ -43,7 +43,7 @@ def _get_rw_functions_c(name, csr_name, reg_base, area_base, nwords, busword, al
stride = alignment//8;
if with_access_functions:
r += "static inline {} {}_read(struct sbusfpga_sdram_softc *sc) {{\n".format(ctype, reg_name)
r += "static inline {} {}_read(struct sbusfpga_{}_softc *sc) {{\n".format(ctype, reg_name, name)
if nwords > 1:
r += "\t{} r = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_{}, {}L);\n".format(ctype, name, hex(reg_base - area_base))
for sub in range(1, nwords):
@@ -54,7 +54,7 @@ def _get_rw_functions_c(name, csr_name, reg_base, area_base, nwords, busword, al
r += "\treturn bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_{}, {}L);\n}}\n".format(name, hex(reg_base - area_base))
if not read_only:
r += "static inline void {}_write(struct sbusfpga_sdram_softc *sc, {} v) {{\n".format(reg_name, ctype)
r += "static inline void {}_write(struct sbusfpga_{}_softc *sc, {} v) {{\n".format(reg_name, name, ctype)
for sub in range(nwords):
shift = (nwords-sub-1)*busword
if shift:
@@ -102,18 +102,18 @@ def get_csr_header(regions, constants, csr_base=None, with_access_functions=True
if with_access_functions and csr.size <= 32: # FIXME: Implement extract/read functions for csr.size > 32-bit.
reg_name = name + "_" + csr.name.lower()
field_name = reg_name + "_" + field.name.lower()
r += "static inline uint32_t " + field_name + "_extract(struct sbusfpga_sdram_softc *sc, uint32_t oldword) {\n"
r += "static inline uint32_t " + field_name + "_extract(struct sbusfpga_" + name + "_softc *sc, uint32_t oldword) {\n"
r += "\tuint32_t mask = ((1 << " + size + ")-1);\n"
r += "\treturn ( (oldword >> " + offset + ") & mask );\n}\n"
r += "static inline uint32_t " + field_name + "_read(struct sbusfpga_sdram_softc *sc) {\n"
r += "static inline uint32_t " + field_name + "_read(struct sbusfpga_" + name + "_softc *sc) {\n"
r += "\tuint32_t word = " + reg_name + "_read(sc);\n"
r += "\treturn " + field_name + "_extract(sc, word);\n"
r += "}\n"
if not getattr(csr, "read_only", False):
r += "static inline uint32_t " + field_name + "_replace(struct sbusfpga_sdram_softc *sc, uint32_t oldword, uint32_t plain_value) {\n"
r += "static inline uint32_t " + field_name + "_replace(struct sbusfpga_" + name + "_softc *sc, uint32_t oldword, uint32_t plain_value) {\n"
r += "\tuint32_t mask = ((1 << " + size + ")-1);\n"
r += "\treturn (oldword & (~(mask << " + offset + "))) | (mask & plain_value)<< " + offset + " ;\n}\n"
r += "static inline void " + field_name + "_write(struct sbusfpga_sdram_softc *sc, uint32_t plain_value) {\n"
r += "static inline void " + field_name + "_write(struct sbusfpga_" + name + "_softc *sc, uint32_t plain_value) {\n"
r += "\tuint32_t oldword = " + reg_name + "_read(sc);\n"
r += "\tuint32_t newword = " + field_name + "_replace(sc, oldword, plain_value);\n"
r += "\t" + reg_name + "_write(sc, newword);\n"

View File

@@ -18,6 +18,7 @@ from litedram.phy import s7ddrphy
from sbus_to_fpga_fsm import *
from sbus_to_fpga_blk_dma import *
from sbus_to_fpga_trng import *
from litedram.frontend.dma import *
@@ -226,6 +227,8 @@ class SBusFPGA(SoCCore):
#self.add_sdcard()
self.submodules.trng = NeoRV32TrngWrapper(platform=platform)
def main():
parser = argparse.ArgumentParser(description="SbusFPGA")
parser.add_argument("--build", action="store_true", help="Build bitstream")

View File

@@ -0,0 +1,94 @@
from migen import *
from migen.genlib.fifo import *
from litex.soc.interconnect.csr import *
class NeoRV32TrngWrapper(Module, AutoCSR):
def __init__(self, platform):
self.add_sources(platform)
rden_i = Signal()
wren_i = Signal()
data_i = Signal(32)
data_o = Signal(32)
self.ctrl = CSRStorage(32, description = "CTRL register; bit 0 : disable ; bit 1 : enable")
self.data = CSRStatus(32, description = "Rnd Data or 0")
self.submodules.ctrl_fsm = ctrl_fsm = FSM(reset_state = "Reset")
ctrl_fsm.act("Reset",
NextState("Idle")
)
ctrl_fsm.act("Idle",
If(self.ctrl.re, # someone has written control
If(self.ctrl.storage[0],
data_i.eq(0),
wren_i.eq(1),
).Elif(self.ctrl.storage[1],
data_i.eq(0xffffffff),
wren_i.eq(1),
)
),
If(self.data.we, # someone has read the data, reset so that the same value is never read twice
NextValue(self.data.status, 0),
)
)
# fill out an intermediate buffer, one byte every 11 cycles
# then copy the 4 bytes to data CST and do it all over again
buf = Array(Signal(8) for a in range(4))
idx = Signal(2)
cnt = Signal(4)
self.submodules.upd_fsm = upd_fsm = FSM(reset_state = "Reset")
upd_fsm.act("Reset",
NextValue(cnt, 11),
NextValue(idx, 0),
NextState("ByteWait")
)
upd_fsm.act("ByteWait",
If(cnt == 0,
rden_i.eq(1),
NextState("ByteWrite"),
).Else(
NextValue(cnt, cnt - 1)
)
)
upd_fsm.act("ByteWrite",
If (data_o[31] & data_o[30],
NextValue(buf[idx], data_o[0:8]),
NextValue(cnt, 11),
NextValue(idx, idx + 1),
If(idx == 3,
NextState("Copy"),
).Else(
NextState("ByteWait"),
)
).Else( # try again
NextValue(cnt, 11),
NextState("ByteWait"),
)
)
upd_fsm.act("Copy",
NextValue(self.data.status, Cat(buf[0], buf[1], buf[2], buf[3])),
NextValue(buf[0], 0),
NextValue(buf[1], 0),
NextValue(buf[2], 0),
NextValue(buf[3], 0),
NextState("ByteWait")
)
self.specials += Instance(self.get_netlist_name(),
i_clk_i = ClockSignal("sys"),
i_rden_i = rden_i,
i_wren_i = wren_i,
i_data_i = data_i,
o_data_o = data_o)
def get_netlist_name(self):
return "neorv32_trng"
def add_sources(self, platform):
platform.add_source("neorv32_trng_patched.vhd", "vhdl")