module P3007A title 'P3007A' "Version 1, Last modified 02-DEC-05" "Calibrates local ring oscillator against reference clock." "The local ring oscillator consists of two gates and runs" "at about 170 MHz. Unlike the P2065A01 code, in which the" "ring oscillator turns on only during LWDAQ command reception," "we leave this ring oscillator running all the time, and the" "entire A3007 circuit consumes about 30 mA from the +5 V" "supply." "Includes a 40-MHz clock generator." "Responds to LWDAQ read job with a binary number that increments" "each time it is read out. With the RS232 instrument and image" "width set to 256, you get a left-right gray scale." "Includes LWDAQ address and command receiver greatly" "abbreviated by using a variety of register clock signals," "and all driven from the calibrated ring oscillator." "Pins" A pin 3; "LVDS input" B pin 10 istype 'com'; "LVDS output" C pin 43; "Comparator Output" LB pin 8 istype 'com'; "Loop Back" !RESET pin 22;"RESET" RCK pin 20; "32 kHz reference clock input" FCK pin 38; "Fast Clock on Global CLK1" FCKO pin 37 istype 'com,keep'; "Source of FCK" "Scratch" X1 pin 72 istype 'com'; X2 pin 71 istype 'com'; "Nodes" R1 node istype 'com,keep'; "Ring Oscillator" MS1..MS0 node istype 'reg'; "Master State" SC15..SC0 node istype 'reg'; "Startup Coun Low Byte Zero" SCZ0 node istype 'com,keep'; "Startup Counter Low Byte Zero" SCZ1 node istype 'com,keep'; "Startup Counter Top Byte Zero" FCS15..FCS0 node istype 'reg'; "Fast Clock Speed" FCSC node istype 'com,keep'; "Fast Clock Speed Carry" SA node istype 'reg'; "Synchronized A" DSA node istype 'reg'; "Delayed SA" ARISE node istype 'reg'; "Rising Edge on A" DA node istype 'reg'; "Delayed A Rising Edge" DDA node istype 'reg'; "Delayed DA" PC12..PC7 node istype 'reg'; "Pulse Counter" AA node istype 'reg'; "Address Active" DAA node istype 'reg'; "Delayed AA" CA node istype 'reg'; "Command Active" DCA node istype 'reg'; "Delayed CA" AS node istype 'reg'; "Address Strobe" CS node istype 'reg'; "Command Strobe" DS node istype 'reg'; "Data Strobe" ER,Q1..Q16 node istype 'reg';"Receiver Bits" DC1..DC16 node istype 'reg';"Device Command Bits" WAKE node istype 'com'; "Wake" DINT3..DINT0 node istype 'reg';"Division Integer" DCOUNT7..DCOUNT0 node istype 'com,keep';"Division Count" DFRAC3..DFRAC0 node istype 'reg';"Division Fraction" EXTRA node istype 'reg'; "Extra Step From Fractional Carry" FS3..FS0 node istype 'com,keep'; "Fractionial Sum" FC3..FC0 node istype 'com,keep'; "Fractional Carry" DCK node istype 'reg'; "Data Clock" TS3..TS0 node istype 'reg'; "Transmit State" TB7..TB0 node istype 'reg'; "Transmission Bits" TBL node istype 'com'; "Transmission Byte Load" TBR node istype 'reg'; "Transmission Byte Ready" TBO node istype 'com'; "Transmit Bit Out" "Sets" ms=[MS1..MS0]; "Calibration State" fcs = [FCS15..FCS0]; "Fast Clock Speed" fcs_1 = [FCS15..FCS8]; "Fast Clock Speed, Top Byte" fcs_0 = [FCS7..FCS0]; "Fast Clock Speed, Low Byte" sc_1 = [SC15..SC8]; "Startup Counter Top Byte" sc_0 = [SC7..SC0]; "Startup Counter Low Byte" pc=[PC12..PC7]; "Pulse Counter" dfrac=[DFRAC3..DFRAC0];"Division Fraction" dint=[DINT3..DINT0];"Division Integer" dcount=[DCOUNT7..DCOUNT0];"Divisor Count" ts=[TS3..TS0];"Transmission State" tb=[TB7..TB0]; "Transmission Bits" equations "Fast Clock Generation" "---------------------" [FCKO,R1]=[R1,!FCKO & !RESET]; "Fast Clock Calibration" "----------------------" SCZ0 = (sc_0 == 0); SCZ1 = (sc_1 == 0); sc_0.clk = RCK; sc_0.ap = RESET; sc_0:=sc_0-1; sc_1.clk = RCK; sc_1.ap = RESET; when SCZ0 then sc_1:=sc_1-1 else sc_1:=sc_1; ms.clk=RCK; ms.aclr=RESET; state_diagram ms; state 0: if SCZ0 & SCZ1 then 1 else 0; "wait two seconds" state 1: goto 2; "clear speed counter" state 2: goto 3; "count ring periods in one RCK period" state 3: goto 3; "run" equations fcs_0.clk = FCK; fcs_0.aclr = RESET; when (ms==2) then fcs_0:=fcs_0+1; else fcs_0:=fcs_0; FCSC = (fcs_0 == ^hFF); fcs_1.clk = FCK; fcs_1.aclr = RESET; when (ms==2) & FCSC then fcs_1:=fcs_1+1; else fcs_1:=fcs_1; "Data Clock Generation" "---------------------" "Generates 40 MHz clock with code we hope can be transported "to other circuits. What's new in this generator is the division "of the fast clock speed by the desired data clock speed to produce" "a binary number with both integer and fractional parts. The data" "clock generator counts down the integer part to zero each" "time it creates a data clock period, and adds the fractional" "part to a cumulative sum. Whenever this sum generates a" "carry, the clock generator waits one extra fast clock period" "before generating its data clock pulse. In this way, the" "average period of the data clock is accurate to a fraction" "of a fast clock period. You can increase the fractional" "accuracy by increasing the size of the fractional sum" "register. In this case we provide four bits of fractional" "sum, for data clock period accuracy +- 1/32 of a fast clock" "period. With fast clock period 6 ns (as it is in the first" "application of this code) and data clock period 25 ns (that's" "40 MHz), we have 25 ns +- 0.2 ns, which is plenty good enough" "for 8-bit serial transmission at 20 MBPS. We assume a thirteen-" "bit fast clock speed counter named FCS15..FCS0. If you use more" "bits, the addition equations for 'dcount' become enormous, and" "you should perform the addition with separate carry bits, as" "we do for our fractional sum bits, by way of illustration." dcount = [0,FCS12..FCS6] +[0,0,FCS12..FCS7] +[0,0,0,0,FCS12..FCS9] +[0,0,0,0,0,0,FCS12..FCS11] +[0,0,0,0,0,0,0,FCS12] -[0,0,0,1,0,0,0,0]; FS0 = DFRAC0 $ DCOUNT0; FC0 = DFRAC0&DCOUNT0; FS1 = DFRAC1 $ DCOUNT1 $ FC0; FC1 = DFRAC1&DCOUNT1 # DFRAC1&FC0 # DCOUNT1&FC0; FS2 = DFRAC2 $ DCOUNT2 $ FC1; FC2 = DFRAC2&DCOUNT2 # DFRAC2&FC1 # DCOUNT2&FC1; FS3 = DFRAC3 $ DCOUNT3 $ FC2; FC3 = DFRAC3&DCOUNT3 # DFRAC3&FC2 # DCOUNT3&FC2; EXTRA.aclr = RESET; EXTRA.clk = FCK; DCK.aclr = RESET; DCK.clk = FCK; dint.aclr = RESET; dint.clk = FCK; dfrac.clk = FCK; dfrac.aclr = RESET; when (dint>0) then { dint := dint-1; dfrac := dfrac; EXTRA := EXTRA; DCK := 0; } when (dint==0) then { when EXTRA then { dint := 0; dfrac := dfrac; EXTRA := 0; DCK := 0; } else { dint := [DCOUNT7..DCOUNT4]; dfrac := [FS3..FS0]; EXTRA := FC3; DCK := 1; } } "LWDAQ Command and Address Decoding" "----------------------------------" [SA,DSA,DA,DDA,ARISE].clk = FCK; [SA,DSA,DA,DDA,ARISE].aclr = RESET; SA := A; DSA := SA; pc.clk = FCK; pc.aclr = RESET; when !ARISE then { ARISE := SA&!DSA; DA := 0; DDA := 0; pc := [FCS12..FCS7]; } when ARISE then { ARISE := !DDA; pc := pc-1; DA := (pc==[0,FCS12..FCS8]); DDA := (pc==0); } "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; "Data Strobe identifies a solitary low pulse on A. We synchronize" "the strobe with the data clock so that we can use it to start" "the bit transmitter. We set DS with its asynchronous preset, and" "clear it on the next rising edge of DCK." DS.clk = DCK; DS.ap = (DDA & SA); DS := 0; "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 the driver so long as DC5 is not set." "On a data_device like this one, !DC5 is required for" "loop-back." when !DC5 then B = A; "Data Return" "-----------" ts.clk = DCK; ts.aclr = RESET; state_diagram ts; state 0:if DS & DC5 then 1 else 0; state 1: if !DC5 then 0; if DC5 & TBR then 2; if DC5 & !TBR then 1; state 2:goto 3;"start bit 0" state 3:goto 4;"TB7" state 4:goto 5; state 5:goto 6; state 6:goto 7; state 7:goto 8; state 8:goto 9; state 9:goto 10; state 10:goto 11;"TB0" state 11:goto 0;"stop bit 1" equations; TBO = ( (ts==0) # (ts==1) # (ts==3) & TB7 # (ts==4) & TB6 # (ts==5) & TB5 # (ts==6) & TB4 # (ts==7) & TB3 # (ts==8) & TB2 # (ts==9) & TB1 # (ts==10) & TB0 # (ts==11) ); TBR.clk = DCK; TBR.aclr = RESET; "TBR:= TBR & (ts!=10) # TBL; TBR:=1; tb.clk = DCK; tb.aclr = RESET; when TBL then tb:=tb+1; else tb:=tb; TBL=(ts==11); when DC5 then B = TBO; X1=DS; X2=TBO; end