2016-11-05 5 views
0

Я пытаюсь реализовать главный модуль SPI с буфером. Я использую этот модуль FSM для его проверки и передачи полученных данных через UART на свою последовательную консоль.Код VHDL работает в симуляции, но не на FPGA

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, где я смещаться из полученных байт

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; 

Судя по моделированию bytes_rec переходов от ее исходного значения х «FFFFFFFF» (MISO всегда высоки) перед УАППАМИ передача происходит.

Simulation Screenshot

Но когда я загрузить сгенерированный битный файл в мою FPGA (XC6SLX9 на v3 Mojo Board), я получаю только нули через UART, даже когда я связываю мисо к источнику 3.3V. Я проверил реализацию UART, которую я использую, передавая через него сигнал «байты», и он работает нормально, поэтому я не думаю, что это виноват.

Это мое первое программирование FPGA, если вы не считаете несколько учебников, которые я реплицировал, поэтому я ожидаю, что ошибка будет приписана этому. Но, пожалуйста, укажите мне его источник. Я могу предоставить другие части моего кода, если возникнет такая необходимость. Спасибо заранее!

ответ

0

Это довольно хороший код, в общем, вы уклонились от множества потенциальных пуль, написав это как единую машину состояний процесса с правильным списком чувствительности.

Я бы сделал одно замечание, что половинки передатчика и приемника UART обычно являются отдельными государственными машинами в отдельных процессах, чтобы обеспечить полнодуплексную связь. Однако я не понимаю, является ли это на самом деле UART, как предлагают названия состояний, или SPI (синхронный) интерфейс, чтобы наблюдение не было релевантным.

Однако есть одна важная ошибка, которая, по крайней мере, относится к increase, rxBufFull, uarttxRdy, возможно, к другим.

Давайте посмотрим на состояние closeUart.

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

(не самое главное, но я закомментировать строки, которые являются избыточными, так как текущее значение state иначе сохраняется - и ненужный код, как правило, плохая идея, если только от добавления многословия и беспорядка. Я также очистил линейный шум в стиле C в булевом выражении)

Ошибка в том, что uarttxRdy, по-видимому, является внешним входом FPGA, не синхронизированным с clk.

Таким образом, обычные гарантии на синхронизацию сигнала и синхронный дизайн, как described here, не применяются к нему.

Итак, вы ожидаете двух результатов от этого утверждения: либо ничего не происходит, либо uarttxRdy очищается, и вы начинаете отправку.

Но представьте себе, что процесс синтеза делает вполне легитимной преобразование (объединить логику и сохранить ворота, или сократить критический путь прохождения сигнала) для:

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

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

и задержки сигнала от входного вывода к каждому из эти сравнения различны.

Я думаю, вы можете видеть, что есть четыре возможных результата, включая начало отправки без очистки uarttxSig или очистка и оставление в этом состоянии по меньшей мере еще одного такта. Любой из них может вкратце испортить ваш конечный автомат.

Таким образом, понятно, что асинхронные входы требуют специальной обработки, чтобы привести их в синхронный домен.

Просто скопируйте их на краю часов и используйте синхронные копии. Вы можете сделать это в отдельном процессе синхронизации, но также совершенно безопасно и нормальная практика добавлять «действия по умолчанию» перед оператором 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) являются синхронными ... то что-то еще должно быть неправильно. Проверьте отчет о синтезе на наличие доказательств того, что некоторая простая ошибка позволяет синтезатору полностью выровнять всю вашу логику! –

+0

Брайан, я попытался упростить свой проект, просто имея SPI-мастер и модули FSM, но когда я его синтезирую (http://pastebin.com/aWndX0eY), он дает мне приличное количество предупреждений (http: // pastebin .com/DKMs4ind), которые, как представляется, вызывают мои проблемы. Не могли бы вы объяснить мне, почему это ограничивает мою логику и что я могу сделать, чтобы избежать этой проблемы? –

Смежные вопросы