A question about a dual-edge detector

Posted on 2010-09-19
Last Modified: 2013-11-13

       I was just trying to make a dual-edge moore based detector, but for some reason its not working correctly... this is what I got so far with the help of some code from a book.

library ieee;
use ieee.std_logic_1164.all;

entity edge_detect is
          clk, reset:  in std_logic;
          level:  in std_logic;
          tick:   out std_logic;
end edge_detect;

architecture moore_arch of edge_detect is
    type state_type is (zero, edge, one);
    signal state_reg, state_next:   state_type;

     process(clk, reset)
         if (reset = '1') then
            state_reg <= zero;
         elsif (clk'event and clk = '1') then
            state_reg <= state_next;
         end if;
      end process;

      process(state_reg, level)
          state_next <= state_reg;
          tick <= '0';
          case state_reg is

          when zero =>
             if (level = '1') then
                state_next <= edge;
             end if;
          when one =>
             if (level = '0') then
                state_next <= edge;
             end if;
          when edge => tick <= '1';
            if (level = '1') then
               state_next <= one;
               state_next <= zero;
            end if;
          end case;
       end process;
end moore_arch;

I'm not sure what the problem is... far as I understand all a dual-edge detector does is tick on both rising and falling edges, so with my logic, the program calls the edge case when the clock ticks a 1 or 0.  

Also, I'm not sure how to go about writing a test bench for this program, because I'm supposed to catch the output in a variable, right?

I'm a beginner in VHDL, so I'd appreciate any example programs/pointers.

Appreciate any help on this.
Question by:errang
  • 2
LVL 12

Assisted Solution

HappyCactus earned 200 total points
ID: 33714393
it seems that "tick" is the output signal, so you can display it in the test bench (it's defined as out std_logic).
A good introduction tutorial (slides from a lecture, really) is this one:


Accepted Solution

Kendor earned 300 total points
ID: 33715200
I can help you with the standard doulos example for an edge detector (see code) and the according testbench.
I shortly took a look at your code. It should basically work but things I didn't like about it:
- make sure you use "when orthers => ... " (for ex: null) as well
- have you thought about what happens when the level unfortunately changes while the transition is taking place from one state to another?

take a look at the code appended and the PDF with the theory. you'll like it ;)
-- Producing a synchronous edge-detect pulsefor the leading and trailing
-- edges of a long (many clocks) asynchronous pulse.

library ieee;
use ieee.std_logic_1164.all;

entity edge_detect is
  port (async_sig : in std_logic;
        clk       : in std_logic;
        rise      : out std_logic;
        fall      : out std_logic);

architecture RTL of edge_detect is
  sync1 : process(clk)
    variable resync : std_logic_vector(1 to 3);
    if rising_edge(clk) then
      -- detect rising and falling edges.
      rise <= resync(2) and not resync(3);
      fall <= resync(3) and not resync(2);
      -- update history shifter.
      resync := async_sig & resync(1 to 2);
    end if;
  end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;

entity edge_tb is end;

architecture test of edge_tb is
  signal clk, async, rise, fall : std_logic := '0';

  UUT : entity work.edge_detect
       port map (async_sig => async,
                 clk => clk,
                 rise => rise,
                 fall => fall);

clk_gen : process begin
  while now < 1000 ns loop
    clk <= not clk;
    wait for 5 ns;
  end loop;
end process;

-- Produce a randomly-changing async signal.
stim : process
  variable seed1, seed2 : POSITIVE;
  variable Rand : REAL;
  variable IRand : INTEGER;
  while now < 1000 ns loop
    wait until FALLING_EDGE(Clk);
    -- make a random real between 0 and 1
    uniform(seed1, seed2, rand);
    -- turn it into a random integer between 50 and 150
    irand := integer((rand * 100.0  - 0.5) + 50.0 );
    -- wait for that many ns
    wait for irand * 1 ns;
    async <= not async;
  end loop;
end process;

end architecture;

Open in new window


Expert Comment

ID: 33715230
to make it clear what the above code does...
it basically takes the signal and stores it for two cycles. it then compares whether an edge has occured by comparing the latest value to an older value (00 -> no edge, 01 -> edge, 10 -> edge, 11 -> no edge). thats the whole trick. I would recommend you not to use a statemachine for this as it needs much more resources.

Author Comment

ID: 33721555
Um... I wanted to accept multiple solutions... and I clicked "Accept Multiple Solutions"... not sure what went wrong.

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will show, step by step, how to integrate R code into a R Sweave document
This is an explanation of a simple data model to help parse a JSON feed
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

837 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question