While I was following along with Duane's blogs (some time ago, now), I had already created the ring counter that I mentioned in my previous blog.
I was poking around some of the capabilities in the ISE (integrated software environment) and I stumbled upon something interesting. Well, a couple of "somethings," in fact. I think maybe one of those somethings is important, but maybe not. That will be for you to decide.
I'll talk about these somethings in my next column. Today, however, I thought I'd share some of what I've learned in the schematic editor without reading all of the documentation. (This is "Manly Man Rule #47," I think -- read instructions only as a last resort.)
As I said, I was following along with Duane's blog -- in particular, these three entries: Adding LEDs & Modifying the Verilog, Bringing Up the IDE, and Creating the .BIT File. To speed things up, click here to access a compressed ZIP file containing my Verilog and UCF (user constraint) files. Feel free to cut and paste as you wish.
In Duane's example, he instantiated a register that was 26 bits deep. His code added 1 to the register at each rising edge of the clock, so, in effect, it was a simple binary counter. He then pulled off the upper 6 bits of the counter to display on his LEDs, thereby giving us a nice slow display to observe.
In the ring counter I talked about last week, I did basically the same thing, only I wired it up as a classical counter in the schematic editor. Digging way back to my college days (shoot, maybe back to my technician days), I seemed to recall that the way to build a digital counter is to feed the "Q!" ("not Q") output from flip-flop "N" into the "D" ("data") input of flip-flop "N," and also into the "CLK" input of flip-flop "N+1," so that's how I built it up.
As a part of building this project, I learned some things about making symbols in the schematic editor that I'd like to share with you. I started off thinking that I'd just "drop a bunch of flops" into the schematic, but it didn't take me very long to decide that this would quickly become very busy, unreadable, and prone to errors.
After pondering the situation for a while, I "thunk" to myself "There must be a better way to do this," and lo, I stumbled around and figured it out! I created a schematic called "ClockDivider" that was based on the structure shown in the figure below (click here to see a larger, more detailed version of this image):
Lesson learned: ISE sometimes (but not always) chokes on modules that start with numbers!
I could then select the whole mess by clicking and dragging over it all; copy and paste five times (kind of neatly); and wire up the six flops I ended up with a "CLK_IN" signal and six divided "CLK_DIV_x" signals as illustrated below (click here to see a larger, more detailed version of this image):
To create a hierarchical symbol from the schematic, you can select the schematic you've created in the "Design > Hierarchy" pane, and then in the "Process" pane you can select "Create Schematic Symbol" as illustrated below. ISE will very niftily create a symbol for you (this beats the heck out of manual symbol creation!).
Now right-mouse-click and select "Run" (you'll be prompted to save changes if you haven't already done so). After you've created a symbol, you can add that symbol as a part in a different schematic. Click the "Add Part" tool button, find your part, and drop it in. Under "Categories" you'll find a path to your working directory as illustrated below. The symbol will be in there. In fact, any symbol you create will be living in that folder. I've not yet figured out how to make a "global" directory that I can reference from anywhere -- I can see the use, but I'm not real concerned about it right now.
I dropped in several clock dividers and wired their "CLK_DIV_64" output to the next guy's "CLK_IN" input as illustrated below (click here to see a larger, more detailed version of this image):
I almost didn't bother putting an input buffer on the input from the PLL input clock net ("CLK1"). I'd like to hear from some of the experts -- how necessary are the IObuffs? What are the benefits of using these and what are the pitfalls (if any). Is it a really bad idea not to buffer I/O, or are there cases where it's a good idea not to do that? And if you don't explicitly instantiate an IObuff, will the compiler implicitly put one in for you?
The ring counter schematic is as illustrated below (click here to see a larger, more detailed version of this image):
I originally didn't set "init" (initialization) states for the flops -- I figured I might get a random state that cycled. Instead, I always got all zeros. That is, my counter apparently did nothing. I dug around a bit and found that you can set the init state of a flop by double-clicking on it. That will bring up the "Object Properties" dialog as illustrated below (click here to see a larger, more detailed version of this image):
As an aside, you can click here to access a compressed ZIP file containing all of the schematics. Now, generate a configuration bit file and load it into the FPGA with the FrontPanel utility. You'll see the LEDs immediately start flashing. You'll also probably notice that the outputs on the XEM board are inverted (the LEDs are pulled up, remember?).
In my next column, we'll look at the differences between Duane's purely Verilog implementation and my schematic implementation. Hopefully this has been slightly useful so far -- has it? I've been reading along, here on the site, and I've heard it loosely stated that "Schematics are a useful visualization tool, but they are bad, bad, bad! All real engineers capture their designs in HDL code." This made me prick up my ears a bit -- why is this so bad? I understand that when you're drawing wires, the nets names are mostly useless for later investigation, but if you have the schematic, who cares? Is this the crux of the badness, or is there something else we should be made aware of?
Also, let me ask about the initialization of flops in a design. Do the compilers always reset every flop to zero (unless otherwise stated), or do we need to explicitly initialize every variable in a module every time?
Related posts (mine):