Vhdl 状态机;为什么只有最后一个州在工作?
我有一个具有6种状态(3种主要状态)的状态机。只有最后一个状态在工作,但前两个不工作(共3个)。只有最后一个状态在工作。我发现了问题,当我移除去抖动电路时,它可以工作,但我需要去抖动电路。我从网上得到了去抖动电路。如果有人能帮忙,我会很高兴的Vhdl 状态机;为什么只有最后一个州在工作?,vhdl,state-machine,fsm,case-when,Vhdl,State Machine,Fsm,Case When,我有一个具有6种状态(3种主要状态)的状态机。只有最后一个状态在工作,但前两个不工作(共3个)。只有最后一个状态在工作。我发现了问题,当我移除去抖动电路时,它可以工作,但我需要去抖动电路。我从网上得到了去抖动电路。如果有人能帮忙,我会很高兴的 type SM_STATES is (state_column_1, scan_col_1, state_column_2, scan_col_2, state_column_3, scan_col_3
type SM_STATES is (state_column_1, scan_col_1, state_column_2, scan_col_2,
state_column_3, scan_col_3);
signal my_state : SM_STATES := state_column_1;
下面是状态机:
scanner_sm : process (clk)
begin -- process key_scanner
if clk'event and clk = '1' then
if state_inc = '1' then -- clock divider finished counting down 100000
-- reset scan_complete
scan_complete <= '0';
case my_state is
when state_column_1 =>
scanned_val <= (others => '0');
original_col <= "110";
my_state <= scan_col_1;
when scan_col_1 =>
case bcd_val is
when "1110" => scanned_val <= "1100100"; -- 1 wrong
when "1101" => scanned_val <= "1100010"; -- 2 wrong
when others => scanned_val <= "0010000";
end case;
my_state <= state_column_2;
when state_column_2 =>
original_col <= "011";
my_state <= scan_col_2;
when scan_col_2 =>
case bcd_val is
when "1110" => scanned_val <= "1011011"; -- 5 wrong
when "1101" => scanned_val <= "1011111"; -- 6 wrong
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_3;
when state_column_3 =>
original_col <= "101";
my_state <= scan_col_3;
when scan_col_3 => -- Reading S1 // The only working state
case bcd_val is
when "1110" => scanned_val <= "1100000"; -- 9/ 1
when "1101" => scanned_val <= "0111110"; -- X/ 2
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_1; -- ************ Error might be here
scan_complete <= '1'; -- ********** Error might be here
when others => scanned_val <= "0000000";
end case;
end if;
end if;
end process scanner_sm;
debounce: process (CLK) is
begin
if (CLK'event and CLK = '1') then
Q0 <= scannel_val;
Q1 <= Q0;
Q2 <= Q1;
end if;
end process;
Final_val <= Q0 and Q1 and (not Q2);
end Behavioral;
scanner\u sm:进程(clk)
开始--处理密钥\u扫描器
如果clk'事件和clk='1',则
如果state_inc='1',那么——时钟除法器完成了100000的倒计时
--重置扫描完成
扫描完成
扫描值“0”);
原始col SCANED(已扫描)val SCANED(已扫描)val(已扫描)val(已扫描)到目前为止,您的代码不完整-您可以在案例语句中直接将信号分配给状态机评估的“我的状态”。为了理解这个问题,我们需要了解模拟器是如何工作的:
与实际硬件相比,模拟器必须以顺序方式使用顺序CPU处理代码。这是通过在无限小的时间距离(所谓的时间距离)内反复运行代码来实现的,直到所有依赖项都已解决,即不再有任何更改
请注意,在此迭代过程中没有经过任何实际时间。在一个正确编写的设计中,模拟器现在等待下一个事件发生——通常是由时钟的滴答声引起的,它再次重新启动顺序迭代
您的示例基本上类似于一个无限循环:my_state的更改总是导致my_state的下一次更改,因此模拟器永远不会固定到一个值,直到它达到硬编码迭代限制,在您的例子中,这是第三个状态
那么,如何解决这个问题呢?我们需要引入时钟,并且需要根据实际模拟时间进行状态转换,通常是等待时钟事件。最佳实践是将组合和顺序部分分为两个不同的过程,如状态机的最小示例所示:
scanner_sm : process (clk)
begin -- process key_scanner
if clk'event and clk = '1' then
if state_inc = '1' then -- clock divider finished counting down 100000
-- reset scan_complete
scan_complete <= '0';
case my_state is
when state_column_1 =>
scanned_val <= (others => '0');
original_col <= "110";
my_state <= scan_col_1;
when scan_col_1 =>
case bcd_val is
when "1110" => scanned_val <= "1100100"; -- 1 wrong
when "1101" => scanned_val <= "1100010"; -- 2 wrong
when others => scanned_val <= "0010000";
end case;
my_state <= state_column_2;
when state_column_2 =>
original_col <= "011";
my_state <= scan_col_2;
when scan_col_2 =>
case bcd_val is
when "1110" => scanned_val <= "1011011"; -- 5 wrong
when "1101" => scanned_val <= "1011111"; -- 6 wrong
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_3;
when state_column_3 =>
original_col <= "101";
my_state <= scan_col_3;
when scan_col_3 => -- Reading S1 // The only working state
case bcd_val is
when "1110" => scanned_val <= "1100000"; -- 9/ 1
when "1101" => scanned_val <= "0111110"; -- X/ 2
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_1; -- ************ Error might be here
scan_complete <= '1'; -- ********** Error might be here
when others => scanned_val <= "0000000";
end case;
end if;
end if;
end process scanner_sm;
debounce: process (CLK) is
begin
if (CLK'event and CLK = '1') then
Q0 <= scannel_val;
Q1 <= Q0;
Q2 <= Q1;
end if;
end process;
Final_val <= Q0 and Q1 and (not Q2);
end Behavioral;
ieee库;
使用ieee.std_logic_1164.all;
实体foo是
最终实体foo;
foo的架构栏是
SM_状态类型为(状态_列_1、扫描_列_1、状态_列_2、扫描_列_2、状态_列_3、扫描_列_3);
发出我的状态信号,我的状态下一步:SM状态;
信号bcd_val:std_逻辑_向量(3到0):=“1110”;
信号时钟:标准逻辑:='1';
信号nRST:std_逻辑:='0';
信号扫描值:标准逻辑向量(6到0);
信号原始列:标准逻辑向量(2到0);
信号扫描完成:标准逻辑;
开始——架构栏
comb:进程(我的状态,bcd\u val)为
开始——过程baz
如果我的州是
当状态_列_1=>
扫描值“0”);
原始列扫描\u val扫描\u val扫描\u val您可以将其视为构建在迭代绑定的答案上
我实现了您的完整状态机过程:
library ieee;
use ieee.std_logic_1164.all;
entity foo is
end entity foo;
architecture fum of foo is
type SM_STATES is (
state_column_1, scan_col_1,
state_column_2, scan_col_2,
state_column_3, scan_col_3
);
signal my_state: SM_STATES; -- defaults to SM_STATES'LEFT
signal state_inc: std_logic := '0';
signal bcd_val: std_logic_vector(3 downto 0) := "1110";
signal clk: std_logic := '0';
signal scanned_val: std_logic_vector(6 downto 0);
signal original_col: std_logic_vector(2 downto 0);
signal scan_complete: std_logic;
begin
scanner_sm:
process (clk)
begin
if clk'event and clk = '1' then
if state_inc = '1' then
scan_complete <= '0';
case my_state is
when state_column_1 =>
scanned_val <= (others => '0');
original_col <= "110";
my_state <= scan_col_1;
when scan_col_1 =>
case bcd_val is
when "1110" => scanned_val <= "1100100"; -- 1 wrong
when "1101" => scanned_val <= "1100010"; -- 2 wrong
when others => scanned_val <= "0010000";
end case;
my_state <= state_column_2;
when state_column_2 =>
original_col <= "011";
my_state <= scan_col_2;
when scan_col_2 =>
case bcd_val is
when "1110" => scanned_val <= "1011011"; -- 5 wrong
when "1101" => scanned_val <= "1011111"; -- 6 wrong
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_3;
when state_column_3 =>
original_col <= "101";
my_state <= scan_col_3;
when scan_col_3 => -- Reading S1 // The only working state
case bcd_val is
when "1110" => scanned_val <= "1100000"; -- 9/ 1
when "1101" => scanned_val <= "0111110"; -- X/ 2
when others => scanned_val <= "0000000";
end case;
my_state <= state_column_1; -- ************ Error might be here
scan_complete <= '1'; -- ********** Error might be here
when others => scanned_val <= "0000000";
end case;
end if;
end if;
end process scanner_sm;
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 200 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 30 ns;
state_inc <= '1';
wait;
end process;
end architecture;
礼物在哪里
if state_inc = '1' then
是
这将使任何人都有机会在进入状态列1之前对扫描完成做出反应。您可能需要检查complete是否应命名为start_或_complete,并作为第一个状态
我对您的流程所做的唯一一件事就是更改缩进,以便更容易看到if语句中的所有内容
(我们警告过您,我们希望看到更多您的模型)您为什么要在Stackoverlow和Stackexchange上发布此消息?没有足够的源代码来回答这个问题,请演示“只有最后一个状态有效,但前两个状态无效(共3个)”。要么包括一个工作测试台,要么显示(希望高分辨率)波形图像。我添加了我的整个过程。我只有一个顶级水平,我用互联网上的例子写了它,这是我写的第一个例子。我不能写完整的源代码。我知道这没有道理,但我不能…我没有一个复位按钮,其实我的电路。。。我可以不用它吗?我在问题中添加了我的完整过程源代码,我有一个时钟和时钟分频器,所以我认为我的时钟应该处理你所说的状态切换,但是我错过了我的下一个状态。我将集中精力实施我的下一个州。我周末没有FPGA,周一我会尝试给出反馈,谢谢你的提示!你也可以分享你的测试平台吗?经过再三考虑,我想我可以使用FPGA的一个按钮来“重置”,但如果有一种方法可以解决这个问题而不重置,我会选择这种方法。你可以分享你的测试平台文件吗?复制并粘贴上述VHDL源代码到一个文件中,进行分析、阐述和模拟。VHDL测试平台有一个通常可以识别的特征,即实体声明中缺少端口接口。如果需要,测试台还将包含一个时钟源,以及执行VHDL设计规范的刺激。这一个的独特之处在于,您只提供了一个流程,因此没有组件实例化,而是直接合并了您的流程。我终于找到了切换不起作用的原因,因为我的去盎司电路。当我删除去抖动电路时,它会工作。我从网上复制了这张底片。这个逻辑对我来说是有道理的,但我不知道为什么它不起作用。我在问题中加入了我的去盎司电路。