From June 25, 2012
Following my success in getting the four light-emitting diodes (LEDs) on my FPGA development board to flash using the provided tutorial, I, examined the contents of the UCF (user constraint file) in a little more detail. In this installment, I'll Duane add two additional LEDs to his development board and modify my Verilog code to drive all six LEDs.
Now it really is excitement time, because we get to modify some Verilog code! Last week we managed to load it into the FPGA, and we saw it perform a binary count on the four red LEDs on the PC board. The next step is to add some extra LEDs along with the code to drive them.
The first step was to root around in my treasure chest of spare parts to find some spare LEDs and 680ohm resistors. I then soldered a current-limiting resistor and some pigtail wire to one of the LEDs, as shown below.
The tip of the yellow LED is visible on the right. The current limiting resistor is hidden under the white shrink wrap. In fact, I created two such LED assemblies. Next I looked at Sheet 5 of the schematic for the development board to examine header J5. I decided to use header pins 4 and 10 for the anode terminals to my LEDs; the cathode terminals will go into pins 5 and 11, both of which are connected to ground.
That's it for the external hardware. Now we have to wire things up inside the FPGA. The first step is to identify the appropriate pins on the chip. The schematic designer identified the PC board nets connecting pins 4 and 10 of header J5 as "FPGA_PMOD1_P4" and
"FPGA_PMOD1_P10" respectively. Those nets connect up to pins C18 and D18 on the FPGA chip.
The next step is to open up the "ledflash.ucf" user constraints file in your favorite editor. From my previous articles, we know that "NET" is the Xilinx reserved word indicating that we are going to wire up a net inside the FPGA, while "LOC" points that net to the physical pin on the chip. So now we are going to add the following two lines right after the existing Line 8:
Line 9: NET LED<4> LOC = C18 | IOSTANDARD = LVCMOS18 | SLEW = SLOW
Line 10: NET LED<5> LOC = D18 | IOSTANDARD = LVCMOS18 | SLEW = SLOW
That's all we have to do to this file. "LED<4>" and "LED<5>" are additional bit positions in the symbol LED. In MCU hardware terms, you can think of "LED" as being an I/O port. Before we modified it, this was a port with four bit positions numbered from 0 to 3 -- now it's a port with six bit positions numbered from 0 to 5.
We're done with this step, so you can close Mr. UCF and open Mr. Verilog in the form of the "ledflash.v" file. (Yes, I know that I was playing with VHDL in my previous columns, but this tutorial comes equipped with both VHDL and Verilog, and now I'm leaning more toward the Verilog because I think it will be easier for me to learn.)
The word "LED" we used in the UCF is not a reserved word -- this is just a signal name that was selected by the author of the tutorial. It can be uppercase or lowercase (or a mixture of the two), but whichever it is, it has to be exactly the same in both the UCF and the Verilog files. Consider the original Verilog file as shown below:
Observe that the signal name "LED" appears in two places: on Line 7 and Line 54. In the case of Line 7, "output" and "wire" are reserved words (click here to see a list of Xilinx Verilog reserved words). The role of Line 7 is to assign output wires to the port symbol "LED." Since port LED originally had four bits, this original version of the code assigns four wires -- "[3:0]." We wish to add two LEDs, which means we need to change this 3 to a 5. We also see this " [3:0]" range used on line 54; again, we need to change the 3 to 5.
Now, just as we did in my last-but-one column, we compile our code and load it into the FPGA by running two files: "implement.bat" followed by "config_S6LX9.bat." Hurray -- it works! No, wait a minute... darn, it didn't work!
Not all of the LEDs are flashing. What went wrong? You may have figured this last part out
faster than I did, but if not, take another look at the original "ledflash.v" and observe the part
on Line 54 where our LEDs are assigned the current values from "led_count[26:23]." Hmmm, what is this "led_count," we ask ourselves?
Well, on Line 49 we see that the reserved word "reg" is used to define a symbol "led_count" as being a data storage element with 27 bits numbered from 0 to 26. The original code on Line 54 assigned four of these bits (bits [26:23]) to our original 4-bit "LED" signal. Since we now have six LEDs on the board and a 6-bit LED signal in our code, we need to modify the assignment on Line 54 to be "led_count[26:21]" as shown in the modified Verilog file below:
But why did the creator of this tutorial decide to use a portion of a 27-bit register to drive the LEDs in the first place? Can you guess? In fact, with a little experimenting, I determined that the "led_count" register essentially acts as a frequency divider / counter. This all makes sense when you think about it. Our system clock is running at 66MHz, where 66MHz / (2^27) equates to approximately 0.5Hz, which is about what the count speed looks like on the most-significant LED.
This is just like using an old 7493 counter, except I can change the number of bits without having to add physical chips. Think of the numbers 0 through 26 as physical wires sticking out of each bit of the counter. Wire 0 has a 33MHz square wave on it (66MHz / 2); wire 1 has a 16.5MHz square wave (half the frequency of wire 0); and so on up to wire 26, which ends up with an 0.5Hz square wave. Now, all six of my LEDs flash as illustrated below:
Actually, purely for illustrative purposes, I've made all of the LEDs stay constantly on in this image. So, I really think we're starting to get somewhere now. How about you? Is this all starting to come together? Are you starting to envision some applications of your own? If so, what do you have in mind?