Mi código VHDL no está procesando una señal entrante correctamente durante un conjunto de tiempo seleccionado

1

Estoy programando usando VHDL, y tengo un problema al procesar una señal entrante cuando intento verla solo durante un período de tiempo específico.

Digamos que tengo una señal entrante, GPIO.

En un proceso (activado por un reloj de 50 MHz), a una señal interna, A, se le asigna el valor de GPIO durante una ventana de .1 ms, mientras que se le asigna '0' para todos los demás tiempos durante un período de 2 ms.

La señal A se pasa a través de un LCELL varias veces para retrasar la señal.

Algunos componentes seleccionados de esta señal retardada (vector A_internal (23 downto 0)) se colocan en un mux4to1 con A (A obtiene NOT-ANDED con una señal retardada para producir una señal más corta, A_s).

A_s luego se cuenta y se usa para calcular otros datos.

Mi problema es este: cuando A está leyendo constantemente GPIO (no pasa por el proceso del reloj 50), el código se ejecuta correctamente. Pero cuando trato de usar este método para ver GPIO solo en ciertos momentos, el código nunca leerá GPIO (o al menos obtengo conteos de 0, siempre). ¿Hay algún error en la forma en que me acerco a este método de "ventana de selección" o hay algo que está haciendo mal en el código en sí mismo que está causando que esto no se lea?

Aquí está el código relevante (por favor, dígame si se necesita alguna otra información para ayudar a responder mi pregunta):

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY Project IS
    PORT (
        Clock_50 : IN STD_LOGIC; -- The 50 MHz clock that is provided on the DE2 Board
        SW       : IN STD_LOGIC_VECTOR(17 DOWNTO 0); -- The switches 0 through 17 on the DE2 Board
        GPIO_0   : IN STD_LOGIC_VECTOR(16 DOWNTO 10); -- The 40 pin expansion header GPIO_0 pins, which can be used as input or output signals
    );
END Project;

ARCHITECTURE Behavior OF Project IS
    -- This component chooses one of the three delayed pulses, inverts the chosen pulse,
    -- then ANDs the inverted, delayed pulse with the original (effectively shortening the original)
    COMPONENT mux4to1
        PORT (
            delayedpulse_0 : IN  STD_LOGIC;
            delayedpulse_1 : IN  STD_LOGIC;    
            delayedpulse_2 : IN  STD_LOGIC;        
            pulse          : IN  STD_LOGIC;
            SW             : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
            pulseout       : OUT STD_LOGIC
        );
    END COMPONENT;

    COMPONENT LCELL
        PORT (
            a_in  : IN  STD_LOGIC;
            a_out : OUT STD_LOGIC
        );
    END COMPONENT;

    -- These SIGNALs represent the four input pulse from the detectors        
    SIGNAL A, B, C, D, AAA, BBB, CCC, DDD: STD_LOGIC;

    -- These SIGNALs represent the three shortened versions of the pulse,
    -- one of which (along with the original signal) will be chosen by the 4-to-1 mux
    SIGNAL A_internal, B_internal, C_internal, D_internal: STD_LOGIC_VECTOR(27 DOWNTO 0);

    -- These SIGNALs represent the shortened pulses output by the mux4to1 COMPONENT        
    SIGNAL A_s, B_s, C_s, D_s: STD_LOGIC;

    --The SYN_KEEP attribute preserves the signals through the compiler,
    --so that they are not automatically optimized away as redundant logic    
    ATTRIBUTE SYN_KEEP : BOOLEAN;
    ATTRIBUTE SYN_KEEP of A_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of B_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of C_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of D_internal: SIGNAL is TRUE;

    -- NOTE: These shared variables are changed and modified in a different process,
    -- which was left out of this code. This is why they are shared variables
    -- and not regular variables used in the one process.
    shared variable PhaseShift     : integer := 0; -- multiples of 20 ns
    shared variable SelectionWidth : integer := 10000;    
Begin
    AAA <= GPIO_0(10);
    BBB <= GPIO_0(12);
    CCC <= GPIO_0(14);
    DDD <= GPIO_0(16);

    -- This creates, using iteration, a chain of LCELL buffers for each A, B, C, D signal,
    -- which act to delay the signals.
    LCA_1: LCELL PORT MAP(a_in=> A, a_out=>A_internal(0));
    Gen_delay_A : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => A_internal(i),a_out => A_internal(i+1));
    END GENERATE;

    LCB_1: LCELL PORT MAP(a_in=> B, a_out=>B_internal(0));
    Gen_delay_B : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => B_internal(i),a_out => B_internal(i+1));
    END GENERATE;

    LCC_1: LCELL PORT MAP(a_in=> C, a_out => C_internal(0));
    Gen_delay_C : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => C_internal(i),a_out => C_internal(i+1));
    END GENERATE;

    LCD_1: LCELL PORT MAP(a_in=> D, a_out => D_internal(0));
    Gen_delay_D : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => D_internal(i),a_out => D_internal(i+1));
    END GENERATE;

    process(Clock_50)
        variable Period : integer := 100000;
        variable count  : integer := 0;    
    begin
        if (rising_edge(Clock_50)) then
            -- Increase the count by one every time there is a rising edge on the 50MHz clock
            count := count+1;

            if (count=0) then
                -- Begin by ignoring the GPIO_0 pins
                A <= '0';
                B <= '0';
                C <= '0';            
                D <= '0';
            elsif (count=1+PhaseShift) then
                -- Each signal begins to read GPIO_0 once the count reaches a certain time, 
                -- set by PhaseShift.
                A <= GPIO_0(10);
                B <= GPIO_0(12);
                C <= GPIO_0(14);
                D <= GPIO_0(16);
            elsif (count=1+PhaseShift+SelectionWidth) then
                -- Once the signals have read GPIO_0 for a set amount of time SelectionWidth,
                -- the signals are then set back to 0.
                A <= '0';
                B <= '0';
                C <= '0';
                D <= '0';
            elsif (count=Period) then
                -- Once the cycle has finished its period,
                -- the count is reset and the process begins again.
                count := 0;
            end if;
        end if;
    end process;

    MA: mux4to1 PORT MAP(A_internal(8), A_internal(16), A_internal(24), AAA, SW(17 DOWNTO 16), A_s);
    MB: mux4to1 PORT MAP(B_internal(8), B_internal(16), B_internal(24), BBB, SW(17 DOWNTO 16), B_s);
    MC: mux4to1 PORT MAP(C_internal(8), C_internal(16), C_internal(24), CCC, SW(17 DOWNTO 16), C_s);
    MD: mux4to1 PORT MAP(D_internal(8), D_internal(16), D_internal(24), DDD, SW(17 DOWNTO 16), D_s);
END Behavior;

Aquí está mi nuevo código con las sugerencias de abajo:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;

ENTITY Project IS
    PORT (
        Clock_50 : IN STD_LOGIC; -- The 50 MHz clock that is provided on the DE2 Board
        SW       : IN STD_LOGIC_VECTOR(17 DOWNTO 0); -- The switches 0 through 17 on the DE2 Board
        GPIO_0   : IN STD_LOGIC_VECTOR(16 DOWNTO 10); -- The 40 pin expansion header GPIO_0 pins, which can be used as input or output signals
    );
END Project;

ARCHITECTURE Behavior OF Project IS
    -- This component chooses one of the three delayed pulses, inverts the chosen pulse,
    -- then ANDs the inverted, delayed pulse with the original (effectively shortening the original)
    COMPONENT mux4to1
        PORT (
            delayedpulse_0 : IN  STD_LOGIC;
            delayedpulse_1 : IN  STD_LOGIC;    
            delayedpulse_2 : IN  STD_LOGIC;        
            pulse          : IN  STD_LOGIC;
            SW             : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
            pulseout       : OUT STD_LOGIC
        );
    END COMPONENT;

    COMPONENT LCELL
        PORT (
            a_in  : IN  STD_LOGIC;
            a_out : OUT STD_LOGIC
        );
    END COMPONENT;

    CONSTANT Period                                        : positive := 100000;        -- number of counts, by multiples of 20 ns (every clock rising edge is 20ns)
    CONSTANT SelectionWidth                                : positive := Period/10;     -- number of counts, by multiples of 20 ns 

    SIGNAL   PhaseShift                                    : natural range 0 to Period-SelectionWidth := 0;
    SIGNAL   count                                         : natural range 0 to Period := 0;        -- one count for every rising edge of 50 MHz clock

    SIGNAL   A, B, C, D, AAA, BBB, CCC, DDD                : STD_LOGIC;    -- These SIGNALs represent the four input pulse from the photon detectors        
    SIGNAL   A_internal, B_internal, C_internal, D_internal: STD_LOGIC_VECTOR(27 DOWNTO 0); -- These SIGNALs represent the three shortened versions of the pulse, one of which (along with the original signal) will be chosen by the 4-to-1 mux
    SIGNAL   A_s, B_s, C_s, D_s                            : STD_LOGIC; -- These SIGNALs represent the shortened pulses output by the mux4to1 COMPONENT     


    ATTRIBUTE SYN_KEEP : BOOLEAN;   --The SYN_KEEP attribute preserves the signals through the compiler, so that they are not automatically optimized away as redundant logic   
    ATTRIBUTE SYN_KEEP of A_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of B_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of C_internal: SIGNAL is TRUE;
    ATTRIBUTE SYN_KEEP of D_internal: SIGNAL is TRUE;


Begin
    AAA <= GPIO_0(10);
    BBB <= GPIO_0(12);
    CCC <= GPIO_0(14);
    DDD <= GPIO_0(16);


clk_count: process(Clock_50)
begin
    if (rising_edge(Clock_50)) then
        if (count<=(Period-1)) then
            count <= count + 1;
        else
            count <= 0;
        end if;

        if (count=(0))then  -- Begin by setting the output pulse to 0
            A <= '0';
            B <= '0';
            C <= '0';           
            D <= '0';
        elsif ((count>(1+PhaseShift)) and  (count<(1+PhaseShift+SelectionWidth)))then  -- Each pin is triggered once the count reaches a certain time delay, set by PhaseShift  
            A <= GPIO_0(10);
            B <= GPIO_0(12);
            C <= GPIO_0(14);
            D <= GPIO_0(16);
        elsif (count>=(1+PhaseShift+SelectionWidth))then  -- Once the pulse has reached a set amount of time SelectionWidth, the pulse is then turned back to 0.
            A <= '0';
            B <= '0';
            C <= '0';
            D <= '0';
        end if;
    end if;
end process;

    LCA_1: LCELL PORT MAP(a_in=> A, a_out=>A_internal(0));  -- This creates, using iteration, a chain of LCELL buffers for each A, B, C, D signal, which act to delay the signals.
    Gen_delay_A : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => A_internal(i),a_out => A_internal(i+1));
    END GENERATE;

    LCB_1: LCELL PORT MAP(a_in=> B, a_out=>B_internal(0));
    Gen_delay_B : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => B_internal(i),a_out => B_internal(i+1));
    END GENERATE;

    LCC_1: LCELL PORT MAP(a_in=> C, a_out => C_internal(0));
    Gen_delay_C : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => C_internal(i),a_out => C_internal(i+1));
    END GENERATE;

    LCD_1: LCELL PORT MAP(a_in=> D, a_out => D_internal(0));
    Gen_delay_D : FOR i in 0 to 23 GENERATE
        LC : LCELL PORT MAP(a_in => D_internal(i),a_out => D_internal(i+1));
    END GENERATE;

    MA: mux4to1 PORT MAP(A_internal(8), A_internal(16), A_internal(24), AAA, SW(17 DOWNTO 16), A_s);
    MB: mux4to1 PORT MAP(B_internal(8), B_internal(16), B_internal(24), BBB, SW(17 DOWNTO 16), B_s);
    MC: mux4to1 PORT MAP(C_internal(8), C_internal(16), C_internal(24), CCC, SW(17 DOWNTO 16), C_s);
    MD: mux4to1 PORT MAP(D_internal(8), D_internal(16), D_internal(24), DDD, SW(17 DOWNTO 16), D_s);
END Behavior;
    
pregunta Cody495

1 respuesta

1

El problema está aquí:

process(Clock_50)
    variable Period : integer := 100000;
    variable count  : integer := 0;    

Esto significa que cada vez que Clock_50 desencadena este proceso, la variable count se establece en 0. Al igual que en los estados

Es por eso que mencioné en los comentarios sobre las variables. Úsalos solo si sabes lo que estás haciendo. Deberías usar señales en su lugar.

    constant Period : positive:= 100000;
    signal count : natural range 0 to Period-1 := 0;
begin
    [...]
    clk_proc: process(Clock_50) -- I added a label. easier for debugging.
    begin
        if (rising_edge(Clock_50)) then
            if (count<(Period-1)) then
                count <= count + 1;
            else
                count <= 0;
            end if;
    
respondido por el JHBonarius

Lea otras preguntas en las etiquetas