3
\$\begingroup\$

I trying to make a simple VHDL program which consist of incrementing a std_logic_vector by one every time button A is pressed. When button B is pressed the value should be reset.

My idea was to do it like this

entity simple is
    Port ( A : in std_logic;
           B : in std_logic;
           CLK : in std_logic;
           debug : out std_logic_vector (7 downto 0));
end simple;

architecture Behavioral of simple is
    signal state: std_logic_vector(7 downto 0) := "00000000";
begin

   increment: process(state, A, B)
    begin
        if (B'event and B = '1') then 
            state <= "00000000";
        end if;
        if (A'event andA = '1') then 
            state <= std_logic_vector(unsigned(state)+1);
         end if;
    end process;


    led_debug: process(CLK)
    begin
        debug <= state;
    end process;    

end Behavioral;

The problem is though i am getting a error - Bad synchronous description, which i cannot understand.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

I reworked your code into a full synchronous description:

  1. Synchronous designs need a clock-signal, but a button signal is no clock. So every process is triggered on a positive edge of Clk.
  2. I changed the type of state to spare some type conversions.
  3. If A is active, then the counter is reset to zero.
  4. Otherwise if B is active, it increments.
  5. I assume your led_debug process should be clocked to, so I added a rising_edge condition.

This solution does not solve the following problem, if A and B are wires from a external button:

  • External signals need to be synchronized with at least 2 FFs, to avoid metastability problems.
  • External buttons mostly need a debounce circuit, because button inputs bounce. There are also electrical or mechanical solutions possible to solve the problem. Have a look into your board descriptions and board schematics.
  • In most cases you want to count button presses. Your current solution measures how long you have pressed the button (this needs also a bigger counter). This problem can be solved by an edge detection circuit.

Here is the rewritten code:

entity simple is
  Port (
    CLK : in std_logic;
    A : in std_logic;
    B : in std_logic;
    debug : out std_logic_vector (7 downto 0)
  );
end entity;

architecture rtl of simple is
  signal state : unsigned(7 downto 0) := (others => '0');

begin
  increment : process(Clk)
  begin
    if rising_edge(Clk) then
      if (B = '1') then 
        state <= "00000000";
      elsif (A = '1') then 
        state <= state + 1;
      end if;
    end if;
  end process;

  led_debug : process(CLK)
  begin
    if rising_edge(Clk) then
      debug <= std_logic_vector(state);
    end if;
  end process;    
end architecture;
\$\endgroup\$
2
  • \$\begingroup\$ Adding another register for debug isn't quite necessary. \$\endgroup\$
    – mkrieger1
    Commented Oct 8, 2016 at 13:09
  • \$\begingroup\$ I translated his code. And yes in some cases you'll need 1 to 3 register stages for a debug port to an internal state. Of cause the debug circuit is more then a LED ... \$\endgroup\$
    – Paebbels
    Commented Oct 8, 2016 at 16:04
0
\$\begingroup\$

I realized It was checking at 2 rising edges within the same process, making the system sensitive to 2 clock, which was giving it a bad synchronous.

\$\endgroup\$
1
  • \$\begingroup\$ The B button can be used as an asynchronous reset. \$\endgroup\$
    – Grabul
    Commented Sep 12, 2015 at 12:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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