"
module P2087A title 'TCPIP-VME Interface (A2087)' "Compilation Notes: Be sure to merge the constraints in" "this file with those in the constraint file A2064F.lci." "The constraint file tells the compiler to set all I/O to" "3.3V CMOS, and to use slow slew rate. The slow slew rate" "causes less interference along the long tracks of the A2087" "printed circuit board." "Version 1: [05-AUG-19] Based on P2064F01. This version is a" "VME master with no support for interrupts or bus arbitration." declarations firmware_version_num=1; test_version=1; "set to 1 to compile the test code" hardware_id=87; "A2064 hardware identifier" hardware_version_num=1; "A2087A" "Connections to the RCM6700" !LNK pin 21; "Ethernet link from RCM" CD0..CD7 pin 51, 73, 52, 74, 57, 71, 58, 72 istype 'com'; "Control Data" CA0..CA5 pin 47, 59, 49, 60, 50, 61; "Control Address" !CDSIN pin 24; "control data strobe, unsynchronized" !CW pin 23; "control write" "Switches" !CSW pin 20; "configuration switch" !RESET pin 5 istype 'com'; "RESET switch input and RESET output" HV0..HV2 pin 16, 17, 18; "Hardware Version" "Indicators" !TP1..!TP8 pin 7, 8, 9, 10, 11, 12, 14, 15 istype 'com,pos'; BUSY pin 6 istype 'com'; VACT pin 19 istype 'com'; "VME Activity" EGRN pin 39 istype 'com'; "Ethernet Green, for power" EYLW pin 38 istype 'com'; "Ethernet Yellow, for activity" "Clock Inputs and Outputs" CLK0OUT pin 36 istype 'com'; CLK0IN pin 156; CLK2OUT pin 70 istype 'com'; CLK2IN pin 68; CKOUT pin 37 istype 'reg'; CK pin 154; FCK pin 66; "fast clock input, 80 MHz" "Internal VME Bus" VA0..VA7 pin 102, 103, 104, 105, 106, 107, 108, 109 istype 'com'; "vme address bus" !AEN0..!AEN4 pin 120, 123, 138, 85, 135 istype 'com'; "address latch output enable" ACK0..ACK4 pin 122, 124, 136, 87, 137 istype 'com'; "address latch clock" ADIR pin 86; "address latch direction" ADIRN pin 146; "address latch direction negated" VD0..VD7 pin 93, 94, 95, 96, 97, 98, 99, 100 istype 'com'; "vme data bus" !DEN0..!DEN3 pin 151, 162, 82, 80 istype 'com'; "data latch output enable" DCK0..DCK3 pin 152, 161, 84, 81 istype 'com'; "data latch clock" DDIR pin 83 istype 'com'; "data latch direction" "VME Control Lines" !DS0,!DS1 pin 142, 141 istype 'reg'; "vme data strobe outputs" !VDS0,!VDS1 pin 159, 160; "vme data strobe inputs" !DTACK pin 170; "vme data acknowledge" GQ3 pin 139 istype 'com, pos'; "assert data acknowledge" !AS pin 145 istype 'reg'; "vme address strobe output" !VAS pin 158; "vme address strobe input" !IACKIN pin 127; "vme interrupt acknowledge daisychain input" !IACKOUT pin 126 istype 'com'; "vme interrupt acknowledge daisychain output" !IACK pin 164; "interrupt acknowledge cycle input" GQ2 pin 125 istype 'com, pos'; "assert IACK" !IRQ7 pin 118; "interrupt request seven" GQ1 pin 121 istype 'com, pos'; "assert IRQ7" !BBSY pin 169; "vme bus busy" GQ7 pin 163 istype 'com, pos'; "assert BBSY" !BG3IN pin 147; "vme bus grant three input" !BG3OUT pin 150 istype 'com, pos'; "vme bus grant three output" !BR3 pin 171; "vme bus request three" GQ6 pin 140 istype 'com, pos'; "assert BR3" !BERR pin 165; "vme bus error' GQ5 pin 149 istype 'com, pos'; "assert BERR" !SYSRST pin 168; "vme system reset" GQ4 pin 148 istype 'com, pos'; "assert SYSRST" "Nodes" DBA0..DBA31 node istype 'reg,keep'; "slave driver base address" VAM0..VAM5 node istype 'reg,keep'; "vme address modifier" !LDA node istype 'reg,keep'; "local data access" BAZ node istype 'com,keep'; "base address zero" RCMOE node istype 'com,keep'; "rcm data output enable" RPD0..RPD7 node istype 'reg'; "ram portal virtual data" LRSEL node istype 'reg'; "local ram select" VSEL node istype 'com'; "vme select" VOE node istype 'com'; "drive the vme data bus VDB." CDS node istype 'reg'; "control data strobe, synchronized" "Constants" id_addr=0; "hardware id location (byte)" hv_addr=18; "hardware version number location (byte)" fv_addr=19; "firmware version number location (byte)" cs_addr=40; "configuration switch address (byte)" dba_addr=42;"driver base address location (byte)" vam_addr=46;"vme addr modifier location (byte)" ram_portal_addr=63; "ram portal address location" "Sets" control_addr=[CA5..CA0]; "control address" control_data=[CD7..CD0]; "control data" driver_base_addr=[DBA31..DBA0]; "slave driver base address" vme_addr_modifier=[VAM5..VAM0]; "vme address modifier" dba0=[DBA7..DBA0]; "first byte of vme address" dba1=[DBA15..DBA8]; "second byte of vme address" dba2=[DBA23..DBA16]; "third byte of vme address" dba3=[DBA31..DBA24]; "fourth byte of vme address" vme_data=[VD7..VD0]; "internal vme data bus" vme_addr=[VA7..VA0]; "internal vme address bus' ram_portal_data=[RPD7..RPD0]; "ram portal virtual data" equations "Clocks" "======" "We divide FCK from 80MHz to 40 MHz. We use CKOUT, which is connected" "externally to the CK input. So CK s 40 MHz and symmetric." CKOUT.clk = FCK; CKOUT := !CKOUT; "RCM to Controller Interface" "===========================" "We synchronize the RCM6700 data strobe with CK." CDS.clk = CK; CDS := CDSIN; "We drive the RCM data lines on any Control Interface read." RCMOE = !CW & CDS; control_data.oe = RCMOE; "The control_data is equal to the vme_data only when the master is" "communicating with a slave. We clock VSEL on the falling edge" "of CK because CDS and LDA are clocked on the rising edge." VSEL = CDS & !CW & !LDA; when VSEL then control_data=vme_data.pin; "We drive the VME data lines on any Control Interface write." VOE = CW & CDS; vme_data.oe = VOE; when CW then vme_data=control_data.pin; "We access the local ram portal when we read from the ram" "portal address with the local base address." LRSEL.clk = !CK; LRSEL := CDS & !CW & LDA & (control_addr==ram_portal_addr); when LRSEL then control_data=ram_portal_data; "VME Interface Configuration" "===========================" "We arrange the bytes of the VME Base Address in big-endian order" "within the Controller's address space." driver_base_addr.clk=CK; driver_base_addr.aclr=RESET; when CDS & CW & (control_addr==dba_addr+3) then dba0:=control_data.pin; else dba0:=dba0.fb; when CDS & CW & (control_addr==dba_addr+2) then dba1:=control_data.pin; else dba1:=dba1.fb; when CDS & CW & (control_addr==dba_addr+1) then dba2:=control_data.pin; else dba2:=dba2.fb; when CDS & CW & (control_addr==dba_addr+0) then dba3:=control_data.pin; else dba3:=dba3.fb; vme_addr_modifier.clk=CK; when RESET then vme_addr_modifier:=^h3D else { when CDS & CW & (control_addr==vam_addr) then vme_addr_modifier:=[CD5..CD0].pin; else vme_addr_modifier:=vme_addr_modifier; } "Base address zero helps our logic compiler." BAZ = (driver_base_addr==0); "We access local data when the driver base address is zero," "or we write to the driver base address or the vme modifier." LDA.clk = CK; LDA := BAZ # (control_addr==dba_addr+3) # (control_addr==dba_addr+2) # (control_addr==dba_addr+1) # (control_addr==dba_addr+0) # (control_addr==vam_addr); "VME Address Buffers" "===================" "VME Address buffers are set to place the address bits onto" "the VME backplane in realtime and function as outputs only." "A is the output from this chip, B is the address on the" "backplane." ADIR=1; "set buffer direction A->B" ADIRN=!ADIR; "negated version of ADIR" ACK0=0; "never clock data into A0-A7" ACK1=0; "never clock data into A8-A15" ACK2=0; "never clock data into A16-A23" ACK3=0; "never clock data into A24-A31" ACK4=0; "never clock data into AM5-AM0. !WRITE, !LWORD" AEN0=1; "always drive A0-A7" AEN1=1; "always drive A8-A15" AEN2=1; "always drive A16-A23" AEN3=1; "always drive A24-A31" AEN4=1; "always drive AM5-AM0. !WRITE, !LWORD" "VME Data Buffers" "===============" "The VME data buffers drive the VME data lines on RCM" "write cycles, and drive the controller data lines on" "read cycles." DDIR=CW; "The VA0 bit is a virtual one we use to stop us getting" "confused about two-byte, one-byte, and four-byte read" "cycles." VA0=CA0; "The VME data strobes are VDS0 and VDS1. We activate" "them whenever we have CDS from the RCM and the access" "is not local. We clock with the falling edge of CK" "because CDS and LDA are clocked on the rising edge." "Our firmware supports only byte-wise reads from the VME" "address space. The code below prohibits DS0 and DS1 from" "being asserted at the same time." [DS0,DS1,AS].clk = !CK; when CDS & !LDA then { DS0 := VA0; DS1 := !VA0; AS := 1; } "We enable the VME data buffers whenever we have VME" "data strobes to match. Right now we have only single-byte "transfers enabled." DEN0=DS0; DEN1=DS1; DEN2=0; DEN3=0; "We clock outgoing data into our 74646 buffers with the" "following two signals on VME write cycles. The data must" "be valid at the rising edge of these clocks, having passed" "from the RCM through the controller to the buffer." DCK0=DS0; DCK1=DS1; DCK2=0; DCK3=0; "Interrupt Handling" "==================" "We do not assert IACK." GQ2=0; "We do not request an interrupt, so we don't assert IRQ7.' GQ1=0; "We forward IACKIN to IACKOUT." IACKOUT=IACKIN; "Bus Arbitration" "===============" "We assume we are the only master. Assert BBSY." GQ7=1; "We will implement bus error later. For now, don't assert it.' GQ5=0; "We forward BG3IN to BG3OUT." BG3OUT=BG3IN; "We do not assert bus request three BR3." GQ6=0; "Readback Registers" "=================" when CDS & !CW & LDA & (control_addr==cs_addr) then control_data=[0,0,0,0,0,0,0,!CSW]; when CDS & !CW & LDA & (control_addr==fv_addr) then control_data=firmware_version_num; when CDS & !CW & LDA & (control_addr==id_addr) then control_data=hardware_id; when CDS & !CW & LDA & (control_addr==hv_addr) then control_data=hardware_version_num; "The local ram portal provides virtual data for" "a local ram portal. Every time we read from the" "local ram portal at address ram_portal_addr, the" "data increments by one." ram_portal_data.aclr = RESET; ram_portal_data.clk = LRSEL; ram_portal_data := ram_portal_data + 1; "LEDs" "====" "We always turn on the green RJ-45 socket light to show power." EGRN=1; "We flash the yellow RJ-45 light with activity." EYLW=LNK; "The LEDs provide diagnostic signals. The test point" "LEDs have pins on the board you can use with a scope" "probe." when (!CSW # !RESET) & (test_version!=1) then { BUSY = CDS; VACT = DS0 # DS1 TP1 = CSW; TP2 = VD0; TP3 = CD0; TP4 = CW; TP5 = CDS; TP6 = DS0 # DS1; TP7 = CDS & (control_addr==ram_portal_addr); TP8 = VSEL; } declarations T24..T0 node istype 'reg'; "timer" timer=[T24..T0]; "timer" countbits=[T24..T21]; "top timer bits" equations "The test firmware creates a moving spot of light" "on the front panel LEDs. The spot changes direction" "when you press the configuration switch, and stops" "when you press reset." "Because this timer just counts up, we can define it" "as one counter and trust that the compiler will figure" "out that it can implement the counter with T-type" "flip-flops and no fancy logic." timer.clk=CK; timer.aclr=RESET; timer:=timer+1; "We use the counter top four bits to drive the LEDs." when !CSW & (test_version==1) then { BUSY=(countbits==13); VACT=(countbits==12); TP1=(countbits==11); TP2=(countbits==10); TP3=(countbits==9); TP4=(countbits==8); TP5=(countbits==7); TP6=(countbits==6); TP7=(countbits==5); TP8=(countbits==4); } "We change direction when we press the CSW switch." when CSW & (test_version==1) then { BUSY=(countbits==6); VACT=(countbits==7); TP1=(countbits==8); TP2=(countbits==9); TP3=(countbits==10); TP4=(countbits==11); TP5=(countbits==12); TP6=(countbits==13); TP7=(countbits==14); TP8=(countbits==15); } end