線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1311
推到 Plurk!
推到 Facebook!

UART VHDL 接收程式會當機!

缺席
mis881085
一般會員


發表:2
回覆:7
積分:6
註冊:2005-04-30

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-10-07 19:10:38 IP:140.118.xxx.xxx 未訂閱
我的程式會當機! 接收那一段,RECEIVER_DATA:以下 可是不是每次都會當機! 當程式執行過一陣子後!就會有不明原因的當機! 誰能幫我看看??    
LIBRARY ieee;
USE ieee.std_logic_1164.all;    ENTITY UART IS            GENERIC
        (
                CLK_DIV        : natural :=        50;
                INSIDE_CLK_DIV        : natural :=        26;
                INSIDE_CLK_MID        : natural :=        13;
                
                
                STOP_BIT        : natural :=        1;
                DATA_BIT        : natural :=        8
        );
        PORT
        (
                CLK        :        IN        STD_LOGIC;
                RESET        :        IN        STD_LOGIC;
                LD        :        IN        STD_LOGIC;
                RX        :        IN        STD_LOGIC;
                DATA_IN        :        IN        STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0);
                STATE_OUT        :        OUT        STD_LOGIC_VECTOR(3 DOWNTO 0);
                DATA_OUT        :        OUT        STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0);
                READY_RX        :        OUT        STD_LOGIC;
                TX_BUSY        :        OUT        STD_LOGIC;
                TX        :        OUT        STD_LOGIC
        );
        
END UART;    ARCHITECTURE UART_START OF UART IS
        TYPE  TX_STATE_TYPE IS (IDLE,LOAD_TX,SHIFT_TX,STOP_TX);        
        TYPE  RX_STATE_TYPE IS (IDLE,READ,SHIFT,STOP_RX);        
                
        SIGNAL TX_FSM :TX_STATE_TYPE;        
        SIGNAL RX_FSM :RX_STATE_TYPE;
        SIGNAL INSIDE_CLK :STD_LOGIC;
        SIGNAL TX_REG :STD_LOGIC_VECTOR(DATA_BIT STOP_BIT DOWNTO 0);
        SIGNAL RX_OUT_REG :STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0);
        
BEGIN
        
SYS_CLK:
        PROCESS(RESET,CLK,INSIDE_CLK)
                VARIABLE CNT : INTEGER;
        BEGIN
                IF (RESET = '1') THEN
                        CNT := 0;                                
                        INSIDE_CLK <= '0';
                ELSIF (CLK'EVENT AND CLK = '1') THEN
                        CNT := CNT   1;
                        IF (CNT > (CLK_DIV)) THEN
                                INSIDE_CLK <= NOT INSIDE_CLK;
                                CNT := 0;
                        END IF;
                END IF;
        END PROCESS;            
RECEIVER_DATA:
        PROCESS(RESET,INSIDE_CLK,RX)
                VARIABLE FRAME_CNT:INTEGER;
                VARIABLE CNT:INTEGER;        
                VARIABLE REG_RX :STD_LOGIC_VECTOR(DATA_BIT   STOP_BIT DOWNTO 0);
                VARIABLE PRE_STATE :STD_LOGIC;
        BEGIN        
                IF (RESET = '1')THEN
                        RX_FSM <= IDLE;
                        FRAME_CNT := 0;
                        CNT := 0;
                        REG_RX := (OTHERS=>'1');
                        PRE_STATE := '1';
                        READY_RX <= '0';
                        RX_OUT_REG <= (OTHERS=>'1');
                ELSIF (INSIDE_CLK'EVENT AND INSIDE_CLK = '1') THEN                
                        CNT := CNT  1;
                        CASE RX_FSM IS
                                WHEN IDLE =>
                                        IF (PRE_STATE = '1' AND RX = '0')THEN
                                                RX_FSM <= READ;
                                        END IF;
                                        FRAME_CNT := 0;
                                        CNT := 0;
                                WHEN READ =>
                                        IF (CNT = (INSIDE_CLK_MID))THEN
                                                REG_RX(REG_RX'HIGH):= RX;
                                        ELSIF (CNT >= INSIDE_CLK_DIV)THEN
                                                RX_FSM <= SHIFT;
                                                FRAME_CNT := FRAME_CNT   1;
                                                CNT := 0;
                                        END IF;
                                WHEN SHIFT =>
                                        IF (FRAME_CNT > (DATA_BIT   STOP_BIT))THEN
                                                READY_RX <= '0';
                                                RX_FSM <= STOP_RX;
                                        ELSE
                                                RX_FSM <= READ;
                                                REG_RX := ('U'®_RX(REG_RX'HIGH DOWNTO 1));
                                        END IF;                                        
                                WHEN STOP_RX =>
                                        IF (REG_RX(REG_RX'HIGH)= '1' AND REG_RX(0)= '0')THEN
                                                RX_OUT_REG <= REG_RX(REG_RX'HIGH-STOP_BIT DOWNTO 1);
                                                READY_RX <= '1';
                                        ELSE
                                                READY_RX <= '0';
                                                RX_OUT_REG <= (OTHERS=>'1');
                                        END IF;
                                        RX_FSM <= IDLE;
                                WHEN OTHERS =>
                                        RX_FSM <= IDLE;
                        END CASE;
                        PRE_STATE := RX;
                        
                        
                END IF;
        END PROCESS;        
        DATA_OUT <= RX_OUT_REG;                    
TRANSFER_DATA:
        PROCESS(RESET,INSIDE_CLK,TX_REG)
                VARIABLE FRAME_CNT:INTEGER;
                VARIABLE CNT:INTEGER;        
                VARIABLE REG_DIN :STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0);
        BEGIN
                IF (RESET = '1')THEN
                        TX_FSM <= IDLE;
                        TX_BUSY <= '0';
                        FRAME_CNT := 0;
                        CNT := 0;
                        REG_DIN := (OTHERS=>'1');
                        TX_REG <= (OTHERS=>'1');
                        STATE_OUT <= "1000";
                ELSIF(INSIDE_CLK'EVENT AND INSIDE_CLK = '1')THEN
                        CNT := CNT   1;
                        IF (CNT > (INSIDE_CLK_DIV))THEN
                                TX_BUSY <= '1';
                                CNT := 0;                
                                STATE_OUT <= "0000";                        
                                                
                                                
                                                        
                                CASE TX_FSM IS
                                        WHEN IDLE =>
                                                IF (LD = '1') THEN
                                                        REG_DIN := DATA_IN;
                                                        TX_FSM <= LOAD_TX;        
                                                        STATE_OUT <= "0001";
                                                ELSE
                                                        REG_DIN := (OTHERS=>'X');                                                        
                                                        TX_BUSY <= '0';        
                                                        STATE_OUT <= "0010";
                                                END IF;        
                                                FRAME_CNT := 0;
                                        WHEN LOAD_TX =>
                                                TX_REG(TX_REG'HIGH)<='1';
                                                TX_REG(TX_REG'HIGH-1 DOWNTO 1)<=REG_DIN;
                                                TX_REG(0)<='0';
                                                FRAME_CNT := 1;
                                                TX_FSM <= SHIFT_TX;        
                                                STATE_OUT <= "0011";
                                        WHEN SHIFT_TX =>
                                                TX_REG <= ('X'&TX_REG(TX_REG'HIGH DOWNTO 1));
                                                FRAME_CNT := FRAME_CNT   1;        
                                                STATE_OUT <= "0100";
                                                IF (FRAME_CNT > (DATA_BIT   STOP_BIT))THEN
                                                        TX_FSM <= STOP_TX;
                                                        STATE_OUT <= "0101";
                                                END IF;
                                        WHEN STOP_TX =>                
                                                TX_FSM <= IDLE;
                                                TX_BUSY <= '0';
                                                REG_DIN := (OTHERS=>'1');
                                                STATE_OUT <= "0110";        
                                        WHEN OTHERS =>
                                                TX_FSM <= IDLE;
                                                TX_BUSY <= '0';
                                                REG_DIN := (OTHERS=>'1');
                                                STATE_OUT <= "0111";        
                                END CASE;
                                
                                                
                        END IF;
                END IF;
        END PROCESS;
        
        
        TX <=TX_REG(0);
            END UART_START;
ssejack
高階會員


發表:87
回覆:143
積分:106
註冊:2005-06-27

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-10-13 13:50:57 IP:59.105.xxx.xxx 未訂閱
您的code 直接 compiler 有問題!
引言: REG_RX := ('U'®_RX(REG_RX'HIGH DOWNTO 1));
是否如下?? REG_RX := 'U'&(REG_RX(REG_RX'HIGH DOWNTO 1)); 您所謂當機是simulation出來的 or 實作的呢? 是否附上 simulation waveform 及有問題處? 另有點疑問,您的 FSM 暫存器 是用 variable ,但 variable 在 process 結束後是無法 hold data 的,也就是說下次再執行process 時 variable 的內容就???遺失了耶!
addn
高階會員


發表:64
回覆:221
積分:202
註冊:2005-03-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-10-14 08:56:02 IP:218.171.xxx.xxx 未訂閱
可不可以說明一下 是如何測試你的接收部分的功能 也有可能問題會發生在這
ssejack
高階會員


發表:87
回覆:143
積分:106
註冊:2005-06-27

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-10-17 13:17:47 IP:59.105.xxx.xxx 未訂閱
Sorry!      上回沒仔細看
引言: REG_RX := ('U'®_RX(REG_RX'HIGH DOWNTO 1));
應為 REG_RX := RX&(REG_RX(REG_RX'HIGH DOWNTO 1)); 另Variable 沒有給其他process 用所以也是沒問題的, 可能有問題的地方於 INSIDE_CLK 和 LD,RX 的setup/hold time關係! 因INSIDE_CLK 為內部除頻產生,固與input 的LD,RX 如有setup/hold time 的問題可能會有非預期的狀態吧! 建議改成以 CLK 的 central clock RX_FSM & FX_RSM 以除頻之 overflow 來當enable 信號,這時候只要對好 CLK,LD,RX,DATA_IN 的 setup/hold time 就應該比較容易沒問題 < class="code"> LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY UART IS GENERIC ( CLK_DIV : natural := 50; INSIDE_CLK_DIV : natural := 26; INSIDE_CLK_MID : natural := 13; STOP_BIT : natural := 1; DATA_BIT : natural := 8 ); PORT ( CLK : IN STD_LOGIC; RESET : IN STD_LOGIC; LD : IN STD_LOGIC; RX : IN STD_LOGIC; DATA_IN : IN STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0); STATE_OUT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); DATA_OUT : OUT STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0); READY_RX : OUT STD_LOGIC; TX_BUSY : OUT STD_LOGIC; TX : OUT STD_LOGIC ); END UART; ARCHITECTURE UART_START OF UART IS TYPE TX_STATE_TYPE IS (IDLE,LOAD_TX,SHIFT_TX,STOP_TX); TYPE RX_STATE_TYPE IS (IDLE,READ,SHIFT,STOP_RX); SIGNAL TX_FSM :TX_STATE_TYPE; SIGNAL RX_FSM :RX_STATE_TYPE; SIGNAL INSIDE_CLK :STD_LOGIC; SIGNAL TX_REG :STD_LOGIC_VECTOR(DATA_BIT STOP_BIT DOWNTO 0); SIGNAL RX_OUT_REG :STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0); signal inside_clk_carry :std_logic; BEGIN SYS_CLK: PROCESS(RESET,CLK,INSIDE_CLK) VARIABLE CNT : INTEGER; BEGIN IF (RESET = '1') THEN CNT := 0; inside_clk_carry <= '0'; -- INSIDE_CLK <= '0'; ELSIF (CLK'EVENT AND CLK = '1') THEN CNT := CNT 1; IF (CNT > (CLK_DIV)) THEN -- INSIDE_CLK <= NOT INSIDE_CLK; CNT := 0; inside_clk_carry <='1'; END IF; END IF; END PROCESS; RECEIVER_DATA: -- PROCESS(RESET,INSIDE_CLK,RX) PROCESS(RESET,CLK,inside_clk_carry,RX) VARIABLE FRAME_CNT:INTEGER; VARIABLE CNT:INTEGER; VARIABLE REG_RX :STD_LOGIC_VECTOR(DATA_BIT STOP_BIT DOWNTO 0); VARIABLE PRE_STATE :STD_LOGIC; BEGIN IF (RESET = '1')THEN RX_FSM <= IDLE; FRAME_CNT := 0; CNT := 0; REG_RX := (OTHERS=>'1'); PRE_STATE := '1'; READY_RX <= '0'; RX_OUT_REG <= (OTHERS=>'1'); -- ELSIF (INSIDE_CLK'EVENT AND INSIDE_CLK = '1') THEN ELSIF (CLK'EVENT AND CLK = '1') THEN if(inside_clk_carry = '1')then CNT := CNT 1; CASE RX_FSM IS WHEN IDLE => IF (PRE_STATE = '1' AND RX = '0')THEN RX_FSM <= READ; END IF; FRAME_CNT := 0; CNT := 0; WHEN READ => IF (CNT = (INSIDE_CLK_MID))THEN REG_RX(REG_RX'HIGH):= RX; ELSIF (CNT >= INSIDE_CLK_DIV)THEN RX_FSM <= SHIFT; FRAME_CNT := FRAME_CNT 1; CNT := 0; END IF; WHEN SHIFT => IF (FRAME_CNT > (DATA_BIT STOP_BIT))THEN READY_RX <= '0'; RX_FSM <= STOP_RX; ELSE RX_FSM <= READ; REG_RX := RX&(REG_RX(REG_RX'HIGH DOWNTO 1)); --REG_RX := ('U'&RX(REG_RX'HIGH DOWNTO 1)); END IF; WHEN STOP_RX => IF (REG_RX(REG_RX'HIGH)= '1' AND REG_RX(0)= '0')THEN RX_OUT_REG <= REG_RX( (REG_RX'HIGH-STOP_BIT) DOWNTO 1); READY_RX <= '1'; ELSE READY_RX <= '0'; RX_OUT_REG <= (OTHERS=>'1'); END IF; RX_FSM <= IDLE; WHEN OTHERS => RX_FSM <= IDLE; END CASE; PRE_STATE := RX; end if; END IF; END PROCESS; DATA_OUT <= RX_OUT_REG; TRANSFER_DATA: -- PROCESS(RESET,INSIDE_CLK,TX_REG) PROCESS(RESET,CLK,inside_clk_carry,TX_REG) VARIABLE FRAME_CNT:INTEGER; VARIABLE CNT:INTEGER; VARIABLE REG_DIN :STD_LOGIC_VECTOR(DATA_BIT-1 DOWNTO 0); BEGIN IF (RESET = '1')THEN TX_FSM <= IDLE; TX_BUSY <= '0'; FRAME_CNT := 0; CNT := 0; REG_DIN := (OTHERS=>'1'); TX_REG <= (OTHERS=>'1'); STATE_OUT <= "1000"; -- ELSIF(INSIDE_CLK'EVENT AND INSIDE_CLK = '1')THEN ELSIF (CLK'EVENT AND CLK = '1') THEN if(inside_clk_carry = '1')then CNT := CNT 1; IF (CNT > (INSIDE_CLK_DIV))THEN TX_BUSY <= '1'; CNT := 0; STATE_OUT <= "0000"; CASE TX_FSM IS WHEN IDLE => IF (LD = '1') THEN REG_DIN := DATA_IN; TX_FSM <= LOAD_TX; STATE_OUT <= "0001"; ELSE REG_DIN := (OTHERS=>'X'); TX_BUSY <= '0'; STATE_OUT <= "0010"; END IF; FRAME_CNT := 0; WHEN LOAD_TX => TX_REG(TX_REG'HIGH)<='1'; TX_REG(TX_REG'HIGH-1 DOWNTO 1)<=REG_DIN; TX_REG(0)<='0'; FRAME_CNT := 1; TX_FSM <= SHIFT_TX; STATE_OUT <= "0011"; WHEN SHIFT_TX => TX_REG <= ('X'&TX_REG(TX_REG'HIGH DOWNTO 1)); FRAME_CNT := FRAME_CNT 1; STATE_OUT <= "0100"; IF (FRAME_CNT > (DATA_BIT STOP_BIT))THEN TX_FSM <= STOP_TX; STATE_OUT <= "0101"; END IF; WHEN STOP_TX => TX_FSM <= IDLE; TX_BUSY <= '0'; REG_DIN := (OTHERS=>'1'); STATE_OUT <= "0110"; WHEN OTHERS => TX_FSM <= IDLE; TX_BUSY <= '0'; REG_DIN := (OTHERS=>'1'); STATE_OUT <= "0111"; END CASE; END IF; end if; END IF; END PROCESS; TX <=TX_REG(0); END UART_START;
mis881085
一般會員


發表:2
回覆:7
積分:6
註冊:2005-04-30

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-10-25 20:13:29 IP:218.160.xxx.xxx 未訂閱
感謝大大的回答 我再試試看
系統時間:2024-07-01 21:26:51
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!