Problemas al combinar contadores para el semáforo

0

Estoy tratando de implementar algo tan simple como el controlador para un solo semáforo usando dos contadores (uno para verde / rojo y otro para amarillo), pero parece que no estoy acertando con la sincronización.

Mi primer contador parecía algo así como

entity counter is
    generic (
        max_count : integer := 50
    );
    port (
        clk : in std_ulogic;
        rst : in std_ulogic;
        count_value : out integer := '0';
        flag : out std_ulogic := '0'
    );
end entity;

architecture behav of counter is
    signal count : natural := 0;
begin
    count_value <= count

    process (rst, clk)
    begin
        if rst = '0' then
            flag <= '0';
            count <= 0;
        elsif rising_edge(clk) then
            count <= (count + 1) mod max_count;
            if count = 0 then
                -- set flag value for one cycle
                flag <= '1';
            else
                flag <= '0';
            end if;
        end if;
    end process;
end architecture behav;

que también establece el valor de marca cuando comienza a contar .

Cuando intenté implementar el semáforo (simplemente una máquina de estado) por medio de este contador, me quedé atascado. Cuando acabo de iniciar el contador rojo / verde c_redgreen una vez, es decir, el contador nunca se reinicia. El problema con este enfoque es, por supuesto, que el tiempo en que el semáforo está en amarillo no se tiene en cuenta (por ejemplo, la luz comienza con rojo y permanece en ese estado durante 50 ciclos, luego se vuelve amarillo durante 5 ciclos, pero luego hay solo 45 ciclos verde, porque el contador no se detuvo durante el tiempo amarillo, etc ...). Pensé que esto podría solucionarse simplemente reiniciando c_redgreen mientras que la luz es amarilla, pero inmediatamente después del restablecimiento, la marca se establece de inmediato y, por lo tanto, no puedo usar algo como if rising_edge(rg_flag) then ... , porque el borde ascendente llega inmediatamente ( porque el contador establece la bandera cuando comienza).

Después de estos problemas, pensé que sería mejor reformular mi contador de la siguiente manera

...
elsif rising_edge(clk) then
    temp := (count + 1) mod max_count;
    count <= temp
    if temp = 0 then
...

para evitar que se establezca el indicador al iniciar , pero cuando inicio el reloj (en el banco de pruebas) con 0, la primera luz roja no dura 50 ciclos, sino solo 49. También estoy no estoy seguro de si es una buena idea que un contador no haga nada hasta que haya alcanzado max_count .

Por lo tanto, mi pregunta es cómo puedo combinar dos contadores (con o sin indicador de inicio) para poder hacer que mis luces rojas / verdes brillen durante n ciclos y mi luz amarilla para m ciclos. Espero haber sido lo suficientemente claro. Si fuera necesario el código de mi semáforo, puedo agregarlo (simplemente no quise hacer esta pregunta por más tiempo). Tampoco necesariamente necesito un semáforo, solo quiero que estos contadores funcionen en paralelo de alguna manera. Gracias de antemano

    
pregunta Mr Tsjolder

1 respuesta

4

Estás pensando demasiado en esto. No hay razón para hacer del contador una entidad separada; simplemente terminas escribiendo un montón de código para hacer explícitamente lo que las herramientas de síntesis pueden hacer por ti implícitamente.

Además, para el ejemplo de semáforos, realmente solo necesita un contador, porque solo necesita un retraso a la vez. El mismo contador puede manejar diferentes retrasos para diferentes estados.

Simplemente haga que el contador forme parte de la máquina de estado principal, algo como esto:

entity traffic_light is
  generic (
    green_time  : natural := 50;
    yellow_time : natural := 20;
  );
  port (
    clk         : in std_ulogic;
    rst         : in std_ulogic;
    -- lights are 3-bit fields that control red, yellow, green
    ns_lights   : out std_logic_vector (2 downto 0);
    ew_lights   : out std_logic_vector (2 downto 0);
  );
end entity;

architecture behav of traffic_light is
  signal state : natural;
  signal count : natural;
begin
  process (clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then         -- active-high synchronous reset
        state <= 0;
        ns_lights <= "100";
        ew_lights <= "100";
        count <= 100;
      else
        case state is

        when 0 =>               -- special start-up state; all lights red
          if count = 0 then
            ns_lights <= "001"; -- switch NS to green
            ew_lights <= "100";
            state <= 1;
            count <= green_time;
          else
            count <= count - 1;
          end if;

        when 1 =>               -- NS green, EW red
          if count = 0 then
            ns_lights <= "010"; -- switch NS to yellow
            ew_lights <= "100";
            state <= 2;
            count <= yellow_time;
          else
            count <= count - 1;
          end if;

        when 2 =>               -- NS yellow, EW red
          if count = 0 then
            ns_lights <= "100"; -- switch NS to red
            ew_lights <= "001"; -- switch EW to green
            state <= 3;
            count <= green_time;
          else
            count <= count - 1;
          end if;

        when 3 =>               -- NS red, EW green
          if count = 0 then
            ns_lights <= "100";
            ew_lights <= "010"; -- switch EW to yellow
            state <= 4;
            count <= yellow_time;
          else
            count <= count - 1;
          end if;

        when 4 =>               -- NS red, EW yellow
          if count = 0 then
            ns_lights <= "001"; -- switch NS to green
            ew_lights <= "100"; -- switch EW to red
            state <= 1;
            count <= green_time;
          else
            count <= count - 1;
          end if;

        when others =>
          state <= 0;
          ns_lights <= "100";   -- switch NS to red
          ew_lights <= "100";   -- switch EW to red
          count <= 100;
        end case;
      end if;
    end if;
  end process;
end architecture behav;
    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas