0
votes

I am revisiting VHDL after many years. I am trying to setup a basic state machine with a counter trigger at some overflow period.

For some reason I am getting state transitions on the falling edge of the m_tick clock. There should only be a transition on the rising edge based on the m_tick <= '1' in the state process? I must be overlooking something.

I am testing in isim. I am sure I'm probably doing some not very smart.

Thanks.

entity nes_ctl is
generic(
        N: integer :=  3;       --17 bit overflow 131k
 );
port(
        clk : in std_logic;
        n_reset : in std_logic
);
end nes_ctl;

architecture Behavioral of nes_ctl is

signal count_reg, count_next: unsigned(N-1 downto 0);   --counter to produce tick
signal m_tick: std_logic;
--state variable
type state_type is (s0,s1,s2,s3,s4,s5);
signal state_reg, state_next: state_type;
signal reset: std_logic;    --inverted reset signal

begin

reset <= not(n_reset);  --invert the reset signal

--syncronos logic
process(clk)
begin
    if(reset= '1') then
        count_reg <= (others=>'0');
        state_reg <= s0;
    elsif (clk'event and clk = '1') then
        count_reg <= count_next;
        state_reg <= state_next;
    end if;
end process;

count_next <= count_reg +1;     --increment counter, will overflow
m_tick <= '1' when count_reg = 0 else '0';      -- tick on every overflow

--STATE MACHINE
process(m_tick)
begin
    if(m_tick <= '1') then  --only when m_tick goes high
        case state_reg is
            when s0 =>
                state_next <= s1;
            when s1 =>
                state_next <= s2;
            when s2 =>
                state_next <= s3;
            when s3 =>
                state_next<= s4;
            when s4 =>
                state_next<= s5;
            when s5 =>
                state_next <= s0;
        end case;   
    else 
        state_next <= state_reg; --keep same state.  no       latches.
    end if;
end process;


end Behavioral;
1
What does a relational operator <= do on std_logic? If you want to detect a rising edge, if rising_edge(m_tick) would be the obvious way - user_1818839
Good point. should have been if (m_tick = '1'). - fragment
My logic was that m_tick triggered the process, so there was an edge on m_tick. The if(m_tick = '1') is the check to see if it was the rising edge. What is the defacto standard for such as check? rising_edge(m_tick) like you sugges? - fragment
I changed the original code to m_tick='1' rather m_tick<='1' and the simulation ran fine. But, I think you guys made some good points that pointed out that this is a gated clock implementation? Which is bad practice? Sorry trying adjust my thinking from embedded processing. OUCH. - fragment

1 Answers

4
votes

m_tick <= '1' will be true any time m_tick is low, not just the rising edge. If you intend to use m_tick as a clock, you need to use m_tick'event and m_tick='1', as you do for clk. If instead you intend the rising edge of m_tick to be a clock enable signal, you need to clock your process with the clk signal and detect the rising edge of m_tick by comparing it with a delayed version:

process(clk)
begin
    if (clk'event and clk = '1') then
        m_tick_q <= m_tick;

        -- only when m_tick goes high
        if m_tick='1' and m_tick_q='0' then
            case state_reg is
            ...