我正在用VHDL制作一个简单的TicTacToe游戏(计算机与用户)并且代码几乎已经完成,但有些东西我无法弄清楚如何处理它。
总体而言,有三个主要模块,基于当前网格的计算机移动,网格状态,其接收由计算机或用户填充哪个单元格,从网格模块检索网格并处理这些组件的主模块以及用户搬家。
所以,在这个主模块中,我有一个Component,它将移动(通过计算机或用户)发送到网格模块,然后在此主模块中更新其当前网格信号,然后更新第二个组件(计算机移动)接收网格状态(即信号)并根据该状态进行移动。因此,这也需要发送到网格模块以进行更新。但是,当按照这个顺序运行时,这并没有真正起作用。
简而言之,我的问题是,如何按照组件执行的顺序更新此主信号,或者更一般地说,如何通过需要成为另一个组件的输入的组件来更新信号组件分别?
感谢您的帮助。
修改
这是主模块代码的一部分
ENTITY currentstate IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid (X or O)
difficulty : IN STD_LOGIC; --difficulty
winner_state : OUT INTEGER RANGE 0 to 2; --who is the winner?
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END currentstate;
---------------------------------
ARCHITECTURE statearch OF currentstate IS
SIGNAL comp_occupy : TO_SELECT;
SIGNAL grid_status : GRID (1 TO 3, 1 TO 3);
COMPONENT grid IS -------saves the grid status
PORT (to_occupy_cell : IN TO_SELECT; start : IN STD_LOGIC; by_user : IN STD_LOGIC; currentgrid : OUT GRID (1 TO 3, 1 TO 3));
END COMPONENT;
COMPONENT compmove IS
PORT (current : IN GRID (1 TO 3, 1 TO 3); dif : IN STD_LOGIC; compsel : OUT TO_SELECT);
END COMPONENT;
BEGIN
U1: grid PORT MAP (to_occupy_cell, start, by_user ,grid_status);
U2: compmove PORT MAP (grid_status, difficulty, comp_occupy);
这是网格模块
ENTITY grid IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END grid;
---------------------------------
ARCHITECTURE gridstatus OF grid IS
BEGIN
PROCESS (to_occupy_cell, start)
VARIABLE temp_grid : GRID (1 TO 3, 1 TO 3);
BEGIN
IF (start = '1' AND start'EVENT) THEN
temp_grid := (others => (others=>0));
END IF;
IF (by_user = '1') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
ELSIF (by_user = '0') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
END IF;
currentgrid <= temp_grid;
END PROCESS;
END gridstatus;
计算机移动模块的实体
---------------------------------
ENTITY compmove IS
PORT(current : IN GRID (1 TO 3, 1 TO 3); --takes in the grid status
dif : IN STD_LOGIC; --difficulty
compsel : OUT TO_SELECT);
END compmove;
---------------------------------
所以,会发生的情况是,信号grid_status应该首先由用户移动自动更新,然后在更新时,它会通过管道传输到compmove
模块,以便计算机决定填充哪个单元。之后,grid_status应该再次更新。此外,'1'是用户移动,'2'是网格中的计算机移动。
希望这能清除我所追求的目标。
(从link引用的图片添加)
编辑2:
感谢大卫和fru1tbat的帮助,我实际上可以让它发挥作用!原来我错过了使compmove对grid_status敏感。 但是,如果用户选择另一个单元格,现在它仅适用于第一轮但不适用于第二轮。以下是更新的代码:
主要模块(当前状态)
ENTITY currentstate IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
difficulty : IN STD_LOGIC; --difficulty
winner_state : OUT INTEGER RANGE 0 to 2); --who is the winner?
END currentstate;
---------------------------------
ARCHITECTURE statearch OF currentstate IS
SIGNAL occupy_to_grid : TO_SELECT;
SIGNAL comp_occupy : TO_SELECT;
SIGNAL user_move : STD_LOGIC;
SIGNAL grid_status : GRID (1 TO 3, 1 TO 3);
COMPONENT grid_ IS -------saves the grid status
PORT (to_occupy_cell : IN TO_SELECT; start : IN STD_LOGIC; by_user : IN STD_LOGIC; currentgrid : OUT GRID (1 TO 3, 1 TO 3));
END COMPONENT;
COMPONENT compmove IS
PORT (current : IN GRID (1 TO 3, 1 TO 3); by_user : IN STD_LOGIC; dif : IN STD_LOGIC; compsel : OUT TO_SELECT);
END COMPONENT;
BEGIN
U1: grid_ PORT MAP (occupy_to_grid, start, user_move,grid_status);
U2: compmove PORT MAP (grid_status, user_move, difficulty, comp_occupy);
PROCESS(comp_occupy, to_occupy_cell)
BEGIN
IF to_occupy_cell'EVENT THEN
occupy_to_grid <= to_occupy_cell;
user_move <= by_user;
END IF;
IF comp_occupy'EVENT THEN
occupy_to_grid <= comp_occupy;
user_move <= '0';
END IF;
END PROCESS;
END statearch;
grid_ module
ENTITY grid_ IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END grid_;
---------------------------------
ARCHITECTURE gridstatus OF grid_ IS
BEGIN
PROCESS (to_occupy_cell, start)
VARIABLE temp_grid : GRID (1 TO 3, 1 TO 3);
BEGIN
IF (start = '1' AND start'EVENT) THEN
temp_grid := (others => (others=>0));
END IF;
IF (by_user = '1') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
ELSIF (by_user = '0') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
END IF;
currentgrid <= temp_grid;
END PROCESS;
END gridstatus;
compmove的初始部分
ENTITY compmove IS
PORT(current : IN GRID (1 TO 3, 1 TO 3); --takes in the grid status
by_user : IN STD_LOGIC; --to only gets triggered when user selects a cell
dif : IN STD_LOGIC; --difficulty
compsel : OUT TO_SELECT);
END compmove;
---------------------------------
ARCHITECTURE comparch OF compmove IS
BEGIN
PROCESS(by_user, current)
VARIABLE tempsel : TO_SELECT := (0,0);
VARIABLE occ_count : INTEGER := 0;
VARIABLE unocc : INTEGER := 0;
BEGIN
IF (dif = '0' AND current'EVENT AND by_user = '1') THEN
--------------bunch of codes here
它几乎就在那里,我相信在compmove的灵敏度列表中只是一个小的改变就可以相应地检索更新的grid_status,因为目前在第一轮之后它没有接受更新的grid_status和comp_occupy保持不变!
答案 0 :(得分:2)
您似乎在网格中的过程敏感度列表中缺少by_user
:
process (to_occupy_cell, start) -- Add by_user to sensitivity list
variable temp_grid : grid (1 to 3, 1 to 3);
begin
if (start = '1' and start'event) then
temp_grid := (others => (others=>0));
end if;
if (by_user = '1') then
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
elsif (by_user = '0') then
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
end if;
currentgrid <= temp_grid;
end process;
唯一符合您描述的是缺少事件触发流程。 by_user的想法不与任何其他输入同时发生。
我还在grid
中的组件声明中的currentstate
与包含两个不同VHDL分析器的类型grid
的类型声明的未声明包中发现名称冲突。 (在编写包并为to_select
和grid
)输入声明之后。
我添加了一个测试平台,并将grid_status
连接到currentgrid
中返回的currentstate
,以便它显示在顶层。
library ieee;
use ieee.std_logic_1164.all;
use work.foobat.all;
entity test is
end entity;
architecture foo of test is
component currentstate is
port (
to_occupy_cell: in to_select; --user choice
start: in std_logic; --initialize the grid
by_user: in std_logic; --how to fill the grid (x or o)
difficulty: in std_logic; --difficulty
winner_state: out integer range 0 to 2; --who is the winner?
currentgrid: out grid (1 to 3, 1 to 3)
); --outputs status of the grid after compmove to be displayed
end component;
signal to_occupy_cell: to_select;
signal start: std_logic := '0';
signal by_user: std_logic := '1';
signal difficulty: std_logic := '0';
signal winner_state: integer range 0 to 2;
signal currentgrid: grid(1 to 3, 1 to 3);
begin
DUT:
currentstate
port map (
to_occupy_cell => to_occupy_cell,
start => start,
by_user => by_user,
difficulty => difficulty,
winner_state => winner_state,
currentgrid => currentgrid -- grid_status
);
STIMULUS:
process
begin
wait for 1 sec;
to_occupy_cell <= (2,2); -- center
start <= '1'; -- write 1 to gridstatus(2,2);
wait for 1 sec;
to_occupy_cell <= (1,1); -- corner
start <= '0'; -- no separate delta cycle event
wait for 1 sec;
wait;
end process;
end architecture;
因此,下面显示的两组网格值是grid_status
端口上的current
(浮出水面)和compmove
。据我所知,grid_status
到达compmove
。
这是用ghdl和gtkwave完成的。 ghdl处理波形中的阵列信号。波形跟踪图像比浏览器中显示的图像大,您可以在单独的选项卡/窗口中打开它,或者以更大的方式查看它。
显示的两个版本grid_status
/ current
的值相同。
注意grid_status
上有三个事件,初始事件写入网格中最左边的行和列。我不确定为什么to_occupy_cell
没有在波形中正确显示,它不会显示为数组但会显示事件。这可能是我宣布to_select
类型的结果。
初始或默认事务,start'event and start = '1'
事务和to_occupy_cell转换(与start
= 0
并发)。
无论如何,关键是grid_status
到达compmove
。
答案 1 :(得分:1)
写入grid_status
信号的进程只接受来自用户的输入(comp_occupy
无法连接到主模块中的任何内容),那么计算机如何通过移动更新网格?您似乎需要的是连接到grid
的{{1}}模块的输入(或一组输入),以及comp_occupy
中的一个修改过程,它监视两个玩家并更新网格要么是来源。
(适用编辑)强>
进一步考虑后,我意识到你的意图可能是为gridstatus
模块提供一个输入,为任何一个玩家添加一个移动。您似乎希望使用grid
上的事件来更新网格,但我没有看到切换by_user
来创建序列的逻辑。你似乎需要(在你的主要组件中):
by_user
然后将process (to_occupy_cell, comp_occupy)
begin
if by_user = '1' then
occupy_to_grid <= to_occupy_grid;
else
occupy_to_grid <= comp_occupy;
end if;
by_user <= not by_user; -- on input from either source, alternate user for next input
end process;
映射到occupy_to_grid
而不是grid
。这假设两个'占用'信号的新值都在同一个delta上分配(否则to_occupy_cell
会意外地来回翻转),所以如果不是这样,你需要相应修改。
如果这与您正在寻找的内容相近,请告诉我。