状态机只适用于一种模式



自上周以来,我一直在处理这个问题,并试图从不同的方式得到正确的答案,但不幸的是,从现在起,它就没有起作用。我有一个状态机,它接收三个模式,并为每个模式制作一个矩阵,然后将所有模式相加并发送到输出。但是状态机发送第一个模式的矩阵来输出。我认为问题是加法器应该与时钟(状态一)一起工作,状态机会随着每个时钟的事件边缘进入下一个状态,因此它无法与加法器同步。但我不知道该怎么解决这个问题。如果有任何帮助,我都会很乐意的。

p.S包装必须包含在代码中。

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:11:16 0NUMBITS-1/11/2012 
-- Design Name: 
-- Module Name:    state_machine - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use work.my_data_types.all;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity state_machine2 is
port(
        pattern      : in std_logic_vector(0 to NUMBITS-1);                 --The incorrect pattern
        clk          : in std_logic;
        result       : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1)
     );     
end state_machine2;
architecture Behavioral of state_machine2 is
    type state is (zero , one, two);
    signal pr_state, nx_state : state ;
    signal s_out_matrix     : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
    signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1):= (others => (others => (others => '0')));
    signal q                : integer;
begin
    process(clk)
    begin
        if(clk'event and clk = '1')then
            pr_state <= nx_state;
        end if;
    end process;
    process(pattern, pr_state)
        variable cnt:     integer := -1;        
    begin
    case pr_state is
        when zero =>
            q <= 0;                                        -- state number
            if(cnt < NUM_TRAIN_PATTERN)then
                cnt := cnt + 1;
                nx_state <= one;
            else
                nx_state <= two;
            end if;
        when one =>
            q <= 1;
    For i in 0 to NUMBITS-1 loop                                    --The multiplication in the pattern
        For j in 0 to NUMBITS-1 loop                                                    
            if(i = j) then
                s_out_matrix(i,j) <= (others => '0');
            elsif(pattern(i) = pattern(j)) then
                s_out_matrix(i,j) <= (0 => '1', others => '0');
            else 
                s_out_matrix(i,j) <= (others => '1');
            end if;
        end loop;
    end loop;
    if(clk'event and clk = '1')then                      -- Sum of the matrixes
        For i in 0 to NUMBITS-1 loop                        
            For j in 0 to NUMBITS-1 loop        
                s_flipflop_adder(i,j) <= s_flipflop_adder(i,j) + s_out_matrix(i,j);
            end loop;
        end loop;
    end if;
            nx_state <= zero;
        when two =>                                 
            q <= 2;
            result <= s_flipflop_adder;
            end case;
            test_q <= q;
        end process;
end Behavioral;
the package:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
package my_data_types is 
    type matrix2D is array (integer range <> , integer range <> ) of signed(2 downto 0);    -- Matrix2D
    constant NUMBITS : integer := 3;
    constant NUM_TRAIN_PATTERN : natural := 3;
end my_data_types;

有几件事很突出。。。

首先,无论何时创建状态机,都需要有一种方法来重置它,理想情况下是一个输入信号,它会迫使顺序元素进入已知状态。在您的情况下,无法重置pr_state,因此无法从代码中知道起始状态应该是什么。此外,避免像为s_flipflop_adder指定默认值那样"重置"顺序元素,因为这可能会导致模拟与实际实现之间的不匹配。

第二,不要在同一过程中生成顺序信号和组合信号。对于每个信号,决定它是顺序的(即触发器,在时钟沿上更新)还是组合的(即几乎立即从其他信号的值更新,仅通过逻辑元件中的传播延迟而减慢)。对于顺序信号,创建一个顺序过程,在该过程中,所有内容都在if rising_edge(clk)if clk'event and clk = '1'语句中(对于大多数目的来说是等效的),并且灵敏度列表中只有时钟(如果是异步的,可能还有重置信号)。对于组合信号,将它们放在组合过程中,这是一个没有时钟和完整灵敏度列表的过程。

在您的设计中,第一个过程是一个适当的顺序过程。然而,第二个过程一开始是一个组合过程(有一个不完整的敏感度列表),但随后有一个对嵌套在case语句分支中的s_flipflop_adder的顺序赋值。信号s_flipflop_adder不太可能被分配,因为clk不在灵敏度列表中,即使是,合成工具也可能不会按照您的意图解释该混合。

最后,不要像使用cnt变量那样使用变量来保存状态信息,并确保只在时钟边缘(即按顺序)更新状态。

考虑到这三点,状态机将看起来更类似于此(我内联了my_data_types包中的定义,只是为了让答案更容易阅读):

library ieee;
use ieee.std_logic_vector_1164.all;
use ieee.std_logic_arith.all;
entity state_machine2 is
port(
    clk          : in std_logic;
    rst          : in std_logic;
    pattern      : in std_logic_vector(0 to NUMBITS-1);
    result       : out matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1) );
end state_machine2;
architecture Behavioral of state_machine2 istype state is (zero , one, two);
    constant NUMBITS            : integer := 3;
    constant NUM_TRAIN_PATTERN  : natural := 3;
    subtype signed3 is signed(NUMBITS-1 downto 0);
    type matrix2D is array (integer range <> , integer range <> ) of signed3;
    signal pr_state         : state;
    signal s_flipflop_adder : matrix2D(0 to NUMBITS-1, 0 to NUMBITS-1);
    signal cnt              : integer;
begin
    process(clk) is
        variable add_operand : signed3;
    begin
        if rising_edge(clk) then
            if rst = '1' then
                pr_state         <= zero;
                cnt              <= -1;
                s_flipflop_adder <= (others => (others => (others => '0')));
            else
                case pr_state is
                when zero =>
                    cnt <= cnt + 1;
                    if cnt < NUM_TRAIN_PATTERN then
                        pr_state <= one;
                    else
                        pr_state <= two;
                    end if;
                when one =>
                    for i in 0 to NUMBITS-1 loop
                        for j in 0 to NUMBITS-1 loop
                            if i = j then
                                add_operand := (others => '0');
                            elsif pattern(i) = pattern(j) then
                                add_operand := (0 => '1', others => '0');
                            else
                                add_operand := (others => '1');
                            end if;
                            s_flipflop_adder(i,j) <= s_flipflop_adder(i,j)
                                                   + add_operand;
                        end loop;
                    end loop;
                when two =>
                    result <= s_flipflop_adder;
                end case;
            end if;
        end if;
    end process;
end Behavioral;

谢谢你发布这个问题,因为这些都是非常常见的错误。

相关内容

最新更新