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

Pseudo random generator tutorial in VHDL (Part 2/3)
by Claudio Avi Chami on 09-04-2016 at 12:00 pm

In the first part of this tutorialwe started with a simple implementation of an LFSR block (Chapter 1) and its test bench (Chapter 2). Let’s make our code look a bit more professional.

Chapter 3 – Upgrading the LFSR code

Good code doesn’t use hard-coded constants as were used on the first part (to define the LFSR width). The downside of using constants is that code updates and maintenance is cumbersome at best. If we want to change the width of the register… we must scan the code and change each and every instance of the constant. There is a great possibility of making mistakes while doing that. Forgetting to change one of the ‘3’s… or changing one that was not related to the register width.

This is not obviously seen in a short piece of code, but as our code gets longer, maintaining hard-coded constants is a sure recipe for trouble.

Instead of using hard-coded constants, it is preferable to use symbols that represent those constant values.
VHDL gives us many ways of defining constants. We can define it in the architecture body, we can define them as GENERICS, or we can define them in a predefined package. In this tutorial we will use this last option.

This new version (v1.1) of the pseudo-random generator includes a predefined constants package (at this stage it contains only one constant), as shown below:

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

package lfsr_pkg is
constant LFSR_W : natural := 11; — LFSR width

end lfsr_pkg;
[/CODE]

Besides the usage of constants in a package, the following features were introduced in this version:

[LIST=1]

  • Addition of a clock enablesignal. The clock enable is usually coded as a conditional block (IF without ELSE) on the synchronous part of a process. Clock enable signals give the FPGA the capability to process signals with change rate slower than that of the clock itself. When clock enable is high, the input is sampled and presented at the output on the rising edge of the clock. When clock enable is low, the FFs of the register keep the last input value sampled.
  • The register size is enlarged (11 bits). The feedback logic was changed to adapt to this new register size. We will see that after this change the output signal looks much more like white noise.


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


    entity lfsr1_1 is
    port (
    reset : in std_logic;
    clk : in std_logic;
    enable : in std_logic; — Enable shifting
    count : out std_logic_vector (LFSR_W-1 downto 0) — lfsr output
    );
    end entity;


    architecture rtl of lfsr1_1 is
    signal count_i : std_logic_vector (LFSR_W-1 downto 0);
    signal feedback : std_logic;


    begin
    feedback <= not(count_i(LFSR_W-1) xor count_i(LFSR_W-3)); — LFSR size 11


    process (reset, clk)
    begin
    if (reset = ‘1’) then
    count_i ‘0’);
    elsif (rising_edge(clk)) then
    if (enable = ‘1’) then
    count_i <= count_i(LFSR_W-2 downto 0) & feedback;
    end if;
    end if;
    end process;

    count <= count_i;


    end architecture;

    [/CODE]

    Notes:

    a- If you look carefully at the waveform below, you will be able to see that this signal is also periodic. However, its period is much longer than that of the block analyzed in chapters 1 and 2.

    b- As an exercise (and before you read the next chapter), you can try to change the test bench for this new version. It can be verified that the new sequence has 511 values, so the period of this pseudo random signal is 10220ns (clk is 50MHz => 20ns for each value x 511 values)

    Chapter 4 – Saving the simulation data output to a file

    In this chapter we will see how to update our test bench to include the changes done on Chapter 3, but we will also add data saving capabilities. In this way we can:

    • Compare the VHDL data output with data generated by our reference design (in our case, a Matlab algorithm)
    • Analyze the data output with other tools (again, in our case, we will use Matlab to produce FFT analysis of the block output).


    If you still didn’t make the changes of the test bench for Chapter 3 by yourself, do not continue reading. Try doing those changes first.


    On the following paragraphs I have put only the changes on the code from previous versions. At the end of this chapter you will be able to find a link to the complete files with all the code.

    On the test bench, a new process was added for data saving. Here is the code fragment which includes this new process:

    [CODE]— Save data to file
    process
    file file_id: text;
    variable line_num: line;
    variable cnt: integer := 0;
    begin
    — Open the file
    file_open(file_id, log_file, WRITE_MODE);
    wait until (enable = ‘1’);
    wait until (clk = ‘1’);

    — Loop and write all values to a file
    for cnt in 0 to 2047 loop
    write(line_num, to_integer(unsigned(count)) );
    writeline(file_id, line_num);
    wait until (clk = ‘1’);
    end loop;

    file_close(file_id);
    endSim <= true;
    wait until (clk = ‘1’);

    end process;
    [/CODE]

    First part of the process: Open a file for data saving. Wait until enable and clkare asserted.

    Data writing loop: The data is converted to unsigned, then to integer (*), and then it is written to a “line”. The “line” is then written to the file. One write is done for each clock rising flank.

    After the loop is completed: Close the data archive. Activate the endSim flag that finishes the simulation run.

    (*) VHDL supports algebraic operations over std_logic_vector signals. But first it has to know how to interpret the vector, either as signed or unsigned.

    The test bench dumps the output data to a file called res.log. The file begins like this:
    [CODE]0
    1
    3
    7
    15
    31
    63
    127[/CODE]

    … and as it was expected, it has 2047 entries until it repeats itself. In the next chapter we will see how to check these values using Matlab.

    References
    LFSR design – Xilinx application note
    Signed and unsigned in VHDL
    Pseudo random generator tutorial part 1
    Pseudo random generator tutorial part 3

    My blog:
    FPGA Site

    P.S. The files for chapters 3 and 4 are available below. Please rename the .txt extension to .vhd prior to simulation or synthesis