为什么我的VHDL状态机不执行减法操作?

时间:2013-11-21 09:33:50

标签: vhdl state-diagram

这是一个长除二进制分频器的模拟。该程序按预期执行,但不管我如何编码它都不会从寄存器的5个MSB中减去除数。

以下是代码:

            library ieee;
            use ieee.std_logic_1164.all;
            use ieee.std_logic_unsigned.all;
            use ieee.std_logic_arith.all;

            ENTITY divider IS

                PORT(
                            Clock               :IN STD_LOGIC;
                            Dividend            :IN STD_LOGIC_VECTOR(7 DOWNTO 0);
                            Divisor         :IN STD_LOGIC_VECTOR(4 DOWNTO 0);
                            Reset               :IN STD_LOGIC;
                            St                  :IN STD_LOGIC;

                            outDRegister            :OUT STD_LOGIC_VECTOR(8 DOWNTO 0):="000000000";
                            outCurrentState         :OUT STD_LOGIC_VECTOR(2 DOWNTO 0):="000";
                            Quotient            :OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
                            Remainder       :OUT STD_LOGIC_VECTOR(4 DOWNTO 0));
            END divider;

            ARCHITECTURE Behavior of divider IS

            SIGNAL DRegister                        :STD_LOGIC_VECTOR(8 DOWNTO 0);
            SIGNAL SubOut                           :STD_LOGIC_VECTOR(4 DOWNTO 0);
            Signal C,ShiftIn, ShiftRes          :STD_LOGIC;
            Signal ShiftEnable                  :STD_LOGIC;
            Signal tempSt                           :STD_LOGIC:='1';
            TYPE    State_type IS (S0, S1, S2, S3, S4, S5);
            SIGNAL y:State_type:=S0;

            BEGIN
            PROCESS(Dividend,Divisor,y, st, reset, clock) IS
            BEGIN
            If (Reset='0') THEN
            Y<=S0;
            ELSIF (Clock'EVENT and CLOCK = '1') THEN

                CASE y IS
                    WHEN S0=>
                        IF(st='0' AND tempSt='1' AND reset = '1') THEN
                            DRegister <= '0'&Dividend;
                            y<=S1;
                        ELSIF(st='1' AND reset = '1') THEN
                            Quotient    <= DRegister(3 DOWNTO 0);
                            Remainder   <= DRegister(8 DOWNTO 4);
                            y<=S0;
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="000";
                        tempSt<=st; 

                    WHEN S1=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            y<=S0;
                        ELSE
                            DRegister <= (DRegister(7 DOWNTO 0) & '0');
                            y<=S2;
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="001";
                    WHEN S2=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="010";     
                        y<=S3;

                    WHEN S3=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';

                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="011";
                        y<=S4;

                    WHEN S4=>
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                            DRegister <= DRegister(7 DOWNTO 0) & '1';
                        ELSE
                            DRegister <= DRegister(7 DOWNTO 0) & '0';
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="100";
                        y<=S5;

                    WHEN S5=>   
                        IF(DRegister(8 DOWNTO 4)>=Divisor) THEN
                            DRegister(8 DOWNTO 4)<=(DRegister(8 DOWNTO 4) - Divisor);--Does not work!! Does nothing.
                        END IF;
                        outDRegister<=DRegister;
                        outCurrentState<="101";

                        y<=S0;

                END CASE;

            END IF;




            END PROCESS;


            END Behavior;

2 个答案:

答案 0 :(得分:0)

第一步是阅读VHDL中变量和信号分配之间的差异。你的问题就在那里。一种解决方案涉及问题状态的中间变量;另一个涉及重写信号分配。

我通常的解释是here,页面底部有一个链接到“VHDL的Crown Jewel”,这也非常值得一读。

另请注意:

  • 有更好的算术库:ieee.numeric_std而不是std_logic_unsigned或std_logic_arith或(最糟糕的是)混合两者。
  • 算术的数据类型比std_logic_vector更好:ieee.numeric_std.unsigned(或签名),甚至是integernatural的子类型;
  • 当您编写一个干净的单进程状态机时,其灵敏度列表仅需要clock, reset
  • 您可以丢失条件表达式周围的括号,If Reset='0' Then很好(这不是您父亲的C编译器)
  • rising_edge(Clock)优先于Clock'EVENT and CLOCK = '1'
    但这些都是主要问题的外围。

答案 1 :(得分:0)

正如您所标记的那样,有问题的代码部分是:

...
DRegister(8 downto 4) <= (DRegister(8 downto 4) - Divisor);  --Does not work!! Does nothing.
DRegister             <= DRegister(7 downto 0) & '1';
...

在VHDL中,信号的值直到当前结束才更新 模拟周期,因此在第二个分配给DRegister时使用的值 第一次分配给DRegister时,上述DRegister不会改变。

因此,第一次分配给DRegister(8 downto 4)的效果被覆盖 第二个分配给DRegister中的所有位,从而减去。{1}} Divisor没有任何效果。

纠正代码的一种方法,所以只对一个DRegister位进行一次分配。

你可能想看看David Koontz的回答 https://stackoverflow.com/a/20104800/2352082因为这涉及类似的问题。