Generating a Random Number

copyright, Peter H. Anderson, Dept of Electrical Enginnering,
Morgan State University, Baltimore, MD 21239, August 9, '97

Introduction.

This discussion presents a simple algorithm for generating a 16-bit random number.

Any part of this 16-bit number may be used for random processes. For example, if only a "coin flip" is desired, any single bit may be used. If it is desired to generate a random number in the range 0, 1, 2 or 3, then any two bits may be used. In this application, random numbers in the range of 0 - 255 were desired and thus only eight of the 16 bits are used.

For applications where a random number in the range of 0-9 is desired, one might use ten bits (0 - 1023) of the 16-bit random number and simply divide by 102. Another possibility would be to simply count the number of ones occuring in nine of the 16-bits.

The Algorithm.

Consider a 16-bit shift register consisting of bytes RAND_HI and RAND_LO. Consider external circuitry which exclusive ors bits RAND_HI.7, RAND_HI.6, RAND_HI.4 and RAND_LO.3 together to produce a feedback bit. A new random number is generated by shifting this 16-bit quantity to the left and then inserting the feedback bit in RAND_LO.0.

This is implemented in routine RANDOM in the following program.

Bit RAND_HI.7 is used to generate the feedback bit. If RAND_HI.6 is a logic one, RAND_HI is exclusive ored with 80H. However, if RAND_HI.6 is a logic zero, RAND_HI is exclusive ored with 00H. Thus RAND_HI.7 is now RAND_HI.7 XOR RAND_HI.6. Note that all other bits in RAND_HI are unchanged.

This process is continued for bits RAND_HI.4 and RAND_LO.3.

Thus, the feedback bit is now in bit RAND_HI.7. This is rotated into the carry without modifying RAND_HI by executing;

	RLF RAND_HI, W

A two byte shift is then executed;

	RLF RAND_LO, F	; feedback bit no in RAND_LO.0
			; C contains former ms bit of RAND_LO
	RLF RAND_HI, F	; former ms bit of RAND_LO now in ls bit of 
			; RAND_HI  

Note that there is a problem with this 16-bit "ring counter" implementation in that if the value is 0000, the next and all subsequent values will also be zero. Thus, this condition is tested in the RANDOM routine and if it is at 0000H, the value is modified to 00FF.

In the program, a call is made to RANDOM. The high byte, RAND_HI is output to eight discrete LEDs on PORTB. The low byte, RAND_LO is used for a delay of 10 - 2560 msecs.

; Program RANDOM.ASM
;
; Illustrates an implementation of a 16-bit random number generator.
;
; Assumes 8 LEDs on PORTB.  A random pattern is displayed for a random
; amount of time.  Continuous loop.
;
; copyright, Peter H. Anderson, MSU, August 9, '97

	LIST p=16c84
#include <c:\mplab\p16c84.inc>	
	__CONFIG 11h

	CONSTANT BASE_VAR=0CH

LOOP3	EQU BASE_VAR+0		; for timing
LOOP2	EQU BASE_VAR+1
LOOP1	EQU BASE_VAR+2

RAND_HI EQU BASE_VAR+3		; 16-bit random number
RAND_LO EQU BASE_VAR+4

MAIN:
	BSF STATUS, RP0
	CLRF TRISB		; all bits on PORTB are outputs
	BCF STATUS, RP0
MAIN_1:
	CALL RANDOM		; generate 16-bit random number
	MOVF RAND_HI, W		; use high byte as random pattern
	MOVWF PORTB
	MOVF RAND_LO, W		; use low byte as random delay
	MOVWF LOOP3
	CALL DELAY
	GOTO MAIN_1		; repeat indefinitely

RANDOM:
	MOVF RAND_HI, W		; if current random is 0000, make it 00FFH
	IORWF RAND_LO, W
	BTFSC STATUS, Z
	COMF RAND_LO, F	

	BTFSS RAND_HI, 6	; hi.7 = hi.7 xor hi.6
	MOVLW 00H
	BTFSC RAND_HI, 6
	MOVLW 80H
	XORWF RAND_HI, F  

	BTFSS RAND_HI, 4	; hi.7 = hi.7 xor hi.4
	MOVLW 00H
	BTFSC RAND_HI, 4
	MOVLW 80H
	XORWF RAND_HI, F  

	BTFSS RAND_LO, 3	; hi.7 = hi.7 xor lo.3
	MOVLW 00H
	BTFSC RAND_LO, 3
	MOVLW 80H
	XORWF RAND_HI, F  

	RLF RAND_HI, W		; carry = hi.7
	RLF RAND_LO, F		; double left shift
	RLF RAND_HI, F

	RETURN

DELAY:		; delays loop3 * 10 msecs

	MOVLW .10		; 10 msecs
	MOVWF LOOP2
DELAY_1:
	MOVLW .110
	MOVWF LOOP1
DELAY_2:
	NOP
	NOP	
	NOP
	NOP
	NOP
	NOP
	DECFSZ LOOP1, F
	GOTO DELAY_2
	DECFSZ LOOP2, F
	GOTO DELAY_1
	DECFSZ LOOP3, F
	GOTO DELAY
	RETURN

	END