Generate Pseudo-random Numbers Using LFSR

When performance is critical, it is essential to avoid even the slightest overhead.

I’ve recently had the chance to implement a test facility scanning through the DRAM unit on various devices to be used by the hardware team in testing if the DRAM can function properly in extreme temperatures. The test is very simple, just involving writing on each block of the memory and then reading back to confirm whether the data remains intact. Generating a sequence of pseudo-random addresses seemed best suited for this kind of task to ensure good coverage of each part of the memory.

Due to the need to traverse through a very large number of blocks in a reasonably short time frame, an efficient algorithm that could utilize the specific underlying hardware would be most desired. And so, here comes LFSR.

LFSR stands for linear feedback shifting register. It is a shift register whose input bit is a linear function of its previous state, quoted from Wikipedia. Its applications include digital counters, pseudo-noise sequences, pseudo-random numbers, etc.

Picture Depicting How LFSR Works
How Does Conventional LFSR Work [Wikipedia]
A four bit LFSR counter, as shown above, can be implemented by having the next state as the result of an XOR of the right most two bits from the current state.

The range of our devices that require this memory test houses a certain type of Xilinx DRAM on board, which employs a LFSR address counter. Xilinx’s documents claim that this type of counter is more efficient than others and as I’m not all too familiar with hardware, I will just take their words.

As mentioned earlier, the test needed to traverse through most of the DRAM in an as close to random as possible fashion. Since the requirement was to write double word size values onto the DRAM and later read them back to verify if the memory remains intact, the number of blocks the test facility needed to traverse would be enormous. Thus, an as efficient as possible algorithm for generating a long sequence of addresses which must come as random as possible but at the same time must be predictable as the values  written now would be retrieved later for verification. LFSR makes a perfect choice here. It can easily generate a large sequence of pseudo-random numbers, and in this case, as the DRAM actually uses a LFSR counter for addressing, the overall performance should benefit even more from the algorithm.

So, how does one generate pseudo-random numbers using LFSR? Since the performance is key to the test facility, an algorithm that requires as fewer processor cycles and as cheap an operating as possible. The following C code, modified based on the one from wikipedia, demonstrates a possible approach.

unsigned long lfsr_mask = 0x300000u;
unsigned long start = 0x00000000;
unsigned long end = 0x10000000;
unsigned long rand_addr = 1u;    // pseudo-random address
do {
    // obtain least significant bit
    unsigned long rand_addr_lsb = rand_addr & 1u;
    // shift register
    rand_addr >>= 1;
    // only apply mask if output bit is 1
    if (rand_addr == 1)
        rand_addr ^= lfsr_mask;

    unsigned long addr = start + rand_addr;
    // Ensure address is aligned properly.
    if ((addr & (sizeof(unsigned long) - 1)) == 0) {
        /*... Do stuff with addr ...*/
    }
}
while (rand_addr != 1u);

A more optimized version of the while loop may look like the following.

do {
    // -(rand_addr & 1u), the negation here ensures that the lfsr_mask
    // is only applied when rand_addr & 1u is 1, as the two's complement
    // of 1 is 0xFFFFFFFF here.
    // Note: rand_addr & 1u can only give either 1u or 0, so its negation
    //       is either all 1's or all 0's.
    rand_addr = (rand_addr >> 1) ^ (-(rand_addr & 1u) & lfsr_mask);
}
while (rand_addr != 1u);

In short, this approach is good for the purpose of the DRAM since we can control how long of a sequence of non-repeated addresses get generated and it is faster on the type of address counter we have for the DRAM.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s