Keysight EDA 2025 Event
WP_Term Object
(
    [term_id] => 106
    [name] => FPGA
    [slug] => fpga
    [term_group] => 0
    [term_taxonomy_id] => 106
    [taxonomy] => category
    [description] => 
    [parent] => 0
    [count] => 339
    [filter] => raw
    [cat_ID] => 106
    [category_count] => 339
    [category_description] => 
    [cat_name] => FPGA
    [category_nicename] => fpga
    [category_parent] => 0
)

Pseudo random generator tutorial in VHDL (Part 1/3)

Pseudo random generator tutorial in VHDL (Part 1/3)
by Claudio Avi Chami on 09-04-2016 at 7:00 am

In this tutorial we will see how to design a VHDL block. We will start with a very simple block and we will gradually add features to it. We will also simulate it and test its output with Matlab. Over the process we will see:

  • How to start a design with a simple block and gradually add features and improvements
  • How to add a test bench (for simulation)
  • Adding parameters to the VHDL block
  • Saving the block data output to files (from simulation)
  • Exporting the files to Matlab in order to:

    • Verify the results (Formal testing), and
    • Analyze the results (in this case, using FFT)

For this tutorial it is assumed that you already have basic knowledge of the VHDL language and know how to use simulation tools (Modelsim will be used, but you can easily adapt the tutorial to other tools you may be familiar with).

Chapter 1 – Initial implementation
We are going to generate random numbers by Hardware. One popular way of generating pseudo-random numbers in HW is by means of an LFSR. LFSR stands for Linear-Feedback Shift Register.

The input bit to the shift register of the LFSR is a linear function of its previous value. The theory used to generate these sequences is based on linear algebra, where the register is interpreted as a polynomial. Each bit in the register is the coefficient of order ‘n’ of such a polynomial.

A register of length n can generate a pseudo-random sequence of maximum length 2[SUP]n[/SUP]-1. There are ‘recipes’ for the linear feedback function needed to generate maximum length sequences for any register length. See the references at the end of the article for more details.

So let’s see our first version of a pseudo-random generator written in VHDL.
For this first example, the polynomial order is very low, i.e. 3 (the shift register has 4 bits), which generates an optimum sequence consisting of 15 values. When we simulate the LFSR, if we keep running the simulation, these 15-values pseudo-random sequence will repeat indefinitely.

That is the reason that these sequences are called pseudo-random. They have a certain variability, but on the other hand, they are repetitive, and even if they are not a trivial sequence, they always will be the same sequence. After the number ‘3’ in this sequence, we will always get the number ‘7’. Of course a real random number does not behave in this way. But we will see later that even with this limitation, pseudo-number sequences can approximate quite well the behavior of white noise.

[CODE]
library ieee;
use ieee.std_logic_1164.all;

entity lfsr1 is
port (
reset : in std_logic;
clk : in std_logic;
count : out std_logic_vector (14 downto 0) — lfsr output
);
end entity;

architecture rtl of lfsr1 is
signal count_i : std_logic_vector (14 downto 0);
signal feedback : std_logic;

begin
feedback <= not(count_i(14) xor count_i(13)); — LFSR size 4

process (reset, clk)
begin
if (reset = ‘1’) then
count_i ‘0’);
elsif (rising_edge(clk)) then
count_i <= count_i(13 downto 0) & feedback;
end if;
end process;
count <= count_i;

end architecture;
[/CODE]

Early VHDL versions didn’t support reading back outputs, that’s why I use count_i as a working signal, which at the end of the block is copied to the output count.

I always use this convention (suffix “_i” for internal signals) and you may want to adopt these and other conventions (like using the ‘_n’ suffix for active low signals) for code clarity and standardization.
The process implements a shift register. The feedback input to the shift register is a linear combination of some of its own bits.

Chapter 2 – Adding a test-bench
Now let’s examine the test-bench for the LFSR we have just created:

[code]
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
use ieee.numeric_std.ALL;
use std.textio.all;

entity tb_lfsr1 is
end entity;

architecture test of tb_lfsr1 is

constant PERIOD : time := 20 ns;

signal clk : std_logic := ‘0’;
signal reset : std_logic := ‘1’;
signal count : std_logic_vector (14 downto 0);
signal endSim : boolean := false;

component lfsr1 is
port (
reset : in std_logic;
clk : in std_logic;
count : out std_logic_vector (14 downto 0)
);
end component;

begin
clk <= not clk after PERIOD/2;
reset <= '0' after PERIOD*10;
endSim <= true after PERIOD*8000;

— End the simulation
process
begin
if (endSim) then
assert false
report “End of simulation.”
severity failure;
end if;
wait until (clk = ‘1’);
end process;

lfrs1_inst : lfsr1
port map (
clk => clk,
reset => reset,
count => count
);
end architecture;
[/code]

A test-bench is always an entity with no ports, that instantiates the device under test (DUT) as a component. The test-bench has signals that are used to exercise the block under test:

  • A 50MHz (20 nsec period) clock.
  • The reset signal which is asserted at the beginning of the test and de-asserted after some time (PERIOD*10).


This block is so simple that it is enough to provide a clock and de-assert reset to get it going.

The process checks the endsimsignal and stops the simulation after some time. In this way, the simulation can be run with the run -all command and will stop by itself.

Let’s see two screenshots of the simulation:



The signal looks (remotely) as a noise signal. It doesn’t look so well since the sequence we used, of only fifteen steps, is very short. We can see that the signal repeats itself each 15 clock cycles. On next entries of this tutorial we will see how to improve the signal.

On the following waveform we can see with more clarity a single cycle with all the 15 values of the output signal:



On the following chapters we will improve this basic code, export the output data of the simulation to files, and analyze this output data with Matlab. See you again!

References
LFSR design – Xilinx application note
Pseudo random generator tutorial part 2
Pseudo random generator tutorial part 3

My blog:
FPGA Site

P.S. The source files are attached as .txt files. Rename the suffix as .vhd to synthesize or simulate.

Share this post via:

Comments

There are no comments yet.

You must register or log in to view/post comments.