Modelsim Altera running an LFSR simulation
On the first part of this tutorial, we started with a simple implementation of an LFSR block (Chapter 1) and it test bench (Chapter 2). Let’s make our code 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 clearly 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 that 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. 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 is only one), as shown below:
Besides the usage of constants and package, the following features were introduced in this version:
- Addition of a clock enable signal. The clock enable is usually coded as a loop (IF without ELSE) on the synchronous part of our code (lines 36 to 38). Clock enable signals enable the FPGA 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. It can be seen that now the output signal looks much more like white noise.
a- If you look with care, 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 50MHz x 20ns for each value)
The sources for this chapter are available here.
Chapter 4 – Saving the simulation data output
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 to do the changes first.
On the following paragraphs I will only put the changes on the code from previous versions. At the end of a chapter you will be able to find a link with the complete files with all the code.
On the test bench, a new process was added for data saving. Here is the code fragment including this new process. The line numbers correspond to the complete file (tb_lfsr1_1.vhd):
Lines 67 to 69: Open a file for data saving. Wait until enable and clk are asserted.
72 to 76: 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.
78 – 80: 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. For more details, please refer to Signed, unsigned and std_logic_vector.
The test bench dumps the output data to a file called res.log. The file begins like this:
… 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.
These are the changes from tb_lfsr1 to tb_lfsr1_1, by line number:
19: data output filename
23, 31, 40, 57: added support for the new signal, i.e. enable
61 a 83: new process for data saving to file
The test bench for this chapter is available here.