2017-05-20 18 views
2

저는 VHDL을 처음 사용하며 FSM 구현에 대한 질문이 있습니다. 그림에 표시된 동작을 원합니다 (여기서 AHDL과 동일한 FSM을 구현했습니다). 내가 VHDL에서 구현할 때 나는 리셋 동작이 다르다 : 리셋 = 1을 감지하고 동시에 FSM이 진행되지 않는 상승 에지가 있지만 S0에서 PS를 계속 유지한다. 문제는 if ... elsif (첫 번째 조건을 올바르게 감지하고 2 번째에 입력하지 않음)입니다. 여러 가지 방법으로 시도했지만 여전히 작동하지 않으며 출력은 00의 첫 번째 상승 에지 이후에도 유지됩니다. VHDL 구현의 Waveforms of AHDL implementation유한 상태 기계 VHDL 재설정

파형 : AHDL 구현의

파형이 발견되지 않을 수도 있습니다 Waveforms of VHDL implementation

LIBRARY ieee; -- Bibliotheksvereinbarung 
USE ieee.std_logic_1164.all; 

ENTITY sumconvol IS -- Schaltungssymbol 
PORT 
(
    x : IN STD_LOGIC; --input of 1st FF 
    clk : IN STD_LOGIC; --clock of all the 3 FFs 
    clrn : IN STD_LOGIC; 
    y : OUT STD_LOGIC_VECTOR (1 downto 0) --vector of output data 
); 
END sumconvol; 

ARCHITECTURE a OF sumconvol IS -- Creation of architecture 
    --SIGNAL output_tmp : STD_LOGIC_VECTOR (1 downto 0); -- temporary variables (e.g. input/output between FFs)7 
    TYPE state_type IS (S0,S1,S2,S3); 
    SIGNAL NS,PS : state_type; 
    SIGNAL stato : STD_LOGIC; 

BEGIN 
    sync_proc: PROCESS (clk,clrn) 
    BEGIN 
     if ((clrn='1')) THEN 
      PS<=S0; 
      y <= "00"; 
     elsif (rising_edge(clk)) then 
      PS <= NS; 
      CASE PS IS 
      when S0 => 
       if ((x='0'))then 
         NS <= S0; 
         y <= "00"; 
        else 
         NS <= S1; 
         y <= "11"; 
       end if; 
      when S1 => 
       if (x='0') then 
        NS <= S2; 
        y<="10"; 
       else 
        NS <= S3; 
        y <= "01"; 
       end if; 
      when S2 => 
       if (x='0') then 
        NS <= S0; 
        y <="11"; 
       else 
        NS <= S1; 
        y <= "00"; 
       end if; 
      when S3 => 
       if (x='0') then 
        NS <= S2; 
        y <="01"; 
       else 
        NS <= S3; 
        y <= "10"; 
       end if; 
      end case; 
     end if; 
    end process sync_proc; 
END a; 
+0

'clrn'은 활성 낮음을 의미하지만 액티브 하이로 사용하고 있습니다 ... 당신은 혼란 스럽습니까? –

+0

아아 예 신호를 잘못명했습니다 ... 활성이 높음 – AM93

+0

테스트 벤치를 보여주십시오. – JHBonarius

답변

2

한 가지, 당신은 PS (이전 상태)를 모두 넣어이며 NS (다음 상태)를 클록 처리합니다. 즉, 레지스터는 에 대해 모두 신호로 추론됩니다. 따라서 NS은 예상보다 1 클럭 늦게 PS으로 설정됩니다. 이는 두 가지 방법으로 해결할 수 있습니다.

1) PS ->NS 부분을 제거하고 state 만 사용하면됩니다.

sync_proc: PROCESS (clk, clr) 
BEGIN 
    if clr = '1' THEN 
     state <= S0; 
     y <= "00"; 
    elsif rising_edge(clk) then 
     CASE state IS 
     when S0 => 
      if x = '0' then 
        state <= S0; 
        y <= "00"; 
       else 
        state <= S1; 
        y <= "11"; 
      end if; 
     when S1 => 
      if x = '0' then 
       state <= S2; 
       y<="10"; 
      else 
       state <= S3; 
       y <= "01"; 
      end if; 
     when S2 => 
      if x = '0' then 
       state <= S0; 
       y <="11"; 
      else 
       state <= S1; 
       y <= "00"; 
      end if; 
     when S3 => 
      if (x='0') then 
       state <= S2; 
       y <="01"; 
      else 
       state <= S3; 
       y <= "10"; 
      end if; 
     end case; 
    end if; 
end process sync_proc; 

2) 프로세스를 시간 지정 프로세스와 조합 프로세스로 분리합니다.

clk_proc: PROCESS (clk, clr) 
BEGIN 
    if clr = '1' THEN 
     PS <= S0; 
     y <= "00"; 
    elsif rising_edge(clk) then 
     PS <= NS; 
     y <= next_y; 
    end if; 
end process; 

comb_proc : process(PS, x) 
begin 
    CASE PS IS 
     when S0 => 
      if x = '0' then 
        NS <= S0; 
        next_y <= "00"; 
       else 
        NS <= S1; 
        next_y <= "11"; 
      end if; 
     when S1 => 
      if x = '0' then 
       NS <= S2; 
       next_y <= "10"; 
      else 
       NS <= S3; 
       next_y <= "01"; 
      end if; 
     when S2 => 
      if x = '0' then 
       NS <= S0; 
       next_y <="11"; 
      else 
       NS <= S1; 
       next_y <= "00"; 
      end if; 
     when S3 => 
      if x = '0' then 
       NS <= S2; 
       next_y <="01"; 
      else 
       NS <= S3; 
       next_y <= "10"; 
      end if; 
    end case; 
end process; 

다음, 당신이 리셋 원하는 것을 이해하지 않습니다. VHDL 코드는 정확히 수행해야하는 작업입니다. 이것은 재설정을 사용하는 적절한 방법입니다. 재설정이 주장되는 한 y은 "00"을 표시해야합니다. 그런 다음 일단 해제되면 y이 다음 클럭 에지에서 변경되어야합니다. 그것은 적절한 디자인입니다. 첫 번째 사진 (AHDL)이 좋지 않습니다 : 재설정 중 y의 활동.

그러나 어쨌든, 당신이 정말로 완고하면, 어떤 트릭을 사용하여 첫 번째 이미지에있는 행동을 얻을 수 있습니다.

sync_proc: PROCESS (clk) 
BEGIN 
    if (rising_edge(clk)) then 
     if clr = '1' THEN 
      state <= S0; 
      y <= "11"; 
     else 
      case state is 
[...] 

추신 "동기 프로세스"에서처럼 sync_proc 프로세스를 호출하고 있습니다. 그러나 코드의 재설정이 비동기식이기 때문에 이것은 사실이 아닙니다 ...

p.s.2 : 신호 대신 일부 적절한 이름을 지정하십시오. x ...

+0

조합 부분의 민감도 목록을 다시 확인하십시오. 변수를 추가 할 경우 (기능 크립이 항상 발생 함) 해당 변수가 할당/의사 결정에 포함되어 있지만 민감도 목록에도 포함되어 있는지 확인하십시오. 너는 막 다른 상태가 있을지도 모른다. – grambo