5 votos

¿Cómo se implementa este sencillo contador en una FPGA sin reloj?

Como parte de una tarea, debo crear estos bloques que se vinculan a un módulo más grande de nivel superior. (hay más bloques que no aparecen en la imagen). Tengo todo funcionando bien, excepto este contador UP/DOWN porque no puedo entender cómo se puede implementar sin un CLK .

enter image description here

El EN_UP y EN_DOWN son simples pulsos que deben incrementar o disminuir un valor interno de 16 bits, que se divide en nibbles y se pone en la salida. Me parece que esto debería ser bastante simple, pero no puedo resolverlo.

He intentado varios enfoques.

1) - Dentro de un único proceso

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;

Esto finalmente se compila sin errores ni advertencias, sin embargo el compilador termina creando el circuito equivocado, atando el EN_UP a la CLK del flip-flip, y el EN_DOWN a la CE (clock enable) . Si bien es cierto que eso forma parte de la ecuación, no lo es para el caso contrario.

2) - Procesos separados

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;

Esto da como resultado: Signal countSignal[15] in unit UD_COUNTER is connected to following multiple drivers:

3) Procesos múltiples con estados Hi-Z

Hice algún intento con Hi-Z que también fracasó.

5voto

fru1tbat Puntos 417

Tienes razón al pensar que tendrás que usar algo de reloj para el mostrador. De lo contrario, no hay nada que contar cuando para contar. O bien falta el reloj en el diagrama, o tendrás que hacer un edge-trigger en las habilitaciones, en cuyo caso el circuito que crees que debería haber sintetizado es imposible, ya que no puedes manejar el mismo registro con dos relojes diferentes. Podrías intentar algo así:

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;

Puede haber mejores formas, pero si realmente no puedes tener un reloj, supongo que esto funcionará. Si las habilitaciones se superponen de alguna manera, por supuesto, esto puede no funcionar como se pretende.

Como indica el mensaje de error, tu versión de dos procesos no funcionará porque estás manejando la misma señal desde dos procesos diferentes. Es posible que haya formas de solucionar esto, pero sería mucho más problemático que la versión de 1 proceso.

Como señala David en los comentarios, esto no funcionará correctamente a menos que tus permisos estén libres de rebotes. El origen de las habilitaciones no está claro en tu post.

3voto

Sammo034 Puntos 26

No necesitas un reloj para esto, pero necesitas entender mejor lo que debes hacer para cada posible entrada dada a tu red.

El primer enfoque es el mejor, así que vamos a analizarlo. Se empieza por comprobar RESET y eso es genial, elsiffing lo que viene después es justo como lo haría.

Ahora vamos a la parte complicada. Se comprueba si EN_DOWN o EN_UP tuvo un flanco ascendente, comprueba que la otra señal es cero y actúa en consecuencia. Eso no tiene sentido para mí, al menos teniendo en cuenta la (poca) especificación que proporcionas.

Dado que está en un proceso en el que ya está sentado en los bordes, yo sólo comprobaría lo que pasó con el event algo. Algo así como

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

Esto me parece mejor y más ajustado a lo que pides.

Para que conste, una forma heurística de hacerlo (para que entiendas que no necesitas un reloj):

tienes tu registro de salida de 16 bits hecho con DFF, y dos redes combinacionales que computan la salida - 1 y la salida + 1. estas dos redes están conectadas a un mux de doble entrada, y la entrada del registro de salida está conectada al mux. los relojes de los DFFs son el o entre count_up y count_down, mientras que el bit de control del mux es uno de ellos. Cuando llega un pulso, el registro se refresca con el valor correcto.

Si no estás satisfecho con la implementación que obtienes después de synthesys puedes intentar implementar mi última idea y ver si te funciona.

1voto

WhatRoughBeast Puntos 20870

A las FPGAs realmente no les gusta funcionar sin reloj. Se obtienen comportamientos muy inesperados. Así que es mucho mejor usar un contador síncrono arriba/abajo con las entradas arriba/abajo muestreadas por un reloj más rápido.

schematic

simular este circuito - Esquema creado con CircuitLab

El periodo del reloj no debe ser mayor que 1/3 del ancho del pulso de subida o bajada.

1voto

Alex Andronov Puntos 178

Es posible diseñar un contador a partir de una lógica puramente combinatoria, si se le dan dos entradas en lugar de una, y las entradas cambian de estado según un patrón bien definido. Por ejemplo, supongamos que tenemos dos entradas P y Q, dos valores de ocho bits X e Y, y los calculamos combinatoriamente de la siguiente manera:

When P is high
  X=Y+1
Else
  X=X

When Q is high:
  Y=X+1
Else
  Y=Y

Si P y Q suben alternativamente, entonces X e Y contarán el número de veces que lo han hecho, siempre que P y Q nunca estén altos simultáneamente; si alguna vez se superponen, entonces los valores de X e Y serán indefinidos.

Aunque los flip flops han sustituido en gran medida el estilo de circuitos anterior, el enfoque de la sincronización en dos fases ha sido históricamente bastante popular, sobre todo porque en las tecnologías NMOS, dada una velocidad de reloj mínima, se podían utilizar circuitos de enclavamiento que eran mucho más baratos que los flip flops. Considere:

schematic

simular este circuito - Esquema creado con CircuitLab

Cada relé debería ser simplemente un único NFET, pero no consigo que se simule correctamente, así que lo he sustituido por un relé. Este circuito implementa un contador de división por dos utilizando cinco transistores activos y tres pull-ups pasivos. La implementación de un flip flop disparado por flancos requeriría más circuitos, así que aunque es necesario generar y distribuir dos relojes en lugar de uno, el efecto global es una "victoria".

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X