It's Monday as I wrote these words, and you know what that means... Well, I do. It means that it's feedback time for my prior week's column. I'd rather complete my blogs a little bit sooner, but I get so much good feedback. If I write my new blog before I've seen the feedback from the previous one, then I invariably perpetuate some of my mistakes. Apart from anything else, this is probably not helpful for those trying to learn along with me.
I've been told that the library "IEEE.std_logic_unsigned.all" is not, in fact, a standard library. Thrakkor pointed that out and gave alternates for the library and the code lines dependent on it. After that, devel@latke noted that I don't need to instantiate the clock buffer and that I was using an obsolete bit of code in my frequency divider. And, he also popped right back for another comment to state that I need to initialize my counter in order for the thing to work in the simulator. That last one took me on a quest for the proper way to represent numbers. The basic VHDL syntax is as follows:
In my current test circuit example, this would come out to:
Ooookay... I suppose there's nothing wrong with that, except that, with 27 zeros, it's not unthinkable to imagine missing one out or adding in an extra one. Fortunately, there is another way as follows:
When used as illustrated above, the VHDL keyword "others" will fill the multi-bit signal (which I'm visualizing as a ribbon cable) with zeros, regardless of how many bits are in the array. This raised a few other questions regarding the representation of values in VHDL. In Verilog, I could have represented that value as: "27'b0," but VHDL is different. A single signal value in VHDL is enclosed in single quotes: '0' or '1.' A multi-bit signal is enclosed in double quotes as in "10101010," which is equivalent to "AA" in hexadecimal. Take a look at the following code (click here to see a larger, more detailed version of this image):
Starting at the top, I commented out Line 3 and replaced it with Line 4. Brian gave me an interesting link to a VHDL Math Tricks of the Trade document that contains some detail on the math libraries. This document notes that "numberic_std" is an IEEE standard while "std_logic_unsigned" is a "de facto" industry standard. It recommends the IEEE standard for new designs. Makes sense to me.
I removed Line 16 and replaced it with Line 17. In this case, "clock_divider" is still the signal name, while "unsigned(26 downto 0)" creates an unsigned 27 bit number using the "numeric_std" library. Meanwhile, ":= (others =>'0')" initializes all of the bits to zero. Lines 20 to 24, my original clock buffer instantiation are removed. Line 28 is obsolete syntax, so I replaced it with Line 29. Finally, Line 34 is replaced with Line 35 (phew!).
On Line 35, "LED" is my 4-bit output signal. The four MSBs (most-significant bits) of my counter are routed to the four LED output signals using "clock_divider(26 downto 23)." The "std_logic_vector( )" on this line is a type conversion from "unsigned" to "std_logic_vector." Presumably this is necessary because LED is a "std_logic_vector."
Now it's time to move on to the next step. First, I'll clean up the code by removing all of the unwanted (commented-out) lines. I made a nice little LED Pmod, so I'm going to plug that in for my next column. If you're following along with me, you can continue to use the board LEDs.
All of this provides a perfect segue into my next subject. To date, I've done all of my work in ISE and with physical hardware, but that can only take an FPGA jockey so far. I need to learn how to simulate things in the simulator. Once I get that going, I'll get moving through VHDL world again. A number of options have been mentioned here on All Programmable Planet (APP), but I have ISE, so I'll try out the simulator that's included in ISE. This means I've got to learn about test benches, but -- fortunately -- that's been covered in other blogs here on APP.
Step one is to pull up the User's Guide included with ISE and dig up any tutorials I can find on the Xilinx website. Step two is to stop writing and start reading. With that, I will bid you adieu until next week. I'll see you then -- "Same blog time; Same blog channel."
@jan "When I talk about HDL based design, I assume that the basics of digital design are mastered. Honestly, I find that an obvious assumption - but perhaps that's wrong."
Amen! HDL based design is still the design of digital HW, no matter how abstractly we describe the behavior of said HW!
"Moreover, I also find it obvious that a digital design engineer is interested in implementation efficiency (area, timing, power) first."
Since we designers also want to remain employed, we are also, and in some cases moreso, interested in the efficiency of the design process itself. As the devices on which our designs are implemented speed up, consume less power and $$ (on a per-gate-equivalent basis), while our designs become larger and more complex, in many cases we can profitably trade a little implementation efficiency for more design process efficiency.
Is this so different from the early days of HLL-based SW development? Sure, the assembly language artisans could craft instruction sequences that would run circles around our best HLL efforts, but at what cost? They could not compete when faced with implementing the scale and complexity of the applications we were producing.
jandecaluwe 2/22/2013 8:35:58 AM User Rank Blogger
Re: What we do is digital circuit design.
@devel "It seems to me that a lot of newbies are trying to learn VHDL without any understanding of the fundamentals of digital design.
That, of course, is completely backwards."
I fully agree. Perhaps what we are facing is a mismatch between hidden assumptions. I'll try to make mine explicit.
When I talk about HDL based design, I assume that the basics of digital design are mastered. Honestly, I find that an obvious assumption - but perhaps that's wrong.
Moreover, I also find it obvious that a digital design engineer is interested in implementation efficiency (area, timing, power) first. Therefore, when I talk about "abstraction" and even "software techniques" I mean that in a bottom-up sense: as an incremental though significant improvement by making better use of existing techniques, based on a strong foundation.
@rfindley: "I was pointing only to two points at the top of the linked page, which answers the question you asked (i.e. how register inference is different with variables). I make no support of anything beyond that point."
Rfindley,
The text which you describe as explaining how registers are inferred from variables uses the right words, but emphasizes the wrong sylables, so to speak, and misses the most critical (and most powerful) point.
It is not a variable that infers a register, it is EACH reference to said variable that infers a register (or not).
Furthermore, a single variable can have several references. Each of those references is either a register, or a potentially unique combinatorial result, depending on what value was most recently assigned and when. In fact, if a prior assignment (in the same clock cycle) to the variable is conditional, then subsequent accesses are conditionally registered or combinatorial values, for which a mux is employed to choose.
Compare that to a signal in a clocked process. Most of us were taught (or left to assume) that writing a signal on a clock edge is what creates a register. But variables are written on clocked edges, and they don't necessarily create registers. Why?
Just like variables, it is the references to signals that are written on clock edges that create the registers. It just so happens that the postponed update semantics ensure that, no matter when a reference is executed relative to an assignment, it is always the value written in some previous clock cycle.
When viewed this way, we have a unified model of register synthesis, whether signals or variables are used.
This unified model also helps us to understand why latches (a different form of storage) are inferred. And guess what? The same preferred solution to avoiding unwanted latches in combintorial processes (default assignments at the beginning of the process) , also avoids unwanted registers inferred from variable references in clocked processes.
On the other hand, when Ben Cohen writes that some synthesis tools may optimize out the register, created for the variable (sic), he apparently has forgotten that if two signals register (sic) the same value, some synthesis tools will optimize one of them away too. Why is it a problem when that happens with a variable, but not with a signal?
Now, before everyone's blood pressure elevates about trying to remember how variable and signal references create registers, I have a simpler idea: Instead of focusing on registers, focus on how many clock cycles (or trips through the process loop) it takes the process to generate an output from an input. Then there will be that many successive registers to create those clock cycle delays.
If you enable retiming and pipelining synthesis optimizations, the registers aren't likely to end up where you thought they might be anyway. But there will still be the same number of clock cycles from process input to output.
@Devel, I was pointing only to two points at the top of the linked page, which answers the question you asked (i.e. how register inference is different with variables). I make no support of anything beyond that point.
@devel: "Once the student understands the digital design part -- and seriously, that's not all that hard, which is why it's often a one-semester course -- then the discussion about implementation details (schematics, HDL) can take place."
I am confused because it looks like the above is your conclusion and I tried to say the same thing but you said it was backwards.
jandecaluwe 2/21/2013 3:47:31 PM User Rank Blogger
Re: Simple Request To The FPGA Experts
@rfindley "No, I don't teach that comment, nor do I use that book. It was the result of a quick google search to save time."
Fortunately.
A quick google search. Right. In your recent post you mentioned it to make your point as follows:
"A quick google search will reveal that there are indeed common misconceptions about VHDL variables during the learning process, especially among certain classes of people."
and:
"There is some behavior or perception that is interfering with proper understanding."
and:
"I think it is valuable to acknowledge this, and find the root cause."
I acknowledge this and your search result is a perfect illustration of my hypothesis about the root cause.
It's not struggling newbies that are the problem. It's not "during the learning process" - the problem is with influential but mediocre engineers who think they have nothing to learn anymore.
The "certain classes of people" that you refer to are the confused "guru's" like this one that just don't get it. They are the ones that spoil the party for newbies.
No, I don't teach that comment, nor do I use that book. It was the result of a quick google search to save time. I was only pointing Devel to the section at the top of the page, which answers the question he asked, and provides some academic examples.
I think Ben doth protest too much, certainly in the box that says, "Avoid using variables in clocked processes." That sort of recommendation might be fine for children, but I'm an adult and I know what I'm doing.
It is common to use a variable as a way to simplify some code. The example of the JK flip-flop is a good one. (Even as I disagree with his coding style, although that book is ancient.) He uses a variable to condense the concatenation J & K into a vector, and then he uses that variable as the condition in the case statement.
In his first example, it should be clear that a register for JK_v won't be inferred; it's just a convenience. (Actually, it's a workaround for the problem of the restrictions on what could be used as a case conditional in older versions of VHDL.) My work-around would've avoided the variable and instead used a typecast:
case std_logic_vector'(J & K) is
but now we have to teach the newbies about typecasts.
Then he provides a second example that looks similar but puts the variable assignment after the case statement. That does infer a register, and as his comment notes, it's probably not desired. That's true enough, but blaming variables for the user's lack of attention isn't warranted.
Duane has decided that the time is ripe to get his ZedBoard bolted onto his robot with a Linux distribution up and running. That was the ultimate plan anyway, so why wait?
To save this item to your list of favorite All Programmable Planet content so you can find it later in your Profile page, click the "Save It" button next to the item.
If you found this interesting or useful, please use the links to the services below to share it with other readers. You will need a free account with each service to share an item via that service.