"

" Copyright (C) 2017 Kevan Hashemi, Brandeis University

" This program is free software; you can redistribute it and/or modify
" it under the terms of the GNU General Public License as published by
" the Free Software Foundation; either version 2 of the License, or
" (at your option) any later version.

" This program is distributed in the hope that it will be useful,
" but WITHOUT ANY WARRANTY; without even the implied warranty of
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
" GNU General Public License for more details.

" You should have received a copy of the GNU General Public License
" along with this program; if not, write to the Free Software
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


"This firmware defines the behavior of U32 on the A2071A, the"
"VME Interface protion of the VME-resident LWDAQ Driver. It acts as an"
"intermediary between the VME backplane and the LWDAQ Controller, which"
"is U1 on the same circuit."

"Version 1 [15-JUN-17] Fully functional."

"Version 2 [11-NOV-19] The VME backplane SYSRST, which appears as VRST in this"
"code, now asserts HRST on the rest of the A2071A, allowing us to use SYSRST"
"to reset all drivers in a crate."

module P2071A

title 'VME Interface for LWDAQ Driver'

declarations

firmware_version=2;
relay_hardware_id=71;


"Interface with Controller"
!ATY pin 19 istype 'com'; "VME Activity to Controller's !ATY input"
!BSO pin 20 istype 'com'; "Board Select to Controller's !BS input"
CA0..CA5 pin 15, 10, 14, 9, 11, 8 istype 'com'; "Control Address to Controller"
!CW pin 17 istype 'com'; "Control Write to Controller"
!CDS pin 16 istype 'reg'; "Data Strobe to Controller"
CD0..CD7 pin 29, 6, 28, 5, 22, 4, 21, 3 istype 'com'; "Data to/from Controller"

"Test Points"
TP1..TP3 pin 72, 69, 66 istype 'com,pos'; "Test Point with pad"

"VME Backplane"
VD0..VD7 pin 97, 94, 93, 92, 91, 87, 86, 85 istype 'com'; "Data to/from VME"
VA16..VA23 pin 38, 39, 42, 44, 48, 53, 55, 58; "Address from VME"
VA1..VA5 pin 30, 31, 34, 35, 36 istype 'com'; "Address from VME"
VAM0..VAM5 pin 56, 54, 47, 43, 37, 60; "Address Modifier from VME"
BA16..BA23 pin 65, 23, 27, 12, 73, 77, 88, 89; "Board Address from S3"
VACK pin 49 istype 'reg'; "VME Data Acknowledge"
!VRST pin 64; "VME Reset"
!HRST pin 71 istype 'com'; "Hardware Reset I/O"
!WRITE pin 59; "VME Write"
VDCK0, VDCK1 pin 84, 100 istype 'reg'; "VME Data Clock"
!VDEN0, !VDEN1 pin 80, 98 istype 'com'; "VME Data Enable"
VDIR0, VDIR1 pin 81, 99 istype 'com'; "VME Data Direction"
!DS0, !DS1 pin 61, 62; "VME Data Strobe"
!VAS pin 50; "VME Address Strobe";
!IACK pin 41; "VME Interrupt Acknowledge"


"Nodes"
VA0 node istype 'reg'; "VME Address Bit Zero"
R1..R4 node istype 'com,keep'; "Ring Oscillator"
CK node istype 'reg'; "Clock"
VDS0, VDS1 node istype 'reg'; "Synchronized VME Data Strobes"
VCCS0..VCCS4 node istype 'reg,keep'; "vme cycle controller state"
VW node istype 'reg'; "VME Latched Write"
RST node istype 'com,keep'; "Reset"
!BS node istype 'reg,keep'; "Board Select"

"Sets"
control_data=[CD7..CD0];
control_addr=[CA5..CA0];
vme_data=[VD7..VD0];
vme_addr_lo=[VA5..VA0];
vme_addr_hi=[VA23..VA16];
addr_modifier=[VAM5..VAM0];
base_addr=[BA23..BA16];
vcc_state=[VCCS4..VCCS0];

"Constants"


equations

"Reset"
"-----"

"Either the VME or the local hardware reset will reset this logic."
RST = VRST # HRST;

"If we get VRST, we assert HRST. Otherwise HRST acts as our reset input."
HRST.oe = VRST;
HRST = VRST;


"Ring Oscillator"
"---------------"

"Our ring oscillator runs continuously, but is reset on power-up by the"
"circuit board !RESET signal. With five gates, the ring runs with a period"
"of 15 ns, implying a gate delay of 15 / 5 / 2 = 1.5 ns, and providing"
"a CK period of 30 ns for CK frequency 33 MHz. With four gates, the CK"
"period is 23 ns. From DS on the VME backplane to DTACK is 160 ns."
[R1..R4] = [!R4 & !RST,R1..R3];
CK.aclr = RST;
CK.clk = R1;
CK := !CK;


"Board Select"
"------------"

"Board select is asserted when we have an address match, the"
"VME address modifiers are correct, and it's not an interrupt."
"We ignore the VME LWORD 32-bit data read flag."
BS.clk = !CK;
BS.aclr = RST;
BS := (base_addr==vme_addr_hi) "A23..A16 match our base address"
    & (  (addr_modifier==^h39) "24-bit non-privileged access"
       # (addr_modifier==^h3D) ) "24-bit supervisory access"
    & !IACK; "Don't respond to interrupt acknowledge"

"We synchronize the data strobes with the internal clock."
VDS0.aclr = RST;
VDS1.aclr = RST;
VDS0.clk = !CK;
VDS1.clk = !CK;
VDS0 := DS0;
VDS1 := DS1;


"VME Cycle Controller"
"--------------------"

"The VME interface is data-strobe controlled, so we do not use"
"the address strobe (AS). Nevertheless, AS is connected to the"
"A2037 to support it's later use as a VME master."

declarations
vcc_rest   =^h00;
vcc_byte_01=^h01;
vcc_byte_02=^h02;
vcc_byte_03=^h03;
vcc_byte_04=^h04;
vcc_byte_05=^h05;
vcc_byte_06=^h06;
vcc_byte_11=^h11;
vcc_byte_12=^h12;
vcc_byte_13=^h13;
vcc_byte_14=^h14;
vcc_byte_15=^h15;
vcc_byte_16=^h16;
vcc_terminate=^h1F;
equations

"We clock the state machine with CK, and clear it on RST."
vcc_state.clk = CK;
vcc_state.aclr = RST;

"The VME cycle controller generates the signals expected by"
"the LWDAQ controller for reading and writing from RAM and"
"status and control registers."
state_diagram vcc_state;
  state vcc_rest:
    if VDS0 & BS then vcc_byte_01;
    if VDS1 & BS then vcc_byte_11;
    if (!VDS0 & !VDS1) # !BS then vcc_rest;

  state vcc_byte_01:goto vcc_byte_02;
  state vcc_byte_02:goto vcc_byte_03;
  state vcc_byte_03:goto vcc_byte_04;
  state vcc_byte_04:goto vcc_byte_05;
  state vcc_byte_05:goto vcc_byte_06;
  state vcc_byte_06:
    if VDS1 then vcc_byte_11;
    else vcc_terminate;

  state vcc_byte_11:goto vcc_byte_12;
  state vcc_byte_12:goto vcc_byte_13;
  state vcc_byte_13:goto vcc_byte_14;
  state vcc_byte_14:goto vcc_byte_15;
  state vcc_byte_15:goto vcc_byte_16;
  state vcc_byte_16:goto vcc_terminate;

  state vcc_terminate:
    if !VDS0 & !VDS1 then vcc_rest;
    else vcc_terminate;
equations


"VME Interface"
"-------------"

"VACK drives !DTACK through a mosfet."
VACK.clk = !CK;
VACK := (vcc_state==vcc_terminate) 
    # ((vcc_state==vcc_byte_06) & !VDS1)
    # (vcc_state==vcc_byte_16);

"We construct VME address bit zero for single and two-byte reads."
VA0.clk = !CK;
VA0 := (vcc_state>=vcc_byte_01) & (vcc_state<=vcc_byte_06);

"VW is a latched version of the VME WRITE signal. VW holds"
"the value of WRITE set up at the beginning of a VME cycle"
"until the cycle ends."
VW.clk = !CK;
when ((vcc_state==vcc_byte_01) # (vcc_state==vcc_byte_11)) then VW := WRITE
else VW := VW;

"VDCKx clocks data byte x into the output buffers as early as"
"possible during a VME cycle."
VDCK0.clk = !CK;
VDCK1.clk = !CK;
VDCK0 := (vcc_state == vcc_byte_05) & !VW;
VDCK1 := (vcc_state == vcc_byte_15) & !VW;

"The VDENx signals enable the VME data buffers. On read cycles,"
"these buffers must drive the data lines even after the address lines"
"have started to change in anticipation of the next cycle."
VDEN0 = (vcc_state != vcc_rest) & (!VW # VA0);
VDEN1 = (vcc_state != vcc_rest) & (!VW # !VA0);

"VDIR drives the DIR input of the data buffers."
VDIR0 = !VW;
VDIR1 = !VW;


"Controller Interface"
"--------------------"

"The control address is made up of VA1..VA5 as well as the VA0"
"we constructed above."
control_addr = vme_addr_lo;

"Control Data Strobe we assert to read and write from the"
"LWDAQ controller."
CDS.clk = !CK;
CDS := ((vcc_state>=vcc_byte_02) & (vcc_state<=vcc_byte_04))
  # ((vcc_state>=vcc_byte_12) & (vcc_state<=vcc_byte_14));

"Control Write is the same as the latched VME Write."
CW = VW;

"We enable control data outputs on write cycles."
control_data.oe = VW;

"The internal control data is equal to the value of the"
"VME data pins."
control_data = vme_data.pin;

"We enable vme data outputs on read cycles."
vme_data.oe = !VW;

"The VME data is equal to the value of the control data"
"pins."
vme_data = control_data.pin;


"VME Activity Indicator"
"----------------------"

"The activity flag is asserted for 65535 CK periods whenever a VME"
"read or write occurs. The cycle itself takes only a dozen cycles,"
"but the time between cycles may be large, depending upon the speed"
"of our VME-TCPIP interface, so we stretch out the duration of the"
"flag to make sure the front panel light shines brightly."

declarations
  AT0..AT15 node istype 'reg'; "Activity Timer"
  activity_timer_hi = [AT15..AT8];
  activity_timer_lo = [AT7..AT0];
  activity_timer = [AT15..AT0];
  ATC,ATR node istype 'com,keep';
equations

activity_timer.aclr = RST;
activity_timer.clk = CK;

ATR = (activity_timer != 0) # (vcc_state != vcc_rest);
when ATR then {
  activity_timer_lo := activity_timer_lo + 1;
} else {
  activity_timer_lo := activity_timer_lo;
}

ATC = (activity_timer_lo == ^hFF);
when ATC then {
  activity_timer_hi := activity_timer_hi + 1;
} else {
  activity_timer_hi := activity_timer_hi;
}

ATY = (activity_timer != 0);

BSO = BS;


"Test Points"
"-----------"

TP1 = CDS;
TP2 = CK;
TP3 = VDS0 # VDS1;


end