www.pudn.com > uart_v11.zip > tx.tdf
%//////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// PROJECT: Programmable Universal Asynchronous Receiver/Transmitter. //
// Keith Willis //
// Copyright © 1998. All Rights Reserved. //
// //
// You may use or distribute this module freely, provided you do not remove this //
// copyright notice or modify the contents of this file. //
// If you have questions or comments, feel free to contact me by email at //
// kcwillis@mech.eng.usyd.edu.au //
// //
// AUTHOR: Keith Willis //
// //
// MODULE: Tx.tdf //
// //
// DESCRIPTION: AHDL File for Asynchronous Transmitter. //
// //
// VERSION: 1.1 //
///////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ======================== //
// | CONFIGURATION REGISTER | //
// =============================================================================================== //
// | Reserved | HS | D1 | D0 | S1 | S0 | P1 | P0 | //
// =============================================================================================== //
// //
// P1-P0: PARITY TYPE 00 = NO PARITY (DEFAULT) //
// 01 = ODD PARITY //
// 10 = EVEN PARITY //
// 11 = NO PARITY //
// //
// S1-S0: NUMBER OF STOP BITS 00 = 1 STOP BIT (DEFAULT) //
// 01 = 1.5 STOP BITS //
// 10 = 2 STOP BITS //
// 11 = 1 STOP BIT //
// //
// D1-D0: NUMBER OF DATA BITS 00 = 5 DATA BITS //
// 01 = 6 DATA BITS //
// 10 = 7 DATA BITS //
// 11 = 8 DATA BITS //
// //
// HS: HANDSHAKING OPTION 0 = NO HANDSHAKING (CONTROLLED EXTERNALLY) //
// 1 = LOCAL HANDSHAKING //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////////%
TITLE "Asynchronous Transmitter";
%//////////////////
// INCLUDE FILES //
//////////////////%
INCLUDE "lpm_dff.inc";
INCLUDE "lpm_mux.inc";
INCLUDE "lpm_counter.inc";
INCLUDE "clk_pdiv.inc";
INCLUDE "filterx.inc";
INCLUDE "par_gen.inc";
INCLUDE "shiftreg.inc";
%////////////////////////////
// USER-DEFINED PARAMETERS //
////////////////////////////%
PARAMETERS
(
FILTER_DEPTH -- Depth, (Number of Stages) in Digital Filters.
);
%/////////////////////
// INPUTS & OUTPUTS //
/////////////////////%
SUBDESIGN TX
(
CLK, RESET, CfgReg[6..0], TxReg[7..0], DIVISOR[16..0], TxSTART : INPUT; -- Controller Interface
TxEND, TxSTATUS : OUTPUT;
/CTS, /DSR : INPUT; -- /CTS & /DSR Inputs
CTSf, DSRf : OUTPUT; -- Inverted Filtered /CTS & /DSR Inputs
Tx : OUTPUT;
)
%//////////////////////////
// VARIABLE DECLARATIONS //
//////////////////////////%
VARIABLE
% INTERNAL VARIABLES %
TxCLK2 : NODE; -- Tx Baud Rate Clock x2
TxCLK, TxCkc : NODE; -- Tx Baud Rate Clock, CLEAR-Input
TxSR, TxSRd[7..0], TxSRe, TxSRl : NODE; -- Tx Data Shift Register, D-Inputs, ENA-Input, LOAD-Input
Txd : NODE; -- (Tx Output Flip-Flop), D-Input
MPLXi[3..0], MPLXs[1..0] : NODE; -- (Tx Output Multiplexer), DATA-Inputs, SEL-Inputs
TxCNT[4..0], TxCNTe, TxCNTc : NODE; -- Transmitter Bit Counter, ENA-Input, ACLR-Input
TxPar, TxPard[7..0] : NODE; -- Tx Parity, DATA-Input
TxENA : NODE; -- Tx Enable Signal
PARITY[1..0] : NODE; -- Parity Type
DATABITS[1..0] : NODE; -- Number of Data Bits
STOPBITS[1..0] : NODE; -- Number of Stop Bits
HANDSHAKE : NODE; -- Handshaking Type
% STATE MACHINES %
Txss : MACHINE WITH STATES (Tx0, Tx1, Tx2, Tx3, Tx4, Tx5, Tx6, Tx7, Tx8); -- Transmitter
%//////////////////
// LOGIC SECTION //
//////////////////%
BEGIN
% DEFAULT VALUES %
DEFAULTS
TxCkc=GND;
TxSRe=GND; TxSRl=GND;
TxCNTe=GND; TxCNTc=GND;
TxEND=GND;
END DEFAULTS;
% IN-LINE ASSIGNMENTS %
TxCLK2 = Clk_PDiv (CLK, DIVISOR[],, RESET # TxCkc) -- Tx Baud Clock x2
WITH (WIDTH=17)
RETURNS (.out);
TxCLK = LPM_DFF (!TxCLK, TxCLK2,,,,,,, RESET # TxCkc,,) -- Tx Baud Clock
WITH (LPM_WIDTH=1)
RETURNS (.q[]);
Tx = LPM_DFF (Txd, TxCLK,,,,,,,, RESET # Tx0,) -- Tx Output Flip-Flop
WITH (LPM_WIDTH=1)
RETURNS (.q[]);
CTSf = FILTERX (CLK, /CTS, RESET,) -- Inverted Filtered /CTS Input
WITH (WIDTH=1, DEPTH=FILTER_DEPTH)
RETURNS (./S_OUT[]);
DSRf = FILTERX (CLK, /DSR, RESET,) -- Inverted Filtered /DSR Input
WITH (WIDTH=1, DEPTH=FILTER_DEPTH)
RETURNS (./S_OUT[]);
TxSR = ShiftReg (TxCLK, TxSRd[], RESET, TxSRl, TxSRe, GND) -- Tx Output Shift Register
WITH (WIDTH=8, MSB_FIRST="NO", SHIFT_MODE="ON")
RETURNS (.dout);
Txd = LPM_MUX (MPLXi[3..0], MPLXs[1..0],,) -- Tx Output Multiplexer
WITH (LPM_WIDTH=1, LPM_SIZE=4, LPM_WIDTHS=2)
RETURNS (.result[]);
TxCNT[] = LPM_COUNTER (0, TxCLK2,, TxCNTe,, RESET # TxCNTc,,,,,,,) -- Tx Bit Counter
WITH (LPM_WIDTH=5, LPM_DIRECTION="UP")
RETURNS (.q[]);
TxPar = Par_Gen (TxPard[7..0]) -- Tx Parity Generator
WITH (WIDTH=8)
RETURNS (.odd/even);
TxENA = LPM_DFF (VCC, CLK, GND,,,,,, RESET # Tx1, TxStart,) -- Tx Enable Signal
WITH (LPM_WIDTH=1)
RETURNS (.q[]);
TxSTATUS = LPM_DFF (VCC, CLK, TxEND,,,,,, RESET # TxStart,,) -- Tx Data Transmitted Flag
WITH (LPM_WIDTH=1)
RETURNS (.q[]);
% COMBINATORIAL LOGIC %
PARITY[]=CfgReg[1..0]; -- UART Control Bits
STOPBITS[]=CfgReg[3..2];
DATABITS[]=CfgReg[5..4];
HANDSHAKE=CfgReg[6];
IF (DATABITS[]==0) THEN TxPard[7..5]=0; TxPard[4..0]=TxReg[4..0]; END IF; -- Ignore High Bits in Parity Generator
IF (DATABITS[]==1) THEN TxPard[7..6]=0; TxPard[5..0]=TxReg[5..0]; END IF;
IF (DATABITS[]==2) THEN TxPard[7]=GND; TxPard[6..0]=TxReg[6..0]; END IF;
IF (DATABITS[]==3) THEN TxPard[7..0]=TxReg[7..0]; END IF;
MPLXi[0]=VCC; -- Assign Multilexer Inputs
MPLXi[1]=GND;
MPLXi[2]=PARITY[1] !$ TxPar;
MPLXi[3]=TxSR;
Txss.CLK = CLK; -- Tx State Machine Clock and Reset
Txss.RESET = RESET;
% TRANSMITTER STATE MACHINE %
CASE Txss IS
WHEN Tx0 =>
MPLXs[]=0; -- Select VCC
TxCkc=VCC; -- Clear Tx Clock
TxCNTc=VCC; -- Clear Tx Bit Counter
TxSRl=VCC; -- Enable Load of Tx Shift Register
TxSRd[7..0]=TxReg[7..0]; -- Setup Data Load for Tx Shift Register
IF (TxENA & ((HANDSHAKE & CTSf & DSRf) # !HANDSHAKE)) THEN -- Wait until New Tx Data and CTS/DSR
Txss=Tx1;
ELSE Txss=Tx0; END IF;
WHEN Tx1 => -- Clear Tx Enable Signal
Txss=Tx2;
WHEN Tx2 =>
MPLXs[]=1; -- Select GND
TxCNTe=VCC; -- Enable Tx Bit Counter
IF (TxCNT[]==2) THEN Txss=Tx3; -- Wait until Start Bit shifted out
ELSE Txss=Tx2; END IF;
WHEN Tx3 =>
MPLXs[]=3; -- Select Data
TxSRe=VCC; -- Shift out Data
TxCNTe=VCC; -- Enable Tx Bit Counter
IF ((DATABITS[]==0 & TxCNT[]==12)
# (DATABITS[]==1 & TxCNT[]==14)
# (DATABITS[]==2 & TxCNT[]==16)
# (DATABITS[]==3 & TxCNT[]==18)) THEN Txss=Tx4; -- Wait until all Data Bits Shifted out
ELSE Txss=Tx3; END IF;
WHEN Tx4 =>
TxCNTc=VCC; -- Clear Tx Bit Counter
IF (PARITY[]==0 # PARITY[]==3) THEN Txss=Tx7; -- Check if Parity Enabled
ELSE Txss=Tx5; END IF;
WHEN Tx5 =>
MPLXs[]=2; -- Select TxPar
TxCNTe=VCC; -- Enable Tx Bit Counter
IF (TxCNT[]==2) THEN Txss=Tx6; -- Wait until Parity Bit Shifted out
ELSE Txss=Tx5; END IF;
WHEN Tx6 =>
TxCNTc=VCC; -- Clear Tx Bit Counter
Txss=Tx7;
WHEN Tx7 =>
MPLXs[]=0; -- Select VCC
TxCNTe=VCC; -- Enable Tx Bit Counter
IF ((STOPBITS[]==0 # STOPBITS[]==3) & TxCNT[]==2) THEN Txss=Tx8; -- Wait until Stop Bit 1 Shifted out
ELSIF (STOPBITS[]==1 & TxCNT[]==3) THEN Txss=Tx8; -- Wait until Stop Bit 1.5 Shifted out
ELSIF (STOPBITS[]==2 & TxCNT[]==4) THEN Txss=Tx8; -- Wait until Stop Bit 2 Shifted out
ELSE Txss=Tx7; END IF;
WHEN Tx8 =>
TxCkc=VCC; -- Clear Tx Clock
TxEND=VCC; -- Set Tx End Flag
Txss=Tx0;
END CASE;
END;