As you may recall, we have progressed beyond the light-emitting diode (LED) flashing tutorial that was provided with the Avnet Spartan-6 LX9 MicroBoard. Now we wish to plug some external switches into our FPGA development board and then use these switches to "Start" and "Stop" the count sequence being displayed on the LEDs.
In my previous column, we got the UCF (user constraints file) taken care of, and we also got a sneak preview of the hardware (LEDs and switches) we are going to connect to our development board. (See: Discovering FPGAs: Playing With LEDs & Switches.)
The next step is to decide what needs to be done with the *.v (Verilog) file that was automatically generated by the system. Let's use the ISE Design Suite to look at this generated code as illustrated below:
The automatically generated *.v (Verilog) code.
ISE gave us a start, but there are quite a few things missing. First, we have inputs and outputs defined, but they aren’t really connected up to anything. To do that, add the reserved word “wire” to the inputs and outputs, as shown in the following image:
Add the reserved word "wire."
Next, copy and paste all of the code from the “ledflash_ISE_ver.v” example file that we completed in an earlier column, Discovering FPGAs: Loading the .BIT File. Copy the code from line 10 through to the end of the file and paste it in starting at line 31 of the new code. If you end up with two “endmodule” statement lines, just delete one of them. (As a convenience, you can click here to download the complete code for today’s exercise.)
Copy the old code.
Don’t run ahead and synthesize, implement, generate, and configure yet, because you won’t get very far and you will likely be a little disappointed. Before doing that, we first have to tell the Verilog code to do something with the LEDs and switches.
For the first shot, we’re just going to connect the switches directly to the LEDs. That’s pretty easy to do in actual hardware, and it’s also reasonably easy to achieve in an FPGA. Down toward the bottom of the code, change the name “LED” on line 76 to match the “COUNTING_LEDS” that we renamed it to. Also, change the bit ranges to match the fact that we’re only counting with four LEDs again. Also, add an “assign” line for each switch/LED pair. When you are done, lines 76, 77, and 78 will read as follows (click here to see a larger, more detailed version of this image):
jandecaluwe 11/23/2012 4:43:27 AM User Rank Blogger
Re: wire and reg
@Karl "The nonblocking operator is easily understood, but the blocking operator behaves as in a combinational always IFF it is assigned before being used else it seems to behave like a nonblocking assign that is synthesized to a flip-flop."
No, it simply behaves as a classic variable, never as a nonblocking assign. Pretty powerful.
"Reg is ambiguous/misnomer now blocking assignment has become ambiguous too."
Misnomer yes, ambiguity no. The semantics are clear and useful. However, it is unfortunate that two different semantics (blocking/nonblocking) are defined on the same object. If you don't like that (as I do), you may want to consider VHDL.
"There is no wonder that there are rules against mixing operators in the same block. It is clear that blocking assignments must have been intended for combinational asynchronous logic and nonblocking were intended for parallel clocked assignments."
That is not correct. Historically, Verilog was defined as a modeling and simulation language - no synthesis in sight. All it had were blocking assignments. Obviously, this was not only to describe combinatorial logic.
Non-blocking assignments were introduced afterwards to make deterministic communication between clocked assignments (as in RTL) possible. The parallel behavior is just a useful side effect. I have proven this in a recent blog about signal assignments.
Interestingly, when writing a test bench few people ever have a problem with blocking assignments. Note that most industrial HDL usage is not dedicated to describe synthesizable hardware, but to build verfication environments and test benches.
The problem starts when people try to attach a simple, straightforward hardware meaning to any declaration and any line they write in their synthesizable code. As I have pointed out on many occasions, that meaning simply isn't there. You have to look at the behavior as a whole.
"The definitions/standards were developed years ago BEFORE computer science and software engineering evolved but now some ignore(do not think about the intent) and read only based on syntax."
As I said, I think you are wrong about the intent. And this is about semantics, not syntax.
"Synthesis should not accept this kind of ambiguity. Instead it tries to work around poor design practice."
What you call "poor design practice" is actually practiced every day by people with an outstanding track record who understand these matters very well. It is called the single process style.
There is no ambiguity for synthesis. There are just some semantics that you don't seem to like. But many others do, including myself.
"There has been much discussion about coding guidelines which are important and guidelines should separate clocked from asynchronous logic."
In practice, I suspect all will agree that a strict separation is impractical. For example, to describe a simple counter, just put the increment assignment in a clocked process. However, this means that even such a simple process infers both flip-flops and combinatorial logic.
Many of those who master variables understand that there's hardly any need for combinatorial processes at all. They will describe all or most of their hardware with clocked processes only. Synthesis will infer registers/combo logic as required. This is just a slightly higher level of abstraction, nothing compared to HLS for example.
@Jack: Yes, to all that you said, but the discussion is about what happens in the clocked always when blocking assignments are included and the signals are not in the sensitivity list.
The nonblocking operator is easily understood, but the blocking operator behaves as in a combinational always IFF it is assigned before being used else it seems to behave like a nonblocking assign that is synthesized to a flip-flop.
Reg is ambiguous/misnomer now blocking assignment has become ambiguous too.
There is no wonder that there are rules against mixing operators in the same block. It is clear that blocking assignments must have been intended for combinational asynchronous logic and nonblocking were intended for parallel clocked assignments.
The definitions/standards were developed years ago BEFORE computer science and software engineering evolved but now some ignore(do not think about the intent) and read only based on syntax.
Synthesis should not accept this kind of ambiguity. Instead it tries to work around poor design practice. There has been much discussion about coding guidelines which are important and guidelines should separate clocked from asynchronous logic.
When the standard was updated to use (*) to be used for the combo always, it should have defined that as the default for the blocking assignments in clocked always -- Better yet require only nonblocking assignments.
AND ALL OF THIS CONTENTIOUS/POINTLESS DISCUSSION COULD HAVE BEEN REPLACED BY SOMETHING CONSTRUCTIVE.
A Verilog "reg" to my understanding is something to hold/store values, which could be synthesized as flip-flops if they are clocked (has clock signal in sensitivity list) or latches if they are asynchronous (all signals in sensitivity list). latches are formed when (as most of us know) there are incomplete case statements or using output enable signal.
However, a "reg" can also form a combinational logic output depending the way you write it so it's like what Jan said, Verilog's reg is a misnomer.
@Jack: I am trying to visualize what is physically synthesized to realize the value of the Verilog reg in the always block. The only logic circuits that can be synthesized are flip-flops and LUTS.
Do you mean that all regs become flip-flops? I don't think so.
Synthesis is to produce a value that can be the din value of a flip-flop in this case. It just so happens that it is termed a reg in Verilog. What is it physically?
@Adam: Hi, here I am again-- Still trying to identify the physical implementation.
"A example of a wire would be
variable_temp := a + b; -- assigning the variable here
op <= variable_temp(bits of interest);"
a and b must have values that come from 1 of 2 places: Either registers or voltages and should be usable in assignments.
Now "A example of a register would be
op <= variable_temp(bits of interest);
variable := a + b;"
In this case it seems that if a and/or b are registers(flip-flops) that a register (variable_temp) was synthesized and its value is used here and would have a value determined by a and b on the previous cycle and will now be updated with the values in this cycle otherwise it will be clocked to the hardwired value in every cycle.
jandecaluwe 11/19/2012 3:22:06 AM User Rank Blogger
Re: wire and reg
"even though you are trying to form a combinational logic output, somehow a "wire" cannot be assigned at the LHS in any "always" block. the output in any "always" block needs to be declared as a "reg". one of the weird thing about verilog. :)"
The best way to understand this is to recognize that a "reg" really is a misnomer. Once again, it has nothing to do with any direct hardware interpretation. Rather, it behaves like a variable that can be assigned to in two different ways.
Note that "reg" has been deprecated in SystemVerilog. It has been replaced by the more neutral word "logic".
even though you are trying to form a combinational logic output, somehow a "wire" cannot be assigned at the LHS in any "always" block. the output in any "always" block needs to be declared as a "reg".
jandecaluwe 11/18/2012 2:48:07 PM User Rank Blogger
Re: wire and reg
@Karl "In the reference link, I think it said that things get synthesized away so there is no storage available to hold these values anyway."
No, the reference link describes the conditions under which storage is synthesized or not.
The general rule is straightforward: if the value of a previous invocation (meaning the previous clock cycle) is referred to, you need a register.
It translates differently to non-blocking versus blocking assignments according to their semantic differences as defined by the language.
"It looks like the whole intent is to give the illusion of sequential function but in reality the actual value is dependent on the flip-flops that are the source of the real input values of the networks."
I don't think there is any illusion involved. In all cases, regardless of the type of assignments used, the synthesized circuit will behave exactly as the RTL. Not just for the combinatorial part, but also for the state sequence as it evolves over clock cycles. The registers holding the state are synthesized as necessary to make this possible, according to the rule described above.
The best way to resolve any confusion about this, is to experiment with small (possible contrived) examples and see how a synthesis tool handles them.
One more thing: "mixing blocking and non-blocking assignments" is never a purpose in itself. It is simply the result of using the language to describe a certain desired behavior elegantly.
@jan: Thanks. I understand what you are saying and it helps. My real difficulty is relating to what is available physically on an FPGA. There are LUTS, flip-flops and memories.
In the reference link, I think it said that things get synthesized away so there is no storage available to hold these values anyway.
It looks like the whole intent is to give the illusion of sequential function but in reality the actual value is dependent on the flip-flops that are the source of the real input values of the networks. That is combinational logic which is done with a network of LUTS drivan by flip-flops. The non-clocked always blocks are just that "allways" resolving the output from the inputs. Since the inputs are clocked flip-flops, the output holds its value from clock to clock and a series of if/else statements are translated to an and-or-invert network that appears to hold values. Even if blocking assignments are included in clocked always, that logic had to have been extracted during synthesis so it would be in the logic net and resolved from flip-flops.
Then if only to avoid confusion it makes sense to not mix blocking and non-blocking because that gives the illusion that the blocking assignments are occuring during the clock edge that triggers the always, Further, the notion of a sensitivity list that mixes clock edges and logic values just makes no sense.
And the if/else in the clocked always does allow muxing of inputs based on conditions but to include blocking assignments is too confusing to people just reying to get a design to work using parallel operations.
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.