VHDL newbie: 'if' on a process sensitivity list element


flag26838

Recommended Posts

Ok, it's late and i'm tired but i can't figure out what's wrong wit this piece of code:

 

http://pastebin.ubuntu.com/8391335/

 

and it errors out during the mapping phase with:

 

ERROR:Place:1108 - A clock IOB / BUFGMUX clock component pair have been found
   that are not placed at an optimal clock IOB / BUFGMUX site pair. The clock
   IOB component <SWITCH<7>> is placed at site <P121>. The corresponding BUFG
   component <SWITCH_7_BUFGP/BUFG> is placed at site <BUFGMUX_X2Y3>. There is
   only a select set of IOBs that can use the fast path to the Clocker buffer,
   and they are not being used. You may want to analyze why this problem exists
   and correct it. If this sub optimal condition is acceptable for this design,
   you may use the CLOCK_DEDICATED_ROUTE constraint in the .ucf file to demote
   this message to a WARNING and allow your design to continue. However, the use
   of this override is highly discouraged as it may lead to very poor timing
   results. It is recommended that this error condition be corrected in the
   design. A list of all the COMP.PINs used in this clock placement rule is
   listed below. These examples can be used directly in the .ucf file to
   override this clock rule.
   < NET "SWITCH<7>" CLOCK_DEDICATED_ROUTE = FALSE; >
 
ERROR:Pack:1654 - The timing-driven placement phase encountered an error.
 
 
any idea what am i doing wrong?
Link to comment
Share on other sites

I don't use VHDL myself, but I'm guessing that VHDL has determined that "en" is a clock.  "en" is set to SWITCH<7>.

 

The mapper is complaining because clocks should normally be connected to dedicated clock input pins so they can use low-skew global routing.  If this is what you want, move SWITCH<7> to a clock pin.  Otherwise add the suggested line to the user constraint file <root_name>.ucf for your design.  Leave off the extra brackets so it looks like:

 

NET "SWITCH<7>" CLOCK_DEDICATED_ROUTE = FALSE;

 

In fact, you might want to leave off the quotes and spaces around "=" as well:

 

NET SWITCH<7> CLOCK_DEDICATED_ROUTE=FALSE;

 

This tells the mapper that you want to route clock "en" using the regular routing and you don't care about clock skew.  You'll still get a warning, but the tools can continue to run.

Link to comment
Share on other sites

but i don't undestand why so, i mean, from a process perspective, any signal listed in a process sensitivy list are just vanilla electronic tracks that, at some point in time, change their logical value hence trigger the process body, so why would the "compiler" assume the en signal is a clock (and thus complain when it's not)?

 

does it have to be a clk to used in a process sensitivy list? is it mandatory? some kind of VHDL constraint maybe?

what i'm trying to achieve, is to trigger the process body only when i "turn on" a specific switch

Link to comment
Share on other sites

What happens to the values of ANODES and SEGMENTS when you turn the 'en' switch off?

 

Because of this the 'en' signal has to drive latches, and I guess this is why it gets promoted to use a low skew clocking network. Were you to assign values to ANODES and SEGMENTS when en = '0' then it would be combinatorial logic, and shouldn't generate these errors.

 

Your sensitivity list should include any signals that if they change the logic needs to be evaluated, in this case 'en', 'value' and 'cell', in this case because if 'en' is asserted you want the display to change as you change the switches.

 

If you were to use "if rising_edge(en) then" you only need the 'en' signal on the sensitivity list (and it would still throw the error)

Link to comment
Share on other sites

Hi,

 

>> are just vanilla electronic tracks that, at some point in time,

No, on an FPGA "clocks" and "information signals" are electrically different, with some possible overlap (that the tool tries to avoid).

 

VHDL (and Verilog) are hardware description languages. Don't think of them as a programming language. The "compiler" will match your code against patterns it can implement (i.e. edge-triggered flipflops, multiplexers, gates, state machines, memory etc). If you use patterns that don't exist in the hardware, you'll run into trouble.

 

Now to me, this looks like a fully combinational circuit, no clocks (as there is no "rising_edge(xyz)" statement or the like). I don't understand the error message in this context, but it wouldn't be the first time that a Xilinx tool says "X" when it means "Y".

 

The standard coding style for FPGAs is synchronous logic. If I were you, I'd adopt it and rewrite the program, get a clock and put everything inside "if rising_edge(clk)".

Link to comment
Share on other sites

Here is a picture of the logical blocks that make up your design as written - you can see that it is using latches:

post-29512-0-12758000-1411381456_thumb.j

 

If you look at the technology schematic, you can see that switch(7) is routed through a clock buffer to the 'gate' input on a latches:

post-29512-0-67449000-1411381762_thumb.j

 

And here is what it looks like if you use "rising_edge(en)" instead, much the same but using D flip-flops.:

post-29512-0-11953300-1411381498_thumb.j

 

I times likes these there are usually some warnings that are helpful once you know what is wrong:

WARNING:Xst:737 - Found 4-bit latch for signal <ANODES>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.WARNING:Xst:737 - Found 7-bit latch for signal <SEGMENTS>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

If you cover all paths through the code setting ANODES and SEGMENTS it becomes combinatorial,

seg_proc: process(en, cell, value)   begin      if en = '1' then         case cell is            when "00"   => ANODES <= "0111";            when "01"   => ANODES <= "1011";            when "10"   => ANODES <= "1101";            when "11"   => ANODES <= "1110";            when others => ANODES <= "1111";         end case;          case value is            when "0000" => SEGMENTS <= "1000000";            when others => SEGMENTS <= "1111111";         end case;     else          ANODES <= "1111";          SEGMENTS <= "1111111";      end if;   end process; 

 

and gets implemented with just LUTs and no clocks:

 

post-29512-0-45454700-1411382320_thumb.j

 

[

Link to comment
Share on other sites

Nice post hamster, thank you. :)

 

Flag, it looks like the latch warning got you in this case. One rule of thumb I always use, after being bitten by problems like this, is the first thing I look for when something isn't making sense is to look at the synthesis report for any warnings about latches. If there are then it means you need to look into the section of code that is generating the latches. It's usually an incomplete statement like hamster showed. I really like how hamster showed looking at the schematic output of the design, that made it very crystal clear what hardware was being implemented. I'm going to remember that one for later. :) The thing to remember is that FPGA's don't have native support for latches, if you need to hold a value then you want a register instead. So if you see a latch being implemented then 9 out of 10 times there is a problem...

 

I think this also clearly demonstrates that you need to think about your design as hardware, as offroad says. It's important to know what hardware your HDL code will implement, if you think of VHDL as a programming language then what is actually happening is going to be a mystery...

 

Jack.

Link to comment
Share on other sites

Nice post hamster, thank you. :)

 

The thing to remember is that FPGA's don't have native support for latches, if you need to hold a value then you want a register instead. So if you see a latch being implemented then 9 out of 10 times there is a problem...

 

Actually, the Xilinx Spartan-3 (including -3A and -3E) and Spartan-6 do have clocked latches: each CLB flip-flop can be an edge-trigged register or a clocked latch, with configurable clock edge or level.  However, use of latches in FPGAs is very rare compared to registers so Jack is right that if you see them in the synthesis report it's usually a problem.

 

IMO, one of the disadvantages of VHDL is that a "signal" can be a combinational net or a register, depending on how it's used.  Flag's example shows how a latch can appear out of nowhere due to a seemingly-unrelated error.  In Verilog, you declare a signal to be a "wire" or a "reg" which avoids the "signal" ambiguity.

Link to comment
Share on other sites

John,

 

Thank you for the clarification, my understanding was that latches are possible on Xilinx FPGA's but they had to be built up from other elements, but I just heard that and took it at face value, I never looked at the datasheet to verify it. Thank you for the additional info.

 

While we are on the topic, in what cases would a latch be preferable over a register? Anyone have any good examples?

 

Jack.

Link to comment
Share on other sites

>>   In Verilog, you declare a signal to be a "wire" or a "reg" which avoids the "signal" ambiguity.

 

I wouldn't bet on that. A "reg" can be used also for temporary variables when assigned with "=". For example, take this construct, a priority decoder that manages access to a shared resource like a memory port.

The temporary variable "busy" allows to write it "flat", without nested "if"s.

"busy" does not result in a hardware register, as it doesn't retain memory.

 

reg busy;

always @(posedge clk) begin

busy = 0; ack_1 <= 0; ack_2 <= 0; ack_3 <= 0; // non-final assignment

if (!busy && request_1) begin

ack_1 <= 1; busy = 1; (do something with request 1)

end

if (!busy && request_2) begin

ack_2 <= 1; busy = 1; (do something with request 2)

end

if (!busy && request_3) begin

ack_3 <= 1; busy = 1; (do something with request 3)

end

...

end

 

But I wouldn't encourage this coding style without good reason, in my own code I highlight blocking assignments with comments so that they stick out. Even though, it's not as confusing as it may seem once I've gotten used to this coding pattern.

Link to comment
Share on other sites

>> in what cases would a latch be preferable over a register?

 

Hi,

 

possibly when we don't have a clock.

For example, one proprietary three-wire standard uses "high-low" on the data wire without clock activity to reset the slave. I could use a non-clocked latch to remember "data wire high while clock low", and handle the reset event at the next clock edge.

 

This is a constructed example, though (a typical slave of this protocol is an ASIC that can use whatever circuitry).

I guess they have to support latches for legacy designs, or if someone insists on using textbook logic (maybe for ASIC emulation?).

Link to comment
Share on other sites

John,

 

Thank you for the clarification, my understanding was that latches are possible on Xilinx FPGA's but they had to be built up from other elements, but I just heard that and took it at face value, I never looked at the datasheet to verify it. Thank you for the additional info.

 

While we are on the topic, in what cases would a latch be preferable over a register? Anyone have any good examples?

 

Jack.

 

I have couple of examples in my XXICC reference The XXICC Anthology rev 0.0k, which is a free download from element14: http://www.element14.com/community/docs/DOC-68247/l/the-xxicc-anthology-rev-00k

 

The examples are in section 11.2 on pages 151-152.  They're not simple examples, but show how a latch can sometimes be used to save a pipeline stage by allowing a register's value to be used in the same cycle that it's updated instead of having to wait for the next clock cycle.

Link to comment
Share on other sites

>>   In Verilog, you declare a signal to be a "wire" or a "reg" which avoids the "signal" ambiguity.

 

I wouldn't bet on that. A "reg" can be used also for temporary variables when assigned with "=". For example, take this construct, a priority decoder that manages access to a shared resource like a memory port.  The temporary variable "busy" allows to write it "flat", without nested "if"s.  "busy" does not result in a hardware register, as it doesn't retain memory.

 

reg busy;

...

But I wouldn't encourage this coding style without good reason, in my own code I highlight blocking assignments with comments so that they stick out. Even though, it's not as confusing as it may seem once I've gotten used to this coding pattern.

 

Thank you for that example, offroad.  I never use blocking assignments in Verilog, so I wasn't aware of this "feature" of the language.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.