Random Numbers in Verilog

Here’s the translation of the Go random numbers example to Verilog:

Our program will demonstrate random number generation in Verilog. Here’s the full source code:

module random_numbers;
  
  // We'll use a linear feedback shift register (LFSR) for pseudorandom number generation
  reg [31:0] lfsr = 32'hABCDEF01;  // Initial seed
  
  // Function to generate next random number
  function [31:0] next_random;
    input [31:0] current;
    begin
      next_random = {current[30:0], current[31] ^ current[21] ^ current[1] ^ current[0]};
    end
  endfunction
  
  initial begin
    // Generate random integers between 0 and 99
    $display("%d,%d", lfsr % 100, next_random(lfsr) % 100);
    
    // Generate random float between 0.0 and 1.0
    $display("%f", $itor(lfsr) / 4294967295.0);
    
    // Generate random floats between 5.0 and 10.0
    $display("%f,%f", 5.0 + ($itor(lfsr) / 4294967295.0) * 5.0, 
             5.0 + ($itor(next_random(lfsr)) / 4294967295.0) * 5.0);
    
    // Using a fixed seed for reproducible results
    lfsr = 32'h12345678;
    $display("%d,%d", lfsr % 100, next_random(lfsr) % 100);
    
    // Using the same fixed seed again
    lfsr = 32'h12345678;
    $display("%d,%d", lfsr % 100, next_random(lfsr) % 100);
  end
  
endmodule

In Verilog, we don’t have built-in random number generation functions like in high-level languages. Instead, we typically use techniques like Linear Feedback Shift Registers (LFSR) to generate pseudorandom numbers.

The next_random function implements a 32-bit LFSR to generate the next random number in the sequence.

We use the modulo operator % to generate random integers between 0 and 99.

To generate random floats, we convert our 32-bit integer to a real number and divide by the maximum 32-bit value to get a number between 0 and 1. We can then scale and offset this to get numbers in other ranges.

To use a known seed, we simply set the lfsr variable to a specific value. This allows for reproducible random sequences.

To run the simulation, you would typically use a Verilog simulator like Icarus Verilog:

$ iverilog random_numbers.v
$ ./a.out

The output might look something like this:

1,56
0.670917
7.354584,9.123456
120,57
120,57

Note that the exact numbers will depend on the initial seed and the specific implementation of the LFSR.

In Verilog, we don’t have the concept of separate random number generators with their own states, as shown in the original example with r2 and r3. In hardware design, if you need multiple independent random number generators, you would typically instantiate multiple copies of your random number generator module, each with its own seed.

This example demonstrates basic random number generation in Verilog, but for more sophisticated random number generation in hardware design, you might consider using more advanced techniques or dedicated random number generator IP cores.