TITLE "PU's control system. Piggy_back data transceiver control PLD";
% Author: A. Barreira Sevillano - CERN/PS Division - Geneve - Switzerland %

SUBDESIGN trx

(
%*********************************************************%
%  Transmitter - Transmitter - Transmitter - Transmitter  %
%*********************************************************%

Ser         : INPUT;    % Clock and NRZ data inputs %
/TXB        : OUTPUT;   % Tx 'busy' flag and strobe %
SOCP        : OUTPUT;   % Edges for the fifo serial output %
M           : OUTPUT;   % Manchester output %
/TXFE,/TXFF : INPUT;    % Tx Fifo 'empty' and 'full' flags %
/TXRS,/TXWR : OUTPUT;   % Tx Fifo reset and write signals %

%********************************************************%
%  Receiver - Receiver - Receiver - Receiver - Receiver  %
%********************************************************%

RXclk,Data  : INPUT;    % Clock and NRZ data inputs %
/RXB,/RS    : OUTPUT;   % Rx 'busy' flag and strobe %
Error       : OUTPUT;   % Rx error bit %
/RXFE,/RXFF : INPUT;    % Rx Fifo 'empty' and 'full' flags %
/RXRS,RXRD  : OUTPUT;   % Rx Fifo reset and read signals %
/RXOE       : OUTPUT;   % Rx fifo output enable %

%****************************************************%
%  Shift Register - Shift Register - Shift Register  %
%****************************************************%

SREG[15..0] : OUTPUT;   % 16 bit shift register for the receiver %

%***************************************************************%
%  VMOD I/O data transfer lines - VMOD I/O data transfer lines  %
%***************************************************************%

% Data transfer lines %
D15,D14    : BIDIR;    % Master reset - Loopback %
D13,D12    : BIDIR;    % Tx fifo clear - Rx fifo clear %
D11,D10,D9 : OUTPUT;   % Carrier - Tx ready - Rx ready %
D8,D7,D6   : OUTPUT;   % Rx error - Tx fifo full - Rx fifo full %
D5,D4      : OUTPUT;   % Tx fife empty - Rx fifo empty %
D3         : BIDIR;    % Tx busy/Start transmission %
D2         : OUTPUT;   % Rx busy %
D1,D0      : BIDIR;    % Tx interrupts enable - Rx interrupts enable %

% Data transfer control lines %
MA0        : INPUT;    % Least significant address line %
/EN0,/EN1  : INPUT;    % Enables %
/WRMOD     : INPUT;    % Write mode %
/RDMOD     : INPUT;    % Read mode %

%*******************************************************%
%  Others - Others - Others - Others - Others - Others  %
%*******************************************************%

Clk        : INPUT;    % 2MHZ clock from the VMOD I/O %
/Reset     : INPUT;    % VMEbus general hardware reset %
Carrier    : INPUT;    % Monitors the carrier detector %
LBin       : INPUT;    % Manchester in to the loopback switch %
LBout      : OUTPUT;   % Manchester out from the loopback switch %
)

VARIABLE

%*********************************************************%
%  Transmitter - Transmitter - Transmitter - Transmitter  %
%*********************************************************%

TXclk          : TFF;      % 2MHz -> 1MHz frequency divider %
TE,TD,TC,TB,TA : DFF;      % Tx state machine bits %
/TXRQ          : DFF;      % Transmission request %
TXParity       : TFF;      % Parity generator T_type Flip-flop %
SOCPena        : NODE;     % Symbolic name for 'Shift enable' %
sd             : NODE;     % Symbolic name for the output data stream %
m0             : MCELL;    % Manchester encoder auxiliary bit %
aux            : MCELL;    % Auxiliary bit for the edges generator %
/TXFC,/TXRS    : DFF;      % Tx fifo reset %

%********************************************************%
%  Receiver - Receiver - Receiver - Receiver - Receiver  %
%********************************************************%

RE,RD,RC,RB,RA : DFF;      % Rx state machine bits %
RXParity,Error : DFF;      % Parity detector and error bit %
FE             : DFF;      % Fifo empty conditions %
/RXFC,/RXRS    : DFF;      % Rx fifo reset %

%****************************************************%
%  Shift Register - Shift Register - Shift Register  %
%****************************************************%

SREG[15..0]    : DFF;      % 16-bits shift register %
Shift          : NODE;     % Shift register control %

%**********************************************************%
%  Control Register - Control Register - Control Register  %
%**********************************************************%

CWrite      : NODE;     % Write operation is going on %
CRead       : NODE;     % Read operation is going on %
M_Reset,/MR : DFF;      % Master reset sinchronization %
LB          : DFF;      % Loopback bit %
RXERR       : DFF;      % Receiver error %
                                                       

BEGIN

%*********************************************************%
%  Transmitter - Transmitter - Transmitter - Transmitter  %
%*********************************************************%

% Frecuency divider %
TXclk.clk = clk;   % Clk -> 2MHz clock from the VMOD I/O %
TXclk.T = VCC;     % TXclk -> 1MHz for TX %

% Transmission request %
/TXRQ.clk = !CWrite;
/TXRQ.D = !D3 # D15;          % Assert request %
/TXRQ.prn = /TXFE & /Reset;   % Remove request %

% Connect clock and reset lines %
(TE,TD,TC,TB,TA).clk = TXclk;
(TE,TD,TC,TB,TA).clrn = /Reset;   % Hardware reset %

% Define Tx state machine secuence %
TE.D = !TA & TE 
    # !TB & TE
    # !TC & TE
    # !TD & TE
    # TA & !TB;

TD.D = TD & TE
    # TA & TB & TC;

TC.D = !TB & TC & TE
    # !TA & TC & TE
    # TA & TB & !TC & TE
    # TD & !TE;

TB.D = !TA & TB & TE
    # TA & !TB & TE
    # !TA & !TB & !TD & !TE
    # TB & !TE & /TXRQ;

TA.D = !TA & TE
    # !TC & !TD & !TE;

% Transmitter 'busy' flag %
/TXB = !TE & !TD & !TC & TB & TA;  % Not busy only in 'Idle' state %

% Edges generator for the FIFO serial output %
SOCPena = TA & !TB # TE;       % SOCP enable symbolic name %

aux = TXclk                % Auxiliary bit %
  # SOCPena & aux;

SOCP = TXclk               % Output %
  # !aux 
  # !SOCPena & SOCP;

% Parity generator %
TXParity.clk = TXclk;
TXParity.T = TA & !TE & TXParity.Q    % Clear during 'Start' or 'Idle' state %
    # (TE # TD) & Ser;                % Toggle if serial data = 1 %
TXParity.clrn = /Reset & /MR;         % Hardware or software reset %

% NRZ output data frame definition %
sd = !TE & !TD & !TC & !TB & TA            % Start bit %
  # (TE # TD) & Ser                        % Data stream %
  # !TE & !TD & TC & !TB & !TA & TXparity; % Parity bit %

% Manchester encoder for such a frame %
M = m0 & TXclk                                 % Manchester output %
  # !m0 & !TXclk & sd
  # !m0 & M & !TXclk
  # m0 & M & sd
  # M & !TXclk & sd;

m0 = m0 & !M                               % Auxiliary bit %
  # m0 & TXclk
  # m0 & !sd
  # !M & !TXclk & !sd;

% Write operation on the Tx fifo %
/TXWR = !(!MA0 & !/EN0 & !/EN1 & !/WRMOD);

%********************************************************%
%  Receiver - Receiver - Receiver - Receiver - Receiver  %
%********************************************************%

% Connect clock and reset lines %
(RE,RD,RC,RB,RA).clk = RXclk;
(RE,RD,RC,RB,RA).clrn = /Reset;    % Hardware reset %

% Define Rx state machine secuence %
RE.D = !RA & RE 
    # !RB & RE
    # !RC & RE
    # !RD & RE
    # !RB & !RD & Data;

RD.D = RD & RE
    # RA & RB & RC;

RC.D = !RB & RC & RE
    # !RA & RC & RE
    # RA & RB & !RC & RE;

RB.D = RA & !RB & RE
    # !RA & RB & RE
    # RD & !RE;

RA.D = !RA & RE
    # !RA & RB;

% Receiver 'busy' flag %
/RXB = !RE & !RD & !RC & !RB & !RA;        % Not busy only in 'Idle' state %

% Receiver strobe %
!/RS = !RE & !RD & !RC & RB & !RA & !RXclk & !Error;  % No strobe if error %

% Parity detector %
RXParity.clk = RXclk;
RXParity.D = RE & (RXParity.Q $ Data);     % Toggle during data bits %
RXParity.clrn = /Reset & /MR;              % Hardware or software reset %

% Error bit %
Error.clk = RXclk;
Error.D = !RE & RD & (RXParity.Q $ Data)   % Set if parity error (parity state) %
    # !RE & RB & Data                      % Set if framing error (stop state) %
    # !/RXB & Error.Q;                     % Hold while receiving %
Error.clrn = /Reset & /MR;                 % Hardware or software reset %

% Rx FIFO empty flag update %
% The Rx fifo 'empty flag' is updated only after a pulse in the read
clock input (RDCLK). Thus, a pulse is to be asserted in such an input
whenever the fifo is empty and a write operation is done.
I use the 'FE' (fifo empty) bit to register any write operation on
the Rx fifo when it was empty. %
FE.clk = RXclk;
FE.D = !/RS & !/RXFE;      % Strobe has been applied and FIFO was empty %
FE.clrn = /Reset & /MR;     % Hardware or software reset %

% Read operation on Rx fifo %
% The first term or RXRD updates the read pointer of the fifo, the second one
serves to update the 'empty fifo' flag. The RXclk is included there to delay
the pulse for half a microsecond %
RXRD = !MA0 & !/EN0 & !/EN1 & !/RDMOD     % Data read operation %
     # FE.Q & !RXclk;                     % Flag update pulse %
/RXOE = !(!MA0 & !/EN0 & !/EN1 & !/RDMOD);

%****************************************************%
%  Shift Register - Shift Register - Shift Register  %
%****************************************************%

% This is a part of the receiver, used as a serial to
pararell converter. The 'Shift' symbolic name is the
only control line. The register holds the data while no
shifting %

Shift = RE;        % Shift enable %

% Connect clock and reset lines %
SREG[].clk = RXclk;
SREG[].clrn = /Reset & /MR;       % Hardware or software reset %

% Shift register %
SREG[15].D = SREG[15] & !Shift # SREG[14] & Shift;
SREG[14].D = SREG[14] & !Shift # SREG[13] & Shift;
SREG[13].D = SREG[13] & !Shift # SREG[12] & Shift;
SREG[12].D = SREG[12] & !Shift # SREG[11] & Shift;
SREG[11].D = SREG[11] & !Shift # SREG[10] & Shift;
SREG[10].D = SREG[10] & !Shift # SREG[9] & Shift;
SREG[9].D = SREG[9] & !Shift # SREG[8] & Shift;
SREG[8].D = SREG[8] & !Shift # SREG[7] & Shift;
SREG[7].D = SREG[7] & !Shift # SREG[6] & Shift;
SREG[6].D = SREG[6] & !Shift # SREG[5] & Shift;
SREG[5].D = SREG[5] & !Shift # SREG[4] & Shift;
SREG[4].D = SREG[4] & !Shift # SREG[3] & Shift;
SREG[3].D = SREG[3] & !Shift # SREG[2] & Shift;
SREG[2].D = SREG[2] & !Shift # SREG[1] & Shift;
SREG[1].D = SREG[1] & !Shift # SREG[0] & Shift;
SREG[0].D = SREG[0] & !Shift # Data & Shift;

%**********************************************************%
%  Control Register - Control Register - Control Register  %
%**********************************************************%

% Write operation on the control register %
CWrite = MA0 & !/EN0 & !/EN1 & !/WRMOD;

% Read operation on the control register %
CRead = MA0 & !/EN0 & !/EN1 & !/RDMOD;

% D15 - Master Reset %
% The master reset bit is first stored in a flip-flop and then
forwarded to a second one, for synchronization with some internal
logic. A low level in the output of the second stage clears the
first one %
M_RESET.clk = !Cwrite;        % First stage %
M_RESET.D = D15;              % D15 bit stored in the first stage %
M_RESET.clrn = /MR & /Reset;  % Clear when it's done or hardware reset %

/MR.clk = TXclk;              % Second stage %
/MR.D = !M_RESET.Q;         % Master reset %
/MR.prn = /Reset;           % Hardware reset %

D15 = TRI(GND,CRead);

% D14 - Loopback Enable %
% Loopback bit %
LB.clk = !CWrite;          % A write operation loads the bit %
LB.D = D14 & !D15;         % LB bit in the control register %
LB.clrn = /Reset;          % Hardware reset sets LB mode off %
D14 = TRI(LB.Q,CRead);     % Bidirectional pin %

% Loopback switch %
LBout = LB.Q & !M          % Loopback switch is on %
    # !LB.Q & LBin;        % Loopback switch is off %

% D13/D12 - Transmitter/Receiver FIFO's reset %
% For this I use four D-type flip-flops, two of them for each part,
transmitter and receiver. The first stage is synchronous with the
VME write access to the control register, and stores the FIFO CLEAR
REQUEST. The second stage uses the Tx clock as a time base, so that
the reset is applied to each fifo during one microsecond. This clears
the request in the first stage %

/TXFC.clk = !CWrite;       % Synchronous with a VME write access %
/TXFC.D = !D13 & !D15;     % Resets transmitter FIFO %
/TXFC.prn = /TXRS.Q;       % Asynchronous set when reset is applied %

/TXRS.clk = TXclk;         % Syncronous with the Tx clock %
/TXRS.D = /TXFC.Q;    % Forwards the reset to the fifo %
/TXRS.clrn = /Reset & /MR; % Hardware or software reset %

/RXFC.clk = !CWrite;       % Synchronous with a VME write access %
/RXFC.D = !D12 & !D15;     % Resets receiver FIFO %
/RXFC.prn = /RXRS.Q;       % Asynchronous set when reset is applied %

/RXRS.clk = TXclk;         % Syncronous with the Tx clock %
/RXRS.D = /RXFC.Q;    % Forwards the reset to the fifo %
/RXRS.clrn = /Reset & /MR; % Hardware or software reset %

D13 = TRI(GND,CRead);
D12 = TRI(GND,CRead);

% D11 - Carrier: Monitors the carrier detector %
D11 = TRI(!Carrier,CRead);

% D10/D9 - Transmitter Ready & Receiver Ready %
% TR is high when Tx is idle and it's fifo empty
RR is high when Rx is idle and it's fifo not empty %
                       
                      

D10 = TRI(GND,CRead);      % 3-State output %
D9 = TRI(GND,CRead);       % 3-State output %

% D8 - RXERR: Receiver error %
RXERR.clk = /RDMOD # !MA0 # /EN0 # /EN1;
RXERR.D = GND;             % Clear when reading the control register %
RXERR.prn = !Error.Q;      % Set whenever Error=1 in the receiver %
RXERR.clrn = /Reset & /MR; % Hardware or software reset %

D8 = TRI(RXERR,CRead);

% D7/D6 - Transmitter FIFO full & Receiver FIFO full %
D7 = TRI(!/TXFF,CRead);
D6 = TRI(!/RXFF,CRead);

% D5/D4 - Transmitter FIFO empty & Receiver FIFO empty %
D5 = TRI(!/TXFE,CRead);
D4 = TRI(!/RXFE,CRead);

% D3 - Transmitter busy/Start transmission %
D3 = TRI(!/TXB,CRead);      % Start transmission is implemented in the transmitter %

% D2 - Receiver busy %
D2 = TRI(!/RXB,CRead);

% D1/D0 - Unused %
D1 = TRI(GND,CRead);      % 3-State output %
D0 = TRI(GND,CRead);      % 3-State output %

END;