El sumador binario simple funciona solo parcialmente

1

EDICIÓN POSTERIOR:

1. También he investigado visualmente el dispositivo Kintex7 después de la implementación (es decir, las interconexiones, etc.) y todo se ve bien, no hay conexiones que indiquen que las cosas no estarían bien (por supuesto, no regresé a las entradas, ya que asumo que si el loopback basado en 2-FIFO funciona, sería el sumador el que está roto de alguna manera).

También encontré este Registro de respuestas de Xilinx . Intenté aplicar la solución sugerida, pero no funcionó.

2. Para el segundo enfoque (entrada manual en Spartan6), me di cuenta de que el problema era un interruptor defectuoso que no configuraba correctamente el valor de entrada a menos que se tuviera cuidado. He probado con cuidado otra vez y obtuve el valor correcto esta vez. Sin embargo, cambié ese diseño para tomar las entradas de ROM / LUT y mostrar un byte a la vez, dependiendo de los interruptores de selección dados como entradas. No hay reloj involucrado más. El problema con el proyecto inicial basado en Vivado persiste, lo que me lleva a creer que podría tratarse de un problema de hardware de síntesis / implementación / defectuoso.

MENSAJE ORIGINAL:

Tengo un diseño PCIe basado en xillybus que está destinado a ser más complejo, pero por ahora, yendo de manera incremental, solo lee pares de valores de 32 bits de un FIFO de entrada de 32 bits conectado a xillybus y los agrega. escribiéndolos en un FIFO de salida de 32 bits conectado a xillybus.

Ahora el problema que veo es el siguiente:
NOTA 1: la forma de onda de salida de la simulación de comportamiento (nivel RTL, síntesis previa) devuelve los valores correctos, es la implementación real en el tablero que parece tener uno o más bits invertidos (opuesto al valor esperado, que es el mismo que el resultado de la simulación)
NOTA 2: Yo, por ejemplo, uso el los valores 0x3F800000 y 0x3F800000 (sí, dos veces el mismo valor), que agregado bit a bit debería ascender a 0x7F000000 ; se mencionará a continuación el resultado (incorrecto) en cada escenario:

  • Si intento un enfoque de bucle invertido (leyendo de la entrada FIFO y enviando la salida a la salida FIFO - por lo tanto, utilizando 2 FIFOs -, NO utilizando solo un FIFO conectado tanto a la entrada como a la salida desde / al xillybus) se devuelven los valores como se esperaba. No lo he probado exhaustivamente, pero parece estar bien para todos los valores que he probado.
  • Si intento ejecutar el diseño en una placa NetFPGA-1G-CML (Kintex-7 XC7K325T-1FFG676 FPGA), obtengo el resultado 0x7E000100 (recuerda, la prueba de bucle invertido funciona)
  • Si trato de ejecutar el diseño equivalente (adaptado a cómo se ingresan los valores, es decir, no a través de PCIe desde la PC, sino manualmente usando interruptores, pulsadores filtrados monopulso-generador y salida en LED) en un Atlys (Spartan-6 XC6SLX45-3CSG324), el resultado es 0x6F00000 (más cerca, ya que solo hay un bit de error, pero aún no es suficiente)

Tenga en cuenta que no tengo ninguna queja en cuanto a las infracciones de restricción de tiempo, y de todos modos he intentado muchas formas de solucionar el problema (es decir, filtrar algunas posibilidades), pero no llegué a ninguna conclusión. Para el registro, incluso transformé el sumador simple en un canal de 2 niveles, para "garantizar" que haya suficiente tiempo para calcular el resultado, pero el resultado fue el mismo (incorrecto).

Aparentemente no puedo ejecutar la simulación funcional o de sincronización post-síntesis o post-implementación, ya que recibo un error molesto que dice

  

ERROR: [VRFC 10-716] el puerto formal o de mode out no puede asociarse con el puerto real pcie_perst_b_ls del modo en [...]

Tenga en cuenta que estoy ejecutando Vivado 2014.2 (que es un poco antiguo, pero ¿ese sería realmente el problema?)

Debajo del código para los 2 enfoques (E / S basada en PCIe basada en xillybus y E / S física simple). Lo siento, no pude formatearlo mejor:

  1. Enfoque para la E / S basada en Kintex-7 PCIe:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity fsm is
        port (
            data_in : in std_logic_vector(31 downto 0);
            data_out : out std_logic_vector(31 downto 0);
            rd_en : out std_logic;
            in_fifo_empty : in std_logic;
            wr_en : out std_logic;
            out_fifo_full : in std_logic;
            clk, rst : in std_logic
        );
    end fsm;
    
    architecture Behavioral of fsm is
    
        component core
           port (
                operand_A_ieee, operand_B_ieee : in std_logic_vector(31 downto 0);
                result_ieee : out std_logic_vector(31 downto 0);
                clk, rst : in std_logic 
           );
        end component;
    
        -- pipeline_depth and pipeline_wr_status are used (only) for pipelined cores to assert wr_en when needed
        -- ('1' added to the MSB of pipeline_wr_status when the second 32-bit operand is read and therefore the 
        -- core processing starts with valid data, so that it signals when a valid result reached the end of the core)
        --constant pipeline_depth : integer := 10;
        --signal pipeline_wr_status : std_logic_vector(pipeline_depth - 1 downto 0) := (others => '0');
    
        type state_type is ( start, readA, waitB, addAB );
        signal state, next_state: state_type;
    
        signal operand_A_ieee : std_logic_vector(31 downto 0) := (others => '0');
        signal result_ieee : std_logic_vector(31 downto 0);
    
    begin
    
        core_inst: core
            port map (
                operand_A_ieee => operand_A_ieee,
                operand_B_ieee => data_in,
                result_ieee => data_out,
                clk => clk,
                rst => rst
            );
    
        -- The loopback test (remove core_inst above) works as expected - in the out FIFO the value read from the in FIFO is saved
        --data_out <= data_in;
    
        SL: process (clk, rst, state, next_state, data_in)--, pipeline_wr_status)
        begin
            if rising_edge(clk) then
                state <= next_state;
                if state = readA then
                    operand_A_ieee <= data_in;
                end if;
                -- needed if pipelined core
                --if next_state = addAB then
                    --pipeline_wr_status <= "1" & pipeline_wr_status(pipeline_depth-1 downto 1);
                --else
                    --pipeline_wr_status <= "0" & pipeline_wr_status(pipeline_depth-1 downto 1);
                --end if;
            end if;
        end process;
    
        -- wr_en flag has beem moved out of the case/process below, for simplicity
        wr_en <= '1' when state = addAB else '0';
        --wr_en <= pipeline_wr_status(0);
    
        -- TODO: add rst signal as input to the state machine
        CL: process(rst, state, in_fifo_empty, out_fifo_full)
        begin
            case (state) is
                when start =>
                    if rst = '1' then
                        next_state <= start;
                        rd_en <= '0';
                    else
                        if in_fifo_empty = '1' then
                            next_state <= start;
                            rd_en <= '0';
                        else
                            next_state <= readA;
                            rd_en <= '1';
                        end if;
                    end if;
                when readA =>
                    if rst = '1' then
                        next_state <= start;
                        rd_en <= '0';
                    else
                        if in_fifo_empty = '1' then
                            next_state <= waitB;
                            rd_en <= '0';
                        else
                            next_state <= addAB;
                            rd_en <= '1';
                        end if;
                    end if;
                when waitB =>
                    if rst = '1' then
                        next_state <= start;
                        rd_en <= '0';
                    else
                        if in_fifo_empty = '1' then
                            next_state <= waitB;
                            rd_en <= '0';
                        else
                            if out_fifo_full = '1' then
                                next_state <= waitB;
                                rd_en <= '0';
                            else
                                next_state <= addAB;
                                rd_en <= '1';
                            end if;
                        end if;
                    end if;
                when addAB => -- aka readB (read of B operator happens here)
                    if rst = '1' then
                        next_state <= start;
                        rd_en <= '0';
                    else
                        if in_fifo_empty = '1' then
                            next_state <= start;
                            rd_en <= '0';
                        else
                            next_state <= readA;
                            rd_en <= '1';
                        end if;
                    end if;   
                when others =>
                    next_state <= start;
                    rd_en <= '0';
            end case;
        end process;
    
    end Behavioral;
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity core is
        port (
            operand_A_ieee, operand_B_ieee : in std_logic_vector(31 downto 0);
            result_ieee : out std_logic_vector(31 downto 0);
            clk, rst : in std_logic
        );
    end core;
    
    architecture Behavioral of core is
    
        component adder
            port (
                A, B: in std_logic_vector(31 downto 0);
                R: out std_logic_vector(31 downto 0)
            );
        end component;
    
    begin
    
        addition: adder port map (operand_A_ieee, operand_B_ieee, result_ieee);
    
    end Behavioral;
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    entity adder is
        port (
            A, B: in std_logic_vector(31 downto 0);
            R: out std_logic_vector(31 downto 0)
        );
    end adder;
    
    architecture Behavioral of adder is
    
    begin
    
        R <= std_logic_vector(unsigned(A) + unsigned(B));
    
    end Behavioral;
    
  2. [SIMPLIFICADO EN COMPARACIÓN CON INICIAL, PERO NO ES IMPORTANTE MÁS - VÉASE MÁS DESPUÉS DE LA EDICIÓN] Enfoque para el Spartan-6 físico (botones, interruptores, LED) E / S:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity top is
    
        port (
            sw : in std_logic_vector(1 downto 0);
            led : out std_logic_vector(7 downto 0)
        );
    
    end top;
    
    architecture Behavioral of top is
    
        signal a : std_logic_vector(31 downto 0) := x"3f800000";
        signal b : std_logic_vector(31 downto 0) := x"3f800000";
        signal r : std_logic_vector(31 downto 0);
    
    begin
    
        r <= std_logic_vector(unsigned(a) + unsigned(b));
        led <= r(8 * (to_integer(unsigned(sw)) + 1) - 1 downto 8 * to_integer(unsigned(sw)));
    
    end Behavioral;
    
    # onBoard SWITCHES
    NET "sw<0>" LOC = "A10"; # Bank = 0, Pin name = IO_L37N_GCLK12,         Sch name = SW0
    NET "sw<1>" LOC = "D14"; # Bank = 0, Pin name = IO_L65P_SCP3,       Sch name = SW1
    
    # onBoard Leds
    NET "led<0>" LOC = "U18"; # Bank = 1, Pin name = IO_L52N_M1DQ15,       Sch name = LD0
    NET "led<1>" LOC = "M14"; # Bank = 1, Pin name = IO_L53P,              Sch name = LD1
    NET "led<2>" LOC = "N14"; # Bank = 1, Pin name = IO_L53N_VREF,     Sch name = LD2
    NET "led<3>" LOC = "L14"; # Bank = 1, Pin name = IO_L61P,              Sch name = LD3
    NET "led<4>" LOC = "M13"; # Bank = 1, Pin name = IO_L61N,              Sch name = LD4
    NET "led<5>" LOC = "D4";  # Bank = 0, Pin name = IO_L1P_HSWAPEN_0,     Sch name = HSWAP/LD5
    NET "led<6>" LOC = "P16"; # Bank = 1, Pin name = IO_L74N_DOUT_BUSY_1, Sch name = LD6
    NET "led<7>" LOC = "N12"; # Bank = 2, Pin name = IO_L13P_M1_2,         Sch name = M1/LD7
    
pregunta BogdanSorlea

2 respuestas

0

Mientras tanto, he descubierto cuál era el problema. Básicamente, tiene que ver con la endianidad de bytes, es decir, xillybus presentará los bytes en un valor de 32 bits en el orden inverso a como se escribieron en el archivo del dispositivo (y se volteará de la misma manera cuando se escribe desde el núcleo a el host).

Para obtener más detalles, consulte: enlace

    
respondido por el BogdanSorlea
1

No puedo decir con seguridad que esto ayude, pero creo que el proceso de "canalización" en la entidad "sumador" es inusual. Usaría un elsif en el aumento de la cobertura del reloj y eliminaría A y B de la lista de sensibilidad.

Además, usar el aumento de nivel de paso puede no ser una buena idea ya que no es una señal de reloj. Una solución alternativa sería hacer algo en esta línea:

process(clk)
begin
    if rising_edge(clk) then
        step_r <= step;
        if step = '1' and step_r='0' then -- Finds rising edge of step
             <Logic>
        end if;
    end if;
end process;
    
respondido por el ks0ze

Lea otras preguntas en las etiquetas