Cómo evitar que disminuya por debajo de 0 y la asignación de puertos

2

Estoy codificando para un acelerador y un velocímetro. Actualmente estoy tratando de evitar que el velocímetro y la transmisión disminuyan por debajo de 0 y permanezcan en 0. Creo que puedo crear sentencias if que lo mantendrán por encima de 0, pero hay una manera más eficiente de hacerlo. También estoy tratando de asignar el velocímetro a dos pantallas de 7 segmentos usando el código para la operación en un FPGA. Si puedes ayudar, te lo agradecería. Gracias. CÓDIGO EDITADO

    LIBRARY IEEE;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.STD_LOGIC_1164.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY GearCounterFirst IS
PORT(
  CLK: IN STD_LOGIC;
  gas: IN STD_LOGIC;
  up: IN STD_LOGIC;
  down: IN STD_LOGIC;
  trans_o: OUT STD_LOGIC_VECTOR (2 downto 0);
  speed_o: OUT STD_LOGIC_VECTOR (7 downto 0);
  acc_o: OUT STD_LOGIC_VECTOR (4 downto 0));
 END GearCounterFirst;

ARCHITECTURE Behavior OF GearCounterFirst IS
    signal trans: std_logic_vector(2 downto 0) := "000";
    signal speed: std_LOGIC_VECTOR(7 downto 0) := "00000000";
    signal acc  : std_LOGIC_VECTOR(4 downto 0) := "00000";

BEGIN
    PROCESS (CLK) 

    BEGIN

    if (rising_edge(CLK)) then

            if (up = '1') then
                if (unsigned(trans) < 5) then
                    trans <= STD_LOGIC_VECTOR(unsigned(trans) + 1);
                elsif (unsigned(trans) = 5) then
                    trans <= trans;
                end if;

            elsif (down = '1') then
                if (unsigned (trans) > 0) then
                    trans <= STD_LOGIC_VECTOR(unsigned(trans) - 1);
                elsif (unsigned (trans) = 0) then
                    trans <= trans;
                end if;
            else 
                    trans <= trans; 
            end if;

        case trans is

            when "000" =>
                if (gas = '1') then
                    if (unsigned(speed) > 0) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                    elsif (unsigned(speed) = 0 ) then
                        speed <= speed;
                        acc <= "00000";
                    end if;
                elsif (gas = '0') then
                        if (unsigned(speed) > 0) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                        elsif (unsigned(speed) = 0 ) then
                        speed <= speed;
                        acc <= "00000";
                        end if;
                    end if;

            when "001" => -- Trans in 1st gear

                if (gas = '1') then    --gas is presed
                    if (unsigned(speed) < 15) then   -- Increase until 15
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) + 5);
                        acc <= "11111";
                    end if;

                elsif (gas = '0') then   -- gas is not pressed
                    if (unsigned(speed) > 0) then    -- decrease until speed is 0
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);   
                        acc <= "00000";
                    elsif (unsigned(speed) = 0) then    -- at 0 speed, stay at 0
                        speed <= "00000000";
                        acc <= "00000";
                    end if;
                end if; 


            when "010" => -- Trans in 2nd gear
                if (gas = '1') then
                    if (unsigned(speed) < 35) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) + 4);
                        acc <= "01111";
                    end if;

                elsif (gas = '0') then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                end if;

            when "011" =>   -- Trans in 3rd gear
                if (gas = '1') then
                    if (speed < 60) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) + 3);
                        acc <= "00111";
                    end if;

                elsif (gas = '0') then
                    if (speed > 0) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                    end if;
                end if;


            when "101" =>   -- Trans in 4th gear
                if (gas = '1') then
                    speed <= STD_LOGIC_VECTOR(unsigned(speed) + 2);
                    acc <= "00011";

                elsif (gas = '0') then
                    speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                    acc <= "00000";
                end if;

            when "110" =>       -- Trans in 5th gear
                if (gas = '1') then
                    speed <= STD_LOGIC_VECTOR(unsigned(speed) + 1);
                    acc <= "00001";

                elsif (gas = '0') then
                    if (unsigned(speed) > 0) then
                    speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                    acc <= "00000";
                    elsif (unsigned(speed) = 0 ) then
                    speed <= speed;
                    acc <= "00000";
                    end if;
                end if;

            when others =>
                if (gas = '1') then
                    if (unsigned(speed) > 0) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                    elsif (unsigned(speed) = 0 ) then
                        speed <= speed;
                        acc <= "00000";
                    end if;
                elsif (gas = '0') then
                        if (unsigned(speed) > 0) then
                        speed <= STD_LOGIC_VECTOR(unsigned(speed) - 2);
                        acc <= "00000";
                        elsif (unsigned(speed) = 0 ) then
                        speed <= speed;
                        acc <= "00000";
                        end if;
                    end if;
        end case;
    end if;

    trans_o <= trans;
    acc_o <= acc;
    speed_o <= speed;
    END PROCESS;
End Behavior;
    

2 respuestas

4

Lo siento, pero no daré una solución completa. Esta respuesta está pensada como un breve tutorial sobre cómo resolver este enigma.

Evitar que disminuya por debajo de cero

  1. Comencemos con el caso trans = "110" (quinto engranaje) y gas = '0' . Aquí, el speed cae en 1 unidad cada ciclo de reloj. Si la velocidad tiene el valor actual 0, el nuevo valor sería -1. Pero, como tiene un unsigned , se ajusta al valor más alto (255). Entonces, ¿qué nuevo valor debe asignarse en caso de que la velocidad ya sea cero? Codifique esto, por ejemplo, utilizando un if como lo indica Brian, cerca de la disminución real de speed . Verifique su implementación usando simulación.

  2. Si resolvió el paso 1, continúe con la cuarta marcha. Aquí, puede disminuir "debajo de 0" en el caso de que la velocidad actual sea 1 o 0. Aplique la solución del paso 1 de manera similar y verifíquela por simulación.

  3. Aplique el esquema para todos los engranajes restantes y verifíquelo mediante simulación. Tenga en cuenta que también puede usar operadores relacionales en la condición if .

  4. Piense en el caso opuesto de que la velocidad también se puede incrementar por encima del valor más alto (255) y, por lo tanto, se ajusta a cero. Aplique los pasos 1 a 3 en consecuencia.

Tengo que enfatizarlo nuevamente: compruebe cada resultado intermedio mediante simulación para detectar errores de codificación antes de reutilizar el código en otra posición.

Salida en pantalla de 7 segmentos

  1. Debe comenzar con un nuevo módulo que decodifique un decimal codificado en binario (BCD, 4 bits) en las líneas de control de una pantalla de 7 segmentos (7 bits). Esto solo sería una lógica de combinación ya que no se debe guardar ningún estado, por lo que no se necesita un reloj. Verifique su decodificador por simulación y en un tablero de FPGA, si tiene uno.

  2. Para mostrar más de un dígito decimal tiene varias opciones:

    • Extienda el decodificador para números hexadecimales y use dos de ellos para el rango 0 a 255 (0x0 a 0xFF).

    • Decodifique el número binario de 8 bits a BCD de 12 bits (3 dígitos a 4 bits). Luego use 3 decodificadores de 7 segmentos.

    • Use un contador BCD para speed y acc . Este es un ejercicio avanzado pero una buena práctica para entender la lógica digital.

Ejemplo de banco de pruebas

library ieee;
use ieee.std_logic_1164.all;

entity GearCounterFirst_tb is
end entity GearCounterFirst_tb;

architecture sim of GearCounterFirst_tb is
  -- component ports
  signal CLK     : STD_LOGIC := '1';
  signal gas     : STD_LOGIC;
  signal up  : STD_LOGIC;
  signal down    : STD_LOGIC;
  signal trans_o : STD_LOGIC_VECTOR (2 downto 0);
  signal speed_o : STD_LOGIC_VECTOR (7 downto 0);
  signal acc_o   : STD_LOGIC_VECTOR (4 downto 0);

begin  -- architecture sim

  -- component instantiation
  DUT: entity work.GearCounterFirst
    port map (
      CLK     => CLK,
      gas     => gas,
      up      => up,
      down    => down,
      trans_o => trans_o,
      speed_o => speed_o,
      acc_o   => acc_o);

  -- clock generation
  CLK <= not CLK after 10 ns;

  -- waveform generation
  WaveGen_Proc: process
  begin
    gas <= '0';
    up <= '0';
    down <= '0';
    wait until falling_edge(clk);
    wait until falling_edge(clk);
    wait until falling_edge(clk);
    up <= '1';
    wait until falling_edge(clk);
    up <= '0';
    wait;
  end process;
end architecture;
    
respondido por el Martin Zabel
0

Para el problema de abajo cero:
En una forma más simple, solo use dos declaraciones de Caso en lugar de una. Un caso que potencialmente aumenta la velocidad y un caso que potencialmente disminuye la velocidad. Luego agregue solo una entrada condicional encima de cada Caso, como: "if (speed > 0)" y la otra: "if (speed < = max_speed)". - Lo último es evitar que se sobrepase el máximo.

Para la asignación a pantallas de 7 segmentos:
Algunos chips aún tienen sus propias instrucciones de conversión de BCD, verifique eso primero, (esto convierte directamente un número hexadecimal de 8 bits en un 8 bits que contiene dos BCD de 4 bits). Una vez en formato BCD, una pantalla de 7 segmentos puede manejarse con BCD de estilo antiguo a chips de controlador de 7 seg.

Ideas para usar el código: puede dividir el número hexadecimal de 8 bits en dos números de 4 bits (con desplazamiento de bits), luego detectar valores por encima de 09, restar la diferencia, pasar cualquier acarreo al byte más alto, combinar los números De vuelta a un solo 8 bits, luego emita los chips del controlador BCD. (Sin los chips BCD, puede pensar en mantener los dos números en formatos BCD de 4 bits separados y luego usar una lista de consulta 0-9 para convertirlos directamente en un formato de 7 segmentos).

    
respondido por el Nedd

Lea otras preguntas en las etiquetas