module P2060 title 'P2060' declarations "Version 3" "[02-JUN-11] We now pulse the x-ray source when either" "DC1 or DC2 are set. When we receive DC1, we set KV to" "zero to select 60 keV. When we receive DC2, we set KV" "to one to select 70 keV. The KV setting remains in place" "until the next command is received." "Version 2" "[01-JUN-11] Establish the count-up and count-down to" "provide guaranteed limit to the duty cycle of the x-ray" "pulse." "Constants" clock_frequency=40000000; "The oscillator is 40 MHz" max_time=2; "Maximum x-ray pulse duration in seconds" off_count=clock_frequency*max_time; min_rest_ratio=32; "must be an integer fraction of 256." "Pins" A pin 12;"LVDS input" B pin 64 istype 'com';"LVDS output" !RESET pin 37;"RESET" CK pin 38;"40 MHz clock input" WAKE pin 66 istype 'com';"WAKE" LB pin 65 istype 'com';"Loop Back, enables LVDS driver" TP1..TP4 pin 69,70,71,72 istype 'com';" LED16..LED1 pin 41..44,47..50,53..56,58..61 istype 'com'; IO3..IO10 pin 5,6,8,9,10,11,14,15 istype 'com'; ON pin 3 istype 'reg'; "X-Ray Pulse On" KV pin 4 istype 'reg'; "Beam Energy 70 kV" "Nodes" SA node istype 'reg';"Synchornized A." DA node istype 'com';"Delayed SA" DDA node istype 'com';"Delayed Delayed SA" ACTIVE node istype 'reg';"transmission active" D1..D9 node istype 'reg';"delay pipeline." DRS0..DRS2 node istype 'reg';"Command Receiver State" CS node istype 'com';"Command Strobe" NCS node istype 'com';"New Command Strobe" AS node istype 'com';"Address Strobe" NAS node istype 'com';"New Address Strobe" DS node istype 'com';"Data Strobe" ER,Q1..Q16 node istype 'reg';"Receiver Bits" DA0..DA15 node istype 'reg';"Device Address Bits" DC1..DC16 node istype 'reg';"Device Command Bits" "Sets" drs=[DRS2..DRS0];"Command Receiver State" equations "Serial Input Decoding" "---------------------" "We synchronize the incoming LVDS logic signal to" "our 40-MHz clock." SA:=A; SA.clk=CK; "We put SA through a pipeline of registers clocked" "with CK so that we can generate the delayed timing" "pulses from the rising edge of SA." [D1..D9]:= [SA,D1..D8]; [D1..D9].clk= CK; [D1..D9].aclr=RESET; "Delayed SA provides is asserted for one CK period 125 ns" "after any rising edge of SA. We use DA and SA to obtain" "the LWDAQ data bit. If SA is high with DA, the data bit" "is one." DA = D4 & !D5; "Delayed Delayed SA is asserted for one CK period 250 ns" "after any rising edge of SA. We use DDA and SA to obtain" "the LWDAQ ACTIVE bit. If SA is low with DDA, ACTIVE is" "true." DDA = D8 & !D9; "We assert ACTIVE whenever the driver is transmitting" "a command data bit." ACTIVE.clk=CK; ACTIVE.aclr=RESET; when !SA & DDA then ACTIVE:=1; when SA & DDA then ACTIVE:=0; when !DDA then ACTIVE:=ACTIVE; "We clock the receiver shift register and the entry" "register with CK, and we clear them on RESET." [ER,Q1..Q16].clk=CK; [ER,Q1..Q16].aclr=RESET; "We shift the receiver bits whenever we have DA" "asserted. We clock the current value of SA into" "the entry register (ER), and shift all the other" "bits over by one. At the beginning of a LWDAQ" "transmission, ER contains a 1 if the transmission" "is a command, and 0 if it is an address. At the" "end of a transmission, ER contains a 1, and Q1" "to Q16 contain the transmitted sixteen-bit word," "either address or command." when DA then [ER,Q1..Q16]:=[SA,ER,Q1..Q15]; else [ER,Q1..Q16]:=[ER,Q1..Q16].fb; "Data Receiver" "-------------" "Data Receiver states." declarations rest=0; command_receive=1; clock_command_register=2; address_receive=3; clock_address_register=4; new_command_strobe=5; new_address_strobe=6; equations drs.clk=CK; drs.aclr=RESET; state_diagram drs; "Stay in the rest state until we receive ACTIVE." "When ACTIVE, we proceed with command receive" "if the data bit in ER is one, otherwise an address" "receive." state rest: if ACTIVE then { if ER then command_receive else address_receive; } else rest; "We stay in command_receive until !ACTIVE." state command_receive: if !ACTIVE then clock_command_register else command_receive; "As we pass through clock_command_register we" "indicate that it is time to clock the receiver" "bits into the command register." state clock_command_register:goto new_command_strobe; "As we pass through new_command_strobe we start" "any action that should be taken when the new command" "arrives. The variable NCS is true when drs is in" "the new_command_strobe state." state new_command_strobe:goto rest; "We stay in address_receive until !ACTIVE." state address_receive: if !ACTIVE then clock_address_register; else address_receive ; "As we pass through clock_address_register we" "indicate that it is time to clock the receiver" "bits into the address register." state clock_address_register:goto new_address_strobe; "As we pass through new_address_strobe we start" "any action that should be taken when the new address" "arrives. The variable NAS is true when drs is in" "the new_address_strobe state." state new_address_strobe:goto rest; equations "Command Strobe is asserted for one CK period at the" "end of a command transmission from the LWDAQ driver." CS = (drs==clock_command_register); "New Command Strobe follows CS when the new command" "is already established in the DC registers." NCS = (drs==new_command_strobe); "Address Strobe is asserted for one CK period at the" "end of an address transmission from the LWDAQ driver." AS = (drs==clock_address_register); "New Address Strobe follows AS when the new address" "is already established in the DA registers." NAS = (drs==new_address_strobe); "Data Strobe is asserted for one CK period after a" "solitary low pulse from the LWDAQ driver. The driver" "uses solitary low pulses that endure for 125 ns and" "are followed by a > 375 ns high pulse to initiate" "serial transmission of data from LWDAQ devices of type" "data_device, like this one." DS = (SA & DDA & (drs==rest)); "We clock the receiver bits into the command register" "on CS." [DC1..DC16].clk=CK; [DC1..DC16].aclr=RESET; when CS then [DC1..DC16]:=[Q1..Q16] else [DC1..DC16]:=[DC1..DC16]; "We clock the receiver bits into the address register" "on AS." [DA0..DA15].clk=CK; [DA0..DA15].aclr=RESET; when AS then [DA0..DA15]:=[Q1..Q16] else [DA0..DA15]:=[DA0..DA15].fb; "This board is always awake, so we don't use DC8." WAKE=1; "This board always loops back, so we don't use DC7.." LB = 1; "H-Bridge Driver" "===============" declarations "Nodes" C0..C31 node istype 'reg';"Counter" CB0F node istype 'com,keep';"Counter Byte 0 Full" CB1F node istype 'com,keep';"Counter Byte 1 Full" CB2F node istype 'com,keep';"Counter Byte 2 Full" CB0E node istype 'com,keep';"Counter Byte 0 Zero" CB1E node istype 'com,keep';"Counter Byte 1 Zero" CB2E node istype 'com,keep';"Counter Byte 2 Zero" CB3E node istype 'com,keep';"Counter Byte 3 Zero" ONRST node istype 'reg,keep';"ON Reset" SC0..SC7 node istype 'reg'; "Slow Clock Counter" SCK node istype 'reg';"Slow Clock" XCK node istype 'com';"X-Ray Clock" "Sets" cb0=[C7..C0]; "counter byte zero" cb1=[C15..C8]; "counter byte one" cb2=[C23..C16]; "counter byte two" cb3=[C31..C24]; "counter byte three" counter=[C31..C0]; "counter" sc=[SC7..SC0]; equations "Counter Byte Full nodes." CB0F=(cb0==255); CB1F=(cb1==255); CB2F=(cb2==255); CB0E=(cb0==0); CB1E=(cb1==0); CB2E=(cb2==0); CB3E=(cb3==0); "We set KV with DC1 or DC2. Any time we receive a new" "command with DC1, we set KV to zero for 60 keV. Any time" "we receive a comand with !DC1 & DC2 we set it to one for" "70 keV. Otherwise, KV remains unchanged." KV.clk = CK; when NCS then { when DC1 then KV:=0; when !DC1 & DC2 then KV:=1; when !DC1 & !DC2 then KV:=KV; } else { KV:=KV } "The ON bit is cleared asynchronously by ONRST," "which is true when the counter is above off_count" ONRST.clk = CK; ONRST := counter >= off_count; ON.aclr = ONRST; "When we get a new command, we set the ON bit" "according to DC1." ON.clk=CK; when NCS then ON:=DC1#DC2 else ON:=ON; "Slow clock counter" sc.clk=CK; when sc==min_rest_ratio then sc:=0 else sc:=sc+1; SCK:=(sc==0); SCK.clk=CK; "The X-Ray clock is either 40 MHz or a fraction thereof," "depending upon whether the x-ray source is on or off." when ON then XCK=CK else XCK=SCK; "The counter is clocked by XCK" counter.clk=XCK; counter.aclr=RESET; "When the x-ray source is powered with ON, we count up fast" "by incrementing the counter by up_step." when ON then { cb0:=cb0+1; when CB0F then cb1:=cb1+1; else cb1:=cb1; when CB1F & CB0F then cb2:=cb2+1; else cb2:=cb2; when CB2F & CB1F & CB0F then cb3:=cb3+1; else cb3:=cb3; } "When the x-ray source is turned off by !ON, we cound down" "slowly by decrementing the counter by down_step until we reach" "a value less than up_step." when !ON then { when !CB0E # !CB1E # !CB2E # !CB3E then { cb0:=cb0-1; when CB0E then cb1:=cb1-1; else cb1:=cb1; when CB1E & CB0E then cb2:=cb2-1; else cb2:=cb2; when CB2E & CB1E & CB0E then cb3:=cb3-1; else cb3:=cb3; } else { counter:=0; } } "Outputs" "=======" [LED1..LED16] = [C16..C31]; TP1 = 1; TP2 = ON; TP3 = KV; TP4 = DC1 # DC2; "IO3 we use to indicate that the pulse limiter is counting" "down." IO3 = !ON & (!CB0E # !CB1E # !CB2E # !CB3E); IO4 = ON; IO5 = KV; end