A field-programmable gate array (FPGA) is an integrated circuit (IC) that lets you implement custom digital circuits. You can use an FPGA to create optimized digital logic for things like digital signal processing (DSP), machine learning, and cryptocurrency mining. Because of the FPGA’s flexibility, you can often implement entire processors using its digital logic. You can find FPGAs in consumer electronics, satellites, and in servers used to perform specialized calculations.
In this series, we will see how an FPGA works and demonstrate how to create custom digital logic using the Verilog hardware description language (HDL).
Previously, we showed how to create finite state machines in Verilog and deploy them to our FPGA (https://youtu.be/pK6XN7sFosI). In this episode, we demonstrate how to write modules in Verilog and use parameters to make hierarchical designs.
The solution to the challenge at the end of the episode can be found here: https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-6-verilog-modules-and-parameters/c7d4d01274be43278d8bc531e6b7acb7
All code examples and solutions for this series can be found here: https://github.com/ShawnHymel/introduction-to-fpga
A module in Verilog is similar to a function or class in programming languages. It allows you to reuse code without needing to copy-and-paste parts of your design. In addition, you can create hierarchical designs that are often easier to diagram and understand from a high-level perspective.
We demonstrate how to create a module out of our clock divider code from a previous episode. This code is wrapped in a module header so that we can instantiate it in another module. Note that it’s often considered good practice to have one module per file.
We also introduce the concept of parameters. Unlike the “defparam” keyword, the “parameter” keyword allows the instantiating code to change values and functionality within the instantiated module. For example, instead of using a static MAX_COUNT value that creates the same clock divider every time, we turn MAX_COUNT into a parameter. This allows the instantiating code to change how much the module divides the input clock by.
In addition, we demonstrate how to use a variable bit-width value as a parameter. The instantiating code can change COUNT_WIDTH, which changes how many bits are used for the counter in the clock divider module.
Finally, we create a top-level design that instantiates two different versions of the module to blink LEDs at different rates (by setting the parameters for each divider module differently).
We show how to define parameters using the 1995 version of Verilog as well as the more common ANSI-style introduced in the 2001 version.
Your challenge is to create a design that continuously counts up and down (alternating between counting up from 0x0 to 0xF and down from 0xF to 0x0). You are to use modules to accomplish this goal. Note that you are welcome to use the clock divider code and counter code from this and previous episodes as a starting point.
Related Project Links:
Related Project Links:
Maker.io – https://www.digikey.com/en/maker
Digi-Key’s Blog – TheCircuit https://www.digikey.com/en/blog
Connect with Digi-Key on Facebook https://www.facebook.com/digikey.electronics/
And follow us on Twitter https://twitter.com/digikey