2014-11-28 7 views
0

VHDL에서 간단한 SPI 마스터를 구현 중입니다. 내가 직면하고있는 문제는 두 플립 플롭을 합성하는 동안 ssdata_rdy에 대해 생성된다는 것입니다. 나는 그 포트에 대한 결과가 항상 지정되어 있다고 생각했기 때문에 이러한 레지스터가 왜 만들어졌으며 어떻게 제거 할 수 있습니까?FSM에서 출력 포트를 위해 생성 된 레지스터는 왜입니까?

내 코드는 ss 또는 data_rdy이없는 상태로 생략되었습니다.

기업 :

library IEEE; 
use IEEE.std_logic_1164.ALL; 

entity mcu is 
    port(clk  : in std_logic; 
     res  : in std_logic; 
     pc  : in std_logic_vector(7 downto 0); 
     pc_new : in std_logic; 
     data_ack : in std_logic; 
     miso  : in std_logic; 
     data  : out std_logic_vector(12 downto 0); 
     data_rdy : out std_logic; 
     mosi  : out std_logic; 
     sclk  : out std_logic; 
     ss  : out std_logic); 
end mcu; 

아키텍처 :

library IEEE; 
use IEEE.std_logic_1164.ALL; 

architecture behaviour of mcu is 
    -- r: send read command 
    -- a: send address 
    -- rx: receive data 
    type state_t is (r0, r1, r2, r3, r4, r5, r6, r7, 
        a0, a1, a2, a3, a4, a5, a6, a7, 
        rx0, rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8, rx9, rx10, rx11, rx12, 
        idle, starting, done); 
    signal state : state_t      := idle; 
    signal datasig : std_logic_vector(12 downto 0); 
begin 
    sclk <= clk; 
    mosi <= datasig(12); 

    sync : process(clk) is 
    begin 
     if rising_edge(clk) then 
      data_rdy <= '0'; 
      ss  <= '0'; 

      if res = '1' then 
       state <= idle; 
      else 
       datasig <= datasig(11 downto 0) & miso; 

       if pc_new = '1' then 
        state <= starting; 
       else 
        case state is 
        when idle => 
         ss  <= '1'; 
         datasig <= (others => '0'); 
         state <= idle; 

        ... 

        when rx12 => 
         data  <= datasig; 
         data_rdy <= '1'; 
         state <= done; 
        when done => 
         if data_ack = '1' then 
          state <= idle; 
         else 
          state <= done; 
         end if; 
       end case; 
       end if; 
      end if; 
     end if; 
    end process sync; 
end behaviour; 

관련 신디사이저 출력 : 또한, 왜 두 레지스터에 state 분할이

=============================================================================== 
| Register Name | Type | Width | Bus | MB | AR | AS | SR | SS | ST | 
=============================================================================== 
| data_rdy_reg  | Flip-flop | 1 | N | N | N | N | Y | N | N | 
|  ss_reg  | Flip-flop | 1 | N | N | N | N | Y | N | N | 
|  data_reg  | Flip-flop | 13 | Y | N | N | N | N | N | N | 
|  state_reg  | Flip-flop | 3 | Y | N | N | N | N | Y | N | 
|  state_reg  | Flip-flop | 2 | N | N | N | N | Y | Y | N | 
|  datasig_reg  | Flip-flop | 13 | Y | N | N | N | N | N | N | 
=============================================================================== 

?

답변

1

출력을 등록하는 것이 일반적으로 좋은 일입니다. 특히 SPI 주변 장치와 같은 외부 장치의 경우보다 안정적인 동작으로 변환 할 수있는 훨씬 더 정교한 타이밍을 허용합니다.

내가 직면 한 문제는 특정 상태에있을 때마다 출력이 true가되도록하려는 경우 클록 된 프로세스 내에서 그 상태에있는 동안 해당 출력을 할당하면 시계가 시작됩니다. 주기 지연.

데이비드 쿤츠 (David Koontz)는 한 가지 대답을 제시합니다. 모든 할당을 해당 출력 에서 클록 된 부분의으로 이동합니다. 실제로는 "상태"신호에만 종속됩니다.

그러나 다른 방법은 클린 타이밍을 위해 레지스터를 보존하고 그 사이클 지연을 제거합니다. 출력 할당을 상태로 천이 시키거나 또는 그 상태로 천이하지 않는 상태의 모든 조건으로 출력 할당을 향상시키는 것입니다. 그래서 예를 들어,

  when rx12 => 
       data  <= datasig; 
       data_rdy <= '1'; 
       state <= done; 

을 수정 상태로 전이 같은 문제와 다른 출력을위한

  when rx11 => 
       if ready_to_go_to_rx12 then 
        data_rdy <= '1'; -- keep data_rdy synched with rx12 
        state <= rx12; 
       end if; 

      when rx12 => 
       data  <= datasig; 
       -- data_rdy <= '1'; -- no, because we leave state rx12 immediately 
       state <= done; 

마찬가지로를 rx12.

신스 도구가 보통 data_rdyrx12이 항상 동시에 어설트되어 있고 이들을위한 레지스터를 공유하고 있음을 식별 할 수 있기 때문에 이것은 특별한 로직을 생성하지 않습니다.

편집 : 내가 다시 또 다른 모습에 와서 data <= datasig;도 말 때문에 또한주기를 등록하고 것으로 나타났습니다 : 난 단지 당신이 언급 한 신호의 하나로서 data_rdy을 고려하면서, 당신이 고려할 필요가있는 경우 data <= datasig; 같은 다른 과제 또한 발전시켜야합니다. (나는 이렇게 추측 할 것이다 : 그것은 새로운 데이터 이전에주기에 data_rdy를 알리는 것이 반 직관적이다!)

0

내가 직면 한 문제는 합성 중에 두 개의 플립 플롭이 ss 및 data_rdy 용으로 작성된다는 것입니다. 나는 그 포트에 대한 결과가 항상 지정되어 있다고 생각했기 때문에 이러한 레지스터가 왜 만들어졌으며 어떻게 제거 할 수 있습니까? data_rdyss에 대한

레지스터는 바로 여기에 작성됩니다

if rising_edge(clk) then 
     data_rdy <= '0'; 
     ss  <= '0'; 

방법은 data_rdy에 할당하고 clk 평가는 IF 문 ss 외부에 그들을 제거 할 수 있습니다.

왜 상태가 두 개의 레지스터로 분할 되었습니까?

32 개의 상태가 있으므로 5 개의 플립 플롭이 올바르게 들립니다. 두 세트의 플립 플롭에 대한 보고서의 마지막 두 열을 보면 세 개의 플립 플롭이 동기식으로 설정되고 두 플립 플롭 세트가 동시에 재설정된다는 것을 알 수 있습니다.

이 약 온다 :

if rising_edge(clk) then 
     data_rdy <= '0'; 
     ss  <= '0'; 

     if res = '1' then 
      state <= idle; 
     else 
      datasig <= datasig(11 downto 0) & miso; 

      if pc_new = '1' then 
       state <= starting; 
      else 
       case state is 
       when idle => 
        ss  <= '1'; 
        datasig <= (others => '0'); 
        state <= idle; 

당신의 기적 교란 상태, 유휴 시작, 또는 국가에 의해 구동되는 입력 멀티플렉서를 사용하기 때문이다.

매핑 된 디자인의 도식적 표현을 볼 수 있다면 계몽적일 것입니다.