2016-11-08 26 views
0

所以我有用於RS232通信鏈路的這個接收器代碼,我應該發送8位帶1個起始位「0」和一個停止位「1」,無奇偶校驗儘管有些人告訴我我的問題是測試平臺而不是代碼,但它在FPGA實現中永遠不起作用,我發送的第一個信號始終是在那之後的任何信號都是正確的地方是錯的。VHDL RS232接收器與Xilinx ISE無法正常工作

這裏是低於

entity Rs232Rxd is 

     port(Reset, Clock16x, Rxd: in std_logic; 

     DataOut1: out std_logic_vector (7 downto 0)); 

     end Rs232Rxd; 

architecture Rs232Rxd_Arch of Rs232Rxd is 

attribute enum_encoding: string; 

-- state definitions 

type stateType is (stIdle, stData, stStop, stRxdCompleted); 

attribute enum_encoding of statetype: type is "00 01 11 10"; 

signal iReset : std_logic; 

signal iRxd1, iRxd2 : std_logic := '1'; 

signal presState: stateType; 

signal nextState: stateType; 

signal iClock1xEnable, iClock1x, iEnableDataOut: std_logic :='0' ; 

signal iClockDiv: std_logic_vector (3 downto 0) := (others=>'0') ; 

signal iDataOut1, iShiftRegister: std_logic_vector (7 downto 0):= (others=>'0'); 

signal iNoBitsReceived: std_logic_vector (3 downto 0):= (others=>'0') ; 

begin 

process (Clock16x) begin 

     if rising_edge(Clock16x) then 

      if Reset = '1' or iReset = '1' then 

       iRxd1 <= '1'; 

       iRxd2 <= '1'; 

       iClock1xEnable <= '0'; 

       iClockDiv <= (others=>'0'); 

      else 

       iRxd1 <= Rxd; 

       iRxd2 <= iRxd1; 

      end if; 

      if iRxd1 = '0' and iRxd2 = '1' then 

       iClock1xEnable <= '1'; 

      end if; 

      if iClock1xEnable = '1' then 

       iClockDiv <= iClockDiv + '1'; 

     end if; 

     end if; 

end process; 


iClock1x <= iClockDiv(3); 

process (iClock1xEnable, iClock1x) 

begin 

    if iClock1xEnable = '0' then 

      iNoBitsReceived <= (others=>'0'); 

      presState <= stIdle; 

    elsif rising_edge(iClock1x) then 

       iNoBitsReceived <= iNoBitsReceived + '1'; 

       presState <= nextState; 

       if iEnableDataOut = '1' then 

       iDataOut1 <= iShiftRegister; 

       --iShiftRegister <= (others=>'0'); 

        else 

         iShiftRegister <= Rxd & iShiftRegister(7 downto 1); 

      end if; 
     end if; 

end process; 

DataOut1 <= iDataOut1; 

process (presState, iClock1xEnable, iNoBitsReceived) 

begin 

-- signal defaults 

iReset <= '0'; 

iEnableDataOut <= '0'; 


case presState is 

    when stIdle => 

    if iClock1xEnable = '1' then 

    nextState <= stData; 

    else 
     nextState <= stIdle; 

    end if; 

    when stData => 

    if iNoBitsReceived = "1000" then 

    iEnableDataOut <= '1'; 

    nextState <= stStop; 

    else 

    iEnableDataOut <= '0'; 

    nextState <= stData; 

    end if; 
    when stStop => 

    nextState <= stRxdCompleted; 

    when stRxdCompleted => 

    iReset <= '1'; 

    nextState <= stIdle; 

    end case; 

end process; 

end Rs232Rxd_Arch; 

回答

0

代碼你的問題並不存在一個Minimal Complete and Verifiable Example。如果不編寫測試臺,問題就不會重複,而且問題缺乏特異性(這裏使用的'信號'和'錯誤'是不精確的)。

有一些意見。

一個停止位後跟一個連續字符的起始位,爲狀態stRxdCompleted留下了空間。此外iNoBitsReceived未設置爲全0時iClock1xEnable變爲無效,這意味着採樣點不被起始位的連續字符的下降沿確定:

rs232rxd_orig_tb.png

這是一個大寫的‘A’立即後跟一個小寫字母'a',停止位緊接着第二個字符的起始位(這是合法的)。

在第一個字符中,您會看到起始位被計爲字符位之一。當啓用變爲無效時,您將看到位計數器未被複位,這將導致採樣點漂移(並且可能最終導致取決於時鐘差異或傳輸失真的採樣錯誤以及缺少同步採樣點復位)。

您還會在第一個字符的最後一個數據位期間看到presState爲stStop,但第二個字符是正確的。仔細觀察一下,我們看到第一個字符的起始位在stData期間發生,而第二個字符不會發生。

當iClock1x停止時,狀態數和狀態轉換有一個基本問題。

你不需要狀態機,你有一個名爲iNoBitsReceived的計數器,它可以存儲所有的狀態,如果你還檢測到幀錯誤,應該在ishiftregister足夠長的時間內容納啓動(也可能是停止)位。

與清零位計數器,空閒時綁到特定計數操作,而沒有單獨的狀態機,沿:

rs232_tb.png

給我們的東西,用少了幾分複雜的工作原理:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity Rs232Rxd is 
    port ( 
     Reset, 
     Clock16x, 
     Rxd:  in std_logic; 
     DataOut1: out std_logic_vector (7 downto 0) 
    ); 
end entity Rs232Rxd; 

architecture foo of Rs232Rxd is 
    signal rxd1:    std_logic; 
    signal rxd2:    std_logic; 
    signal baudctr:    unsigned (3 downto 0); 
    signal ctr16x:    unsigned (3 downto 0); 
    signal enab1xstart:   std_logic; 
    signal enable1x:   std_logic; 
    signal ninthbit:   std_logic; 
    signal sampleenab:   std_logic; 
    signal shiftregister:  std_logic_vector(7 downto 0); 

begin 
CLOCK_DOMAIN: 
    process (clock16x) 
    begin 
     if rising_edge(clock16x) then 
      rxd1 <= rxd; 
      rxd2 <= rxd1; 
     end if; 
    end process; 

    enab1xstart <= not rxd1 and rxd2 and not enable1x; 

ENABLE_1X: 
    process (clock16x, reset) 
    begin 
     if reset = '1' then 
      enable1x <= '0'; 
     elsif rising_edge(clock16x) then 
      if enab1xstart = '1' then 
       enable1x <= '1'; 
      elsif ninthbit = '1' then 
       enable1x <= '0'; 
      end if; 
     end if; 
    end process; 

SAMPLE_COUNTER: 
    process (clock16x, reset, ninthbit) 
    begin 
     if reset = '1' or ninthbit = '1' then 
      ctr16x <= (others => '0'); -- for simulation 
     elsif rising_edge(clock16x) then 
      if enab1xstart = '1' or enable1x = '1' then 
       ctr16x <= ctr16x + 1; 
      end if; 
     end if; 
    end process; 

    sampleenab <= not ctr16x(3) and ctr16x(2) and ctr16x(1) and ctr16x(0); 

BAUD_COUNTER: 
    process (clock16x, reset) 
    begin 
     if reset = '1' then 
      baudctr <= (others => '0'); 
     elsif rising_edge(clock16x) and sampleenab = '1' then 
      if baudctr = 8 then 
       baudctr <= (others => '0'); 
      else 
       baudctr <= baudctr + 1; 
      end if; 
     end if; 
    end process; 

NINTH_BIT: -- one clock16x period long, after baudctr changes 
    process (clock16x, reset) 
    begin 
     if reset = '1' then 
      ninthbit <= '0'; 
     elsif rising_edge(clock16x) then 
      ninthbit <= sampleenab and  baudctr(3) and not baudctr(2) and 
             not baudctr(1) and not baudctr(0); 
     end if; 
    end process; 

SHIFT_REG: 
    process (clock16x, reset) 
    begin 
     if reset = '1' then 
      shiftregister <= (others => '0'); -- for pretty waveforms 
     elsif rising_edge(clock16x) and sampleenab = '1' then 
      shiftregister <= rxd2 & shiftregister(7 downto 1); 
     end if; 
    end process; 

OUTREG: 
    process (clock16x, reset) 
    begin 
     if reset = '1' then 
      dataout1 <= (others => '0'); 
     elsif rising_edge(clock16x) and ninthbit = '1' then 
      dataout1 <= shiftregister; 
     end if; 
    end process; 

end architecture; 

VHDL基本標識符不區分大小寫,名稱不是特別有啓發性。上述兩個波形的格式表明名稱的變化很方便。

如果將移位寄存器的長度延長1或2,則可以在停止位期間檢測到幀錯誤。改變移位寄存器的長度將需要對移位寄存器輸出進行限幅,以寫入數據輸出。

請注意,此體系結構是使用軟件包numeric_std編寫的,而不是Synopsys軟件包std_logic_arith。您也沒有提供實體聲明之前的上下文條款。

該體系結構還產生使能和使用16x時鐘,而不是產生1x時鐘。

它是在找到原始架構中糾正問題的變化量之後編寫的,似乎勢不可擋。 (如有疑問,重新來過。)用於

這個測試平臺:

library ieee; 
use ieee.std_logic_1164.all; 

entity rs232rxd_tb is 
end entity; 

architecture foo of rs232rxd_tb is 
    signal reset:  std_logic := '0'; 
    signal clock16x: std_logic := '0'; 
    signal rxd:   std_logic := '1'; 
    signal dataout1: std_logic_vector (7 downto 0); 
begin 
DUT: 
    entity work.rs232rxd 
     port map (
      reset => reset, 
      clock16x => clock16x, 
      rxd => rxd, 
      dataout1 => dataout1 
     ); 
CLOCK: 
    process 
    begin 
     wait for 3.255 us; -- 16X clock divided by 2, 9600 baud 104.16 us 
     clock16x <= not clock16x; 
     if now > 2.30 ms then 
      wait; 
     end if; 
    end process; 

    STIMULI: 
    process 
    begin 
     wait for 6.51 us; 
     reset <= '1'; 
     wait for 13.02 us; 
     reset <= '0'; 
     wait for 13.02 us; 
     wait for 40 us; 
     rxd <= '0'; 
     wait for 104.16 us; -- start bit 
     rxd <= '1'; 
     wait for 104.16 us; -- first data bit, bit 0 = '1' 
     rxd <= '0'; 
     wait for 104.16 us; -- second data bit, bit 1 = '0' 
     rxd <= '0'; 
     wait for 104.16 us; -- third data bit, bit 2 = '0'; 
     wait for 104.16 us; -- fourth data bit, bit 3 = '0'; 
     wait for 104.16 us; -- fifth data bit, bit 4 = '0'; 
     wait for 104.16 us; -- sixth data bit, bit 5 = '0'; 
     rxd <= '1'; 
     wait for 104.16 us; -- seventh data bit, bit 6 = '1'; 
     rxd <= '0'; 
     wait for 104.16 us; -- eigth data bit, bit 7 = '0'; 
     rxd <= '1'; 
     wait for 104.16 us; -- stop bit (= '1') 
     --wait for 104.16 us; -- idle 
     rxd <= '0'; 
     wait for 104.16 us; -- start bit 
     rxd <= '1'; 
     wait for 104.16 us; -- first data bit, bit 0 = '1' 
     rxd <= '0'; 
     wait for 104.16 us; -- second data bit, bit 1 = '0' 
     rxd <= '0'; 
     wait for 104.16 us; -- third data bit, bit 2 = '0'; 
     wait for 104.16 us; -- fourth data bit, bit 3 = '0'; 
     wait for 104.16 us; -- fifth data bit, bit 4 = '0'; 
     rxd <= '1'; 
     wait for 104.16 us; -- sixth data bit, bit 5 = '1'; 
     wait for 104.16 us; -- seventh data bit, bit 6 = '1'; 
     rxd <= '0'; 
     wait for 104.16 us; -- eigth data bit, bit 7 = '0'; 
     rxd <= '1'; 
     wait for 104.16 us; -- stop bit (= '1') 
     wait; 
    end process; 
end architecture; 

你可以看到,新的架構都具有相同的基本要素,雖然主頻工藝元素在單獨的進程中聲明。

沒有狀態機進程。通過與移位寄存器(奇偶校驗,兩個停止位,7個數據位等)分開輸入來實現全功能UART接收器,該架構可擴展。奇偶校驗可以連續執行。