VHDL 编写的2M 波特率串口接收模块,在串口接收信号时,正常工作后,只要串口接收争取后,程序运行没问题。但重复复位或多次上电,经常有串口不能正常工作的现象?我是通过对串口接收的正确的标识信号进行翻转驱动LED灯来指示的。结果经常出现上面的问题,目前待查原因,请高手分析问题,下面是串口接收的程序代码!
LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL;
--LIBRARY ALTERA; --USE ALTERA.MAXPLUS2.ALL;
LIBRARY LPM; USE LPM.LPM_COMPONENTS.ALL; -- ****************************************************************************
ENTITY Rx_Com IS GENERIC (Rx_D_Width : POSITIVE := 8;Check:STRING:="Even";Check_En:STRING:="En"); PORT( Clk : IN STD_LOGIC; Rst : IN STD_LOGIC; Rx_Clk : IN STD_LOGIC; -----------串口接收时钟 Rx : IN STD_LOGIC; -----------串口接收数据 Dout : OUT STD_LOGIC_VECTOR(Rx_D_Width-1 DOWNTO 0); -------------串口接收数据输出 Rxrdy : OUT STD_LOGIC; -------------串口接收数据有效使能 Rxerr : OUT STD_LOGIC; -------------串口接收错误标志 Clrdiv : OUT STD_LOGIC -------------串口接收时钟产生使能标志 ); END Rx_Com; -- **************************************************************************** ARCHITECTURE Arch_Rx_Com OF Rx_Com IS
CONSTANT Bit_Valid : STD_LOGIC:='1'; CONSTANT Bit_Invalid : STD_LOGIC:='0'; ----------------接收状态机-------------------------------------------------------------------------------- TYPE State IS (Idle,Start_rx,Edge_Rx,Shift_Rx,Stop_Rx,Rx_Ovf,Rx_Crc); SIGNAL Rxfsm : State;
SIGNAL Rx_Reg : STD_LOGIC_VECTOR(Rx_D_Width DOWNTO 0); --------------接收数据寄存器 SIGNAL Rxbitcnt : INTEGER RANGE 0 TO (Rx_D_Width+3); --------------接收计数器 SIGNAL Rxrdyi,Clrdivi : STD_LOGIC; --------------中间寄存器 SIGNAL Rx1,Rx2,Rx3,Rx4 : STD_LOGIC; SIGNAL Rxrdyi_Buf : STD_LOGIC; SIGNAL Rx_Clk_Reg : STD_LOGIC_VECTOR(1 DOWNTO 0); BEGIN -------------------------------------------------------------------------------
PROCESS(Clk,Rst) BEGIN IF(Rst=Bit_Valid) THEN Rxrdy<=Bit_Invalid; Clrdiv<=Bit_Invalid; ELSIF Clk'EVENT and Clk=Bit_Valid THEN Rxrdyi_Buf<=Rxrdyi; IF (Rxrdyi_Buf=Bit_Valid) AND (Rxrdyi=Bit_Invalid) THEN Rxrdy <= Bit_Valid; ELSE Rxrdy <= Bit_Invalid; END IF; Clrdiv <= Clrdivi; ----------------------------------- IF (Rx_Clk='1') THEN Rx_Clk_Reg<="01"; ELSE Rx_Clk_Reg<="10"; END IF; END IF; END PROCESS;
PROCESS(Rst,Clk) VARIABLE Rxbitcnt : INTEGER RANGE 0 TO (Rx_D_Width+3); VARIABLE Highcnt : INTEGER RANGE 0 TO 20; VARIABLE Par : STD_LOGIC; VARIABLE Par_Reg ,Rx4_Reg : STD_LOGIC_VECTOR(1 DOWNTO 0); BEGIN IF Rst=Bit_Valid THEN Rx_Reg <= (OTHERS=> Bit_Invalid); Dout <= (OTHERS=> Bit_Invalid); Rxbitcnt := 0; Rxfsm <= Idle; Rxrdyi <= Bit_Invalid; Clrdivi <= Bit_Invalid; Rxerr <= Bit_Invalid; Par := Bit_Invalid; Rx1<=Bit_Valid; Rx2<=Bit_Valid; Rx3<=Bit_Valid; Rx4<=Bit_Valid; Highcnt:=0; ELSIF Clk'EVENT and Clk=Bit_Valid THEN Rx1<=rx; Rx2<=Rx1; Rx3<=Rx2; Rx4<=Rx3; -- CASE Rxfsm IS -- WHEN Idle => IF (Rxfsm=Idle) THEN Par:=Bit_Invalid; Rxbitcnt := 0; Rxrdyi <= Bit_Invalid; Clrdivi <= Bit_Valid; IF (Rx4 = Bit_Invalid) THEN Rxfsm <= start_rx; Clrdivi <= Bit_Invalid; END IF; -- WHEN start_rx => ELSIF (Rxfsm=start_rx) THEN IF Rx_Clk = Bit_Valid THEN -- IF Rx_Clk_Reg="01" THEN IF Rx4 = Bit_Valid THEN Rxfsm <= Rx_Ovf; ELSE Rxfsm <= Edge_Rx; END IF; END IF; -- WHEN Edge_Rx => ELSIF (Rxfsm=Edge_Rx) THEN IF Rx_Clk = Bit_Valid THEN -- IF Rx_Clk_Reg="01" THEN Rxfsm <= Shift_Rx; IF(Check_En="En")THEN IF Rxbitcnt = Rx_D_Width+1 THEN Rxfsm <= Stop_Rx; ELSE Rxfsm <= Shift_Rx; END IF; ELSE IF Rxbitcnt = Rx_D_Width THEN Rxfsm <= Stop_Rx; ELSE Rxfsm <= Shift_Rx; END IF; END IF; END IF; --WHEN Shift_Rx => ELSIF (Rxfsm=Shift_Rx) THEN IF Rx_Clk = Bit_Valid THEN -- IF Rx_Clk_Reg="01" THEN Rxbitcnt := Rxbitcnt + 1; IF (Rxbitcnt=1) THEN Par:=Rx4; END IF; Rx_Reg <= Rx4 & Rx_Reg(Rx_Reg'high DOWNTO 1); Rxfsm <= Edge_Rx; END IF; --WHEN Stop_Rx => ELSIF (Rxfsm=Stop_Rx) THEN IF Rx_Clk = Bit_Valid THEN IF (Rx4 = Bit_Valid) THEN Rxfsm <= Rx_Crc; ELSE Rxfsm <= Rx_Ovf; END IF; END IF; -- WHEN Rx_Ovf => ELSIF (Rxfsm=Rx_Crc) THEN FOR i IN 1 TO (Rx_D_Width) LOOP Par:=Par XOR Rx_Reg(i); END LOOP; IF ((Check="Even") AND (Par='0')) OR ((Check="Odd") AND (Par='1')) THEN Rxrdyi <= Bit_Valid; ELSE Rxrdyi <= Bit_Invalid; END IF; Dout <=Rx_Reg((Rx_D_Width-1) DOWNTO 0); --// Rxrdyi <= Bit_Valid; Rxfsm<=Rx_Ovf ; ELSIF (Rxfsm=Rx_Ovf) THEN Rxrdyi <= Bit_Invalid; -- Rxerr <= Bit_Valid; IF (Highcnt=15) then Highcnt:=0; Rxfsm <= Idle; ELSIF Rx4 = Bit_Valid THEN Highcnt:= Highcnt+1; END IF; -- WHEN OTHERS => ELSE Rxfsm <= Idle; --END CASE; END IF; END IF; END PROCESS;
END Arch_Rx_Com;
|