commit the neorv32trgn-based trng
This commit is contained in:
@@ -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) {
|
||||
|
||||
207
NetBSD/9.0/usr/src/sys/dev/sbus/sbusfpga_trng.c
Normal file
207
NetBSD/9.0/usr/src/sys/dev/sbus/sbusfpga_trng.c
Normal 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);
|
||||
}
|
||||
43
NetBSD/9.0/usr/src/sys/dev/sbus/sbusfpga_trng.h
Normal file
43
NetBSD/9.0/usr/src/sys/dev/sbus/sbusfpga_trng.h
Normal 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_ */
|
||||
382
sbus-to-ztex-gateware-migen/neorv32_trng_patched.vhd
Normal file
382
sbus-to-ztex-gateware-migen/neorv32_trng_patched.vhd
Normal 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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
|
||||
94
sbus-to-ztex-gateware-migen/sbus_to_fpga_trng.py
Normal file
94
sbus-to-ztex-gateware-migen/sbus_to_fpga_trng.py
Normal 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")
|
||||
|
||||
Reference in New Issue
Block a user