"
module P3008A
title 'P3008A'
"Verion 2, Last Modified 05-JAN-07"
"Pins"
declarations
A pin 3; "LVDS input"
B pin 19 istype 'com'; "LVDS output"
LB pin 16 istype 'com'; "Loop Back"
!RESET pin 22;"RESET"
RCK pin 93; "32 kHz reference clock input"
!CSD pin 70; "Chip Select for DAC"
SCLKD pin 71; "Serial Clock for DAC"
DIND pin 72; "Data In for DAC"
FSD pin 69; "Frame Synch for DAC"
LOEN pin 67; "Local Oscillator Enable"
COEN pin 8; "Calibration Oscillator Enable"
S0 pin 60; "Select IF0"
S1 pin 58; "Select IF1"
S2 pin 59; "Select IF2:
S3 pin 61; "Select IF3"
CFR pin 5; "Calibration Frequency Reset"
"Nodes"
FCK node istype 'com,keep'; "Fast Clock"
R1..R2 node istype 'com,keep'; "Ring Oscillator"
CS1..CS0 node istype 'reg'; "Calibration State"
CC15..CC0 node istype 'reg'; "Clock Calibration"
CCLC node istype 'com,keep'; "Clock Calibration Lo Carry"
P2..P0 node istype 'reg'; "Pulse"
CD4..CD0 node istype 'reg'; "Clock Divider"
DC1..DC16 node istype 'reg';"Device Command Bits"
DA node istype 'com'; "Delayed A"
DDA node istype 'com'; "Delayed DA"
WAKE node istype 'com'; "Wake"
SA node istype 'reg'; "Synchronized A"
AA node istype 'reg'; "Address Active"
DAA node istype 'reg'; "Delayed AA"
CA node istype 'reg'; "Command Active"
DCA node istype 'reg'; "Delayed CA"
ER,Q1..Q16 node istype 'reg';"Receiver Bits"
AS node istype 'reg'; "Address Strobe"
CS node istype 'reg'; "Command Strobe"
STX node istype 'com'; "Serial Transmit"
SCD7..SCD0 node istype 'reg'; "Serial Clock Divider"
DTS4..DTS0 node istype 'reg'; "DAC Transmission State"
CFD7..CFD0 node istype 'reg'; "Calibration Frequency Delay"
"Sets"
cs=[CS1..CS0]; "Calibration State"
calib=[CC15..CC0]; "Ring Oscillator Calibration"
calib_lo=[CC7..CC0]; "Calibration LO Byte"
calib_hi=[CC15..CC8]; "Calibration HI Byte"
ps=[P2..P0]; "Pulse State"
scd=[SCD7..SCD0]; "Serial Clock Divider"
dts=[DTS4..DTS0]; "DAC Transmission State"
cfd=[CFD7..CFD0]; "Calibration Frequency Delay"
"Constants"
frequency_delay=255;
equations
"Calibration controlling state machine."
cs.clk=RCK;
cs.aclr=RESET;
state_diagram cs;
state 0: if (calib==^hFFFF) then 1
else 0; "wait for 65,536 periods of RCK"
state 1: goto 2; "clear calibration counter"
state 2: goto 3; "count ring periods in RCK period"
state 3: goto 3; "enable pulse generator"
equations
"Calibration counter."
calib.clk=FCK;
calib.aclr=RESET;
"Use the calibration counter, running off RCK, to"
"provide a post-reset delay. This delay allows the"
"ring oscillator frequency to stabilize."
when (cs==0) then {
FCK=RCK;
CCLC=(calib_lo==^hFF);
calib_lo:=calib_lo+1;
when CCLC then calib_hi:=calib_hi+1
else calib_hi:=calib_hi;
}
"Reset the calibration counter."
when (cs==1) then {
FCK=RCK;
calib:=0;
}
"Count the number of FCK ring oscillator cycles in one"
"RCK period."
when (cs==2) then {
[FCK,R2,R1]=[R2,R1,!FCK];
CCLC=(calib_lo==^hFF);
calib_lo:=calib_lo+1;
when CCLC then calib_hi:=calib_hi+1
else calib_hi:=calib_hi;
}
"Run the fast clock at full speed off its ring oscillator."
"Use the pulse state machine to control the low bits of the"
"calibration counter. We use the upper bits to divide FCK"
"for DA and DDA."
when (cs==3) then {
[FCK,R2,R1]=[R2,R1,!FCK];
calib_hi:=calib_hi;
when (ps==0) then calib_lo:=calib_hi;
when (ps==1) then calib_lo:=calib_lo-1;
when (ps==3) then calib_lo:=calib_hi;
when (ps==2) then calib_lo:=calib_lo-1;
when (ps==6) then calib_lo:=calib_hi;
}
"We use the pulse counter to generate delayed versions"
"of the LWDAQ input (A). First we synchronise A with"
"fast clock."
[SA].clk = FCK;
[SA].aclr = RESET;
SA := A;
ps.aclr = RESET;
ps.clk = FCK;
state_diagram ps
state 0:if SA then 1 else 0;
state 1:if (calib_lo==0) then 3 else 1;
state 3:goto 2;
state 2:if (calib_lo==0) then 6 else 2;
state 6:if !SA then 0 else 6;
equations
"DA and DDA provide rising edges 120 ns and 240 ns after"
"any rising edge of SA."
DA = !(ps==1);
DDA = !(ps==2);
"We clock the receiver shift register and the entry"
"register with DA, and we clear them on RESET."
[ER,Q1..Q16].clk = DA;
[ER,Q1..Q16].aclr = RESET;
[ER,Q1..Q16] := [SA,ER,Q1..Q15];
"Address Active provides a pulse that begins with DDA"
"on the start bit of an address transmission, and ends"
"with the stop bit of an address transmission."
AA.clk = DDA;
AA.aclr = RESET;
AA:=(!AA & !SA & !ER) # (AA & !SA);
"Delayed AA allows us to create AS."
DAA.clk=FCK;
DAA:=AA;
"Address Strobe provides a pulse at the end of an address"
"transmission."
AS.clk = FCK;
AS := DAA & !AA;
"Command Active provides a pulse that begins with DDA"
"on the start bit of a command transmission, and ends"
"with the stop bit of a command transmission."
CA.clk = DDA;
CA.aclr = RESET;
CA:=(!CA & !SA & ER) # (CA & !SA);
"Delayed CA allows us to create CS."
DCA.clk=FCK;
DCA:=CA;
"Command Strobe provides a pulse at the end of a command"
"transmission."
CS.clk = FCK;
CS := DCA & !CA;
"We clock the receiver bits into the command register"
"on a falling edge of CS."
[DC1..DC16].clk = CS;
[DC1..DC16].aclr = RESET;
[DC1..DC16] := [Q1..Q16];
"WAKE bit."
WAKE = DC8;
"We enable the return LVDS driver when DC7 is set."
LB = DC7;
"We loop back A to B."
B = A;
"We use DC1 and DC2 to select one of S0..S3."
S0 = [DC2..DC1] == 0;
S1 = [DC2..DC1] == 1;
S2 = [DC2..DC1] == 2;
S3 = [DC2..DC1] == 3;
"We always enable the Local Oscillator, so that it will"
"warm up and be ready to use. Older versions of the firmware"
"used DC3 to turn on the Local Oscillator, leading to"
"instability in the Spectrometer's frequency response, as its"
"VCO warmed up and cooled between data samples."
LOEN = 1;
"We always assert Chip Select for the TLV5623 DAC."
CSD = 1;
"We use DC4 as Frame Synch for the TLV5623 DAC. When"
"DC4 is HI, FS goes LO, indicating a new eight-bit"
"data word is about to be transmitted."
FSD = !DC4;
"We use Q5 as DIN for the TLV5623 DAC. We don't use"
"DC5 because we want DIN to be established for over"
"25 ns before the falling edge of SCLK. This falling"
"edge occurs on the falling edge of DCA, which is only"
"a few nanoseconds after the rising edge of CS that"
"clocks DC5."
DIND = Q5;
"SCLK is the fourth and final connection to the DAC. It"
"clocks data bits into the DAC on its falling edges. We"
"produce one falling edge on SCKL at the end of a command"
"reception that sets DC6."
SCLKD = !DC6 # DCA;
"We use DC9 for COEN, which enables the Calibration"
"Oscillator."
COEN = DC9;
"We use DC10 to control the Calibration Oscillator input. When"
"we receive a new command with DC10 set to 1, we start the"
"calibration frequency delay. When the delay reaches 255, we"
"assert CFR. When CFR is asserted, the oscillator TUNE input"
"drops to 0 V with a time constant of 10 ms. When we unassert"
"CFR, TUNE rises to 3.3 V with a time constant of 10 ms."
cfd.clk=RCK;
cfd.aclr=!DC10;
when cfd