I'm trying to work through an example of the WAIT ON statement. Every time I try to compile my code the the compiler, Quartus II gives me the following error message.
Error (10533): VHDL Wait Statement error at T1.vhd(23): Wait Statement must contain condition clause with UNTIL keyword
The model Architecture is below. Its function is not important only the reason why the compiler is asking for a UNTIL statement. All the examples I have seen, internet and books show its use as such below:
ARCHITECTURE dflow OF T1 IS
SIGNAL middle : std_logic;
BEGIN
P1 : PROCESS IS
BEGIN
IF CLK = '1' THEN
middle <= input;
END IF;
WAIT ON CLK;
END PROCESS P1;
OUTPUT <= MIDDLE;
END ARCHITECTURE dflow;
I think the basic problem here is that the line
WAIT ON CLK;
is waiting for any type of event on CLK. This could be a transition from 'H' to '1', for example, or it could be either a rising OR falling edge of CLK. In either of these cases, there is no real hardware in the FPGA that can work in this way. It may seem obvious to you that you are looking for a rising edge, because of the if CLK = '1' line, but this is not how the synthesis tool is seeing it.
By adding an until, you can narrow down which particular event you are interested in, hopefully selecting something that can actually be realised in the FPGA. Examples:
wait on clk until clk = '1'; -- Detect a rising edge, OK (ish, see below)
wait on clk until clk = '0'; -- Detect a falling edge, OK (^^)
This method is analogous to the clk'event and clk = '1' technique of edge detection. This is not a recommended method, because you can get a simulation mismatch with reality due to the simulator responding to transitions from 'H' to '1' (among other possibilities), something the hardware cannot do.
The recommended method of detecting edges is with the rising_edge and falling_edge functions:
wait until falling_edge(clk); -- OK, no ambiguity here.
Finally, the whole structure represented here looks pretty non-standard. The common way to write a clocked process is like this:
process (clk)
begin
if (rising_edge(clk)) then
-- Do something
end if;
end process;
Related
I am reading the book Free Range VHDL and here is an example of chapter 8.
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_fsm1 is
port ( TOG_EN : in std_logic;
CLK,CLR : in std_logic;
Z1 : out std_logic);
end my_fsm1;
-- architecture
architecture fsm1 of my_fsm1 is
type state_type is (ST0,ST1);
signal PS,NS : state_type;
begin
sync_proc: process(CLK,NS,CLR)
begin
-- take care of the asynchronous input
if (CLR = '1') then
PS <= ST0;
elsif (rising_edge(CLK)) then
PS <= NS;
end if;
end process sync_proc;
comb_proc: process(PS,TOG_EN)
begin
Z1 <= '0'; -- pre-assign output
case PS is
when ST0 => -- items regarding state ST0
Z1 <= '0'; -- Moore output
if (TOG_EN = '1') then NS <= ST1;
else NS <= ST0;
end if;
when ST1 => -- items regarding state ST1
Z1 <= '1'; -- Moore output
if (TOG_EN = '1') then NS <= ST0;
else NS <= ST1;
end if;
when others => -- the catch-all condition
Z1 <= '0'; -- arbitrary; it should never
NS <= ST0; -- make it to these two statements
end case;
end process comb_proc;
end fsm1;
Is there any difference if I remove NS from the sensitivity list of sync_proc?
sync_proc: process(CLK,NS,CLR)
begin
-- take care of the asynchronous input
if (CLR = '1') then
PS <= ST0;
elsif (rising_edge(CLK)) then
PS <= NS;
end if;
end process sync_proc;
After examining the question this is considered a duplicate of as well as it's answer lacking any authoritative reference as to when a signal belongs in the sensitivity list it may be worth asking where is that information derived from?
You could note Free Range VHDL only mentions wait as a reserved word in VHDL. There's much more to it than that. A process statement described in the VHDL standard (IEEE Std 1076-2008 10.3 Process statement) tells us:
If a process sensitivity list appears following the reserved word process, then the process statement is assumed to contain an implicit wait statement as the last statement of the process statement part; this implicit wait statement is of the form
wait on sensitivity_list ;
And then goes on to dicuss how the rules of 10.2 Wait statement are applied to a sensitivity list consisting of the reserved word all.
The syn_proc from architecture fsm1 of entity my_fsm1 from Free Range VHDL Listing 7.1 Solution to Example 18 has a sensitivity list in accordance with the rules found in 10.2 Wait statement for an implicitly generated sensitivity.
However, that's not the complete set of authorities. There's also IEEE Std 1076.6-2004 (RTL Synthesis, now withdrawn) 6.1.3.1 Edge-sensitive storage from a process with sensitivity list and one clock:
d) The process sensitivity list includes the clock and any signal controlling an <async_assignment>.
Where <async_assignment> is defined in 6.13 Modeling edge-sensitive storage elements:
<async_assignment>. An assignment to a signal or variable that is not controlled by <clock_edge> in any execution path.
And <clock_edge>is defined by convention (1.4) as one of the forms for clock_edge defined in BNF found in 6.1.2 Clock edge specification.
(translation: d) above means what you think it means when you read it.)
This tells us what signals are necessary here. There are no restrictions on unnecessary signals in the process sensitivity list. However their effect can be discerned from IEEE Std 1076-2008 10.2 Wait statement:
The suspended process also resumes as a result of an event occurring on any signal in the sensitivity set of the wait statement. If such an event occurs, the condition in the condition clause is evaluated. If the value of the condition is FALSE, the process suspends again. Such repeated suspension does not involve the recalculation of the timeout interval.
For a wait statement:
wait_statement ::=
[ label : ] wait [ sensitivity_clause ] [ condition_clause ] [ timeout_clause ] ;
it helps if you know the condition clause is optional as indicated by the square brackets above:
The condition clause specifies a condition that shall be met for the process to continue execution. If no condition clause appears, the condition clause until TRUE is assumed.
That means the process will resume for any event on any of the signals in the process sensitivity list and will traverse it's sequential statements.
There is no harm to the state of the design hierarchy during simulation by executing the sync_proc for an event on signal NS. Neither assignment statement in the if statement subject to conditions will execute. You could also note the same holds true for an event on the falling edge of CLK.
The objective in paring the sensitivity list is to minimize the number of times the process is resumed needlessly. The bigger more complex the design model the slower simulation will proceed, particularly dragging around needless resumptions and suspensions.
Of the three signals shown in the process sensitivity list only three binary value transitions are of interest, and none on signal NS. The current value of NS is assigned to PS on the rising edge of CLK.
A process suspends and resumes in a particular wait statement. A process with a sensitivity list shall not contain an explicit wait statement (10.3), meaning it will have only one wait statement, the implicit one.
It would seem with your first question on VHDL here you've reached beyond the limits of answers the book Free Range VHDL can supply.
A better entreaty on the subject might be The Designer's Guide to VHDL, 3rd edition by Peter Ashenden.
The idea being conveyed here that you can't get why without knowing how.
We always use process block with clock and reset in sensitivity list to describe sequence circuit.And use process block with every driver signals in sensitivity list to describe combinational circuit.
Sometimes sensitivity list is only important for simulations but if you forget a signal or add too many signals in sensitivity list you may get the wrong simulation result. Most time the real FPGA function will work fine if your logic is correct.
But it can cause some problem.
For example, if you describe a function like a=b&c in an always block with sensitivity (b); But you forget c. Then in your simulation a will not change when c is changed. But the circuit in real FPGA, will be the correct description of the function a=b&c. And you may get a warning when you synthesize your code.
You can call it ‘pre-sim and post-sim inconsistent’.
The real scary thing is that your pre-sim is right but your post-sim is wrong. That may cause the FPGA to incorrect function.
So I advise you to describe the circuit than the function when you write VHDL code.
I have a question on VHDL. The code below is for a +/- 2 degree thermostat it works and simulates well, but I have a few unexplained warnings one of them in particular is really bugging me.
LIBRARY IEEE;
USE IEEE.std_logic_1164.all, IEEE.std_logic_arith.all;
ENTITY thermo IS
PORT (
Tset, Tact: in integer;
Heaton: out std_logic
);
END ENTITY thermo;
ARCHITECTURE sequential OF thermo IS
BEGIN
PROCESS (Tact, Tset) IS
VARIABLE ONOFF: std_logic;
BEGIN
IF Tact <= (Tset - 2) then
ONOFF := '1';
ELSIF Tact >= (Tset + 2) then
ONOFF := '0';
ELSE ONOFF := ONOFF;
END IF;
Heaton <= ONOFF;
END PROCESS;
END ARCHITECTURE sequential;
The warning message thats bugging me is this:
Warning (10631): VHDL Process Statement warning at thermo.vhd(19): inferring latch(es) for signal or variable "ONOFF", which holds its previous value in one or more paths through the process<
Like I said the code works ok on ModelSim but this makes me think i am going about things the wrong way. Any suggestions ?
Thanks
Danny J
The process is specified to hold the current value of ONOFF with the line:
ELSE ONOFF := ONOFF;
Holding the value based on combinatorial inputs, like Tact and Tset, requires a latch, as reported in the warning, since usually latches means that the designer created code with an unintentional side effect.
If you want to keep the state, then consider making a clocked process instead; a template is provided in this answer.
If you want a combinatorial output, then get ridge of the internal ONOFF process variable, and make sure that an explicit value is assigned in all branches of the if statement.
You have described a SR latch for the signal ONOFF. This works fine in simulation but makes problems in FPGAs as well as digital circuits build from discrete components.
Your latch is set when the expression Tact <= (Tset - 2) is true. Now image a point in time, when the latch is currently in state '0' and Tact = Tset. Thus, the latch keps '0' as expected. This works as long as Tact is not changing. Now let the temperature fall to Tact = Tset-1. According to the above expression, the latch should keep in state '0'. But, this cannot be ensured in real hardware because the expression is not evaluated at once. Instead the multi-bit comparator for the <= operator may produce a glitch because the comparator itself is composed of several gates. If one of these gates is switching faster than another one, there might be an intermediate result, where the expression is true and, thus, your latch becomes '1'.
To notify the designer, that latches are susceptible for glitches, the synthesis compiler issues the above warning. To circumvent this problem, the FPGA offers D flip-flops which state is only updated on clock-edges. The timing analyzer of the FPGA toolchain ensures, that the evaluation of the above expression is completed before the next rising (or falling) clock-edge. So, the designer has not to worry about glitches!
You can describe a clock-edge triggered SR flip-flop in VHDL which is then mapped to the D flip-flop of the FPGA by the synthesis tool. The code style is as follows:
signal Q : std_logic; -- declare signal in the declarations part of the architecture
...
process(clock)
begin
if rising_edge(clock) then -- flip-flop triggered at the rising clock edge
if set_expression then
Q <= '1';
elsif reset_expression then
Q <= '0';
end if;
end if;
end if;
The state of the SR flip-flop is saved in the signal Q. I have used a signal instead of an variable here, because variables are harder to debug. (I recommend to use signals as often as possible.) In this code example, if both set_expression and reset_expression are both true, then the "set" takes precedence. (Can be flipped if required.) If none of the expressions is true, then the old state is saved as required by a flip-flop.
In my coding when I write this statement, it is simulated, but not synthesizable. why? Now what should I do to solve this problem???
IF ((DS0='1' OR DS1='1')and rising_edge(DS0) and rising_edge(DS1) AND DTACK='1' AND BERR='1') THEN
RV0 <= not RV;
else
RV0 <= RV;
The most important thing when doing FPGA-designs is to think hardware.
An FPGA consists of a number of hardware blocks, with a predetermined set of inputs and outputs - the code you write needs to be able to map to these blocks. So even if you write code that is syntactically correct, it doesn't mean that it can actually map to the hardware at hand.
What your code tries to do is:
IF ((DS0='1' OR DS1='1')and rising_edge(DS0) and rising_edge(DS1) AND DTACK='1' AND BERR='1') THEN
(...)
If DS0 and DS1 currently have a rising edge (implying that they're also both '1', making the first part with (DS='1' OR DS1='1') redundant), and if DTACK and BERR are both 1, then do something.
This requires an input block that takes two clock inputs (since you have two signals that you want to test for rising edges simultaneously), and such a block does not exist in any FPGA I've encountered - and also, how close together would such two clock events need to be to be considered "simultaneous"? It doesn't really make sense, unless you specify it within some interval, for instance by using a real clock signal (in the sense of the clock signal going to the clock input of a flip-flop), to sample DS0 and DS1 as shown in Morten Zilmers answer.
In general, you'd want to use one dedicated clock signal in your design (and then use clock enables for parts that need to run slower), or implement some cross-clock-domain synchronization if you need to have different parts of your design run with different clocks.
Depending on the IDE environment you use, you may have access to some language templates for designing various blocks, that can help you with correctly describing the available hardware blocks. In Xilinx ISE you can find these in Edit > Language Templates, then, for instance, have a look at VHDL > Synthesis Constructs > Coding Examples > Flip Flops.
An addition to sonicwave's good answer about thinking hardware and synthesis to
the available elements.
The rising_edge function is generally used to detect the rising edge of a
signal, and synthesis will generally use that signal as a clock input to a
flip-flop or synchronous RAM.
If what you want, is to detect when both DS0 and DS1 goes from '0' to
'1' at the "same" time, then such check is usually made at each rising edge
of a clock, and the change is detected by keeping the value from the
previous rising clock.
Code may look like:
...
signal CLOCK : std_logic;
signal DS0_PREV : std_logic;
signal DS1_PREV : std_logic;
begin
process (CLOCK) is
begin
if rising_edge(CLOCK) then
if (DS0 = '1' and DS0_PREV = '0') and -- '0' to '1' change of DS0
(DS1 = '1' and DS1_PREV = '0') and -- '0' to '1' change of DS1
DTACK = '1' AND BERR = '1' then
RV0 <= not RV;
else
RV0 <= RV;
end if;
DS0_PREV <= DS0; -- Save value
DS1_PREV <= DS1; -- Save value
end if;
end process;
...
My question is in regards to the following code:
library ieee;
use ieee.std_logic_1164.all;
entity exam is port (
I,CLK,RESET : in std_logic;
Q : out std_logic
);
end entity;
architecture exam_arc of exam is
signal temp_sig : std_logic;
begin
process (CLK,RESET)
begin
if RESET = '1' then
temp_sig <='0';
elsif CLK'event and CLK='1' then
temp_sig <= I;
end if;
Q <= temp_sig;
end process;
end exam_arc;
It seems that this piece of code simulates a D flip flop that operates on rising edge of the clock, however the answer [this question is taken from an exam] to this question claims that this D flip flop operates on falling edge of the clock.
What kind of flip flop this VHDL code simulates?
It's a trick question. Note that the process wakes up on both rising and falling clock edges, and that the intermediate signal temp_sig is assigned on the rising_edge.
Put that together with the semantics of signal assignment (postponed assignment) and see what you get.
Cross check via simulation as Jim suggests...
Separate the assignment to Q into it's own process statement with the same sensitivity list. The simulation models behavior will be identical although they vary in the number of processes.
DUT:
process (CLK,RESET)
begin
if RESET = '1' then
temp_sig <='0';
elsif CLK'event and CLK ='1' then
temp_sig <= I;
end if;
-- Q <= temp_sig;
end process;
QDEVICE:
process (CLK, RESET)
begin
Q <= temp_sig;
end process;
The edge sensitive storage device assigning temp_sig is clearly a positive edge clocked flip flop sensitive to CLK and asynchronously reset by RESET (high).
Is the QDEVICE process a synthesis target construct? It behaves as a follower latch to the temp_sig flip flop, but there is no indication as to the polarity of an enable. See IEEE Std 1076.6-2004 IEEE Standard for VHDL Register
Transfer Level (RTL) Synthesis, 6.2.1.1 Level-sensitive storage from process with sensitivity list:
A level-sensitive storage element shall be modeled for a signal (or variable) when all the following apply:
c) There are executions of the process that do not execute an explicit
assignment (via an assignment statement) to the signal (or variable).
Without qualification (by level) rule c is not met. Further in the original process you cite the behavior doesn't map to one of the IEEE Std 1076.6-2004 6.2 Clock edge specifications none of which include using an intermediary signal.
Brian is right it's a trick question. A flip flop with a follower-something-else providing delay. And the 'U' value in the simulation for q until an event on CLK or RESET should be telling.
You could just synthesize it yourself.
See also ffv3 http://www.cs.uregina.ca/Links/class-info/301/register/lecture.html which is almost the same.
Update
I was missguided by the missing formatting – in fact it actually is toggling on the falling edge as another answer already shows.
Although all asignments are done in sequence, signal assignments still happen at the end of the process, and thus temp_signal is half a clock cycle old (next falling edge) and does not contain the recently asigned value.
http://www.gmvhdl.com/process.htm
How does signal assignment work in a process?
Have you simulated it? When does Q change and why? When do signals update? During a rising edge, does Q get the value of I? Make sure to simulate it.
Lets look at the following line of code:
elsif CLK'event and CLK='1' then
CLK is your timing signal (aka the clock).
CLK'event is triggered when there is a change in the value of CLK.
CLK='1' means that the clock is equal to high.
So if the clock has changed and it is currently in the high state then we will execute the code within this ELSIF statement.
We know that there are only 2 states for bit variables, so if CLK changed AND it changed to a high state then it was originally in a low state. This means that the code will only execute when the clock goes from low to high.
If you wanted to execute on a high to low trigger then you would change the statement to read like this:
elsif CLK'event and CLK='0' then
I have used below statement, frequently. However, I wonder
if ( clock'event and clock = '1' ) then
[do something]
we really need to write clock'event in above statement ?
If yes, why?
You could get the simulation to work perfectly without the clock'event condition, but the synthesis will come out wrong.
The IEEE standard on synthesizable VHDL requires that you add clock'event.
It is commonly accepted good practice to write if rising_edge(clock) instead. This conveys your intention a lot better. Both rising_edge and falling_edge functions are allowed as synthesizable VHDL constructs.
For simulation:
process (clock) is
-- stuff
begin
if clock='1' then -- EVIL! don't do this
-- do things
end if;
end process;
Assuming that clock just switches from '0' to '1' and back (no meta-values), the behavior would be identical to what you'd get with a clock'event condition. Again, this will not synthesize to what you want! You'll probably get a latch, not a D flip-flop.
(Bonus points for whomever tries to synthesize this and gets back with the results!)
Yes, otherwise the following code executes the entire time your clock signal is high, not just at the rising edge of the clock.