0
\$\begingroup\$

This is my simulation

I'm assigning different values to btnin my testbench

btn <= "1000000";
sw <= "00000001";
wait for 50*CLK_PERIOD/2;
btn <= "0101000";
sw <= "00000000";
wait for 50*CLK_PERIOD/2;

And I'm trying to check the previous state with the current state and set the interrupt

process(clk)
begin
    if clk'event and clk='1' then
        if rst = '1' then
            irq <= '0';
            irq_count <= 0;
        else
            if sw /= prev_sw_state and
                btn /= prev_btn_state and
                irq_mask(19) /= '1' then
                    irq_count <= irq_count + 1;
                    irq <= '1';
            else
                irq <= '0';
            end if;
            prev_sw_state <= sw;
            prev_btn_state <= btn;
        end if;
    end if;
end process;

The interrupt does get triggered. No problem. But the waveform doesn't look right. There should be a one clk cycle difference between prev state and current state. Am I doing something wrong?

\$\endgroup\$
  • 2
    \$\begingroup\$ You will probably find a single delta cycle (NOT clock cycle!) delay before the signal assignment. I suspect you have set up the testbench so that clk and sw_state are set in the same delta cycle, in which case that's exactly what you will see. Quick experiment in testbench : sw <= new value after 1 ns; and observe the clock cycle delay appears. Proper fix : learn how signal assignment and delta cycles work. This is absolutely fundamental. \$\endgroup\$ – Brian Drummond Jun 11 '15 at 22:56
1
\$\begingroup\$

If you had posted this on Stackoverflow someone would have down voted it for not being a Minimum, Complete and Verifiable example. I created one also noting that your process and waveform rst polarity don't match. I corrected the process instead of the testbench and reproduced your waveform:

sameclk_tb_as_is.png (clickable)

Note your process has another defect. Assuming that irq_count is an integer type (the reset assignment is to 0) it can overflow given enough events. This should be a simulation artifact, synthesis will assume it's a binary counter modulo length for range. In general you should protect against overflow in simulation.

So after that I added a 1 ns delay per Brian's comment to both sw and btn after the first value is assigned:

STIM:
    process
    begin
        btn <= "1000000";
        sw <= "00000001";
        wait for 1 ns;
        wait for 50*CLK_PERIOD/2;
        btn <= "0101000";
        sw <= "00000000";
        wait for 50*CLK_PERIOD/2;
        btn <= "0011000";
        sw <= "11001100";
        wait for 50*CLK_PERIOD/2;
        btn <= "0001100";
        sw <= "00000100";
        wait for 50*CLK_PERIOD/2;
        wait;
    end process;

And lo and behold the 1 clock offset shows up:

sameclk_tb_sw_btn_delayed.png (clickable)

To get rid of the first 'spurious' irq you could reset prev_btn_state to btn and prev_sw_state to sw, or with less complexity provide a one clock holdover before irq is allowed to go HIGH following rst going invalid (making no statement of what polarity you settle on).

There was no evidence for how or where the LEDs were driven, I skipped those. My waveform method doesn't provide constants (CLK_PERIOD).

This is what was required to demonstrate why the missing clock delay, address potential errors and prior, to reproduce your waveform:

library ieee;
use ieee.std_logic_1164.all;

entity sameclk is
    port (
        clk:    in      std_logic;
        rst:    in      std_logic;
        btn:    in      std_logic_vector (6 downto 0);
        sw:     in      std_logic_vector (7 downto 0);
        irq:    out     std_logic
    );
end entity;

architecture foo of sameclk is
    signal irq_mask: std_logic_vector (31 downto 0) := (others => '0');
    signal irq_count:   natural;
    signal prev_btn_state:  std_logic_vector (btn'range);
    signal prev_sw_state:   std_logic_vector (sw'range);
begin
unlabeled:
    process(clk)
    begin
        if clk'event and clk = '1' then
            if rst = '0' then
                irq <= '0';
                irq_count <= 0;
            else
                if sw /= prev_sw_state and
                    btn /= prev_btn_state and
                    irq_mask(19) /= '1' then
                        if irq_count = natural'HIGH then
                            irq_count <= 0;
                        else
                            irq_count <= irq_count + 1;
                        end if;
                        irq <= '1';
                else
                    irq <= '0';
                end if;
                prev_sw_state <= sw;
                prev_btn_state <= btn;
            end if;
        end if;
    end process;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity sameclk_tb is
end entity;

architecture foo of sameclk_tb is
    constant CLK_PERIOD: Time := 10 ns;
    signal clk: std_logic := '1';
    signal rst: std_logic := '0';
    signal btn: std_logic_vector (6 downto 0);
    signal sw:  std_logic_vector (7 downto 0);
    signal irq: std_logic;
begin
CLOCK:
    process
    begin
        wait for CLK_PERIOD/2;
        clk <= not clk;
        if Now > 200 * CLK_PERIOD/2 then
            wait;
        end if;
    end process;
DUT: 
    entity work.sameclk
        port map (
            clk => clk,
            rst => rst,
            btn => btn,
            sw  => sw,
            irq => irq
        );
STIM:
    process
    begin
        btn <= "1000000";
        sw <= "00000001";
        wait for 1 ns;
        wait for 50*CLK_PERIOD/2;
        btn <= "0101000";
        sw <= "00000000";
        wait for 50*CLK_PERIOD/2;
        btn <= "0011000";
        sw <= "11001100";
        wait for 50*CLK_PERIOD/2;
        btn <= "0001100";
        sw <= "00000100";
        wait for 50*CLK_PERIOD/2;
        wait;
    end process;
RESET:
    rst <= '1' after CLK_PERIOD;
end architecture;

It could have been consolidate by merging the entity/architecture with it's testbench, but I figured on showing the code it would be easier if they are separate than demonstrating there are no delta cycle delays associating actuals and formals in ports (I don't have the ability in ghdl to display delta cycles in waveforms).

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. I thought the code I showed was sufficient enough for the problem I stated. Except that I dint mention about the clk polarity. Is there anything else that I could add that would make it more understandable and absolutely necessary? \$\endgroup\$ – Neil Patrao Jun 13 '15 at 7:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.