This is my VHDL code:
entity Operation is
port (
clk16: in std_logic; // 16 MHz input clock
start_cmd: inout std_logic; // open drain line. When CPLD sees it is pulled low, it keeps pulling it low till the operation is finished
clk_out: buffer std_logic; // output clock derived from clk16
);
end Operation;
architecture a of Operation is
type T_STATE is (STOPPED, STARTING, ....another states....);
signal state: T_STATE := STOPPED;
begin
process (clk16, clk_out)
begin
if rising_edge(clk16) then
clk_out <= not clk_out; -- create clk_out clock
end if;
if rising_edge(clk_out) then
case state is
when STOPPED =>
if start_cmd = '0' then
state <= STARTING;
start_cmd <= '0' -- sometimes this doesn't happen
end if;
when STARTING =>
-- code continues here.... after the operation is finished, start_cmd <= 'Z' is "executed"
I have start_cmd signal connected to my CPLD. It is open drain signal with pull up that is connected also to another device. When another device wants CPLD to start some operation, it pulls start_cmd to low. When CPLD sees start_cmd is low it also pulls the line low. After a while another device releases the line. When the operation by CPLD is finished, CPLD releases the line. As nobody is now pulling the line low, the line goes high. Another device then knows that CPLD's operation finished.
The problem is that sometimes (10 %) start_cmd <= '0' is not "executed" so start_cmd signal returns high once another device stops pulling start_cmd low. Another device then detects false "operation finished".
Can you see any problem why start_cmd <= '0' is not "executed" sometimes?
I debugged my device using oscilloscope and I can see that this situation happens when another device pulls start_cmd to low exactly at rising edge of clk_out.
This VHDL is implemented on MAX V CPLD using Quartus Prime.
First - I think you should always initialize the inout with 'Z' at start up
Add a new state INIT to T_STATE
type T_STATE is (INIT,STOPPED, STARTING, ....another states....);
and initialise state to INIT
signal state: T_STATE := INIT;
case state is
when INIT =>
start_cmd <= 'Z';
state <= STOPPED;
when STOPPED =>
:
Second I'm not sure about the requirement of the clk_out buffer . I don't think it is needed unless there is a specific reason. It seems like all you need is
if falling_edge(clk16) then
case state is
:
Related
I have the following simple FSM description in VHDL:
library ieee;
use ieee.std_logic_1164.all;
entity coverage1 is
port (
clk : in std_logic;
rst : in std_logic;
req : in std_logic;
ack : out std_logic
);
end entity coverage1;
architecture rtl of coverage1 is
type STATES is (IDLE, RUNNING, FINISH);
signal fsm_cs : STATES := IDLE;
signal fsm_ns : STATES;
begin
process (fsm_cs, req) is
begin
fsm_ns <= fsm_cs;
ack <= '0';
case fsm_cs is
when IDLE =>
if req = '1' then
fsm_ns <= RUNNING;
end if;
when RUNNING =>
fsm_ns <= FINISH;
when FINISH =>
ack <= '1';
fsm_ns <= IDLE;
when others =>
null;
end case;
end process;
process (clk) is
begin
if rising_edge(clk) then
if rst = '1' then
fsm_cs <= IDLE;
else
fsm_cs <= fsm_ns;
end if;
end if;
end process;
end architecture;
And this testbench:
library ieee;
use ieee.std_logic_1164.all;
entity coverage1_tb is
end entity coverage1_tb;
architecture tb of coverage1_tb is
signal clk : std_logic := '1';
signal rst : std_logic;
signal req : std_logic;
signal ack : std_logic;
signal finished : boolean := false;
begin
coverage1_1: entity work.coverage1
port map (
clk => clk,
rst => rst,
req => req,
rdy => rdy,
ack => ack);
clk <= not clk after 5 ns when not finished else unaffected;
process
begin
rst <= '1';
wait until rising_edge(clk);
rst <= '0';
req <= '0';
wait until rising_edge(clk);
req <= '1';
wait until rising_edge(clk);
req <= '0';
wait until rising_edge(clk) and ack = '1';
wait until rising_edge(clk);
finished <= true;
wait;
end process;
end architecture tb;
The FSM does not reach 100% code coverage in ModelSim/QuestaSim. I found two issues:
The others case, which is not required because the enumeration is fully covered by all choices, is requested to be covered. But this branch is not reachable... Why does QuestaSim expect coverage for this branch?
QuestaSim shows a false state diagram for my example FSM. The diagram contains self-edges for the states: RUNNING and FINISH. These edges do not exist nor can they be covered.
If I remove the default assignment fsm_ns <= fsm_cs; and add an else branch in the IDLE state, I'll get full coverage.
if req = '1' then
fsm_ns <= RUNNING;
else
fsm_ns <= IDLE;
end if;
Why does the state diagram show false edges and why can't I use default assignments?
I could live with bullet item 1, but item 2 is a problem. If I write my FSMs in that style, I'm duplicating a lot of unneeded code and most synthesizers won't recognize the FSM pattern! So I'll lose FSM optimizations and checking in synthesis.
Some observations, again using ghdl.
Commenting out the rdy port, ghdl again reports 100% coverage.
Ironically the null in "others" clause gets 20 hits ... which is suspicious. As it's the last active line in the process I believe any events that wake the process but don't do anything are recorded here.
A null; added after end case collects these 20 hits, confirming this - but the others case still isn't recorded as a coverage hole (despite having no hits). My hypothesis is that because null generates no code it isn't being tracked. Adding a harmless but trackable action fsm_ns <= IDLE; to the when others branch now gives a coverage hole (which, annoyingly, receives spurious hits when the null after end case is removed.
Summary :
it's worth testing the effect of an active statement as a hook for tracking coverage in when others, and a null after end case so that "end of process" code isn't incorrectly logged on the last case arm
ghdl needs some tidying up in these two areas, perhaps translating null as a 'nop' to hook the coverage to.
Sorry I can't shed light on Modelsim's behaviour here.
However, code that is present but not reachable - "dead code" - is seen as representing a design error in high integrity practices, so I regard Modelsim as correct to highlight it, and ghdl as incorrect in cases where it does not.
It's somewhat related to the issue of safe state machine design where an SEU (perhaps from a cosmic ray) corrupts the state register. Note that with less than 2**n members of STATES, there WILL be an "other" state, and with a null action, this SM will lock up there if it ever reaches that state. (However, deleting the "others" clause won't correct that, and a synthesis tool may conclude the "others" clause is unreachable and delete it anyway. Safe SM design is another topic)
The when others is shown as not covered, as expected. You can exclude it with:
-- coverage off
when others => null;
-- coverage on
I do this in every case statement where the others case can't be
hit.
I get 100% state coverage, even without the else branch. The if conditional in IDLE state has 100% branch coverage, even without an else branch (Active: 4, True Hits: 1, AllFalse: 3). For 100% FSM coverage you should exclude the implicit changes by the reset signal, or you have to pull the reset in every FSM state. You can exclude the reset state changes with -nofsmresettrans swith when compiling.
I get the same behaviour using Modelsim DE 10.5c and 10.6 and Questa 10.6.
BTW: I can't get FSM coverage if parts of the FSM are inside a generate block which depends on a generic, so I had to outcomment the generate stuff and only leave in one of the reset processes. I think this is an Modelsim/Questa limitation that it don't recognizes FSMs inside of generate blocks, but I'm not. The help also hints that FSMs using generics aren't regognized. Maybe that's the case here.
I have a baffling problem.. As part of a buffering process I am assigning one std_logic_vector to another, by simply doing:
dataRegister <= dataRegisterBuf;
The process is synced to a clock. See here for the full process:
--! This process buffers the data register synced to sclk when state is state_bufferingToSclk and sets registerReady when done
SclkDomainBuffering: process(sclk)
variable step: natural := 0;
begin
if (rising_edge(sclk)) then
if (state = state_bufferingToSclk) then
if (step = 0) then
dataRegister <= dataRegisterBuf;
step := 1;
elsif (step = 1) then
registerReady <= '1';
step := 2;
end if;
else
step := 0;
registerReady <= '0';
end if;
end if;
end process SclkDomainBuffering;
The problem is, when simulating this in Modelsim, dataRegister does not take the value of dataRegisterBuf, instead every '1' in the vector becomes 'X'. So for example if dataRegisterBuf is "00010", dataRegister becomes "000X0". I can't for the life of me figure out why. Here is a simulation showing it happening: http://i.imgur.com/znFgqKl.png
I have stepped through the entire code and I can't see anything out of the ordinary. At the time it happens, line 84 in the code above does indeed execute, and that is the only statement that is executed that has anything to do with the two registers in question as far as I can tell.
Here's a Minimal Complete and Verifiable example created from your question and comments:
library ieee;
use ieee.std_logic_1164.all;
entity baffling_problem is
end entity;
architecture foo of baffling_problem is
type state_type is (state_bufferingToClk, state_bufferingToSclk);
signal state: state_type; -- defaults to 'LEFT, state_bufferingToClk
signal dataRegisterBuf: std_logic_vector (31 downto 0) :=
(1 | 2 => '1', others => '0');
signal dataRegister: std_logic_vector (31 downto 0) := (others => '0');
signal registerReady: std_logic;
signal sclk: std_logic := '1';
begin
SclkDomainBuffering: process(sclk)
variable step: natural := 0;
begin
if (rising_edge(sclk)) then
if (state = state_bufferingToSclk) then
if (step = 0) then
dataRegister <= dataRegisterBuf;
step := 1;
elsif (step = 1) then
registerReady <= '1';
step := 2;
end if;
else
step := 0;
registerReady <= '0';
end if;
end if;
end process SclkDomainBuffering;
SOMEOTHERPROCESS:
process (state)
begin
if state = state_type'LEFT then -- other than state_bufferingToSclk
dataRegister <= (others => '0');
end if;
end process;
STIMULI:
process
begin
wait for 20 ns;
sclk <= '0';
wait for 5 ns;
sclk <= '1';
wait for 0 ns; -- state transitions in distinct delta cycle
state <= state_bufferingToSclk;
wait for 20 ns;
sclk <= '0';
wait for 5 ns;
sclk <= '1';
wait for 20 ns;
wait;
end process;
end architecture;
And this gives the behavior your describe:
See IEEE Std 1076-2008 14.7.3 Propagation of signal values, 14.7.3.1 General:
As simulation time advances, the transactions in the projected output waveform of a given driver (see 14.7.2) will each, in succession, become the value of the driver. When a driver acquires a new value in this way or as a result of a force or deposit scheduled for the driver, regardless of whether the new value is different from the previous value, that driver is said to be active during that simulation cycle. For the purposes of defining driver activity, a driver acquiring a value from a null transaction is assumed to have acquired a new value. A signal is said to be active during a given simulation cycle if
— One of its sources is active.
— One of its subelements is active.
— The signal is named in the formal part of an association element in a port association list and the corresponding actual is active.
— The signal is a subelement of a resolved signal and the resolved signal is active.
— A force, a deposit, or a release is scheduled for the signal.
— The signal is a subelement of another signal for which a force or a deposit is scheduled.
So the signals (dataReady(1) and dataReady(2) are active their sources is active.
An explanation of why their values are the resolved value of their drivers is found in 14.7.3.2 Driving values, none of the signals comprising dataReady are basic signals, see paragraph 3 f).
And why you see the value of dataReady as "00000000000000000000000000000XX0" is described in 14.7.3.3 Effective values.
The VHDL language describes how an elaborated design model is simulated as well as describing the syntax and semantics. An elaborated design model consists of processes described in a hierarchy interconnected by signals, and signals have history not just value. Signal updates are scheduled in projected output waveforms (see 10.5 Signal assignment statement).
A lot of users just starting out in VHDL apply what they know of the behavior of other languages to VHDL, an example is the superfluous (but not forbidden) parentheses surrounding a condition in an if statement. Knowledge of other languages doesn't address signal behaviors (determined by the architecture of simulation models driven by simulation cycles.
One of the things you'll note is that processes (11.3) suspend and resume based on explicit or implicit wait statements (10.2).
All concurrent statements are elaborated into processes and or processes and block statements (11. Concurrent statements).
Subprogram calls are either expressions (functions, 9.3.4) or statements (procedures, 10.7).
No signal value is updated while any process that is scheduled to be active (those projected output waveforms matching the current simulation time, 14.7.4 Model execution, 14.7.3.4 Signal update).
Signals driven in multiple processes represent multiple collections of hardware. The problem shows up because you've used resolved data types, if you had used unresolved data types you would have gotten an elaboration error instead (6.4.2.3 Signal declarations, paragraph 8). Resolved signals are allowed to have multiple drivers.
The resolution table for std_logic elements is found in the package body for package std_logic_1164(See footnote 15 Annex A Description of accompanying files for access to the source of VHDL packages included with the standard). The resolution table will resolve a '0' and a '1' to an 'X'.
And if all this sounds complex you can learn simple rules of thumb to prevent problems.
In this case a rule of thumb would be to always drive a signal from a single process.
As people in the comments said, the problem was that another process was driving the same data register. I did not understand that even though that other process only changed the value of the register in a different state, it would still drive the signal during every other state. I fixed the problem by moving everything related to that register into a single process.
I have written a simulation process that sets or changes signals sequentially as required, I use wait statements normally to wait certain time intervals or wait on signal assignments, but that is true only when I know when a signal should be coming, an example:
reset <= '1';
write <= '0';
read <= '0';
wait for 25 ns;
reset <= '0';
chipselect <= '1';
wait until clk = '1';
but now I need to do something different, I have a signal that is normally 0, and I need to pause simulation stimulus whenever it is turned to 1. the signal however is not timed. meaning I cannot do it with a simple wait statement because the simulation will wait for it only at a certain time. I want that effect to happen at all times. how to do something like this?
Based on the description, I understand that you want to pause stimuli
generation based on a signal, so stimuli time is extended corresponding to the
time of the pause.
For this a signal with the active time (named active_time below) can be
created, and stimuli can then be generated based on this time. The active time
is only running when the active_stimuli is TRUE.
A support procedure (named active_wait_for below) corresponding to wait for
can then be created to wait for the requested amount of active time, for use in
the stimuli generation process.
Suggestion for code:
architecture syn of tb is
-- Active declarations
signal active_stimuli : boolean := TRUE;
constant ACTIVE_RESOLUTION : time := 1 ps;
signal active_time : time := 0 ps;
-- Wait procedure for active delay
procedure active_wait_for(delay : time) is
variable active_time_start_v : time;
begin
active_time_start_v := active_time;
if delay > 0 ps then
wait until active_time >= active_time_start_v + delay;
end if;
end procedure;
-- Stimuli signal
signal stimuli_a : std_logic;
signal stimuli_b : std_logic;
begin
-- Active time generation
process is
begin
wait for ACTIVE_RESOLUTION;
if active_stimuli then
active_time <= active_time + ACTIVE_RESOLUTION;
else -- Save execution time in loop by wait until
wait until active_stimuli;
end if;
end process;
-- Stimuli generation
process is
begin
stimuli_a <= '0';
stimuli_b <= '0';
wait until active_time >= 2 ns;
stimuli_a <= '1';
active_wait_for(3 ns);
stimuli_b <= '1';
wait;
end process;
...
Waveform showing operation is below:
Note that polarity is different than the signal in the question, but naming was
clearer with this polarity.
Some ideas for "pausing" a stimulus process on an interrupt-type signal:
Rewrite the stimulus as a clocked process (a state machine, for example) and use the interrupt as a clock enable. This may be a pain, though.
Maybe easier, whenever you wait, wait something like this:
wait until clk = '1';
if interrupt = '1' then
wait until interrupt = '0';
wait until clk = '1';
end if;
or if it's not a synchronous wait:
wait for 100 ns;
if interrupt = '1' then
wait until interrupt = '0';
end if;
You could, of course, write a procedure to make these easier. There may be simpler/more elegant ways to code those, but what I wrote should work.
Is this what you want:
process (start) begin
if rising_edge(start) then
-- Respond to start signal rising
end if;
end process;
There is nothing stopping your from writing another process in your testbench/simulation to wait for that other condition to happen. An example of when you might want to do this is when you are simply counting the number of events of a certain condition.
For example:
Signal_Waiter : process(interrupt)
begin
if rising_edge(interrupt) then
-- do stuff here such as increment a counter
end if;
end process;
Since this process is completely independent from your "stimulus" section of code, it is always ready to wakeup and process. In this case, it will wake up whenever the signal interrupt changes.
Be careful if you are driving stimulus signals from the separate process, because you can't have two processes driving the same signal. If you need feedback to your main control process, you could do that with a signal or a shared variable.
I am trying to figure out a way to break out of a procedure if some external event occurs. Let's say I have a procedure like this:
procedure p_RECEIVE_DATA (
o_data : out std_logic) is
begin
wait until rising_edge(i2c_clock);
o_data := i2c_data;
wait until falling_edge(i2c_clock);
end procedure P_RECEIVE_DATA;
Now what I want is if an external signal, let's call it r_STOP gets asserted at any time, I want this procedure to exit immediately. Is there a nice way to do this? I was thinking that if this Verilog I could use fork/join_any to accomplish this, but there is no equivalent to fork and join in VHDL. Does anyone have any suggestions?
First of all, the code you have here might be just fine for a test or simulation. If this is what it's for, then great. However, keep in mind that code written as you have above is not synthesizable. You can compile and run it in a simulation setup, but you almost certainly won't be able to turn this into a hardware design for an FPGA, ASIC, or any other type of physical device. (In general, procedures can be used in synthesis only when they are called in a process and have no wait statements (or, less commonly, and only in some tools, when all of the wait statements are exactly the same).)
So to answer exactly what you've asked, the way to break out of a procedure is to call return when the condition you are interested in is met. For example if you wanted a global "r_stop" signal as you suggested make this procedure exit early no matter what whenever it changed to a '1', then you'd look for that explicitly:
procedure p_RECEIVE_DATA (
o_data : out std_logic) is
begin
wait until rising_edge(i2c_clock) or r_stop = '1';
if r_stop = '1' then return; end if;
o_data := i2c_data;
wait until falling_edge(i2c_clock) or r_stop = '1';
if r_stop = '1' then return; end if;
end procedure P_RECEIVE_DATA;
Again, if this is not testbench code, but is meant to be synthesizable, you need to take a different approach and model your logic as an explicit finite state machine.
I'm not sure there's a nice solution to this in VHDL. It's a bit like making an inferred state machine with a reset signal, which is also not pleasant.
You can do:
wait until rising_edge(clk); exit when reset = 1;
within a loop.
I guess you could do:
wait until rising_edge(clk); if stop = '1' then return; end if;
but again, not pleasant!
Here my 2 cents.
You can do this in your main thread/process by calling trigger control signals for those other threads/processes.
Depending on the state of those control signals you can wait for any thread(join_any), all threads(join) or just do not wait (join_none).
Driving signals from multiple processes is a bad idea unless you really know what you're doing (multiple driver problem). Therefore the activation and deactivation signal for each thread should be different since they are controlled from different processes/drivers. That is the reason why i have written 2 control signals 1.started and 2.finished for each thread.
It is very important that a signal/interface is only written in one process in your code.
The code use waits so the same problems stated by wjl are applicable for synthesis.
If you want it synthetizable then put thread_0_active in the sensitivity list and do if rising_edge(thread_0_active) then inside the process. This will encapsulate the code and will be executed only in case of the rising condition. Of course the code inside this process should be synthetizable and contain no waits.
A state machine can only run and be in one state at a time.
I think you are interested on a direct equivalente to the systemverilog fork behavior. I have tried to make the example as close as possible.
The code below:
signal thread_0_started : std_logic:='0';
signal thread_0_finished : std_logic:='0';
signal thread_1_started : std_logic:='0';
signal thread_1_finished : std_logic:='0';
--......
p_main_father : process
variable father_v : std_logic_vector( 32-1 downto 0 );
begin
--Do other things in your main thread using variables
--
--Now fork a thread activating it.
thread_0_started <= '1';
thread_1_started <= '1';
--signals are activated and now we need to wait when they are finished
--here both threads are started at the same time concurrently.
----------------------
--a fork .. join_any would be to do an "or" until the logic
wait until (thread_0_finished = '1') or (thread_1_finished = '1');
-------------------
--a fork .. join would be to do an "and" with the logic
--wait until (thread_0_finished = '0') and(thread_1_finished = '0');
--a fork .. join_none would be to just NOT do "wait until" and ignore that the threads were activated!!!
thread_0_started <= '0';--restore started state in case this main thread want to start them again.
thread_1_started <= '0';
end process;
child_thread_0 : process
variable prdata_v : std_logic_vector( 32-1 downto 0 );
begin
if thread_0_started = '0' then
thread_0_finished <= '0';--important disable finished if not started
end if;
wait until rising_edge(thread_0_started);--trigger event
--Do your things inside de thread_0 that consume time. e.g. calling other process
thread_0_finished <= '1';
end process;
child_thread_1 : process
variable prdata_v : std_logic_vector( 32-1 downto 0 );
begin
if thread_1_started = '0' then
thread_1_finished <= '0';--important disable finished if not started
end if;
wait until rising_edge(thread_1_started);
--Do your things inside de thread_1 that consume time. e.g. calling other process
thread_1_finished <= '1';
end process;
I am stuck with the following situation
I am designing a vhdl project for uart. There are two components namely uart_rx.vhd and uart_tx.vhd.
I suppose uart_tx goes in Mark state initially upon receiving the value '0' to signal: ready. Signal
Ready is uninitialized, i.e. ready = 'U'.
uart_tx waits for input from uart_rx.vhd. As soon as uart_tx receives '0' from uart_rx, FSM goes to Start instead of Mark.
Here is the algorithm I've used:
if ready = o
state <= Mark
else
state <= Start
Write a testbench and an initialisation for ready:
signal ready : std_logic := '0';