Tic Tac Toe的VHDL代码

时间:2017-11-23 20:12:47

标签: vhdl fpga tic-tac-toe

我正在做一个简单的tic tac toe游戏,但有问题。

显然,"播放器"信号永远不是我想要的。我尝试将它声明为布尔值并将其初始化为true,但它从未进入if子句;但是,当我把它改为假时,它也没有进入该条款。然后,我尝试将其更改为位,是的..同样的问题

library ieee;
use ieee.std_logic_1164.all;

entity ticTacToe is
port(
    hex: OUT STD_LOGIC_VECTOR(0 TO 6);
    useless         : out bit           := '1';
    win_X           : out bit           := '1';
    win_O           : out bit           := '1';
    row0line0_in    :   in  std_logic   := 'U';
    row1line0_in    :   in  std_logic   := 'U';
    row2line0_in    :   in  std_logic   := 'U';
    row0line1_in    :   in  std_logic   := 'U';
    row1line1_in    :   in  std_logic   := 'U';
    row2line1_in    :   in  std_logic   := 'U';
    row0line2_in    :   in  std_logic   := 'U';
    row1line2_in    :   in  std_logic   := 'U';
    row2line2_in    :   in  std_logic   := 'U'
);
end ticTacToe;


architecture behaviour of ticTacToe is
    signal player           : bit; --X starts game
    shared variable wins    : boolean   := false;

    shared variable row0line0   :   std_logic   := 'U';
    shared variable row1line0   :   std_logic   := 'U';
    shared variable row2line0   :   std_logic   := 'U';
    shared variable row0line1   :   std_logic   := 'U';
    shared variable row1line1   :   std_logic   := 'U';
    shared variable row2line1   :   std_logic   := 'U';
    shared variable row0line2   :   std_logic   := 'U';
    shared variable row1line2   :   std_logic   := 'U';
    shared variable row2line2   :   std_logic   := 'U';


    function winner(row0line0, row0line1, row0line2, row1line0, row1line1,
        row1line2, row2line0, row2line1, row2line2:std_logic) return boolean is
    begin
        --check if X wins
        if(row0line0 = '1' and row0line1 = '1' and row0line2 = '1') then
            win_X <= '0';
        end if;
        if(row0line0 = '1' and row1line0 = '1' and row2line0 = '1') then
            win_X <= '0';
        end if;
        if(row0line0 = '1' and row1line1 = '1' and row2line2 = '1') then
            win_X <= '0';
        end if;
        if(row1line0 = '1' and row1line1 = '1' and row1line2 = '1') then
            win_X <= '0';
        end if;
        if(row2line0 = '1' and row2line1 = '1' and row2line2 = '1') then
            win_X <= '0';
        end if;
        if(row2line0 = '1' and row1line1 = '1' and row0line2 = '1') then
            win_X <= '0';
        end if;
        if(row0line1 = '1' and row1line1 = '1' and row2line1 = '1') then
            win_X <= '0';
        end if;
        if(row0line2 = '1' and row1line2 = '1' and row2line2 = '1') then
            win_X <= '0';
        end if;

        --check if O wins
        if(row0line0 = '0' and row0line1 = '0' and row0line2 = '0') then
            win_O <= '0';
        end if;
        if(row0line0 = '0' and row1line0 = '0' and row2line0 = '0') then
            win_O <= '0';
        end if;
        if(row0line0 = '0' and row1line1 = '0' and row2line2 = '0') then
            win_O <= '0';
        end if;
        if(row1line0 = '0' and row1line1 = '0' and row1line2 = '0') then
            win_O <= '0';
        end if;
        if(row2line0 = '0' and row2line1 = '0' and row2line2 = '0') then
            win_O <= '0';
        end if;
        if(row2line0 = '0' and row1line1 = '0' and row0line2 = '0') then
            win_O <= '0';
        end if;
        if(row0line1 = '0' and row1line1 = '0' and row2line1 = '0') then
            win_O <= '0';
        end if;
        if(row0line2 = '0' and row1line2 = '0' and row2line2 = '0') then
            win_O <= '0';
        end if;

    return false;   
    end winner;

begin
    --variable becomes '0' for player O and '1' for player X
    process(row0line0_in, row0line1_in, row0line2_in, row1line0_in, row1line1_in,
        row1line2_in, row2line0_in, row2line1_in, row2line2_in)is
    begin
        if(row0line0_in'event and row0line0_in = '1')then
            if(player = '0')then
                row0line0 := '1';
            else
                useless <= '0';
                row0line0 := '0';
            end if;
        end if;

        if(row0line1_in'event and row0line1_in = '1')then
            if(player = '0')then
                row0line1 := '1';
            else
                row0line1 := '0';
            end if;
        end if;

        if(row0line2_in'event and row0line2_in = '1')then
            if(player = '0')then
                row0line2 := '1';
            else
                row0line2 := '0';
            end if;
        end if;

        if(row1line0_in'event and row1line0_in = '1')then
            if(player = '0')then
                row1line0 := '1';
            else
                row1line0 := '0';
            end if;
        end if;

        if(row1line1_in'event and row1line1_in = '1')then
            if(player = '0')then
                row1line1 := '1';
            else
                row1line1 := '0';
            end if;
        end if;

        if(row1line2_in'event and row1line2_in = '1')then
            if(player = '0')then
                row1line2 := '1';
            else
                row1line2 := '0';
            end if;
        end if;

        if(row2line0_in'event and row2line0_in = '1')then
            if(player = '0')then
                row2line0 := '1';
            else
                row2line0 := '0';
            end if;
        end if;

        if(row2line1_in'event and row2line1_in = '1')then
            if(player = '0')then
                row2line1 := '1';
            else
                row2line1 := '0';
            end if;
        end if;

        if(row2line2_in'event and row2line2_in = '1') then 
            if(player = '0')then
                row2line2 := '1';
            else
                row2line2 := '0';
            end if;
        end if;
        player <= not player;
    end process;

    --check winner
    process(player)is
    begin
        wins    :=  winner(row0line0, row0line1, row0line2, row1line0, row1line1,
        row1line2, row2line0, row2line1, row2line2);
    end process;
end behaviour;

如果有人知道问题可能是什么,我会很感激!

2 个答案:

答案 0 :(得分:2)

我在这里看到几个主要问题。

  1. 您的设计没有时钟信号。它试图在所有输入上进行边沿触发(例如,gradle.properties),这不太可能合成到工作逻辑。

    你需要一个时钟信号。如果你不熟悉这个概念,那么现在是时候回到书本上阅读如何设计顺序逻辑了。

  2. 您的设计正在尝试将// Hypothetical code, does not actually compile: val a: Int? = 1 // A boxed Int (java.lang.Integer) val b: Long? = a // implicit conversion yields a boxed Long (java.lang.Long) print(a == b) // Surprise! This prints "false" as Long's equals() // check for other part to be Long as well 用作row0line0_in信号的值。该值仅在模拟中有意义,它用于表示未初始化的值;在综合中,这些信号都将以任意值(可能为0)进行初始化。如果您确实想要存储三个不同的值,则需要使用多位类型。

  3. 第一个进程中的表达式'U'与任何事件都没有关联。这将在模拟中出现意外行为(当任何输入的值发生变化时,值可能会发生变化,从0到1或反之亦然),并且它将无法合成(因为没有合理的触发方式)这个逻辑在多个时钟的两个边缘上。)

答案 1 :(得分:2)

duskwuff的答案中指出的所有问题都是正确的,可能会解决您的问题。但是,我想补充一些糟糕的VHDL问题:

我强烈建议您立即停止使用bit类型。如果要表达逻辑,请仅使用std_logic。原因可以找到here。我认为95%的时间(绝对是你的情况),相同的论点也适用于boolean类型的使用。

另外,请不要使用shared variable。这是VHDL。它的硬件描述,而不是程序代码。 VHDL没有定义当变量的冲突访问发生时会发生什么。 VHDL中的共享变量具有非常少且非常具体的用例。你似乎是一个初学者,所以我的建议是:忘记这个概念存在。它不可能为您提供良好的代码或编码实践。仅使用信号。

在您的情况下,变量声明也恰好完全没有任何作用。您的函数声明包含所有变量的声明,VHDL通常使用最本地的声明。您的架构 - 全局共享变量永远不会被使用。仅分配了wins变量,但它永远不会被分配给输出或回读,因此它也是无用的。您应该将wins声明为signal wins : std_logic并删除其他共享变量。

最后,稍微提高一点。您非常热衷于初始化输入,输出,信号和变量。也许这是因为你已经学会了作为一个程序员这样做,也许是因为你读到了应该的地方。但请注意,这些初始化不能保证是可综合的。在没有从ROM加载配置比特流的ASIC或基于闪存的FPGA上,很可能这些初始化不起作用。这可能并且将导致时髦的未定义行为,其中批量的一个芯片将在室温下可靠地初始化为0,而另一个芯片将可靠地初始化为1(我已经看到这种情况发生在Microsemi FPGA上)。如果您按照duskwuff建议并初始化为'1''0',则存在模拟不匹配的风险(即,使用这些初始化的模拟与实际硬件的工作方式不同)。 考虑不在声明时初始化您的信号,而是在重置时初始化它们。这样,如果您忘记重置信号并知道出现问题,您将在模拟器中看到状态U