Why this matters
Conventional computing spends most of its energy moving data between memory and a clocked arithmetic unit — the memory wall. Two long-standing but resurgent ideas sidestep it. Stochastic computing represents a number as the probability that a bit in a random stream is 1, so a multiplier becomes a single AND gate. Neuromorphic computing represents information as sparse spikes in time, so a processor only does work when something happens. Both trade exactness for extreme hardware economy — and both map naturally onto FPGAs. The sections below build each idea from the ground up.
Learn the field — from first principles
New here? The learning path is the guided route through all of this, in eight levels — or dive straight into a pillar below.
01Stochastic computing
Encode a number $p\in[0,1]$ as a stream of random bits that are 1 with probability $p$. Then arithmetic becomes almost free in hardware: multiplying two independent streams is a single AND gate, and averaging them is a single multiplexer. You pay for it in precision — a longer stream is a more accurate number.
$$p_{\text{AND}} = p_1 \cdot p_2 \qquad\qquad p_{\text{MUX}} = \tfrac{1}{2}(p_a + p_b) \qquad\qquad \sigma \;\propto\; \frac{1}{\sqrt{N}}$$
Deeper: why AND multiplies, and the accuracy trade-off
For two independent Bernoulli streams, the probability that both bits are 1 at a given position is the product of the individual probabilities, so a bitwise AND produces a stream whose 1-density is $p_1 p_2$ — an exact multiplier with a single gate and no carry chain. The catch is variance: estimating the density from $N$ bits is a binomial mean, so the standard error falls only as $1/\sqrt{N}$. Doubling the precision costs four times the stream length. Real designs manage this with de-correlated random sources (independent LFSRs), stochastic number generators that compare the target value to a pseudo-random number, and formats like bipolar coding for signed values. SC-NeuroCore simulates all of this bit-true against the generated RTL.
02Spiking neural networks
A biological neuron integrates incoming current onto a membrane voltage; when the voltage crosses a threshold it emits a spike and resets. Information lives in when spikes happen, not in dense numbers, so computation is event-driven and sparse. The simplest useful model is the leaky integrate-and-fire (LIF) neuron.
$$\tau_m \frac{dv}{dt} = -(v - E_L) + R\,I(t), \qquad \text{spike if } v \ge v_{\text{th}} \Rightarrow v \leftarrow v_{\text{reset}}$$
Deeper: temporal coding, plasticity, and event-driven energy
Below threshold the membrane relaxes toward its resting potential $E_L$ with time constant $\tau_m$; a steady current above rheobase makes the neuron fire periodically at a rate that grows with the current. Learning is local and spike-timing dependent (STDP): a synapse strengthens when the pre-synaptic spike precedes the post-synaptic one and weakens otherwise, $\;\Delta w = A_+ e^{-\Delta t/\tau_+}$ for $\Delta t>0$ and $-A_- e^{\Delta t/\tau_-}$ for $\Delta t<0$. Because a silent neuron does no work, event-driven hardware toggles far fewer registers than a clocked datapath — SC-NeuroCore's event RTL measures 15–39× fewer toggles. SC-NeuroCore ships 174 neuron models, from LIF to biophysical Hodgkin–Huxley-class and pancreatic β-cell oscillators transcribed from the primary literature.
03Neuromorphic hardware
The point of both ideas is hardware. Stochastic and spiking primitives are cheap to build directly in logic: an AND-gate multiplier, an address-event (AER) spike router, an event neuron that only updates when it receives a spike. The workflow trains a network in a normal deep-learning stack, then lowers it — float → fixed-point → bitstream → Verilog → FPGA.
Deeper: the train-to-hardware lowering, and formal proof
A network is trained in PyTorch with surrogate-gradient spikes, quantised to Q8.8 fixed-point, expanded into stochastic bitstreams driven by deterministic LFSR seeds, then compiled through an IR (with an MLIR/CIRCT path) to SystemVerilog and synthesised for one of several FPGA targets (e.g. iCE40 via Yosys + nextpnr). Because every stage is bit-true, the Python model and the RTL agree cycle-for-cycle, and 72 properties across the HDL modules are formally proved with SymbiYosys. The full pipeline is shown below under Build with SC-NeuroCore.
04Hyperdimensional computing
A related idea represents concepts as very high-dimensional random vectors (e.g. 10 000 bits). Two cheap, reversible operations do the work: binding ties a value to a role (bitwise XOR), and bundling superposes items into a set (element-wise majority). Because random high-dimensional vectors are nearly orthogonal, the representation is robust to noise and bit flips — a natural fit for the same event-driven fabric.
$$\text{bind: } z = x \oplus y \qquad \text{bundle: } s = \mathrm{sign}\!\Big(\sum_i x_i\Big) \qquad \text{similarity: } 1 - \tfrac{d_H(a,b)}{D}$$
Deeper: why high dimension buys robustness
In $D$ dimensions with $D$ large, two independent random $\pm1$ vectors have a normalised dot product concentrated tightly around zero (variance $1/D$), so unrelated symbols are almost orthogonal and a bundle of many items still lets each member be recovered by nearest-neighbour. Binding is its own inverse ($x \oplus y \oplus y = x$), which makes key–value structures and sequences expressible with only XOR, majority and permutation — all single-cycle in hardware. This is why HDC/VSA pairs so well with stochastic and spiking substrates.
05Encoding & primitives
Everything above starts by turning ordinary numbers into streams or spikes. Rate coding maps a value to a spike count; temporal coding puts information in precise timing; a stochastic number generator makes a bitstream by comparing the target value to a pseudo-random number each cycle. These few primitives — encode, integrate, spike, weight — compose into whole networks.
$$b_t = \big[\,r_t < p\,\big], \quad r_t \sim \text{LFSR} \qquad\Rightarrow\qquad \Pr[b_t = 1] = p$$
Deeper: from a value to a bitstream (the SNG)
A stochastic number generator draws a uniform pseudo-random value $r_t$ from an LFSR each cycle and outputs $1$ when $r_t < p$; over many cycles the 1-density converges to $p$. Choosing independent seeds for operands that will be combined keeps their streams de-correlated, which is what makes the AND-multiplier exact. SC-NeuroCore also supports fixed-point and micro-floating-point (MXFP) encodings for the parts of a model that need more precision than a practical stream length affords.
Build with SC-NeuroCore — train-to-hardware pipeline
A documented path from neuron equations through bit-true co-simulation and generated hardware artefacts to supported FPGA synthesis workflows.
PyTorch SNN
Training
6 surrogates, 12 cells
99.49% MNIST
→
→
SC Bitstream
Simulation
bit-true, LFSR
→
IR Compiler
SystemVerilog
+ MLIR/CIRCT
→
127 Analysis Functions
19 HDL Modules + 72 Formal Properties
HDC/VSA (10K-bit)
Rust SIMD Engine (PyO3) | AVX-512 / AVX2 / NEON / SVE / RVV | 174 Neuron Models | NetworkRunner (161 models, Rayon-parallel)
# Install with the Rust SIMD engine
pip install sc-neurocore-engine
# ODE → FPGA in one command
sc-neurocore compile "dv/dt = -(v-E_L)/tau + I/C" \
--threshold "v > -50" --reset "v = -65" \
--params "E_L=-65,tau_m=10,C=1" --init "v=-65" \
--target ice40 --testbench --synthesize