状态机的VHDL代码

时间:2012-10-26 17:28:31

标签: vhdl adc

我正在尝试用VHDL编写一个ADC的逐次逼近寄存器。我正在制作一台状态机。我对最终状态块中的代码(current_state = S_LSB)有点不确定。这段代码有效吗?有没有更好的方法在返回状态之前重置DigitalOutTemp和OutTemp?

注意比较器的值取决于DigitalOutTemp输出经过数模转换器后的输出。

LIBRARY ieee;
USE     ieee.std_logic_1164.all;

ENTITY SARegister IS
PORT (
    Comparator, Clock                     : IN std_logic;
    DigitalOutFinal, DigitalOutTemp   : OUT std_logic_vector (13 downto 0)
);
END;

ARCHITECTURE Behavioural OF SARegister IS

CONSTANT S_MSB      : STD_LOGIC_VECTOR(3 downto 0) := "0000";
CONSTANT S_TWELVE   : STD_LOGIC_VECTOR(3 downto 0) := "0001";
CONSTANT S_ELEVEN   : STD_LOGIC_VECTOR(3 downto 0) := "0010";
CONSTANT S_TEN      : STD_LOGIC_VECTOR(3 downto 0) := "0011";
CONSTANT S_NINE     : STD_LOGIC_VECTOR(3 downto 0) := "0100";
CONSTANT S_EIGHT    : STD_LOGIC_VECTOR(3 downto 0) := "0101";
CONSTANT S_SEVEN    : STD_LOGIC_VECTOR(3 downto 0) := "0110";
CONSTANT S_SIX      : STD_LOGIC_VECTOR(3 downto 0) := "0111";
CONSTANT S_FIVE     : STD_LOGIC_VECTOR(3 downto 0) := "1000";
CONSTANT S_FOUR     : STD_LOGIC_VECTOR(3 downto 0) := "1001";
CONSTANT S_THREE    : STD_LOGIC_VECTOR(3 downto 0) := "1010";
CONSTANT S_TWO      : STD_LOGIC_VECTOR(3 downto 0) := "1011";
CONSTANT S_ONE      : STD_LOGIC_VECTOR(3 downto 0) := "1100";
CONSTANT S_LSB      : STD_LOGIC_VECTOR(3 downto 0) := "1101";

SIGNAL Next_state       : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Current_state    : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL OutTemp          : STD_LOGIC_VECTOR(13 DOWNTO 0);    

BEGIN

PROCESS (Clock)
BEGIN

    IF (rising_edge (Clock)) THEN       
        Current_state <= Next_state;
    END IF;

END PROCESS;

PROCESS (Current_state, Comparator)
BEGIN
    Next_state <= Current_state;
    DigitalOutTemp <= "10000000000000";
    OutTemp <= "10000000000000";
    DigitalOutFinal <= "00000000000000";

    IF (Current_state = S_MSB) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(13) <= '0';
            OutTemp(13) <= '0';
        END IF;
        DigitalOutTemp(12) <='1';
        OutTemp(12) <= '1';
        Next_state <= S_TWELVE;

    ELSIF (Current_state = S_TWELVE) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(12) <= '0';
            OutTemp(12) <= '0';
        END IF;
        DigitalOutTemp(11) <='1';
        OutTemp(11) <= '1';
        Next_state <= S_ELEVEN;

    ELSIF (Current_state = S_ELEVEN) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(11) <= '0';
            OutTemp(11) <= '0';
        END IF;
        DigitalOutTemp(10) <='1';
        OutTemp(10) <= '1';         
        Next_state <= S_TEN;

    ELSIF (Current_state = S_TEN) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(10) <= '0';
            OutTemp(10) <= '0';
        END IF;
        DigitalOutTemp(9) <='1';
        OutTemp(9) <= '1';          
        Next_state <= S_NINE;

    ELSIF (Current_state = S_NINE) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(9) <= '0';
            OutTemp(9) <= '0';
        END IF;
        DigitalOutTemp(8) <='1';
        OutTemp(8) <= '1';          
        Next_state <= S_EIGHT;

    ELSIF (Current_state = S_EIGHT) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(8) <= '0';
            OutTemp(8) <= '0';
        END IF;
        DigitalOutTemp(7) <='1';
        OutTemp(7) <= '1';          
        Next_state <= S_SEVEN;

    ELSIF (Current_state = S_SEVEN) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(7) <= '0';
            OutTemp(7) <= '0';
        END IF;
        DigitalOutTemp(6) <='1';
        OutTemp(6) <= '1';          
        Next_state <= S_SIX;

    ELSIF (Current_state = S_SIX) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(6) <= '0';
            OutTemp(6) <= '0';
        END IF;
        DigitalOutTemp(5) <='1';
        OutTemp(5) <= '1';          
        Next_state <= S_FIVE;

    ELSIF (Current_state = S_FIVE) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(5) <= '0';
            OutTemp(5) <= '0';
        END IF;
        DigitalOutTemp(4) <='1';
        OutTemp(4) <= '1';          
        Next_state <= S_FOUR;

    ELSIF (Current_state = S_FOUR) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(4) <= '0';
            OutTemp(4) <= '0';
        END IF;
        DigitalOutTemp(3) <='1';
        OutTemp(3) <= '1';          
        Next_state <= S_THREE;

    ELSIF (Current_state = S_THREE) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(3) <= '0';
            OutTemp(3) <= '0';
        END IF;
        DigitalOutTemp(2) <='1';
        OutTemp(2) <= '1';          
        Next_state <= S_TWO;

    ELSIF (Current_state = S_TWO) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(2) <= '0';
            OutTemp(2) <= '0';
        END IF;
        DigitalOutTemp(1) <='1';    
        OutTemp(1) <= '1';      
        Next_state <= S_ONE;

    ELSIF (Current_state = S_ONE) THEN
        IF (Comparator = '0') THEN 
            DigitalOutTemp(1) <= '0';
            OutTemp(1) <= '0';
        END IF;
        DigitalOutTemp(0) <='1';
        OutTemp(0) <= '1';          
        Next_state <= S_LSB;

    ELSIF (Current_state = S_LSB) THEN
        IF (Comparator = '0') THEN
            DigitalOutTemp(0) <= '0';
            OutTemp(0) <= '0';
        END IF;

        DigitalOutFinal <= OutTemp;

        DigitalOutTemp <= "10000000000000";
        OutTemp <= "10000000000000";

        Next_state <= S_MSB;

    END IF;
END PROCESS;
END;

1 个答案:

答案 0 :(得分:0)

很难说出你的代码想要完成什么,所以我想我会做一些可以帮助你的一般性观察。

您的代码中有许多不必要的重复,您可以通过使用计数器来索引您的位而不是每个状态中的硬编码索引来修复,例如使用从MSB计数的计数器idx到LSB你可以这样做:

...

elsif (current_state = COMPARE) then

  OutTemp(idx)     <= comparator;

  if idx > 0 then
    OutTemp(idx-1) <= '1';
    idx            <= idx - 1;
    next_state     <= current_state;
  else
    idx            <= MSB;
    next_state     <= idle;
  end if;
end if;

这假设您要将OutTemp(idx-1)设置为先前的状态,这对我来说有点无意义,但可能是您的外部硬件所需要的......

您还通过分配信号和端口复制了OutTemp,我会删除您对端口DigitalOutTemp的所有分配,而是将以下内容添加到您的时钟进程中:

process (clock)
begin

  if rising_edge(clock) then      
    Current_state <= Next_state;
    DigitalOutTemp <= OutTemp;
  end if;
end process;

这将同步设置DigitalOutTemp,如果您不想这样,您可以将其设置在时钟进程之外,但我会建议您同步设置它以避免故障。

回答你的问题,最后的状态:

    ELSIF (Current_state = S_LSB) THEN
      IF (Comparator = '0') THEN
          DigitalOutTemp(0) <= '0';
          OutTemp(0) <= '0';
      END IF;

      DigitalOutFinal <= OutTemp;

      DigitalOutTemp <= "10000000000000";
      OutTemp <= "10000000000000";

      Next_state <= S_MSB;

    END IF;

..只需将DigitalOutTemp设置为“10000000000000"”和DigitalOutFinal即可添加到之前状态OutTemp中的任何内容。您似乎期望OutTemp已经通过作业进一步更新到OutTemp(0),但事实并非如此。OutTemp(0)的作业是预定的,用于整个过程;它不是'立即可见。

IF语句中OutTemp(0)DigitalOutTemp(0)的分配将不会执行任何操作,因为您的预定写入会被您对其进一步向下的分配取消。

所以要回答你的问题,它看起来像是有效的代码,它可能会编译和合成,但它不会表现出你似乎期望的行为。

希望这有帮助。