Learning Verilog itself is not a difficult task, but creating a good design can be. But we focus on simple designs here and I will try my best to explain things as simple as possible.
If you had been programming with procedural languages such as C, C++, you will have to make up your mind to understand that not all things happen sequentially in the digital world. A lot of things happen parallel too. When I started learning Verilog, I used to write code sequentially as if I was writing a C program. C programs are running on microprocessors, which execute one instruction at a time sequentially. So it is easy to write a program in a way how you want things to happen one step at a time.
And if you look closely, this is the weak point of microprocessors / microcontrollers.
They can do only one thing at a time, one and only one thing (of course I’m talking about single core devices!). But unlike microprocessors, digital circuits (FPGAs, CPLDs, and ASICs) can do many things at the same time. And you need to learn how to visualize many things happening at the same time in contrast to many things happening at different times, one thing at a time, in a procedural language.
A Verilog module is a design unit similar to a black-box, with a specific purpose as engineered by the RTL designer. It has inputs, outputs and it functions as per its intended design. A simplest Verilog module could be a simple NOT gate, as shown in the second image below, whose sole job is to invert the incoming input signal. There is no upper bound on the complexity of the Verilog modules, they can even describe complete processor cores! Verilog deals with digital circuits.
In Verilog realm, modules can be considered as equivalent to components in a digital circuit, as simple as a gate or a complex entity like ALU, counter, etc… Modules are analogous to classes in C++ in a way that it is self-contained and give a finite number of methods (ports) to interact with the external world.
Modules can be instantiated like classes are instantiated in C++ too. But beware; modules are not 100% similar to classes when it is implemented. For easy understanding, a module can be simply represented graphically as a box with a number of ports.
The ports can be inputs, outputs or bidirectional. Ports can be single bit or multiple bits in width. The image below represents a module with a few inputs and outputs. The number of inputs and outputs, their width and direction will depend solely on the functionality of the module.
Fundamentally Verilog (or most HDLs for that matter) is all about creating modules, interconnecting them and managing the timing of interactions.
Enough talk, we didn’t even write a “Hello World” program yet. So how do we get our hands dirty with Verilog? Let us design a NOT gate in Verilog, simulate it and test it in real hardware. A NOT gate (a.k.a an inverter) would be the simplest of all gates. The output of an inverter is always the negation of the input. ie; B = !A, where A is the input and B is the output. Below table summarize the behavior of NOT gate as a truth table.