%interfacing PU_VME port% subdesign PU_port2 ( clk, /reset, % soft reset from vme_port1.tdf% vmeadd[13..6], %vme address as command% vmedatain[31..0], %latched vme data from vme_port.tdf% vme_r/w, % retimed vme write from vme_port% ST[5], %vme sequential control from vme_port.tdf% PU_RDY %PU_RDY FROM PU MODULE, FROM PU_VME% :input; PU_DAT[7..0], %PU_DAT[] FROM/TO VME FPGA% PU_/DS %data strobe to or from PU% :BIDIR; PU_READBACK[31..0], %VME READ BACK DATA FROM PU% ADD[3..0], %VME ADDRESS TO PU_VME% R/W, %VME R/W TO PU_VME, START at time of ST9 % /CS, %CHIP SELECT TO PU_VME% /RST, %/RESET TO PU_VME% PU_BSY %PU BSY FLAG TO VME_PORT% :OUTPUT; ) VARIABLE SEL :lcell; CNTW[2..0] :DFF; %VME WRITE SEQUENTIAL CONTROL % PU_DATW[7..0] :TRI; %TRI-BUFFER FOR VME DATA BYTES WRITE TO PU% PU_DSNW :TRI; %TRI0BUFFER FOR PU_/DSN TO PU% FRAME_W :DFF; %ENABLE CNTW FROM S==S5 TO CNTW[]==4% DRW :DFF; %retimed vme_r/w for control% DREGA[7..0] :DFF; DREGB[7..0] :DFF; DREGC[7..0] :DFF; DREGD[7..0] :DFF; DCOPY[31..0] :DFFE; %READ BACK DATA STORE REGISTER, click data at cntr[]==4% HLD :NODE; %HOLD NEXT VME DATA/ADD TRANSFER% TT :TFF; %USED TO GENERATE PU_/DS TO PU% DCLR : dff; %generate REGISTER clrn for CNTW[],CNTR[] AND DRW% CNTR[2..0] :DFF; %VME READ SEQUENTIAL CONTROL% FRAME_R :DFF; %ENABLE CNTR[] FROM ST[5] TO CNTR[]==4% BEGIN %PU SELECT% SEL = (VMEADD[13..11] == 1); /CS = !SEL; %RESET to PU_VME% IF (VMEADD[13..11] == 1) & (VMEADD[10..6] == 9) THEN /RST = !VMEDATAIN[0]; %BIT0 IS SET WHEN RESET PU% ELSE /RST = VCC; END IF; %pu_BSY TO VME_PORT% PU_BSY = !PU_RDY # HLD; HLD = FRAME_W.Q # FRAME_R.Q; %VMEADD TO PU_VME% ADD[3..0] = VMEADD[9..6]; %vmeadd[10] is not used% %R/W TO PU_VME% DRW.CLK = CLK; DRW.CLRN = DCLR; DRW.D = !vme_r/w; R/W = VME_R/W; %NEW, EXTEND PU'S R/W TO THE END OF WRITE CYCLE% %pu_dat BYTE WRITE/READ SEQUENTIAL CONTROL % FRAME_W.CLK = CLK; FRAME_W.CLRN = /RESET; FRAME_W.D = ST[5] & !vme_r/w & PU_RDY & SEL # FRAME_W.Q & !(CNTW[]==4); %SERVED AS A write FRAME TO ENABLE W OPERATION% CNTW[2..0].CLK = TT; CNTW[].CLRN = DCLR.Q; IF FRAME_W THEN CNTW[2..0].D = CNTW[].Q +1; ELSE CNTW[].D = CNTW[].Q; END IF; FRAME_R.CLK = CLK; FRAME_R.CLRN = /RESET; FRAME_R.D = (ST[5] & vme_r/w & SEL & PU_RDY # FRAME_R & !(CNTR[]==4)); CNTR[2..0].CLK = !pu_/ds & !drw; CNTR[].CLRN = DCLR.Q; IF FRAME_R THEN CNTR[].D = CNTR[].Q +1; ELSE CNTR[].D = CNTR[].Q; END IF; DCLR.CLK = CLK; DCLR.CLRN = /RESET; DCLR.D = ST[5] # FRAME_W.Q # FRAME_R; %VME DATA BYTES WRITE to PU% PU_datW[7..0].IN = (CNTW[]==1) & VMEDATAIN[31..24] %highest vme byte goes out first% # (CNTW[]==2) & VMEDATAIN[23..16] # (CNTW[]==3) & VMEDATAIN[15..8] # (CNTW[]==4) & VMEDATAIN[7..0]; PU_DATW[7..0].OE = !vme_r/w; PU_DAT[] = PU_DATW[].OUT; TT.CLK = CLK; TT.CLRN = FRAME_W.Q; TT.T = drw; PU_DSNW.OE = !vme_r/w; pu_dsnW.IN = TT.Q # (cntw[]==0) ; PU_/DS = PU_DSNW.OUT; %VME READ BACK% DREGA[7..0].CLK = !PU_/DS; DREGA[].CLRN = R/W; DREGA[7..0].D = PU_DAT[7..0]; %first in byte goes to the highest POSITION of dcopy% DREGB[7..0].CLK = !PU_/DS; DREGB[].CLRN = R/W; DREGB[].D = DREGA[7..0]; DREGC[7..0].CLK = !PU_/DS; DREGC[].CLRN = R/W; DREGC[].D = DREGB[7..0]; DREGD[7..0].CLK = !PU_/DS; DREGD[7..0].CLRN = R/W; DREGD[7..0].D = DREGC[7..0]; DCOPY[31..0].CLK = CLK; %TRIGGED ON PU_/DS'S RISING EDGE% DCOPY[31..0].CLRN = /RESET; DCOPY[31..0].ENA = (CNTR[]==4); DCOPY[31..24].D = DREGD[7..0].Q; DCOPY[23..16].D = DREGC[7..0].Q; DCOPY[15..8].D = DREGB[7..0].Q; dcopy[7..0].D = DREGA[7..0].Q; PU_READBACK[31..0] = DCOPY[31..0].Q; END;