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;
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:=Din(0);
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;