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.
Related
I created the following Counter with a compare match functionality:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity Counter is
generic (
N : natural := 24
);
port (
-- Input counter clock
clk : in std_logic := '0';
-- Enable the counter
enable : in std_logic := '0';
-- Preload value loaded when clk is rising and load is 1
load_value : in std_logic_vector((N-1) downto 0) := (others => '0');
-- Set to 1 to load a value
load : in std_logic := '0';
-- Compare match input is compared with the counter value
compare_match_value : in std_logic_vector((N-1) downto 0) := (others => '0');
-- Is 1 when compare_match_value = counter_value
compare_match : out std_logic := '0';
output_value : out std_logic_vector((N-1) downto 0) := (others => '0')
);
end Counter;
architecture Behavioral of Counter is
signal counter_value : unsigned((N - 1) downto 0) := to_unsigned(0, N);
begin
output_value <= std_logic_vector(counter_value);
process (clk) is
begin
if rising_edge(clk) then
if enable = '1' then
if load = '1' then
counter_value <= unsigned(load_value);
else
counter_value <= counter_value + 1;
end if;
else
if load = '1' then
counter_value <= unsigned(load_value);
end if;
end if;
end if;
end process;
process (counter_value) is
begin
if unsigned(compare_match_value) = counter_value then
compare_match <= '1';
else
compare_match <= '0';
end if;
end process;
end Behavioral;
The behavior of my counter is to be fully synchronous with the input clk signal. Disabling the counter is always possible and the value is held at the current count value. A load value can be assigned with the load and load_value signal. Whenever the load signal is high and a rising edge is detected, the counter value is updated to the load_value.
Another feature is the compare unit which outputs high on compare_match output. The simulation works as expected but I have a few questions when synthesizing this design on spartan 3 fpga.
Is this considered a good design of my counter because I'm still not much experienced in VHDL.
Are there any undefined states when using the compare unit in further logic in my design? As I see it compare_match is calculated whenever the counter_value is updated.
When using a large number for N, is there anything special about the delay I need to consider?
In general it seems to me a quite good description.
However, I would like to point out some minor things (that might me some answers to your 1st question).
1) As, I see right now your counter does not contain any reset (neither asynchronous nor synchronous). In general you cannot predict the starting point of your counting (even if, probably, it will be all '0's at start-up).
In my opinion, it would be a neater design if you could have a reset signal.
I also noticed that the loading is activated regardless of the fact that the counter is enabled or not. I have no comment about this since it could be a specification for your design. Maybe you can compact the code by moving the "if load" part outside of the "if enable" (i.e. changing the order to the comparisons).
To improve the readability (especially when the designs will be more complex), I advise you to label the process. This will help you to identify the different part of the design.
You can skip lot of the extra-typing if you use the VHDL-mode of emacs. It has built in templates that would take care of the "boring" part related to coding.
I also see that you have default values for your input ports. In my opinion, this is not a very good practice; they would be ignored by synthesizer leading to an IP that might behave differently than what you expect. In general, do not make assumptions (a part those that are specified) on the external signals.
Finally, I have a comment about the compare part.
This goes for both question 1) & 2)
1-2)
In the compare process, you have just listed counter_value in the sensitivity-list.
This means that the process would be activated only when counter_value changes.
Since you compare it with a signal (compare_match_value) that is an input to the block (hence it can change values) it would be better to have it too in the sensitivity-list. Otherwise, the comparison would not apply (i.e. the process would not be activated) when you change compare_match_value.
Linting tools and synthesizer might complain about it (stating warning like incomplete sensitivity-list). As matter of fact it is good practice to list all the signals that may change in the list for combinatorial processes.
Regarding the comparison itself, the way you described it is absolutely fine and you would not have uncovered states. Basically you have specified all possible conditions so no surprises there.
3)
Regarding your 3rd question, since you are targeting an FPGA, you could "relax" about it. FPGAs have dedicated structure for fast arithmetic operations and (as long as you do not use all of them) the synthesizer would use them to close time.
Also in ASIC, synthesizer would probably select an appropriate arithmetic structure to close time.
If you want to be on the safe side, you can add a register at the output of the comparison block. This will prevent creating a long combinatorial path especially if you IP has to be integrated with other blocks. Of course this extra-register would add an 1-clock-cycle latenc, but it will improve your overall timing.
I hope these suggestions could be useful to you and cover (at least partially) your doubts.
Keep on coding :)
It has been a while since I have used VHDL and Verilog and while studying some material I came up with this question.Unfortunately I do not any specific example or issue.
At first, you can only specify signals in a sensitivity list and no variables.
For synthesis:
There is usually no difference, because synthesis doesn't rely on sensitivity lists.
For simulation:
If you specify to few signals, you might not see the expected behavior. If you specify to much signals, you might see a behavior that does not match the synthesis behavior.
In addition, by specifying more signals than required, the simulation loop will be slower due to more possible events that must be checked.
For sequential logic, Design Compiler produces an error if a redundant signal in the sensitivity list is not suitable to be a reset or clock signal. Multiple reset signals are permitted, but there is no permission for multiple clocks.
Let's think that is what we intend to design.
always_ff #(posedge clk, posedge rst)
if (rst)
a <= 1'b0;
else if (en)
a <= b:
If we add en, a, b, or c to the sensitivity list, the error message below is produced.
The expression in the reset condition of the 'if' statement in this
'always' block can only be a simple identifier or its negation.
(ELAB-303)
This is the code causing the error (en is the uninvited signal).
always_ff #(posedge clk, posedge rst, posedge en)
if (rst)
a <= 1'b0;
else if (en)
a <= b;
The en signal is not suitable to be a reset, because it doesn't set a to a constant value.
In the code below, the redundant signal is c. It's not used inside the always block, so can't be a reset. Then it becomes a candidate for clock, but we have clk signal too. The same error message is produced here.
always_ff #(posedge clk, posedge rst, posedge c)
if (rst)
a <= 1'b0;
else if (en)
a <= b;
The code snippet below is synthesizable. Since c sets a signal to a constant value, it can be a reset as well as rst signal. DC will synthesize it, but the combinational logic on the reset path may cause timing violations.
always_ff #(posedge clk, posedge rst, posedge c)
if (rst)
a <= 1'b0;
else if (c)
a <= 1'b1;
else if (en)
a <= b;
My last example has a redundant signal in the sensitivity list w/o any trigger condition (pos/negedge). DC produces a different error here.
always_ff #(posedge clk, posedge rst, c)
if (rst)
a <= 1'b0;
else if (c)
a <= 1'b1;
else if (en)
a <= b;
The event depends on both edge and nonedge expressions, which
synthesis does not support. (ELAB-91)
All these cases can be extended, but the results are not guaranteed to be the same with the other synthesis tools.
We always use always block with clock and reset in sensitivity list to describe sequence circuit.And use always 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 in sensitivity list you may get the wrong simulations. In 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 infer incorrect logic.
fpga verilog vhdl
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;
...
For example in an unclocked process, all signals have to be set in every case to prevent latches from being implemented.
But is this also the matter in a clocked process? I keep thinking this is not the case, but a friend of mine tells me I have to set all signals in all cases to prevent the synthesis from introducing latches even here.
A properly implemented clocked process will create registers where an unclocked process would create latches.
And registers are different from latches, especially in our ability to predict their timings; as well as being better supported in FPGAs, so this is usually a Good Thing.
"Properly implemented" means that ONLY Clock and (maybe) Reset) are in the sensitivity list.
I was surprised recently because the following code produces latches, even though only clock and reset are on the sensitivity list:
library ieee;
use ieee.std_logic_1164.all;
entity unwanted_latches is
port (
clock: in std_logic;
reset: in std_logic
);
end;
architecture rtl of unwanted_latches is
function update_vector(vector: std_logic_vector) return std_logic_vector is
variable return_value: std_logic_vector(vector'range);
begin
return_value := vector;
return_value(0) := not return_value(0);
return return_value;
end;
signal my_vector: std_logic_vector(7 downto 0) := (others => '0');
begin
update_my_vector: process (clock, reset) begin
if reset then
my_vector <= (others => '0');
elsif rising_edge(clock) then
my_vector <= update_vector( my_vector );
end if;
end process;
end;
The exact message output by Quartus 12.1 is:
Warning (10631): VHDL Process Statement warning at
unwanted_latches.vhd(25): inferring latch(es) for signal or variable
"my_vector", which holds its previous value in one or more paths
through the process
So, my strict answer to your question would have to be: yes, a clock process can introduce latches. But I'm more inclined to agree with #MartinThompson that this is a tool problem.
Sounds like there may be a terminology issue...
Flipflops are edge-triggered storage elements
Latches are level-sensitive storage elements
You can't get a latch in a clocked process that's done right - just the clock in the sensitivity list (and if the reset is asynchronous, that too). Any tool which produces latches from that description is broken.
(I guess it's possible that, in olden times, you might get flipflops that you didn't want if you didn't initialise signals that weren't supposed to the made into flipflops, but there's a lot of ancient but wrong "lore" around where VHDL is concerned)
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