Implementing a Simple Counter on FPGA Without a Clock

vhdl

As part of an assignment, I must create these blocks that tie in to a larger top level module. (there are more blocks not pictured). I have everything working fine, except this UP/DOWN counter because I can't really work out how this can possibly be implemented without a CLK.

enter image description here

The EN_UP and EN_DOWN signals are simple pulses that should increment or decrement an internal 16-bit value, which gets split into nibbles and put on the output. I feel as if this should be fairly simple, but I can't work this out.

I've tried multiple approaches.

1) – Inside a single process

count : PROCESS (RESET, EN_UP, EN_DOWN)
BEGIN
    if(RESET = '1') then
        countSignal <= x"0000";
    elsif(rising_edge(EN_UP) and EN_DOWN = '0') then
        countSignal <= countSignal + 1;
    elsif(rising_edge(EN_DOWN) and EN_UP = '0') then
        countSignal <= countSignal - 1;
    end if;
END PROCESS;

This ultimately compiles with no errors or warnings, however the compiler ends up creating the wrong circuit, tying the EN_UP to the CLK of the flip-flip, and the EN_DOWN to the CE (clock enable). While yes, that is part of the equation, it doesn't mirror that for the opposite case.

2) – Separate processes

countUP : PROCESS (RESET, EN_UP)
BEGIN
    if(RESET = '1') then
        countSignal <= x"0000";
    elsif(rising_edge(EN_UP) and EN_DOWN = '0') then
        countSignal <= countSignal + 1;
    end if;
END PROCESS;

countDOWN : PROCESS (RESET, EN_DOWN)
BEGIN
    if(RESET = '1') then
        countSignal <= x"0000";
    elsif(rising_edge(EN_DOWN) and EN_UP = '0') then
        countSignal <= countSignal - 1;
    end if;
END PROCESS;

This results in: Signal countSignal[15] in unit UD_COUNTER is connected to following multiple drivers:

3) Multiple processes with Hi-Z states

I tried some attempt with Hi-Z which also failed.

Best Answer

You're right in thinking that you will have to use something for a clock for the counter. Otherwise there is nothing to tell it when to count. Either the clock is missing from the diagram, or you will have to edge-trigger on the enables, in which case the circuit you think it should have synthesized to is impossible, as you can't drive the same register with two different clocks. You might try something like:

en_either <= en_up or en_down;

process (en_either, rst)
begin
  if rst = '1' then
    count <= (others => '0');
  elsif rising_edge(en_either) then
    if en_up = '1' then
      count <= count + 1;
    else
      count <= count - 1;
    end if;
  end if;
end process;

There may be better ways, but if you really can't have a clock, I suppose that will work. If the enables overlap in any way, of course, this may not work as intended.

As the error message indicates, your two-process version will not work because you're driving the same signal from two different processes. There may be ways to work around this, but it would be much more trouble than the 1-process version.

As David points out in the comments, this will not work properly unless your enables are bounce-free. The source of the enables isn't clear from your post.