2016-11-05 4 views
0

버퍼가있는 SPI 마스터 모듈을 구현하려고합니다. 이 FSM 모듈을 사용하여 테스트하고 수신 된 데이터를 UART를 통해 직렬 콘솔에 전송합니다. I는 UART 전에 "FFFFFFFF"X로 시작 값으로 전환 bytes_rec 시뮬레이션으로 판단받은 바이트VHDL 코드가 시뮬레이션에서는 작동하지만 FPGA에서는 작동하지 않습니다.

if(rx_upd <='0' and loadFromRxBuf ='1') then 
     rx_upd <='1'; 
     rx <= rx_buffer(d_width*buffer_size-1 downto d_width*(buffer_size-1)); 
     rx_buffer<= rx_buffer(d_width*(buffer_size-1)-1 downto 0) & x"00"; 
elsif(rx_upd ='1' and loadFromRxBuf ='0') then 
     rx_upd <='0'; 
end if; 

을 (미소 항상 높다) 밖으로 이동 여기서 여기서

library IEEE; 
USE ieee.std_logic_1164.all; 
USE ieee.std_logic_arith.all; 
USE ieee.std_logic_unsigned.all; 

entity FSM_SPI_buf is 
Port (clk: in STD_LOGIC; 
      increase: in STD_LOGIC; 
      reset: in STD_LOGIC; 
      busy : in STD_LOGIC; 
      tx : out STD_LOGIC_VECTOR (7 downto 0); 
      rx : in STD_LOGIC_VECTOR (7 downto 0); 
      transmit : out STD_LOGIC; 
      loadFromRXBuf : out STD_LOGIC; 
      loadToTxBuf : out STD_LOGIC; 
      rxBufEmpty : in STD_LOGIC; 
      rxBufFull : in STD_LOGIC; 
      txBufEmpty : in STD_LOGIC; 
      txBufFull : in STD_LOGIC; 
      led: out STD_LOGIC_VECTOR (7 downto 0); 
      uartTXData: out STD_LOGIC_VECTOR(7 downto 0); 
      uartRXData: in STD_LOGIC_VECTOR(7 downto 0); 
      uartTXSig: out STD_LOGIC; 
      uartTXRdy: in STD_LOGIC ; 
      uartRXCont: out STD_LOGIC; 
      uartRXSig: in STD_LOGIC; 
      uartRXFrameError: in STD_LOGIC 
     ); 
end FSM_SPI_buf; 

architecture Behavioral of FSM_SPI_buf is 
type statex is (start,updateTX, closeTX, send,openRX, receive, closeRX, 
sendUART,closeUART, stop); 
signal state: statex:=start; 
signal counter: integer range 0 to 5 := 0; 
signal bytes:STD_LOGIC_VECTOR(31 downto 0) := x"030001FF"; 
signal bytes_rec:STD_LOGIC_VECTOR(31 downto 0):=x"03040506"; 
begin 

process(clk, reset) begin 

if(clk'event and clk = '1') then 
     case state is 
      when start => 
       if(increase = '0') then 
        state <= updateTX; 
        counter <= 0; 
        uartrxCont <= '1'; 
       else 
        state <= start; 
       end if; 
      when updateTX => 
       if(counter < 4) then 
        loadToTxBuf <= '1'; 
        tx<=bytes(31 - counter * 8 downto 32 - (counter+1) * 8); 
        counter <= counter + 1; 
        state <= closeTX; 
       else 
        state <= send; 
       end if; 
      when closeTX =>      
        loadToTxBuf <= '0'; 
        state <= updateTX; 
      when send => 
       transmit <= '1'; 
       counter <= 0; 
       if (rxbuffull = '1') then 
        state <=openRX; 
       end if; 
      when openRX => 
       transmit <= '0'; 
       if(counter < 4) then 
        loadFromRxBuf <= '1'; 
        state <=closeRX; 
       else 
        counter <= 0; 
        state <= sendUART; 
       end if; 
      when closeRX => 

       loadFromRXBuf <= '0'; 
       state <= receive; 
      when receive => 
       bytes_rec(31 - (counter) * 8 downto 32 - (counter+1) * 8)<=rx; 
       counter <= counter + 1; 
       state <= openRX; 
      when sendUART => 
       if(counter < 4) then 
        if uarttxRdy = '1' then 
         uarttxData <=bytes_rec(31 - (counter) * 8 downto 32 - (counter+1) * 8); 
         uarttxSig <= '1'; 
         counter <= counter + 1; 
         state <= closeUART; 
        end if; 

       else 
        state <= stop; 
       end if; 
      when closeUART => 
       if (uarttxRdy= '0') then 
        uarttxSig <= '0'; 
        state <= sendUART; 
       else 
        state <= closeUART; 
       end if; 
      when stop => 
       if (uarttxRdy= '0') then 
        uarttxSig <= '0'; 
       end if; 
       if(increase = '1') then 
        state <= start; 
       else 
        state <= stop; 
       end if; 
     end case; 
elsif(reset = '1') then 
    counter <= 0; 
    state <= updateTX; 
end if; 

end process; 

end Behavioral; 

는 SPI 모듈로부터 발췌 전송이 발생합니다.

Simulation Screenshot

하지만 내 FPGA에 (모조 보드 v3의 XC6SLX9를) 생성 된 비트 파일을 업로드 할 때 나는 3.3 소스에 된장을 묶어 경우에도 나는 UART를 통해서만 제로를받을 수 있습니다. 내가 그것을 통해 신호 "바이트"를 전송하여 사용하고 UART 구현을 확인했습니다 그리고 그것은 잘 작동 그래서 그것은 비난하는 것 같아요.

복제 한 자습서를 세지 않으면 처음 프로그래밍 FPGA입니다. 따라서 오류가 발생했을 것으로 예상됩니다. 그러나 가능한 원인을 알려주십시오. 필요가 생기면 내 코드의 다른 부분을 제공 할 수 있습니다. 미리 감사드립니다.

답변

0

이 코드는 전체적으로 올바른 감도 목록을 가진 단일 프로세스 상태 시스템으로 작성하여 많은 잠재적 인 총알을 피할 수 있습니다.

전이중 통신을 허용하기 위해 UART의 송신기와 수신기의 반은 일반적으로 별도의 프로세스에서 별도의 상태 시스템이 될 것이라는 하나의 관찰을했습니다. 그러나 이것이 관찰이 관련이 없도록 SPI (동기식) 인터페이스 또는 상태 이름이 제안하는 것처럼 실제로 UART인지 명확하지 않습니다.

그러나 중요한 오류가 있습니다. 이는 적어도 increase, rxBufFull, uarttxRdy에 적용될 수 있습니다.

closeUart 상태를 살펴 보겠습니다. 그리고 경우에만 불필요한 코드가 상세하고 혼란을 추가하는, 일반적으로 나쁜 생각 -

 if uarttxRdy = '0' then 
      uarttxSig <= '0'; 
      state <= sendUART; 
     -- else 
     -- state <= closeUART; 
     end if; 

은 (안 요점은,하지만 난 state의 현재 값이 그렇지 않으면 유지되기 때문에 중복 라인을 주석 처리했습니다. 또한 부울 표현식을 중심으로 C 스타일의 라인 노이즈를 제거했습니다.

여기서 실수는 uarttxRdyclk으로 동기화되지 않은 것으로 보아 FPGA의 외부 입력입니다.

이와 같이 신호 타이밍 및 동기 설계에 대한 일반적인 보장은 described here으로 적용되지 않습니다.

이 문구에는 두 가지 결과가 예상됩니다. 아무 일도 일어나지 않거나 uarttxRdy이 삭제되고 보내기가 시작됩니다.

그러나 합성 공정이 매우 정당한 변환하게 상상 (논리 결합 및 게이트를 저장하거나 중요한 신호 경로를 단축하기 위하여) :

 if uarttxRdy= '0' then 
      uarttxSig <= '0'; 
     end if; 

     if uarttxRdy= '0' then 
      state <= sendUART; 
     end if; 

의 각각으로의 입력 핀에서의 신호 지연 이러한 비교는 다릅니다.

uarttxSig을 지우지 않고 보내기를 시작하거나 지우고 최소 1 클럭주기 동안이 상태로 남아있는 것을 포함하여 네 가지 가능한 결과가 있음을 알 것 같습니다. 이 두 가지 중 하나를 사용하면 상태 머신을 크게 망칠 수 있습니다.

비동기 입력은 동기식 도메인으로 가져 오기 위해 특수 처리가 필요합니다.

단순히 시계 가장자리에 복사하고 동기 복사본을 사용하십시오. 별도의 동기화 프로세스에서이 작업을 수행 할 수 있지만 상태 시스템의 Case 문 앞에 "기본 작업"을 추가하는 것이 안전하고 정상적인 방법입니다. 예를 들어 :

if rising_edge(clk) then 
    -- default actions : synch external inputs 
    uarttxRdy_s <= uarttxRdy; 
    -- state machine 
    case state is 

    when closeUART => 
     if uarttxRdy_s = '0' then 

이 문제는 종종 잘못 표시 "metastability"그러나 그것은되지 않습니다 : 그것은 단지 다른 신호 경로의 결과입니다 비동기 입력의 다른 용도로 길이.

비동기 입력이 클럭 에지와 거의 동일한 시간 (펨토초 이내)에 도달하면 레지스터에 유효한 '0'또는 '1'논리 레벨이 표시되지 않고 비 -수평. 그것은 핀 지점에서 볼 베어링의 균형을 맞추는 것과 같고, 볼은 조만간 떨어질 것입니다.

현재 FPGA의 경우 가능성은 거의 없지만 걱정이된다면 각 외부 신호에 두 번째 단계의 동기화를 추가하십시오.

+0

답장을 보내 주셔서 감사합니다. 그에 따라 코드를 수정합니다. 나는 uartTXRdy가 외부 입력이 아니라는 것을 분명히하지 않았 음을 유감스럽게 생각합니다. 실제로 UART 모듈에서 오는 신호입니다. 내가 사용하고있는 코드는 https://github.com/Domipheus/UART에서 확인할 수 있습니다. 그리고 txRdy는 다음 값을 취합니다 : 유휴 상태 일 때 1 ', 전송할 때'0 '. –

+0

이 모델에 대한 모든 외부 입력 (uartTxRdy뿐만 아니라)이 동기이면 ... 뭔가 다른 것이 틀림 없습니다. synth가 모든 논리를 완벽하게 다듬을 수있는 간단한 실수가 있다는 증거를 합성 보고서에서 확인하십시오! –

+0

Brian, SPI 마스터와 FSM 모듈 만 있으면서 프로젝트를 단순화하려고했지만 (http://pastebin.com/aWndX0eY) 합성하면 (http : // pastebin .com/DKMs4ind), 내 문제를 일으키는 것으로 보입니다. 내 논리의 일부를 왜 왜 다듬 었는지 설명하고이 문제를 피하기 위해 무엇을 할 수 있습니까? –