第一部分: 串口接收程序
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 100;
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;
Rx4<=(Rx1 AND Rx2) OR (Rx2 AND Rx3) OR (Rx1 AND 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;
Rxerr <= Bit_Valid;
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;
Rxerr <= Bit_Valid;
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;
Rxerr <= Bit_Valid;
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_Invalid;
-- Rxerr <= Bit_Valid;
IF (Highcnt=40) then
Highcnt:=0;
Rxfsm <= Idle;
ELSIF Rx4 = Bit_Valid THEN
Highcnt:= Highcnt+1;
END IF;
IF (Rx4 = Bit_Invalid) THEN
Highcnt:=0;
END IF;
-- WHEN OTHERS =>
ELSE
Rxfsm <= Idle;
--END CASE;
END IF;
END IF;
END PROCESS;
END Arch_Rx_Com;
第二部分:
串口发送部分
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 Tx_Com IS
GENERIC(Tx_D_Width : POSITIVE := 8; Check: STRING:="Even";Check_En:STRING:="En");
PORT(
Clk : IN STD_LOGIC;
Rst : IN STD_LOGIC;
Tx_Clk : IN STD_LOGIC; ---------串口发送时钟
Din : IN STD_LOGIC_VECTOR(Tx_D_Width-1 DOWNTO 0); ---------串口发送数据
Tx_En : IN STD_LOGIC; ---------串口发送使能
Txbusy : OUT STD_LOGIC; ---------串口状态
Star_Clk : OUT STD_LOGIC; ---------串口发送时钟使能
Tx : OUT STD_LOGIC ---------串口数据按位发送
);
END Tx_Com;
-- ****************************************************************************
ARCHITECTURE Arch_Tx_Com OF Tx_Com IS
CONSTANT Bit_Valid : STD_LOGIC:='1';
CONSTANT Bit_Invalid : STD_LOGIC:='0';
CONSTANT Idle :STD_LOGIC_VECTOR(3 DOWNTO 0):=X"0";
CONSTANT Par_Tx :STD_LOGIC_VECTOR(3 DOWNTO 0):=X"1";
CONSTANT Load_tx :STD_LOGIC_VECTOR(3 DOWNTO 0):=X"2";
CONSTANT Shift_tx :STD_LOGIC_VECTOR(3 DOWNTO 0):=X"3";
CONSTANT Stop_tx :STD_LOGIC_VECTOR(3 DOWNTO 0):=X"4";
SIGNAL Txdiv : INTEGER RANGE 0 TO 10;
SIGNAL Regdin : STD_LOGIC_VECTOR(Tx_D_Width-1 DOWNTO 0);
SIGNAL Tx_reg : STD_LOGIC_VECTOR(Tx_D_Width+2 DOWNTO 0);
SIGNAL Tx_En_Buf : STD_LOGIC;
SIGNAL Tx_Clk1,Star_Clk1 : STD_LOGIC;
SIGNAL Tx_Clk_Reg : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL Txbitcnt : INTEGER RANGE 0 TO (Tx_D_Width+3);
SIGNAL Cnt : INTEGER RANGE 0 TO 3;
SIGNAL Tx_Data_Buf : STD_LOGIC_VECTOR((Tx_D_Width+Tx_D_Width-1) DOWNTO 0);
--TYPE STATE IS (Idle,Par_Tx,Load_tx,Shift_tx,Stop_tx);
SIGNAL Txfsm : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
-------------------------------------------------------------------------------
----- syn transmit with system clock-----------------------------------------------
PROCESS(Clk,Rst)
BEGIN
IF (Rst=Bit_Valid) THEN
--Tx<=Bit_Invalid;
Tx<=Bit_Valid;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
--IF (Clk_Work="011" ) THEN
Tx <= Tx_reg(0);
IF (Tx_Clk='1') THEN
Tx_Clk_Reg<="01";
ELSE
Tx_Clk_Reg<="10";
END IF;
--END IF;
END IF;
END PROCESS;
-----Input Signal Delay a Clock-----------------------------------------------
PROCESS(Clk,Rst)
BEGIN
IF (Rst=Bit_Valid) THEN
Tx_En_Buf<=Bit_Invalid;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
--IF (Clk_Work="011" ) THEN
Tx_En_Buf <= Tx_En;
--END IF;
END IF;
END PROCESS;
--------------------------------
-- Tx_ FSM
--------------------------------
PROCESS(Rst,Clk)
VARIABLE Pari: STD_LOGIC;
BEGIN
IF Rst=Bit_Valid THEN
Tx_reg <= (OTHERS=> Bit_Valid);
Txbitcnt <= 0;
Txfsm <= Idle;
Txbusy <= Bit_Invalid;
Regdin <= (OTHERS=> Bit_Invalid);
Star_Clk<=Bit_Invalid;
Cnt<=0;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
-- IF (Clk_Work="011" ) THEN
IF (Tx_En_Buf=Bit_Invalid) AND (Tx_En = Bit_Valid) THEN
Tx_Data_Buf<=Tx_Data_Buf((Tx_D_Width+Tx_D_Width-1) DOWNTO Tx_D_Width) & Din;
ELSIF (Tx_En_Buf=Bit_Valid) AND (Tx_En = Bit_Invalid)THEN
Tx_Data_Buf<=Tx_Data_Buf((Tx_D_Width-1) DOWNTO 0) & Tx_Data_Buf((Tx_D_Width+Tx_D_Width-1) DOWNTO Tx_D_Width);
Cnt<=Cnt+1;
ELSE
Tx_Data_Buf<=Tx_Data_Buf;
END IF;
--CASE Txfsm IS
-- WHEN Idle =>
IF (Txfsm=Idle) THEN
Star_Clk<=Bit_Invalid;
Tx_reg <= (OTHERS=> Bit_Valid);
IF (Cnt>0) THEN
Regdin <=Tx_Data_Buf((Tx_D_Width+Tx_D_Width-1) DOWNTO Tx_D_Width);
Pari:=Tx_Data_Buf(Tx_D_Width);
Txbusy <= Bit_Valid;
Txfsm <= Par_Tx;
Cnt<=Cnt-1;
ELSE
Txbusy <= Bit_Invalid;
Txfsm <= Idle;
Regdin<=(OTHERS=>Bit_Invalid);
Pari:=Bit_Invalid;
END IF;
--WHEN Par_Tx=>
ELSIF (Txfsm=Par_Tx) THEN
FOR i IN 1 TO (Tx_D_Width-1) LOOP
Pari:=Pari XOR Regdin(i);
END LOOP;
Txfsm<=load_tx;
Star_Clk<=Bit_Valid;
--WHEN Load_tx =>
ELSIF (Txfsm=Load_tx) THEN
--IF Tx_Clk=Bit_Valid THEN
IF Tx_Clk_Reg="01" THEN
Txfsm <= Shift_tx;
IF (Check_En="En")THEN
Txbitcnt <= Tx_D_Width+3;
IF (Check="Even") THEN
Tx_reg <= Bit_Valid & Pari & Regdin & Bit_Invalid;
ELSIF (Check="Odd") THEN
Tx_reg <= Bit_Valid & (NOT Pari) & Regdin & Bit_Invalid;
END IF;
ELSE
Txbitcnt <= Tx_D_Width+2;
Tx_reg <= Bit_Valid & Bit_Valid & Regdin & Bit_Invalid;
END IF;
END IF;
--WHEN Shift_tx =>
ELSIF (Txfsm=Shift_tx) THEN
--IF Tx_Clk=Bit_Valid THEN
IF Tx_Clk_Reg="01" THEN
Txbitcnt <= Txbitcnt-1;
Tx_reg <= Bit_Valid & Tx_reg(Tx_reg'high DOWNTO 1);
IF Txbitcnt = 1 THEN
Txfsm <= Stop_tx;
END IF;
END IF;
--WHEN Stop_tx =>
ELSIF (Txfsm=Stop_tx) THEN
Txfsm <= Idle;
-- WHEN OTHERS =>
ELSE
Txfsm <= Idle;
--END CASE;
END IF;
END IF;
-- END IF;
END PROCESS;
END Arch_Tx_Com;
第三部分:
串口时钟产生
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
LIBRARY LPM;
USE LPM.LPM_COMPONENTS.ALL;
-- ****************************************************************************
ENTITY Uart_Clk_Generate IS
GENERIC ( Baud_Set:INTEGER:=19200);
PORT(
Clk : IN STD_LOGIC;
Rst : IN STD_LOGIC;
Star_Clk : IN STD_LOGIC;
Clrdiv : IN STD_LOGIC;
Tx_Clk : OUT STD_LOGIC;
Rx_Clk : OUT STD_LOGIC
);
END Uart_Clk_Generate;
-- ****************************************************************************
ARCHITECTURE Arch_Uart_Clk_Generate OF Uart_Clk_Generate IS
CONSTANT Bit_Valid : STD_LOGIC:='1';
CONSTANT Bit_Invalid : STD_LOGIC:='0';
CONSTANT BuadSet : INTEGER RANGE 0 TO 1042:=1042;
SIGNAL Txdiv : INTEGER RANGE 0 to BuadSet;
SIGNAL Rxdiv : INTEGER RANGE 0 to BuadSet;
SIGNAL Tx_Clkset : INTEGER RANGE 0 to BuadSet;
SIGNAL Rx_Clkset : INTEGER RANGE 0 to BuadSet;
BEGIN
-------------------------------------------------------------------------------
--------------------------------
-- Buad Produce
--------------------------------
Buad_Produce:PROCESS(Rst,Clk)
BEGIN
IF Rst=Bit_Valid THEN
Tx_Clkset<=0;
Rx_Clkset<=0;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
CASE Baud_Set IS
WHEN 19200=>
-- Tx_Clkset<=2604; ---50HZ
-- Rx_Clkset<=1302;
Tx_Clkset<=1042; ---20MHZ
Rx_Clkset<=521;
WHEN 9600=>
-- Tx_Clkset<=1042; ---20MHZ
-- Rx_Clkset<=521;
WHEN 2000000=>
Tx_Clkset<=10;
Rx_Clkset<=5;
WHEN 62500=>
Tx_Clkset<=320;
Rx_Clkset<=160;
WHEN OTHERS=>
Tx_Clkset<=1042;
Rx_Clkset<=521;
END CASE;
END IF;
END PROCESS Buad_Produce;
--------------------------------
-- Tx clock generation
--------------------------------
Tx_Clk_Gen:PROCESS(Rst,Clk)
BEGIN
IF Rst=Bit_Valid THEN
Tx_Clk <= Bit_Invalid;
Txdiv <= 0;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
IF Star_Clk = Bit_Invalid THEN
Txdiv <= 0;
ELSIF Txdiv=(Tx_Clkset-1) THEN
Txdiv <= 0;
ELSE
IF (Txdiv=0) THEN
Tx_Clk <= Bit_Valid;
ELSE
Tx_Clk <= Bit_Invalid;
END IF;
Txdiv <= Txdiv + 1;
END IF;
END IF;
END PROCESS Tx_Clk_Gen;
--------------------------------
-- Rx sampling clock generation
--------------------------------
Rx_Clk_Gen:PROCESS(Rst,Clk)
BEGIN
IF Rst=Bit_Valid THEN
Rx_Clk <= Bit_Invalid;
Rxdiv <= 0;
ELSIF Clk'EVENT AND Clk=Bit_Valid THEN
Rx_Clk <= Bit_Invalid;
IF Clrdiv = Bit_Valid THEN
Rxdiv <= 0;
ELSIF Rxdiv =(Rx_Clkset-1) THEN
Rxdiv <= 0;
Rx_Clk <= Bit_Valid;
ELSE
Rxdiv <= Rxdiv + 1;
Rx_Clk <= Bit_Invalid;
END IF;
END IF;
END PROCESS Rx_Clk_Gen;
-------------------------------------------------------------------------------
END Arch_Uart_Clk_Generate;
第四部分:串口子程序调用
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
LIBRARY LPM;
USE LPM.LPM_COMPONENTS.ALL;
-- ****************************************************************************
ENTITY Uart_Gen IS
GENERIC (Rx_D_Width: POSITIVE:=8;Tx_D_Width: POSITIVE:=8;Check:STRING:="Even";Check_En:STRING:="En";Baud_Set:POSITIVE:=19200;Module_En:STRING:="Enable");
PORT
(Clk : IN STD_LOGIC;
Rst : IN STD_LOGIC;
Tx_En : IN STD_LOGIC;
Tx_Data: IN STD_LOGIC_VECTOR(Tx_D_Width-1 DOWNTO 0);
Rxd : IN STD_LOGIC;
Txd : OUT STD_LOGIC;
Tx_Busy: OUT STD_LOGIC;
Rx_Rdy : OUT STD_LOGIC;
Rx_Data: OUT STD_LOGIC_VECTOR(Rx_D_Width-1 DOWNTO 0);
Com_Err: OUT STD_LOGIC
);
END Uart_Gen;
ARCHITECTURE Arch_Uart_Gen OF Uart_Gen IS
COMPONENT Uart_Clk_Generate IS
GENERIC ( Baud_Set:INTEGER:=19200);
PORT(
Clk : IN STD_LOGIC;
Rst : IN STD_LOGIC;
Star_Clk : IN STD_LOGIC;
Clrdiv : IN STD_LOGIC;
Tx_Clk : OUT STD_LOGIC;
Rx_Clk : OUT STD_LOGIC
);
END COMPONENT;
COMPONENT Tx_Com IS
GENERIC(Tx_D_Width : POSITIVE := 8; Check: STRING:="Even";Check_En:STRING:="En");
PORT(
Clk : IN STD_LOGIC;
Rst : IN STD_LOGIC;
Tx_Clk : IN STD_LOGIC;
Din : IN STD_LOGIC_VECTOR(Tx_D_Width-1 DOWNTO 0);
Tx_En : IN STD_LOGIC;
Txbusy : OUT STD_LOGIC;
Star_Clk : OUT STD_LOGIC;
Tx : OUT STD_LOGIC
);
END COMPONENT;
COMPONENT 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;
Dout : OUT STD_LOGIC_VECTOR(Rx_D_Width-1 DOWNTO 0);
Rxrdy : OUT STD_LOGIC;
Rxerr : OUT STD_LOGIC;
Clrdiv : OUT STD_LOGIC;
Rx : IN STD_LOGIC
);
END COMPONENT;
SIGNAL Clrdiv_Buf: STD_LOGIC;
SIGNAL Star_Clk_Buf: STD_LOGIC;
SIGNAL Tx_Clk_Buf: STD_LOGIC;
SIGNAL Rx_Clk_Buf: STD_LOGIC;
BEGIN
Uart_Gen:IF (Module_En="Enable")GENERATE
Uart_Clk_Generate_Ins:Uart_Clk_Generate
GENERIC MAP (Baud_Set=>Baud_Set)
PORT MAP
(
Clk=>Clk,
Rst=>Rst,
Star_Clk=>Star_Clk_Buf,
Clrdiv=>Clrdiv_Buf,
Tx_Clk=>Tx_Clk_Buf,
Rx_Clk=>Rx_Clk_Buf
);
Tx_Com_Ins: Tx_Com
GENERIC MAP(Tx_D_Width=>Tx_D_Width, Check=>Check,Check_En=>Check_En)
PORT MAP(
Clk=>Clk,
Rst=>Rst,
Tx_Clk=>Tx_Clk_Buf,
Din=>Tx_Data,
Tx_En=>Tx_En,
Txbusy=>Tx_Busy,
Star_Clk=>Star_Clk_Buf,
Tx=>Txd
);
Rx_Com_Ins: Rx_Com
GENERIC MAP(Rx_D_Width=>Rx_D_Width, Check=>Check,Check_En=>Check_En)
PORT MAP(
Clk=>Clk,
Rst=>Rst,
Rx_Clk=>Rx_Clk_Buf,
Dout=>Rx_Data,
Rxrdy=>Rx_Rdy,
Rxerr=>Com_Err,
Clrdiv=>Clrdiv_Buf,
Rx=>Rxd
);
END GENERATE;
END Arch_Uart_Gen;