Up one 6502 8 bit PRNG. By Lee Davison. Up to top

Introduction.

This is a short peice of code that generates a maximal length, 8 bit, pseudo random number sequence. This is the 6502 version of Z80 random. A 32 bit 68k version can be found here.

The code.

This routine is no great shakes in the speed stakes, it's just a demo of a usefull technique.


; returns pseudo random 8 bit number in A. Affects A, X and Y.
; (r_seed) is the byte from which the number is generated and MUST be
; initialised to a non zero value or this function will always return
; zero. Also r_seed must be in RAM, you can see why......

rand_8
	LDA	r_seed		; get seed
	AND	#$B8		; mask non feedback bits
				; for maximal length run with 8 bits we need
				; taps at b7, b5, b4 and b3
	LDX	#$05		; bit count (shift top 5 bits)
	LDY	#$00		; clear feedback count
F_loop
	ASL	A		; shift bit into carry
	BCC	bit_clr		; branch if bit = 0

	INY			; increment feedback count (b0 is XOR all the	
				; shifted bits from A)
bit_clr
	DEX			; decrement count
	BNE	F_loop		; loop if not all done

no_clr
	TYA			; copy feedback count
	LSR	A		; bit 0 into Cb
	LDA	r_seed		; get seed back
	ROL	A		; rotate carry into byte
	STA	r_seed		; save number as next seed
	RTS			; done

r_seed
	.byte	1		; prng seed byte (must not be zero)

Other number lengths.
A maximal length pseudo random number generator is basically just a shif register with feedback from the later stages to generate the next input bit. The form for a generator of length n with feedback from t is shown below.
Pseudo random sequence generator.

You don't have to limit the length to only 8 bits, any number of bits from two upwards will work if you chose the right feedback tap(s). Here is a table of some values.

Bits [n] Tap(s) [t] Length Bits [n] Tap(s) [t] Length
21 32
4315  5331 
6563  76127 
86,5,4255  95511 
1071023  1192047 
1211,10,44095  1312,11,88191 
1413,12,216383  151432767 
1615,13,465535  1714131071 
1811262143  1918,17,14524287 
20171048575  21192097151 
22214194303  23188388607 
2423,22,1716777215  252233554431 
2825268435455  2927536870911 
31282147483647     

In the last case, with 31 bits, if you took a new value once a second the sequence wouldn't repeat for over sixty eight years. Even clocked at 1MHz it would still take over thirty five minutes to cycle through every state.

Faster, shorter method.

The above pseudo random number generator is known as a Fibonacci generator and, while it works, it turns out there is a much better generator to implement with a microprocessor.

Galois pseudo random sequence generator.

The Galois generator needs only to test the state of one bit and that can be tested after the shift has been performed. The state of this bit determines whether the feedback term is exclusive ORed with the result. This single bit test and multiple bit feedback is easily done as can be seen from the code below.


; returns pseudo random 8 bit number in A. Affects A. (r_seed) is the
; byte from which the number is generated and MUST be initialised to a
; non zero value or this function will always return zero. Also r_seed		
; must be in RAM, you can see why......

rand_8
	LDA	r_seed		; get seed
	ASL			; shift byte
	BCC	no_eor		; branch if no carry

	EOR	#$CF		; else EOR with $CF
no_eor
	STA	r_seed		; save number as next seed
	RTS			; done

r_seed
	.byte	1		; prng seed byte, must not be zero

You don't have to limit the length to only 8 bits, any number of bits from three upwards will work if you chose the right feedback value. Here is a table of some values that have been chosen to give a feedback value that fits in a byte, this makes implementation on an 8 bit micro as short as possible. For these values bit n is the least significant bit in the value and the tested bit is the bit shifted out from bit 1.

Bits [n] Feedback Length Bits [n] Feedback Length
3$03 4$0315 
5$1731  6$2763 
7$4B127  8$CF255 
9$B7511  10$E71023 
11$EB2047  12$EB4095 
13$BB8191  14$BB16383 
15$DD32767  16$D765535 
17$AF131071  18$E7262143 
19$AF524287  20$F31048575 
21$B72097151  22$BB4194303 
23$F38388607  24$DB16777215 
25$9333554431  26$B167108863 
27$B1134217727  28$E1268435455 
29$C3536870911  30$AF1073741823 
31$8B2147483647  32$AF4294967295 

This is now the form of sequence generator used to generate values for the RND() function in EhBASIC.

"The generation of random numbers is too important to be left to chance."
Robert R. Coveyou.

Last page update: 30th July, 2012. e-mail me