I am a vhdl begginner, and in need of help for my problem. I have 2 signals that i need to monitor. One is CHECK and the other OK. Every time i ask for a CHECK, I should get OK (HIGH or LOW). I need to monitor contantly 6 consecutive CHECK pulses, and count the OK. If i have 6 OK (LOW) then i need to produce the output (HIGH), any other case output (LOW). I have writen some code that does not produce the wanted output above. But i have a fundamental question first. can this be done in one process?
--one process
if ...
reset clauses
elsif
count pulses and set a variable to 6
else
if variable = 6, produce output
end if;
or do i need more?
--first process
start counter on rising_edge of CHECK
-- second process
count pulses and set a signal some value (6)
-- third process
monitor signal and if =6, produce output
EDIT: Here is the code i tried, but failed... will look into FSM...
counter_operation:process (RESETn, CHECK, OK)
variable counter : unsigned (2 downto 0);
variable lost_count : unsigned (2 downto 0);
begin
-- if reset it asserted ensure counter is not running
if ( RESETn = '0') then
trip_signal <= '0';
lost_count := to_unsigned (0,3);
counter := to_unsigned (0,3);
-- run counter and perform actions
elsif (rising_edge(CHECK)) then
-- increment counter and limit maximum value
counter := counter+1;
if (counter > to_unsigned(6,3) ) then
counter := to_unsigned (0,3);
lost_count := to_unsigned (0,3);
end if;
-- check for first OK(LOW)
if (counter = to_unsigned(1,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check for second consecutive OK(LOW)
if (counter = to_unsigned(2,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check for third consecutive OK(LOW)
if (counter = to_unsigned(3,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check for fourth consecutive OK(LOW)
if (counter = to_unsigned(4,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check for fifth consecutive OK(LOW)
if (counter = to_unsigned(5,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check for sixth consecutive OK(LOW)
if (counter = to_unsigned(6,3)) then
if (OK = '0') then
lost_count := lost_count + to_unsigned (1,3);
else
lost_count := lost_count;
end if;
end if;
-- check if we lost 6 consecutive
if (lost_count = to_unsigned (6,3)) then
trip_signal <= '1';
else
trip_signal <= '0';
end if;
end if;
end process counter_operation;
I definetely have something wrong in here, because pre and post simulation do not produce the same results. Pre-sim seems to work, but post-sim does not.
EDIT (2): for the FSM, something like this?
library IEEE;
use IEEE.std_logic_1164.all;
entity FSM_1 is
port (
CHECK : in std_logic;
CRC :in std_logic;
CLK : in std_logic;
RESETn :in std_logic;
OUT_SIG : out std_logic
);
end FSM_1;
architecture arch of FSM_1 is
-- signal, component etc. declarations
type TargetSeqStates is (IDLE, FIRST_CHECK, SECOND_CHECK, THIRD_CHECK, FOURTH_CHECK, FIFTH_CHECK, SIXTH_CHECK);
signal curr_st, next_st : TargetSeqStates;
begin
--------------------------------------------------------------------------------
-- Using the current state of the counter and the input signals, decide what the next state should be
--------------------------------------------------------------------------------
NxStDecode:process (CHECK, OK, curr_st)
begin
-- default next-state condition
next_st <= IDLE;
-- TODO...
-- TODO...
end process NxStDecode;
--------------------------------------------------------------------------------
-- At the desired clock edge, load the next state of the counter (from 1.) into the counter
-- create the current-state variables
--------------------------------------------------------------------------------
CurStDecode:process (CLK, RESETn)
begin
-- Clear FSM to start state
if (RESETn = '0') then
curr_st <= IDLE;
elsif (rising_edge(CLK)) then
curr_st <= next_st;
end if;
end process CurStDecode;
--------------------------------------------------------------------------------
-- Using the current state of the counter and the input signals, decide what the values of all output signals should be
--------------------------------------------------------------------------------
DecOutputs;process (curr_st)
begin
-- TODO....
-- TODO...
end process DecOutputs;
end arch;
I guess the TODO parts are dependent of the state diagram? Also, do I need the CLK? It seems that I need to change state, on rising_edge of CHECK, not CLK.
Final Edit:
counter_operation:process (RESETn, CHECK, OK, CLK)
variable lost_counter : integer := 0;
variable last_CHECK : std_logic;
begin
if ( RESETn = '0') then
D_TRIP <= '0';
lost_counter := 0;
else
if (rising_edge(CLK)) then
if (CHECK /= last_CHECK) then
if (OK = '0') then
lost_counter := lost_counter + 1;
else
lost_counter := 0;
end if;
D_TRIP <= '0';
if (lost_counter = 6) then
D_TRIP <= '1';
lost_counter := 0;
end if;
end if;
last_CHECK := CHECK;
end if;
end if;
end process counter_operation;
I'd say making a single-process state machine is the best way to start. It saves some potential problems with latches being formed, and stops you jumping all over the place trying to see what is going on in each state (for which you have to look in two or even three separate places). But I'm not sure you need a full blown FSM!
Your original code doesn't look too bad. A quick comment on it:
You can add integers to unsigned vectors, so you don't have to do this:
you can just do:
I'd make
lost_counter
aninteger
too, rather than an unsigned vector, as you are not requiring it to wrap around, nor wanting values greater than 2**31, nor do you want direct access to the bits. Therefore an integer is a win all round.It looks like you want to find 6 consecutive 0 bits - the following code is how I would do it - it will go inside the clocked process (of your first try):
Update regarding clocks...
Yes, it's pretty much mandatory to have a clock, so the rising_edge is done on the clock, and then you use that transition to sample all the signals you are interested in. There are other ways of doing it, but they are only for very advanced special cases. The method of using a single clock for every process is called "synchronous design" and it is so widely used that all the tools really expect it of you.
In order to find the rising edge of your CHECK signal, you will have to look at it (sample it) on the rising edge of your clock, store the value, and then compare it with the next value when you get the next clock edge. If the last one was a zero and the current one is a one, you know it has "risen" between the clock edges, and you can do whatever you like at that point. See also my answer here on this subject:
https://stackoverflow.com/a/20472791/106092
This is a pretty standard state machine, and most designers will use from one to three processes for a state machine. If you are just starting out then using three processes may make things easier for you. The processes would be:
Note that the first two processes are purely combinational logic while the third is a clocked, sequential process.