组合代码中VHDL可能的信号误解

组合代码中VHDL可能的信号误解,vhdl,fpga,Vhdl,Fpga,我的代码是纯组合的。只有一个元素为模拟提供了一些同步性。这是一个4*4 led矩阵,其中只有从右上角开始的3*3是有效的。比如: 我有4个并发进程,它们取决于所解释的信号: architecture arc1 of mt is signal led_R_in : std_logic_vector (15 downto 0) := (others => '1'); signal led_G_in : std_logic_vector (15 downto 0) := (others =&g

我的代码是纯组合的。只有一个元素为模拟提供了一些同步性。这是一个4*4 led矩阵,其中只有从右上角开始的3*3是有效的。比如:

我有4个并发进程,它们取决于所解释的信号:

architecture arc1 of mt is

signal led_R_in : std_logic_vector (15 downto 0) := (others => '1');
signal led_G_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal led_B_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal counter : std_logic_vector (1 downto 0) := "00";

begin

PROCESS (row, cD, cC, cB, cA)  -- execute if any of these change
BEGIN
    CASE row IS 
    WHEN "1000" => -- row 1 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(0) <= '0'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
            WHEN OTHERS => led_R_in(0) <= '1'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(1) <= '0'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
            WHEN OTHERS => led_R_in(1) <= '1'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(2) <= '0'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
            WHEN OTHERS => led_R_in(2) <= '1'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(3) <= '0'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
            WHEN OTHERS => led_R_in(3) <= '1'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
        END CASE;

    WHEN "0100" => -- row 2 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(4) <= '0'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
            WHEN OTHERS => led_R_in(4) <= '1'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(5) <= '0'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
            WHEN OTHERS => led_R_in(5) <= '1'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(6) <= '0'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
            WHEN OTHERS => led_R_in(6) <= '1'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(7) <= '0'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
            WHEN OTHERS => led_R_in(7) <= '1'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
        END CASE;

    WHEN "0010" => -- row 3 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(8) <= '0'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
            WHEN OTHERS => led_R_in(8) <= '1'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(9) <= '0'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
            WHEN OTHERS => led_R_in(9) <= '1'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(10) <= '0'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
            WHEN OTHERS => led_R_in(10) <= '1'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(11) <= '0'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
            WHEN OTHERS => led_R_in(11) <= '1'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
        END CASE;
    WHEN OTHERS => Null; -- not necessary, although for avoiding latches creation I will have to assign them.
    END CASE;
END PROCESS;

PROCESS (led_R_in)  -- executes when led_R_in changes
BEGIN
    -- leds are ON at '0' value
    -- the problem is that, when initialising, the first row of leds will be blue, which means that
    -- led_R_in 0, 1, 2 are 0, but they should be 1 as stated in their default values
    -- the second and third row initialises correctly to green values, although the response to changes in the inputs are not only affecting them but also their neighbours, which I think it could be a problem of the FPGA pin assignment.
    if (led_R_in(0)='0' AND ((led_R_in(1)='0' AND led_R_in(2)='0') OR (led_R_in(4)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(10)='0'))) then
        led_B(0) <= '0';
        led_R(0) <= '1';
        led_G(0) <= '1';
    else
        led_R(0) <= led_R_in(0);
        led_G(0) <= '0';
        led_B(0) <= '1';
    end if;
    if (led_R_in(1)='0' AND ((led_R_in(0)='0' AND led_R_in(2)='0') OR (led_R_in(5)='0' AND led_R_in(9)='0'))) then
        led_B(1) <= '0';
        led_R(1) <= '1';
        led_G(1) <= '1';
    else
        led_R(1) <= led_R_in(1);
        led_G(1) <= '0';
        led_B(1) <= '1';
    end if;
    if (led_R_in(2)='0' AND ((led_R_in(0)='0' AND led_R_in(1)='0') OR (led_R_in(10)='0' AND led_R_in(6)='0') OR (led_R_in(5)='0' AND led_R_in(8)='0'))) then
        led_B(2) <= '0';
        led_R(2) <= '1';
        led_G(2) <= '1';
    else
        led_R(2) <= led_R_in(2);
        led_G(2) <= '0';
        led_B(2) <= '1';
    end if;
    if (led_R_in(4)='0' AND ((led_R_in(0)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(6)='0'))) then
        led_B(4) <= '0';
        led_R(4) <= '1';
        led_G(4) <= '1';
    else
        led_R(4) <= led_R_in(4);
        led_G(4) <= '0';
        led_B(4) <= '1';
    end if;
    if (led_R_in(5)='0' AND ((led_R_in(2)='0' AND led_R_in(8)='0') OR (led_R_in(1)='0' AND led_R_in(9)='0') OR (led_R_in(0)='0' AND led_R_in(10)='0') OR (led_R_in(6)='0' AND led_R_in(4)='0'))) then
        led_B(5) <= '0';
        led_R(5) <= '1';
        led_G(5) <= '1';
    else
        led_R(5) <= led_R_in(5);
        led_G(5) <= '0';
        led_B(5) <= '1';
    end if;
    if (led_R_in(6)='0' AND ((led_R_in(2)='0' AND led_R_in(10)='0') OR (led_R_in(5)='0' AND led_R_in(4)='0'))) then
        led_B(6) <= '0';
        led_R(6) <= '1';
        led_G(6) <= '1';
    else
        led_R(6) <= led_R_in(6);
        led_G(6) <= '0';
        led_B(6) <= '1';
    end if;
    if (led_R_in(8)='0' AND ((led_R_in(2)='0' AND led_R_in(5)='0') OR (led_R_in(4)='0' AND led_R_in(0)='0') OR (led_R_in(9)='0' AND led_R_in(10)='0'))) then
        led_B(8) <= '0';
        led_R(8) <= '1';
        led_G(8) <= '1';
    else
        led_R(8) <= led_R_in(8);
        led_G(8) <= '0';
        led_B(8) <= '1';
    end if;
    if (led_R_in(9)='0' AND ((led_R_in(1)='0' AND led_R_in(5)='0') OR (led_R_in(10)='0' AND led_R_in(8)='0'))) then
        led_B(9) <= '0';
        led_R(9) <= '1';
        led_G(9) <= '1';
    else
        led_R(9) <= led_R_in(9);
        led_G(9) <= '0';
        led_B(9) <= '1';
    end if;
    if (led_R_in(10)='0' AND ((led_R_in(9)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(0)='0') OR (led_R_in(6)='0' AND led_R_in(2)='0'))) then
        led_B(10) <= '0';
        led_R(10) <= '1';
        led_G(10) <= '1';
    else
        led_R(10) <= led_R_in(10);
        led_G(10) <= '0';
        led_B(10) <= '1';
    end if;
END PROCESS;

PROCESS  -- executes at the beginning (when is equal to "00") and changes its value every 10 ms
BEGIN
    counter <= counter + "01";  -- there is an intended combinational loop here, so that it does this forever changing the row.
    WAIT for 10 ms;  
END PROCESS;

PROCESS (counter) -- executes at the beginning (when is equal to "00") and when counter changes (every 10 ms)
BEGIN
    CASE counter IS
        WHEN "00" => row <= "1000";
        WHEN "01" => row <= "0100";
        WHEN "10" => row <= "0010";
        WHEN OTHERS => Null;  -- for avoiding the automatic generation of latches due to non existing assignments. although it could also be row <= "0001"
    END CASE;
END PROCESS;

END arc1;

为什么它不能使用我想要的行为?

我建议将测试台和实际fpga代码分开。你试过综合代码吗?我没有尝试过,但我认为您将生成大量锁存。是的,我已经合成了代码并正确映射到我的设备,它会给我一些与我声明但未使用的内容相关的警告。是的,它会生成锁存器,虽然这些锁存器现在对我来说并不重要,但我可以稍后通过赋值消除它们。它们也可能是问题的根源。一个纯粹的组合过程没有初始值,所以这可能是问题所在。这是一个奇怪的代码,这是你的测试台还是你的实际代码?如果这是您的结核病,那么您为什么要对其进行输入?在模拟过程中如何设置这些输入?唯一可行的方法是为MT组件创建一个测试台,将所有输入设置为正确的值,然后再次运行模拟。或者删除这些输入并创建一个处理过程,或者将它们设置为默认值;在里面?
entity mt is
    PORT ( 
    cD, cC, cB, cA : in std_logic;  -- comparators for each column. cA is not necessary / not used.
    row : inout std_logic_vector (3 downto 0) := (others => '0'); -- detection of each row.
    led_R, led_G, led_B : out std_logic_vector (15 downto 0) := (others => '1')  -- '1' indicates they are OFF. 12 to 15 will not be used (as well as 3, 7, 11 positions)
    );
end mt;
architecture arc1 of mt is

signal led_R_in : std_logic_vector (15 downto 0) := (others => '1');
signal led_G_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal led_B_in : std_logic_vector (15 downto 0) := (others => '1'); -- don't think they are necessary
signal counter : std_logic_vector (1 downto 0) := "00";

begin

PROCESS (row, cD, cC, cB, cA)  -- execute if any of these change
BEGIN
    CASE row IS 
    WHEN "1000" => -- row 1 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(0) <= '0'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
            WHEN OTHERS => led_R_in(0) <= '1'; led_G_in(0) <= '1'; led_B_in(0) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(1) <= '0'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
            WHEN OTHERS => led_R_in(1) <= '1'; led_G_in(1) <= '1'; led_B_in(1) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(2) <= '0'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
            WHEN OTHERS => led_R_in(2) <= '1'; led_G_in(2) <= '1'; led_B_in(2) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(3) <= '0'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
            WHEN OTHERS => led_R_in(3) <= '1'; led_G_in(3) <= '1'; led_B_in(3) <= '1';
        END CASE;

    WHEN "0100" => -- row 2 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(4) <= '0'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
            WHEN OTHERS => led_R_in(4) <= '1'; led_G_in(4) <= '1'; led_B_in(4) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(5) <= '0'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
            WHEN OTHERS => led_R_in(5) <= '1'; led_G_in(5) <= '1'; led_B_in(5) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(6) <= '0'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
            WHEN OTHERS => led_R_in(6) <= '1'; led_G_in(6) <= '1'; led_B_in(6) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(7) <= '0'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
            WHEN OTHERS => led_R_in(7) <= '1'; led_G_in(7) <= '1'; led_B_in(7) <= '1';
        END CASE;

    WHEN "0010" => -- row 3 --
        -- (LEDs are active at logic level 0)
        CASE cD IS
            WHEN '1' => led_R_in(8) <= '0'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
            WHEN OTHERS => led_R_in(8) <= '1'; led_G_in(8) <= '1'; led_B_in(8) <= '1';
        END CASE;
        CASE cC IS
            WHEN '1' => led_R_in(9) <= '0'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
            WHEN OTHERS => led_R_in(9) <= '1'; led_G_in(9) <= '1'; led_B_in(9) <= '1';
        END CASE;
        CASE cB IS
            WHEN '1' => led_R_in(10) <= '0'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
            WHEN OTHERS => led_R_in(10) <= '1'; led_G_in(10) <= '1'; led_B_in(10) <= '1';
        END CASE;
        CASE cA IS  -- not necessary
            WHEN '1' => led_R_in(11) <= '0'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
            WHEN OTHERS => led_R_in(11) <= '1'; led_G_in(11) <= '1'; led_B_in(11) <= '1';
        END CASE;
    WHEN OTHERS => Null; -- not necessary, although for avoiding latches creation I will have to assign them.
    END CASE;
END PROCESS;

PROCESS (led_R_in)  -- executes when led_R_in changes
BEGIN
    -- leds are ON at '0' value
    -- the problem is that, when initialising, the first row of leds will be blue, which means that
    -- led_R_in 0, 1, 2 are 0, but they should be 1 as stated in their default values
    -- the second and third row initialises correctly to green values, although the response to changes in the inputs are not only affecting them but also their neighbours, which I think it could be a problem of the FPGA pin assignment.
    if (led_R_in(0)='0' AND ((led_R_in(1)='0' AND led_R_in(2)='0') OR (led_R_in(4)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(10)='0'))) then
        led_B(0) <= '0';
        led_R(0) <= '1';
        led_G(0) <= '1';
    else
        led_R(0) <= led_R_in(0);
        led_G(0) <= '0';
        led_B(0) <= '1';
    end if;
    if (led_R_in(1)='0' AND ((led_R_in(0)='0' AND led_R_in(2)='0') OR (led_R_in(5)='0' AND led_R_in(9)='0'))) then
        led_B(1) <= '0';
        led_R(1) <= '1';
        led_G(1) <= '1';
    else
        led_R(1) <= led_R_in(1);
        led_G(1) <= '0';
        led_B(1) <= '1';
    end if;
    if (led_R_in(2)='0' AND ((led_R_in(0)='0' AND led_R_in(1)='0') OR (led_R_in(10)='0' AND led_R_in(6)='0') OR (led_R_in(5)='0' AND led_R_in(8)='0'))) then
        led_B(2) <= '0';
        led_R(2) <= '1';
        led_G(2) <= '1';
    else
        led_R(2) <= led_R_in(2);
        led_G(2) <= '0';
        led_B(2) <= '1';
    end if;
    if (led_R_in(4)='0' AND ((led_R_in(0)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(6)='0'))) then
        led_B(4) <= '0';
        led_R(4) <= '1';
        led_G(4) <= '1';
    else
        led_R(4) <= led_R_in(4);
        led_G(4) <= '0';
        led_B(4) <= '1';
    end if;
    if (led_R_in(5)='0' AND ((led_R_in(2)='0' AND led_R_in(8)='0') OR (led_R_in(1)='0' AND led_R_in(9)='0') OR (led_R_in(0)='0' AND led_R_in(10)='0') OR (led_R_in(6)='0' AND led_R_in(4)='0'))) then
        led_B(5) <= '0';
        led_R(5) <= '1';
        led_G(5) <= '1';
    else
        led_R(5) <= led_R_in(5);
        led_G(5) <= '0';
        led_B(5) <= '1';
    end if;
    if (led_R_in(6)='0' AND ((led_R_in(2)='0' AND led_R_in(10)='0') OR (led_R_in(5)='0' AND led_R_in(4)='0'))) then
        led_B(6) <= '0';
        led_R(6) <= '1';
        led_G(6) <= '1';
    else
        led_R(6) <= led_R_in(6);
        led_G(6) <= '0';
        led_B(6) <= '1';
    end if;
    if (led_R_in(8)='0' AND ((led_R_in(2)='0' AND led_R_in(5)='0') OR (led_R_in(4)='0' AND led_R_in(0)='0') OR (led_R_in(9)='0' AND led_R_in(10)='0'))) then
        led_B(8) <= '0';
        led_R(8) <= '1';
        led_G(8) <= '1';
    else
        led_R(8) <= led_R_in(8);
        led_G(8) <= '0';
        led_B(8) <= '1';
    end if;
    if (led_R_in(9)='0' AND ((led_R_in(1)='0' AND led_R_in(5)='0') OR (led_R_in(10)='0' AND led_R_in(8)='0'))) then
        led_B(9) <= '0';
        led_R(9) <= '1';
        led_G(9) <= '1';
    else
        led_R(9) <= led_R_in(9);
        led_G(9) <= '0';
        led_B(9) <= '1';
    end if;
    if (led_R_in(10)='0' AND ((led_R_in(9)='0' AND led_R_in(8)='0') OR (led_R_in(5)='0' AND led_R_in(0)='0') OR (led_R_in(6)='0' AND led_R_in(2)='0'))) then
        led_B(10) <= '0';
        led_R(10) <= '1';
        led_G(10) <= '1';
    else
        led_R(10) <= led_R_in(10);
        led_G(10) <= '0';
        led_B(10) <= '1';
    end if;
END PROCESS;

PROCESS  -- executes at the beginning (when is equal to "00") and changes its value every 10 ms
BEGIN
    counter <= counter + "01";  -- there is an intended combinational loop here, so that it does this forever changing the row.
    WAIT for 10 ms;  
END PROCESS;

PROCESS (counter) -- executes at the beginning (when is equal to "00") and when counter changes (every 10 ms)
BEGIN
    CASE counter IS
        WHEN "00" => row <= "1000";
        WHEN "01" => row <= "0100";
        WHEN "10" => row <= "0010";
        WHEN OTHERS => Null;  -- for avoiding the automatic generation of latches due to non existing assignments. although it could also be row <= "0001"
    END CASE;
END PROCESS;

END arc1;