VHDL奇怪的比特错误似乎毫无意义

时间:2016-02-04 09:22:27

标签: arrays vhdl bit fpga

我有一个带有Xilinx Spartan-3A的Micro-Nova FPGA开发板。我试图让它使用3个引脚在覆盆子pi上通过GPIO进行通信:REQ,ACK,DATA。如果我取消注释bit_data赋值并注释掉" bit_data:= data_out(data_ofs);"代码工作正常。并且在Pi上我得到一个连续的10101010 ......等等。但是如果我将代码粘贴在下面,我会在随机时间得到错误的位,例如。 1010110100 ......等。

知道可能是什么问题吗?:

FPGA上的VHDL:

public static Object executeScript(String script) throws InterruptedException, ExecutionException {
        if(Platform.isFxApplicationThread()) {
            return webEngine.executeScript(script);
        } 
        FutureTask<Object> task = new FutureTask<>(new Callable<Object>() {
             @Override
             public Object call() throws Exception {
                 return webEngine.executeScript(script);
             }
         });
         Platform.runLater(task);
         return task.get();

    }

Pi上的Bash脚本:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity xclock is

Port(CLK : in STD_LOGIC;
     REQ : in STD_LOGIC;
     ACK : out STD_LOGIC;
     DATA : out STD_LOGIC);

end xclock;

architecture Behavioral of xclock is

begin

    process(CLK)

        variable data_ofs : integer range 0 to 2 := 0;
        variable data_out : std_logic_vector(1 downto 0) := "01";
        variable bit_data : std_logic := '0';
        variable ack_data : std_logic := '0';
        variable LASTREQ : std_logic := '0';
        variable seconds : integer range 0 to 50000000 := 0;
        variable tick : integer range 0 to 50000000 := 0;

    begin

        if CLK'event and CLK = '1' then

            tick := tick + 1;
            if tick = 49999999 then
                tick := 0;
                seconds := seconds + 1;
                if seconds = 49999999 then
                    seconds := 0;
                end if;
            end if;

            if seconds > 1 then
                if REQ /= LASTREQ and REQ /= ack_data then
                    LASTREQ := REQ;
                    if REQ = '1' then
                        --bit_data := '1';
                        ack_data := '1';
                    else
                        --bit_data := '0';
                        ack_data := '0';
                    end if;
                    bit_data := data_out(data_ofs);
                    data_ofs := data_ofs + 1;
                    if data_ofs = 2 then
                        data_ofs := 0;
                    end if;
                end if;
            end if;

            DATA <= bit_data;
            ACK <= ack_data;

        end if;

    end process;

end Behavioral;

任何帮助将不胜感激。把头发拉出来!

1 个答案:

答案 0 :(得分:0)

我花了一些时间试图弄清楚你的代码应该如何工作(协议是什么),但我放弃了。建立其他人的建议,你可能会尝试进行以下修改,看看它是否有所不同。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity xclock is

port(CLK : in STD_LOGIC;
     REQ : in STD_LOGIC;
     ACK : out STD_LOGIC;
     DATA : out STD_LOGIC);

end xclock;

architecture Behavioral of xclock is

   signal req_reg1, req_reg2, req_int, last_req : std_logic := '0';
   signal bit_data_reg, ack_reg                 : std_logic;

begin

    process(CLK)

        variable data_ofs : integer range 0 to 2 := 0;
        variable data_out : std_logic_vector(1 downto 0) := "01";
        variable bit_data : std_logic := '0';
        variable ack_data : std_logic := '0';
        variable seconds : integer range 0 to 50000000 := 0;
        variable tick : integer range 0 to 50000000 := 0;

    begin

        if CLK'event and CLK = '1' then

            -- Input registers help prevent metastability on REQ line
            -- Note that if there is significant bounce or glitching, then
            -- you will also need a deglitcher.
            req_reg1 <= REQ;
            req_reg2 <= req_reg1;
            req_int  <= req_reg2;

            tick := tick + 1;
            if tick = 49999999 then
                tick := 0;
                seconds := seconds + 1;
                if seconds = 49999999 then
                    seconds := 0;
                end if;
            end if;

            if seconds > 1 then
                -- Using the registered inputs instead of the direct REQ input.
                if req_int /= last_req and req_int /= ack_data then
                    last_req <= req_int;
                    if req_int = '1' then
                        ack_data := '1';
                    else
                        ack_data := '0';
                    end if;
                    bit_data := data_out(data_ofs);
                    data_ofs := data_ofs + 1;
                    if data_ofs = 2 then
                        data_ofs := 0;
                    end if;
                end if;
            end if;

            -- Register outputs to ensure consistent OREG packing, if enabled
            bit_data_reg <= bit_data;
            ack_reg      <= ack_data;

            DATA         <= bit_data_reg;
            ACK          <= ack_reg;

        end if;

    end process;

end Behavioral;

对代码的修改做了两件事:

  • 注册输入REQ几次以降低亚稳态的可能性,然后仅使用注册值而不是引脚本身。 (Read more
  • 注册输出(两次)以确保输出寄存器可以放在OREG(在IOB中),这可确保输出焊盘的时钟到输出时序一致。在设备的边界,如果可能的话,最好放置一个普通的FF寄存器级,以确保可以封装到OREG中。否则,可能会有从最后一个注册阶段返回到您的设计的反馈路径,从而阻止打包。