I am taking a digital design course and I didn't get something. RTL design includes datapath and controller, that's ok but what's the relation between these and verilog modules. For example, is controller a module in verilog? Generally, how RTL can be coded in verilog?
First of all, Verilog is a Hardware Description Language used to describe a collection of digital hardware, and a
module is just a way of hierarchically encapsulating your description. Each
module boundary can be physical, like the pins of an FPGA or IC, or printed circuit board, or it can be logical, like a data path or controller. In any case, a Verilog
module represents some functional component of your design ranging from a simple
and gate (or smaller) invisible to the unaided eye, to a system as big as a room (or bigger). But in general, the contents of a module takes up some amount of physical space, as well as some amount of power consumption, heat, etc.
The content of a module can be a collection of other module instances, or a description written at many different abstraction levels, of which RTL is just one of many possible levels. RTL, or register transfer level, is code that can easily be synthesized from what looks like a procedural program into digital hardware.
One of the problems with many courses is that due to time pressure they try to teach concepts with problems that are too small to need those concepts.
A design is basically a hierarchy of modules. In synthesis your top level module usually describes "everything on the chip"; submodules then describe parts of the design. In simulation, your top level module is usually your testbench code and then the code you want to test is instantiated as a submodule.
There are several advantages to splitting a design into modules.
- It can group logically related code together.
- Synthesis tools will usually present resource use on a per module basis. If you don't split your design into modules you won't be able to tell which part of your code is using up all the resources.
- It can encapsulate local details, signals are local to a module unless you explicitly route them in and out.
- It can allow blocks of code to be reused.
There are also downsides though.
- Routing signals in and out of a module requires wiritng more boilerplate code.
- Too many levels of abstraction can make it hard to see what is going on.
RTL design includes datapath and controller, that's ok
RTL means we describe what happens to each register on each clock cycle using a subset of the language that the synthesis tools knows how to handle.
The tool mostly* doesn't know or care if a given register is "datapath" or "control" just that you define what happens to it in a way that it understands.
For example, is controller a module in verilog?
It's entirely up to you, you could merge the datapath and controller together in a single always block. You could have an always block for the controller and then build up your datapath out of a mixture of assign statements, always blocks and submodules. You could have a submodule for the datapath but not the controller.
Which works best depends on the problem, if the data handling is simple then putting everything in one always block may make the most sense. If the data handling gets more complex it may make sense to move it out of the always block and describe it in a more structual manner to better control resource use.
Personally I would only split the controller and datapath into seperate modules if I had a good reason, maybe they are very large, maybe I want to use one controller to drive multiple copies of the datapath, something like that.
Hmm... Let's suppose I want to design a system on Basys3. Random leds will blink sequentially and user will try to repeat this sequence. User's score will be incremented for each correct answer. How can I implement such system? Should I try to design controller-datapath system or Verilog modules? I am very confused.
Lets break this down.
First we need a source of "random" numbers. Probably the best way to do this is to have a continuously running psuedo random number generator. The time the user presses the start button then picks which "random" number and hence which LED pattern the user gets.
I would suggest making the "random" number generator its own module so it can be resused in other projects. Probably something like a linear feedback shift register is adequate.
You also probably need a button debouncer that takes the signals from the buttons and converts messy presses into a signal that is high for exactly one clock cycle. This would be made into a module to allow multiple instances to be instantiated for the different buttons.
The actual game code I would probably write as a single always block. You could try and split it up but in my opinion the overheads of handshaking between different parts would likely outweigh the gains.
* An exception to this is state machine state registers. If you follow standard state machine idioms then the tool will typically translate from whatever state numbers you used in your program to a state encoding chosen for synthesis efficiency (often 1-hot).