For anyone interested, here's my little python script for simulating bit truncation:

`import numpy as np`

# test truncation/rounding on a sequence of numbers with random values

divs = [2, 4, 8, 16] # test with these divisors

methods = ['ceil', 'round'] # test with these truncation methods

Xlength = 128 # length of each sequence

Niter = 32 # number of iterations to perform, each on a different X

Xrms = 64 # RMS of noise X

# pre allocate saved data

Xall = np.zeros((Niter, Xlength))

Yall = np.zeros_like(Xall)

Xmean = np.zeros((Niter, 1))

Ymean = np.zeros_like(Xmean)

# generate Niter random X sequences

for idx in range(Niter):

X = np.random.normal(loc=0.0, scale=Xrms, size=Xlength)

X = np.round(X)

Xall[idx, :] = X + 4 * Xrms # offset so X is always positive

for div in divs:

for method in methods:

for idx in range(Niter):

# get pseudorandom X

X = np.squeeze(Xall[idx, :]).copy()

# choose truncation method and calculate output Y

if method == 'floor':

Y = np.floor(X/div)*div

elif method == 'ceil':

Y = np.ceil(X/div)*div

elif method == 'round':

# add a tiny bit to X before rounding, to avoid wrong result due to float precision

Y = np.round(X/div+Xrms*1e-6)*div

# save Y to Yall

Yall[idx, :] = Y

# save mean of X and Y

Xmean[idx] = np.mean(X)

Ymean[idx] = np.mean(Y)

# get mean error Emean (the "DC bias")

Emean = np.mean(Ymean-Xmean)

# AC RMS of Y (ignores DC component)

Yacrms = (np.mean((Yall-np.mean(Ymean))**2))**0.5

# get the AC RMS error between Y and X (ignores DC bias)

Eacrms = (np.mean((Yall-Emean-Xall)**2))**0.5

# print results

print('div={0}, method={1}, Emean={2:.3f}, Yacrms={3:.3f}, Eacrms={4:.3f}'.format(div, method, Emean, Yacrms, Eacrms))

print('done')

Here's the output:

`div=2, method=ceil, Emean=0.509, Yacrms=64.009, Eacrms=0.500`

div=2, method=round, Emean=0.509, Yacrms=64.009, Eacrms=0.500

div=4, method=ceil, Emean=1.505, Yacrms=64.031, Eacrms=1.117

div=4, method=round, Emean=0.493, Yacrms=64.016, Eacrms=1.116

div=8, method=ceil, Emean=3.455, Yacrms=64.132, Eacrms=2.271

div=8, method=round, Emean=0.562, Yacrms=63.970, Eacrms=2.283

div=16, method=ceil, Emean=7.477, Yacrms=64.255, Eacrms=4.559

div=16, method=round, Emean=0.383, Yacrms=64.258, Eacrms=4.659

done

So the benefit of rounding vs ceil/floor truncation is clear when looking at Emean (the DC bias). The truncation method doesn't seem to impact the output noise level at all (Yacrms).

Note that these results are with the input noise level well above the quantization threshold (64LSB in this case), as would be expected at the output of an un-optimized decimation filter.