
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
