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:
-
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;
-
[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