1

我在确定我的代码为什么不能正常工作时遇到了一些困难。我正在尝试使用 3 位操作码创建 ALU。

除一种情况外,所有情况均无法正常工作;操作码 011 (SEQ)。它被定义为 if(a==b) z<='0' 和 output<='0'。a 和 b 是输入,z 是零标志。我希望通过以下 VHDL 代码获得此功能

....
    BEGIN

    result <= dummy_result;

    PROCESS (a, b, op) 

        VARIABLE carry: STD_LOGIC:='0';

         --DEFINE ALIAS TO SEPERATE ALU-OP SIGNAL
        alias NEG_TSEL      : STD_LOGIC IS op(2);
        alias ALU_SELECT    : STD_LOGIC_VECTOR(1 downto 0) IS op(1 downto 0);
    BEGIN
         if ALU_SELECT="11" THEN

                if NEG_TSEL='0'  THEN   -- SEQ

                    if a = b THEN
                        dummy_result <="00000";
                    end if;

                elsif NEG_TSEL='1' THEN     --SCO

                    cout <= '1';
                    result <= "XXXXX";


                end if;


        elsif ALU_SELECT="00" THEN...

使用此代码,当 op = 011 时,结果始终设置为零。

当我将代码更改为:

            .....
            if a = b THEN
                dummy_result <="00000";

            else
                dummy_result <= "10101";
            end if;
.....

它工作正常,但结果不能改变,所以我将它改为“dummy_result <= dummy_result;”而不是“10101”向量 但这给了我与原始案例相同的结果。

有什么建议么?难道我做错了什么?

4

2 回答 2

0

这是我对您的代码的问题:

就个人而言,我觉得在每个循环中,您都应该向 、 和 . 输出result一些cout东西zero。目前,您始终输出到zero,但您仅有条件地输出到其他两个端口。这可能会创建闩锁,这可能不是您想要的。因此,例如 SCO 操作,也应该向 推送一些东西cout,而 SCO 操作应该向dummy_result信号推送一些东西。

您的减法实现未按您的预期工作。

when "110" => -- SUB
    tmp_b <= NOT b;
    carry := '1';

    for i in 0 to 4 loop
        dummy_result(i) <= carry XOR a(i) XOR tmp_b(i);
        carry := (a(i) AND tmp_b(i)) OR (tmp_b(i) AND carry) OR (carry AND a(i));
    end loop;
    cout <= carry;

tmp_b是一个信号。那里发生的逻辑将与此过程中的其他所有事情同时发生,而不是顺序发生。您可能希望它是一个变量,就像carryis 一样。


我还想让你知道 case 语句(相对于 if 链)。您的代码可能如下所示:

PROCESS (a, b, op)
    VARIABLE carry: STD_LOGIC:='0';
BEGIN

    case op is
        when "011" => -- SEQ
            dummy_result <= "00000";

        when "111" => -- SCO
            cout <= '1';

        when "000" => -- AND
            dummy_result <= a AND b;

        ...

        when others =>
            dummy_result <= "00000";
            cout <= '0';
    end case;
end process;

回到最初的问题SEQ,你的原始代码如下所示:

when op = "011" =>
    if a = b then
        dummy_result <= "00000";
    end if;

正如我上面提到的,这里的问题是这很可能是一个闩锁。当 a /= b 时,您需要输出您期望的值,而不能只是dummy_result <= dummy_result. 如果你把它推到物理电线和芯片上,你期望它变成什么?

相反,您应该将最后一个 dummy_result 的值传递给该实体,或者如果特定操作应该保存结果的值,您应该输出“00000”并输出一个附加信号,说明保存前一个值的任何内容(在注册),不应该更新它。

于 2013-02-04T05:18:21.400 回答
0

此处的目的是除非另有指定,否则 dummy_result 旨在保留“result”的先前值。不幸的是,这个单元被实现为一个组合过程,没有时钟。

因此,存储不能在该单元中可靠地实现。
因此,它必须在本单元之外实施。
几乎可以肯定已经是了;在作为时钟进程实现的寄存器中。

因此,将该寄存器的输出作为新的输入端口“prev_result”带回并使用默认分配给 dummy_result。这不仅将克服您迄今为止发现的特定故障,而且将克服所有其他“dummy_result”(还有另一个)缺失的分配,以同步方式保留“result”的旧值。

    PROCESS (a, b, op, prev_result) 
       -- declarations here
    BEGIN
       -- default assignment
       dummy_result <= prev_result;

       if ALU_SELECT="11" THEN
          if NEG_TSEL='0' THEN    -- SEQ
             if a = b THEN
                dummy_result <="00000";
             end if;
       ...
    END PROCESS;

我认为你会更好地重组设计以使 ALU 成为一个时钟进程,但如果你按照指示不要这样做,那么你将不得不采用这个(或类似的)解决方案。

于 2013-02-05T18:05:05.207 回答