Thursday, 9 April 2015

vhdl - How is this simple counter implemented on an FPGA without a clock?


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.



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.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...