up until now we've been putting all of our verilog code inside a single
module that's inside a single file while that's fine for very simple designs you can
probably guess it will very quickly get out of control and become hard to debug the more code
you add let's see how to create modular code so that we can start creating more complex designs
in a previous part i challenged you to create a clock divider that drove a counter we're going
to create a module for just that clock divider so we can use it independently of our other logic one
big advantage of creating modules for our basic building blocks is that we can easily instantiate
multiple copies of that module which saves us from having to rewrite or copy and paste code
it's generally a good idea to put the code for one verilog module in a single file so that it's easy
to find and debug errors in your modules so our clock divider code will be in one file and will
instantiate two copies of it these copies are also called instances to do that we'll need another
file that holds our top level design this module will instantiate the clock divider twice each with
different parameters it will also contain some necessary glue logic such as inverting the reset
button signal and connecting inputs and outputs to our physical pin names by allowing our top level
module to instantiate the clock dividers with different parameters we can change the way each
one functions at the time of instantiation without needing to add additional signal lines or logic
note that i combine the output of the two dividers into one bus you'll sometimes see
buses in diagrams drawn with a thicker line or they might have a diagonal line with a number
that tells you how many lines are in that bus in this case we'll set the parameters of the dividers
so that the two output leds blink at different rates let's make this design in verilog to start
let's make a new folder for our project i'm going to call it clock dividers one we're going to
have two different examples here and i'm going to start by creating my clock divider that is a basic
module and this is going to be very similar to a class if you've done any sort of object-oriented
programming we'll be able to create instances of this module creating our module should look
very similar to all of the other examples we've done before we're just going to declare our ports
in this case our inputs and our outputs note that the output needs to be registered in this case
as we're going to use a clock to control it and store its signal level at the output of our module
previously we've used local parameters or local param in order to define constants for our module
i'm going to introduce this new keyword called parameter local params were only defined within
that module and could not be changed outside of that module this is opposed to parameters which we
can declare here they create an initial value that can be used as a constant throughout the module
however parameters can be changed outside of the module and in our top level design we're going
to be able to change these when we instantiate a particular object or not really an object but an
instance of this module what i'm doing is setting a default value for each of these parameters so
if you don't define them when you instantiate this particular module they still get some value notice
that i can use parameters to define bus widths in this case count width i'm saying is 24 bits so
when i create the max count value i can declare how wide that bus is in this case it's 24 bits
wide because i'm using this variable or constant rather to declare the width of this vector
as before we can declare internal signals like wires and registers to help store values or so
we can name particular wires or lines within the module if you did the challenge with the
counter where you had to create your own clock divider much of this should look very familiar i'm
actually using the same code that was found in my solution the only difference is that i don't have
any logic to invert the reset signal because now i'm assuming it's going to be active high instead
we'll leave inverting that signal to the top level design because we're going to be attaching it to a
button which may not always be the case if you're using a clock divider let me fix my spelling here
and i'm going to save this file the next thing i need to do is create my physical constraint file
as we've seen before i'm going to declare a couple of named signals or wires and associate them with
physical pins on the fpga in this case i've named the line that's connected to physical pin 21 clock
as that's connected to the 12 megahertz oscillator on the ice stick and i've also connected
two pins for my leds pin 98 and 99 and finally i've got one reset button that's using the same
hardware connections that we made in previous episodes with the four buttons but in this
case i only need one and that's the reset button let's save this i'm going to create my design here
and i'm going to fix the naming error so that everything will work so i'm going to
open my topdesign.v and i'm going to keep my physical constraint file open here so you can
see it nothing changed i just fixed the naming error and let's go ahead and write our top level
design as with any module i'm going to declare the module name along with the ports in this case my
inputs and outputs note that even though the output of my clock divider module is registered i
cannot connect that directly to another registered element i can only connect an output of a module
to a wire that's because the output of a module can change at any time say similar to something
like a button pushing you can then register that output but you have to connect it through
something like an always block and then clock that output and save it in a registered element as we
saw in our diagram we're going to take the reset button and we're going to create a little bit of
glue logic here where we're just going to invert that signal call it rst and send that signal to
our two instantiated clock dividers to instantiate a module you first call the module name clock
divider that should line up with clock divider the name of the module here the synthesis tool
accepts the verilog files that we provided and in this case appio is going to send yosis
all of the files that it finds together in our project folder in this case it's going to find
clock divider.v and topdesign.v and send those to yosis and joseph is going to figure out that hey
i'm calling clock divider to instantiate the module here and that lines up with the clock
divider module name that i found in this other file for now i recommend keeping all of your
files for one project in the same folder so that appio can find them however you will probably come
across more complex design where different modules and test benches are stored in separate folders
and you have to bring those all together in that case you'll probably want to call yosis manually
and give it the location of those source files let's head back to our top level design once we've
called that module and given a name in this case i'm going to call it div one for divider one we
then connect the wires and register elements that are inside of this top level design to
the inputs and outputs inside of the instantiated module to do that we call dot the name of the port
so in this case it's clk for clock and then in parentheses the name of the wire or registered
element that is in our top level design the module that's instantiating this other module in this
case it's also called clk for clock so these two things are now connected together by a wire we're
going to do the same with the reset signal that is in the clock divider and it's connected to
this reset wire which is an inversion of the reset button and if it was confusing earlier about which
name refers to which signal in which module here is a better example dot out is the name of the
output registered element or the registered wire or signal in the clock divider module and the led1
is connected to led1 in this case and actually i want this to be led0 because we're going to use
led1 for the second clock divider in order to set the parameters that are in this instantiated unit
or module we are going to use this keyword called def param i keep thinking it's default parameter
but it's probably closer to something like define parameter in this case we are going to define the
count width parameter that's found in only the div 1 instantiated module which is given by the count
width parameter here we're going to overwrite this 24 with 32 bits you don't actually need 32 bits
for this but let's just pretend you want it to be 32 bits wide for whatever reason we're also going
to override that max count default parameter value with one million five hundred thousand
minus one that should allow the led to blink a little faster than what's set here note that this
is an old-school way of defining parameters i'm going to show you the new way to do it as it was
updated with the 2001 version of verilog but this way you can see what def param is in case you run
across it in other people's code now i'm going to instantiate the second clock divider module
and i'm going to call it div 2. the code for this looks just like the code we used
to instantiate the first clock divider module but we're going to connect the output to led1 instead
you'll notice here that it shares the clock and reset lines with the first clock divider we will
also not define the parameters for div 2 which means that it should use these default parameters
that we set in the source code for the clock divider let's save this we'll open up a terminal
and navigate into our clock dividers project i'm going to call opio init and give it my
board in this case the istick i think it's always a good idea to verify your code to make sure that
it should in theory synthesize and then we will call opio build once synthesis is done hopefully
you get no errors we will upload that to our board if you were using windows you might run across
this error where it says lib usb open failed if you went through the process of installing
the drivers using zadig and everything worked fine but you suddenly find it's not working any longer
one of two things is going on here first check to make sure you have no other ftdi devices plugged
in like in my case the analog discovery 2. once you've verified that try moving the
ice stick or whatever ftdi device you're using for this to the port that you originally installed
the drivers on windows likes to remember which port you plugged a particular usb device into
and then always use that driver for that device when it's plugged into that port so try moving
it to a different port let's see if it works again if plugging your board into different ports still
doesn't work you might have to reinstall the drivers with opio drivers dash dash
ftdi dash enable use the drop-down list make sure interface 0 for your fpga board is selected
in this case windows is attempting to use this ftdi bus driver for some reason
and we want to kick it back to libusbk so let's click replace driver and let that install
this only seems to happen when i'm constantly unplugging and plugging usb ports back into
my computer in this case it's a laptop which seems to confuse windows as long as i'm using the same
usb port for my istick and not constantly shuffling around ids with things like usb
hubs then windows should be fine it's just i run into this every now and then because like i said
i'm on a laptop once that's done opio upload should in theory work and send my synthesized
design over to my fpga as you can see the two leds are flashing at different rates the first
one should be flashing at about four hertz and the second one should be flashing at about one hertz
the 2001 version of verilog introduced a new way to define and use parameters it more closely
resembles how parameters are passed between functions in ansi c so this style is often
referred to as ansi parameters in verilog or ansi c style parameters use them let's go back to our
clock divider we're not going to define them inside of our module but rather as an extra set
of almost ports it's just a parameter list that's defined before our ports we denote this parameter
list with a pound or hashtag symbol and a new set of parentheses the ports list gets pushed
down below as we define the parameters first just like we see with the ports parameters are defined
in list style where each one is separated by a comma instead of a semicolon which is what
we were using earlier we can still give them default values as given by these equal signs
let's save this design we'll go over to our top design verilog code with the addition of
this ansi style of parameter definition you no longer need to call the def param keyword here
instead you can do another pound sign and another set of parentheses here except that you want to do
it before you declare the name of the instantiated module inside this new list we're going to use the
dot notation again and we're going to set count width to 32 and max count to 1500 000
minus one make sure we close out our parentheses and let's save this file we'll verify our code
that looks good we'll build it and send it off to our fpga with any luck it should work exactly the
same as it did before indeed the leds are flashing exactly the same way as before the challenge for
this part is to create a modular design that causes the leds to count up and then count
down there are a number of ways to accomplish this but i might recommend using the clock divider we
just made to feed two different counting state machines that are instantiated as modules when
one module is done counting up it sends a signal to the next module which will start counting down
you'll have to think about what the glue logic looks like in order to have two different modules
control the same set of leds good luck with this challenge as it can be a little tricky
next time we'll see how to use our modular code to create test benches being able to simulate our
designs can potentially save us a lot of headaches from having to debug actual hardware happy hacking
you