"
module P2082A

title 'P2082A'

"Version 1"

"[24-FEB-15] Start with P2075A05.abl. We change pin assignments. We remove RST"
"the power-up reset. We are going to rely on the chip's internal power-up reset"
"to clear all registers to zero. We have support for CCD1 and CCD2 and ON1..ON4."
"We select the TB resistor to make sure the instrumentation amplifier output does"
"not saturate."

"Version 2"

"[31-MAR-15] We use DC14 and DC15 to select between four virtual devices within"
"the same circuit. Together, DC14 and DC15 are dev_sel. When 0 we select the"
"first of two dual-image sensorm, quad LED array devices. When 3 we select the"
"second such device. When 1 we select the octal thermometer. When 2 we selet a"
"data transceiver that we do not implement in this code."

"[03-APR-15] We increase the length of the HI pulse on H from 7 to 12 HCK periods."
"The commercial-grade 7.5-ns device has HCK period roughly 15 ns, so we now have"
"the pixel value being asserted for 180 ns instead of only 105 ns. We assert R for"
"two clock periods immediately after H goes LO. In quadruple-pixel readout, we now"
"allow two HCK periods for the initial HI and LO pulses, which greatly eases the"
"demands on the clock drivers."

"Version 3"

"[06-MAY-15] We make sure TSEL, TT, TB, T1..T4 are all 0V when the board is asleep."
"Otherwise, with gate bias applied to the mosfets, they suffer damage by 330 Gy of"
"ionizing radiatino and the RTD readout fails. With no bias, they survive to at least"
"1.6 kGy."


declarations

"Constants"
da_delay = 7; "CK periods to DA"
dda_delay = 16; "CK periods to DDA"
run_time = dda_delay+3; "CK periods to run"

"Inputs"
A pin 65; "LVDS Input"

"Outputs"
B pin 64 istype 'com'; "LVDS Output"
LB pin 67 istype 'com'; "Loop Back"			
WAKE pin 58 istype 'com'; "Wake"
TP1..TP3 pin 34,37,31 istype 'com';
!V1,!V2,!V3 pin 22,17,19 istype 'com'; "Vertical Clocks"
RDP pin 10 istype 'com'; "Read Pulse"
H1,H2 pin 15,16 istype 'com'; "Horizontal Clocks"
S1,S2 pin 14,11 istype 'com'; "Substrate Clocks"
R pin 9 istype 'com'; "Reset Clock"
!I1,!I2,I3,I4 pin 28,30,43,42 istype 'com'; "CCD Input Select"
IEN pin 29 istype 'com'; "CCD Enable"
ON1..ON4 pin 20,21,56,53 istype 'com'; "Turn On LEDs"
!TSEL pin 71 istype 'com'; "Select Temperature Sensor Readout"
T1..T4 pin 6, 8, 78, 72 istype 'com'; "Select Individual Temperature Sensors"
TT pin 69 istype 'com'; "Select Top Reference Temperature"
TB pin 70 istype 'com'; "Select Bottom Reference Temperature"

"Command Receiver Nodes"
SA node istype 'reg'; "Synchronized A"
DSA node istype 'reg'; "Delayed SA"
DA node istype 'reg'; "Delayed A Rising Edge"
DDA node istype 'reg'; "Delayed DA"
AA node istype 'reg'; "Address Active"
CA node istype 'reg'; "Command Active"
ER,Q1..Q16 node istype 'reg'; "Receiver Bits"
LT4..LT0 node istype 'reg'; "LWDAQ Timer"
lt = [LT4..LT0];
DS node istype 'com'; "Data Strobe"
DC1..DC16 node istype 'reg';"Device Command Bits"
DA0..DA15 node istype 'reg';"Device Address Bits"

"Ring Oscillator Notes"
RO1,RO2 node istype 'com,keep'; "Ring Oscillator"
CK node istype 'reg,keep'; "Clock"
RUN node istype 'reg,keep';
equations 


"Clock Generation"
"----------------"

"The RUN flag controls the ring oscillator. When the ring"
"oscillator runs, it causes lt to increment. When lt reaches"
"a threshold, we clear the RUN flag."
RUN.aclr = (lt == run_time);
RUN := 1;
RUN.clk = A;

"Here we generate our clock with a ring oscillator."
"The ring oscillator consists of two combinatorial gates."
RO1 = RO2;
RO2 = !RO1 & RUN;
CK.clk = RO1;
CK:=!CK;


"Command and Address Decoding"
"----------------------------"

"This LWDAQ receiver uses the 40-MHz data clock to generate"
"the DA and DDA signals. We synchronise the incoming serial"
"logic signal, A, with the data clock."


"We synchronize A with DCK, and provide a delayed"
"version of A that allows us to detect edges."
[SA,DSA].clk = CK;
SA := A;
DSA := SA;

"This timer allows us to generate the Delayed A (DA)"
"and Double-Delayed A (DDA) signals for serial reception."
lt.clk = CK;
lt.aclr = !RUN;
lt := lt+1;
DA.clk = !CK;
DA := (lt==da_delay);
DDA.clk = !CK;
DDA := (lt==dda_delay);

"The command or address bits enter a sixteen-bit shift register."
[ER,Q1..Q16].clk = DA;
[ER,Q1..Q16] := [SA,ER,Q1..Q15];

"Address Active, or AA, provides a pulse that begins with DDA"
"on the start bit of an address transmission, and ends with DDA"
"on the stop bit of an address transmission. We clock the receiver"
"bits into the address register on a rising edge of AS."
AA.clk = DDA;
AA := (!AA & !CA & !SA & !ER) # (AA & !SA);
[DA0..DA15].clk = !AA;
[DA0..DA15] := [Q1..Q16];

"Command Active, or CA, provides a pulse that begins with DDA"
"on the start bit of a command transmission, and ends with DDA"
"on the stop bit of a command transmission. We clock the receiver"
"bits into the command register on a rising edge of CS."
CA.clk = DDA;
CA := (!AA & !CA & !SA & ER) # (CA & !SA);
[DC1..DC16].clk = !CA;
[DC1..DC16] := [Q1..Q16];

"Data Strobe identifies a solitary low pulse on A. A"
"solitary low pulse, combined with DTX, indicates that"
"the drivers is expecting this device to upload eight"
"bits of data."
DS = DDA & SA & !AA & !CA;


"Generic Command Bit Allocation"
"------------------------------"

declarations
dev_sel = [DC15,DC14];
dual_ccd_A = 0;
dual_ccd_B = 3;
octal_rtd = 1;
data_tx = 2;
equations

"WAKE bit."
WAKE = DC8;

"We enable the return LVDS driver when DC7 is set."
LB = DC7;

"When the loopback bit is set, we send B back to A. When we"
"implement a data device, we will allow B to take on values"
"generated by a data transmitter state machine. For now, we"
"just set B = A always."
when LB then {
  B = A
} else {
  B = A
}


"CCD Devices"
"-----------"

"Here we define the behavior of the two dual-ccd, quad-led devices"
"provided by the Bar Head."

declarations
ccd_sel node istype 'com,keep'; "Select A CCD Device"
H node istype 'com'; "Horizontal Clock"
HCS0..HCS3 node istype 'reg'; "Horizontal Clock State"
hcs=[HCS3..HCS0];
HRO1,HRO2 node istype 'com,keep'; "Horizontal Ring Oscillator"
HCK node istype 'reg'; "Horizontal Clock"
HRUN node istype 'reg'; "Horizontal Clock Run"
equations

ccd_sel = ((dev_sel == dual_ccd_A) # (dev_sel == dual_ccd_B));

"The read pulse, substrate clock, and vertical phases are shared by"
"both dual_ccd_A and dual_ccd_B. These signals we receive directly"
"from the driver in the command bits. 
when WAKE & ccd_sel then {
  RDP = DC1;
  S1 = DC6;
  S2 = !DC6;
  V3 = DC5;
  V2 = DC4;
  V1 = DC3;
} else {
"When the dual ccd devices are not selected, and when the Bar Head is"
"asleep, we want all the ccd clock phase outputs to be zero so that we"
"do not drive any current into the level shifting op-amps. Phases V1-V3"
"are negated at the pins, so if we want a LO or 0 value at the pin, we"
"must set these to HI or 1."
  RDP = 0;
  S1 = 0;
  S2 = 0;
  V3 = 1;
  V2 = 1;
  V1 = 1;
}


"The Horizontal Ring Osicllator provides timing for the horizontal"
"clock of the image sensor. We use the same system we use for the"
"main ring oscillator. Here we start the ring when DC2 is set and
"we see a falling edge on A and we have selected one of the two"
"dual-ccd devices."
HRUN.aclr = (hcs == 15);
HRUN := 1;
HRUN.clk = !A & DC2 & ccd_sel;
HRO1 = HRO2;
HRO2 = !HRO1 & HRUN;
HCK.clk = HRO1;
HCK := !HCK;

"The Horizontal Clock state machine provides the timing we need"
"to generate the horizontal clock pulses and reset pulse."
hcs.clk = HCK;
hcs.aclr = !HRUN;
hcs := hcs+1;

"The H bit controls the horizontal clock phases. When DC2 is unasserted, we"
"always assert H, which drives H1 lo and H2 hi. This is the state we are in"
"during vertical transfer. But once DC2 goes hi, in preparation for horizontal"
"transfer, H will be unasserted for a while, until the first negative pulse on"
"SA clocks the first pixel into the output gate."
H = !DC2 
  # (hcs==1) 
  # (hcs==2) 
  # ((hcs==3)&!DC16)
  # ((hcs==4)&!DC16)
  # (hcs==5)
  # (hcs==6)
  # (hcs==7)
  # (hcs==8)
  # (hcs==9)
  # (hcs==10)
  # (hcs==11)
  # (hcs==12);

"When we create the horizontal clock outputs, we make sure they are 0V when"
"the board is alseep. The reset pulse follows the horizontal clock pulse."
when WAKE & ccd_sel then {
  H2 = H;
  H1 = !H;
  R = ((hcs==13) # (hcs==14));
} else {
  H2 = 0;
  H1 = 0;
  R = 0;
}


"We select no image sensor unless the Bar Head is awake and we have one of"
"the dual ccd devices selected. With dual_ccd_A we use DC9 to select between"
"image sensor one and two. With dual_ccd_B we do the same for image sensors"
"three and four."
when !WAKE # !ccd_sel then {
  I1 = 0;
  I2 = 0;
  I3 = 0;
  I4 = 0;
  IEN = 0;
}
when WAKE & (dev_sel == dual_ccd_A) then {
  I1 = DC9;
  I2 = !DC9;
  I3 = 0;
  I4 = 0;
  IEN = 1;
}
when WAKE & (dev_sel == dual_ccd_B) then {
  I1 = 0;
  I2 = 0;
  I3 = DC9;
  I4 = !DC9;
  IEN = 1;
} 

"We turn on no LED arrays when the board is asleep or no ccd device is selected"
"When we do select ccd device A, we map DC10-DC13 t108 have no output pins.
when !WAKE # !ccd_sel then {
  ON1 = 0;
  ON2 = 0;
  ON3 = 0;
  ON4 = 0;
"  ON7 = 0;
"  ON8 = 0;
"  ON9 = 0;
"  ON10 = 0;
}
when WAKE & (dev_sel == dual_ccd_A) then {
  ON1 = DC10;
  ON2 = DC11;
  ON3 = DC12;
  ON4 = DC13;
"  ON7 = 0;
"  ON8 = 0;
"  ON9 = 0;
"  ON10 = 0;
}
when WAKE & (dev_sel == dual_ccd_B) then {
  ON1 = 0;
  ON2 = 0;
  ON3 = 0;
  ON4 = 0;
"  ON7 = DC10;
"  ON8 = DC11;
"  ON9 = DC12;
"  ON10 = DC13;
} 

"When we select the octal rtd device, we direct the instrumentation"
"amplifier output to the R+/R- amplifier. When the board is asleep"
"we likewise select the instrumentation amplifier, which means !TSEL"
"is LO, which means there is no bias on transistor Q15's gate in"
"the A2082, which is necessary for radiation resistance."
when !WAKE # (WAKE & (dev_sel == octal_rtd)) then {
  TSEL = 1;
} else {
  TSEL = 0;
}

"We select the reference and rtd switches with DC1-5, DC9-DC13. We don't"
"implement T5-T8 in this code. We make sure that at least TB is selected"
"whenever the board is awake. When the board is asleep, all mosfet gates"
"should be at 0V."
when !WAKE then {
  TB = 0;
  TT = 0;
  T1 = 0;
  T2 = 0;
  T3 = 0;
  T4 = 0;
}
when WAKE & (dev_sel == octal_rtd) then {
  TB = DC1 # (!TT & !T1 & !T2 & !T3 & !T4);
  TT = DC2;
  T1 = DC3;
  T2 = DC4;
  T3 = DC5;
  T4 = DC9;
} 
when WAKE & (dev_sel != octal_rtd) then {
  TB = 1;
  TT = 0;
  T1 = 0;
  T2 = 0;
  T3 = 0;
  T4 = 0;
}


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

TP1 = CA;
TP2 = DDA;
TP3 = HCK;

end