No se pueden extraer los valores esperados en VHDL en el primer ciclo de reloj

Se supone que el diseño VHDL a continuación extrae los bits N de los cuatro valores x_0, x_1, x_2 y x_3 y crea un nuevo valor en cada reloj, pero esto no sucede.

Encuentre a continuación el diseño y la salida generada para algunos valores forzados para x_0 = 1100, x_1 = 0100, x_2 = 0010 y x_3 = 1011.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gen_input is
    port (x_0,x_1,x_2,x_3 : in std_logic_vector(3 downto 0);
            y : out std_logic_vector(3 downto 0);
            clk : std_logic);
end gen_input;

architecture Behavioral of gen_input is
signal i : integer := 0;    
begin
    inst_process : process (clk,x_3,x_2,x_1,x_0)
                        begin
                        if(clk'event and clk='1') then
                            if(i < 4) then
                            y <= x_3(i)&x_2(i)&x_1(i)&x_0(i);
                            i <= i + 1;
                            else 
                            i <= 0;
                            end if;     
                        end if; 
                        end process inst_process;
end Behavioral;

La salida generada:Salida para valores asignados de x_0, x_1, x_2 y x_3

(1) los paréntesis redondean las expresiones innecesarias (esto no es c), (2) hace 25 años, la función riser_edge simplificó la detección del borde del reloj (3) no hay un banco de pruebas, así que no podemos probarlo nosotros mismos (4) en realidad no hay una pregunta aquí y (5) el código parece estar haciendo exactamente lo que esperaba.
@BrianDrummond, no se requieren paréntesis alrededor de las expresiones, pero son opcionales para un autor. Personalmente, creo que hacen que la condición de prueba sea distinta y mucho más clara para el lector en una página de VHDL. El punto 2 es cierto. ¿Puede expandir el punto 5 en una explicación o respuesta?
@TonyM Son opcionales, pero me parecen desordenados. Tal vez sea diferente para los lectores más jóvenes criados en c. En cuanto al punto 5, cualquier explicación de la semántica de asignación de señales y los ciclos delta debería ser suficiente; si no están completamente claros, quizás el interrogador necesite hacer una pregunta real.
Bienvenido al sitio. Tenga en cuenta que esto no es una casa de diseño gratuita, un servicio de respuesta de tareas o una enciclopedia técnica en línea, copiada a pedido. La gente le ayudará a dar el siguiente paso si su pregunta demuestra que ha hecho todo lo posible por su cuenta, cosa que me temo que no sucede con la suya. Edite su pregunta y mejórela considerablemente. Haga una pregunta específica, mostrando su trabajo y hallazgos hasta el momento con considerable detalle con cualquier esquema. Cuanto mejor sea la calidad de la pregunta, mejor será la calidad de las respuestas que atraerá. Una vez más, una cálida bienvenida al sitio.
Brian tiene un punto válido sobre la función riser_edge. Una transición de 'U' a '1' en clk satisface la condición clk'event and clk='1mientras que no cumpliría rising_edge(clk)lo que requiere una transición de '0' o 'L' a '1' o 'H' (filtrando el valor del parámetro y el último valor a través de la función A_X01). Tenga en cuenta que el primer valor que no es U y_genes el segundo valor de bit de X_3 - X_0. Por favor, plantee una pregunta.
Si clk tuviera un valor inicial de '0' o usara riser_edge(clk), vería que el primer valor sale correctamente (observando que ordeno de derecha a izquierda). Tenga en cuenta lo que sucede cuando i = 4 (no se muestra aquí).
El uso de la función sunrise_edge resuelve esto para mí, gracias. @TonyM, la publicación no fue para familiarizarme con la sintaxis, que no es el punto de consulta aquí.

Respuestas (1)

y crea un nuevo valor en cada reloj pero esto no está sucediendo

La razón por la que esto no sucede es porque su código tiene un ciclo de reloj en el que no se asigna ninguna salida:

if(clk'event and clk='1') then
    if(i < 4) then
        y <= x_3(i)&x_2(i)&x_1(i)&x_0(i);
        i <= i + 1;
    else 
        i <= 0; -- here you have no assignment to y
    end if;     
end if;

Además, su código sería más simple si declarara icomo variableen lugar de como signal, que es probablemente lo que quiere hacer de todos modos. Vea esto para algunas discusiones sobre las diferencias.

Este código es probablemente lo que estás buscando (como una simulación):

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity gen_input is
end gen_input;

architecture Behavioral of gen_input is

    signal y   : std_logic_vector(3 downto 0);
    signal clk : std_logic := '0';

    constant x_0 : std_logic_vector(3 downto 0) := b"1100";
    constant x_1 : std_logic_vector(3 downto 0) := b"0100";
    constant x_2 : std_logic_vector(3 downto 0) := b"0010";
    constant x_3 : std_logic_vector(3 downto 0) := b"1011";

begin

    clkgen: process
    begin
        wait for 10 ns;
        clk <= not clk;
    end process clkgen;

    inst_process : process (clk)
        variable i : natural range 0 to 3 := 0;
    begin
        if rising_edge(clk) then
            y <= x_3(i) & x_2(i) & x_1(i) & x_0(i);
            i := i + 1;
            if i = 4 then
                i := 0;
            end if;
        end if;
    end process inst_process;
end Behavioral;

Tenga en cuenta que, dado que ise declara como variabledentro del proceso, puede incrementarlo iy luego verificarlo inmediatamente para ver si debe restablecerse a 0. También puede hacer esto:

if i = 3 then
    i := 0;
else
    i := i + 1;
end if;

pero es más escribir y no es necesario. De cualquier manera, terminará con exactamente el mismo RTL.

Aquí está la simulación:

simulación

Y, de hecho, para discutir conmigo mismo, probablemente no necesite la declaración if en absoluto, ya que la variable i estará limitada a solo 2 bits (para el rango de 0 a 3), y simplemente cambiará de manera natural. Pero no pude hacer que el sim funcionara sin reiniciarlo explícitamente. Probablemente esto sea solo una configuración de simulación en Vivado.