element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
FPGA
  • Technologies
  • More
FPGA
Blog FPGA: Waves 7: Random Sequence Generator
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join FPGA to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: jc2048
  • Date Created: 10 Nov 2019 11:33 PM Date Created
  • Views 1246 views
  • Likes 5 likes
  • Comments 3 comments
  • xp2
  • experimenting
  • fpga
  • vhdl
  • brevia 2 board
  • lattice
  • noise
  • jc2048
  • random_number_generator
Related
Recommended

FPGA: Waves 7: Random Sequence Generator

jc2048
jc2048
10 Nov 2019

Introduction

 

I have a small Brevia 2Brevia 2 development board from Lattice Semiconductor featuring one of their XP2-family FPGAs. I'm using it to explore, in a very simple, basic kind of way, digital signal generation and processing. These blogs aren't tutorials and there's no structured path to any of it: it's just me experimenting and trying things out.

 

In this blog, I've diverted away from sinewaves and I'm experimenting with random sequences. Not the truly random sort, such as you might get from a natural process like thermal noise or radioactive decay, but a computed sequence that has similar statistical properties to a random one. The two books that got me started on this were 'Seminumerical Algorithms' by Donald Knuth and 'Numerical Recipes In C' by Press, Teukolsky, Vettering, and Flannery.

 

Linear Congruential Generator

 

The generator I'm going to try for here is a simple one given in Numerical Recipes in C, though the multiplier and constant are due to Knuth. The formula is

 

new_random = last_random * 1664525 + 1013904223 (mod 2^32)

 

It's quick because it only involves a multiply and an addition, though I don't really need speed as I'm only generating a sample every 10us.

 

The unsigned multiplier and adder I'll generate with IPExpress. Then it's just a matter of wiring in the constants and picking off the high part of the result to send to the DAC, with the code to send to the DAC just copy-and-pasted from a previous blog. I didn't register the multiplier: I figured that the arithmetic would complete quite easily in the 10us between samples. If you wanted this to run at a fast clock rate, you'd need to look carefully at the timing through the two components.

 

Here's the code, usual caveats apply.

 

------------------------------------------------------------------
--              ***** waves_random_word *****                  --
-- Random number generator                                      --
------------------------------------------------------------------
-- JC 10th November 2019                                        --
------------------------------------------------------------------
-- Rev    Date         Comments                                 --
-- 01     10-Nov-2019                                           --
------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity waves_random_word_con is port(
  clk_in:   in std_logic;        --- system clock in (50 MHz oscillator)
  --- DAC connections
  mcp4821_ncs: out std_logic;        --- DAC cs
  mcp4821_sck: out std_logic;        --- DAC sck
  mcp4821_sdi: out std_logic;        --- DAC sdi
  mcp4821_nldac: out std_logic;        --- DAC load
  --- misc control signals on evaluation board that it might be good to hold at fixed levels
  spi_cs:   out std_logic;        --- 
  hold_n:   out std_logic;        --- 
  sram_cen:  out std_logic;        --- 
  sram_oen:  out std_logic;        --- 
  sram_wen:  out std_logic;        --- 
  uart_tx:  out std_logic);        --- 
 
end waves_random_word_con;
architecture arch_waves_random_word of waves_random_word_con is
signal spi_send, spi_ncs, spi_ncs_del: std_logic;
---signal waveform_count: std_logic_vector (11 downto 0);
signal spi_output_sr_bit_count: std_logic_vector (5 downto 0);
signal spi_output_sr: std_logic_vector (15 downto 0);
signal interval_count: std_logic_vector (8 downto 0);
signal random_value: std_logic_vector (31 downto 0);
signal mult_result: std_logic_vector (63 downto 0);
signal multiplier_value: std_logic_vector (31 downto 0);
signal constant_value: std_logic_vector (31 downto 0);
signal add_result: std_logic_vector (31 downto 0);
--- declare the multiplier and the adder modules as components
component mult_module is
    port (
        DataA: in  std_logic_vector(31 downto 0); 
        DataB: in  std_logic_vector(31 downto 0); 
        Result: out  std_logic_vector(63 downto 0));
end component;
component add_module is
    port (
        DataA: in  std_logic_vector(31 downto 0); 
        DataB: in  std_logic_vector(31 downto 0); 
        Result: out  std_logic_vector(31 downto 0));
end component;
begin
 waves_random_word_stuff: process (clk_in)
  begin
   if (clk_in'event and clk_in='1') then
  
    --- interval_count counts at the clock rate (50MHz)
    --- count divides by 500, so spi_send occurs every 10us (100ksps)
    if (interval_count(8 downto 0) = b"000000000") then     --- if zero
     interval_count(8 downto 0) <= b"111110011";      --- preset to 499
     spi_send <= '1';
    else
     interval_count(8 downto 0) <= interval_count(8 downto 0) - 1; --- count down
     spi_send <= '0';
    end if;
    --- spi ncs goes low when triggered by spi_send, goes hi again when bitcount reaches 31
    
    if (spi_send = '1') then
     spi_ncs <= '0';
    elsif (spi_output_sr_bit_count(5 downto 0) = b"111111") then
     spi_ncs <= '1';
    end if;
    
    spi_ncs_del <= spi_ncs;
    --- spi output bit count only counts when enable spi cs is low
    
    if (spi_ncs = '0') then
     spi_output_sr_bit_count(5 downto 0) <= spi_output_sr_bit_count(5 downto 0) + 1;
    else
     spi_output_sr_bit_count(5 downto 0) <= b"000000";
    end if;
    --- sequence generator
    --- this is storage part
    --- see the instantiated components below for the rest
    if (spi_send = '1') then
     random_value(31 downto 0) <= add_result(31 downto 0);
    end if;
    --- spi output shift register
    
    if (spi_send = '1') then             --- load register...
     spi_output_sr(11 downto 0) <= random_value(31 downto 20);    ---  random data 
     spi_output_sr(15 downto 12) <= b"0011";         ---   dac control bits
    elsif (spi_ncs = '0' and spi_output_sr_bit_count(1 downto 0) = b"11") then --- shift register...
     spi_output_sr(15 downto 1) <= spi_output_sr(14 downto 0);    ---  the register contents
     spi_output_sr(0) <= '0';
    end if;
   end if;
   
   --- generator control parameters
   
   multiplier_value <= b"00000000000110010110011000001101";
   constant_value <=  b"00111100011011101111001101011111";
   --- connecting various signals to output pins
   
   mcp4821_ncs <= spi_ncs;
   mcp4821_sck <= spi_output_sr_bit_count(1);
   mcp4821_sdi <= spi_output_sr(15);
   mcp4821_nldac <= '0';
  
   --- hold these device control pins at a fixed level to stop them flapping around
   spi_cs <= '1';
   hold_n <= '1';
   sram_cen <= '1';
   sram_oen <= '1';
   sram_wen <= '1';
   uart_tx <= '1';
  end process waves_random_word_stuff;
 
  --- instantiate the multiplier and the subtractor for the oscillator
  --- and make the signal connections
  
  mult_module1: mult_module
   port map(
    DataA => multiplier_value(31 downto 0),
    DataB => random_value(31 downto 0),
    Result => mult_result(63 downto 0));
    
  add_module1: add_module
   port map(
    DataA => constant_value(31 downto 0), 
    DataB => mult_result(31 downto 0), 
    Result => add_result(31 downto 0));
end arch_waves_random_word;

 

Here's how the output looks. The blue trace is the DAC output, the yellow the filter output. The filtered output is delayed somewhat [which, of course, is inevitable with an analogue filter].

 

image

 

Here's how multiple, accumulated traces look; away from the trigger point, that looks quite satisfyingly noisy.

 

image

 

Here it is on a longer trace

 

image

 

Finally, here's the best the 'scope can manage in the way of an FFT. This is accumulated over several seconds. The cut-off of the reconstruction filter is somewhere close to the centre of the screen, so the noise is roughly tracing out its response for me [roughly because the sin x/x response of the zero-order hold of the DAC will also be mixed in with it].

 

image

 

Below the cut-off, the spectrum is reasonably level, so there the numbers I'm generating approximate to 'white' noise.

 

That was very quick and easy to do. It doesn't take many slices but it's quite expensive in one respect because it uses up one DSP block to build the 32 x 32 multiplier.

 

Trade Offs

 

Here is the floor plan using the hard multiplier in the DSP block (the 36x36 multiplier is the turquoise block).

   MULT36             1/3            33% used
   SLICE             49/2376          2% used

 

 

image

 

This, in contrast, is the floorplan if I ask IPExpress to build the multiplier from slices.

   SLICE            336/2376         14% used

 

image

 

Conclusion

 

That was an interesting little diversion on my journey. Now I've got to decide whether to go back to CORDIC routines or continue investigating noise.

Associated blogs:

FPGA: Making Waves
FPGA: Waves 2: Simple Sinewave
FPGA: Waves 3: Computed Sinewave Oscillators
FPGA: Waves: 4 Tinker, Taylor, Soldier, Sine
FPGA: Waves: 5 CORDIC Sine

FPGA: Waves 6: Reconstruction Filter

 

  • Sign in to reply

Top Comments

  • neuromodulator
    neuromodulator over 5 years ago +2
    There are techniques to perform true random number generation on FPGAs, if you want to continue exploring RNGs.
  • neuromodulator
    neuromodulator over 5 years ago +2
    When I learned about meta-stability I thought that maybe it could be used to generate a TRNG. After googling a bit I found that there are indeed approaches that use meta-stabiliy to build TRNG, but there…
  • jc2048
    jc2048 over 5 years ago in reply to neuromodulator +1
    What were you thinking of? I had thought of doing a crypto-style hash (which obviously has to have good statistical properties), but that would still be pseudo random.
Parents
  • neuromodulator
    neuromodulator over 5 years ago

    When I learned about meta-stability I thought that maybe it could be used to generate a TRNG. After googling a bit I found that there are indeed approaches that use meta-stabiliy to build TRNG, but there are other approaches as well. Here are some random links that I found:

     

    https://www.esat.kuleuven.be/cosic/publications/thesis-307.pdf

    https://www.esat.kuleuven.be/cosic/publications/article-790.pdf

    https://people.csail.mit.edu/devadas/pubs/ches-fpga-random.pdf

    http://eprints.whiterose.ac.uk/103707/1/Camera_ready.pdf

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • neuromodulator
    neuromodulator over 5 years ago

    When I learned about meta-stability I thought that maybe it could be used to generate a TRNG. After googling a bit I found that there are indeed approaches that use meta-stabiliy to build TRNG, but there are other approaches as well. Here are some random links that I found:

     

    https://www.esat.kuleuven.be/cosic/publications/thesis-307.pdf

    https://www.esat.kuleuven.be/cosic/publications/article-790.pdf

    https://people.csail.mit.edu/devadas/pubs/ches-fpga-random.pdf

    http://eprints.whiterose.ac.uk/103707/1/Camera_ready.pdf

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube