module P2060C title 'P2060C' declarations "RS-232 Interface (A2060C) Firmware." "Version 2:" "Add transmission of XON character to the RS-232 transmission. The" "XON is transmitted when the driver requests an RS-232 byte from" "the A2060C." "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'; "IO1..IO10 pin 3,4,5,6,8,9,10,11,14 istype 'com';" SOUT pin 3 istype 'com'; SIN pin 9; "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" DA1..DA16 node istype 'reg';"Device Address Bits" DC1..DC16 node istype 'reg';"Device Command Bits" RCD0..RCD15 node istype 'reg';"Receiver Clock Divider" RCDC node istype 'com';"Receiver Clock Divider Carry" RCDZ node istype 'com,keep';"Receiver Clock Divider Zero" TCD0..TCD15 node istype 'reg';"Transmitter Clock Divider" TCDC node istype 'com';"Transmitter Clock Divider Carry" TCDZ node istype 'com,keep';"Transmitter Clock Divider Zero" STS0..STS4 node istype 'reg';"Serial Transmitter State" SRS0..SRS4 node istype 'reg';"Serial Receiver State" RD0..RD7 node istype 'reg';"Received Data" SSIN node istype 'reg';"Synchronized SIN" BD0..BD7 node istype 'reg';"Buffered Data" DTS4..DTS0 node istype 'reg';"Data Transmitter State" "Sets" drs=[DRS2..DRS0];"Command Receiver State" sts=[STS4..STS0];"Serial Transmitter State" srs=[SRS4..SRS0];"Serial Receiver State" rcd=[RCD15..RCD0];"Receiver Clock Divider" rcd0=[RCD7..RCD0];"Receiver Clock Divider Lower Byte" rcd1=[RCD15..RCD8];"Receiver Clock Divider Upper Byte" tcd=[TCD15..TCD0];"Transmitter Clock Divider" tcd0=[TCD7..TCD0];"Transmitter Clock Divider Lower Byte" tcd1=[TCD15..TCD8];"Transmitter Clock Divider Upper Byte" rd=[RD7..RD0];"Received Data" bd=[BD7..BD0];"Buffered Data" dts=[DTS4..DTS0];"Data Transmitter State" "Constants" tcd_end_count=4167; rcd_end_count=4167; rcd_half_count=2083; srs_end_count=22; equations "Command and Address Receiver" "----------------------------" "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 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." [DA1..DA16].clk=CK; [DA1..DA16].aclr=RESET; when AS then [DA1..DA16]:=[Q1..Q16] else [DA1..DA16]:=[DA1..DA16].fb; "We wake up the +-15V power when DC8 is set." WAKE = DC8; "We enable the return LVDS driver when DC7 is set." when DC7 then LB = 1; "We loop back the synchronized value of 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 = SA; "RS-232 Transmitter" "==================" "The RS-232 transmitter sends out the bytes written to the" "A2060C using the top eight bits of the command word. Bit" "DC9 is the least significant bit and DC16 is the most significant." "By RS-232 convenction, the least significant bit is the first" "one we transmit." "Every time we write a new command word to the A2060C, we get" "an NCS strobe. If bit DC6 is set, this means we should transmit" "bits DC9..DC16 as an RS-232 byte. If bit DC5 is set, we should" "get ready to receive RS-232 bytes." "Because the A2060C has no data buffer, it must be ready to receive" "RS-232 bytes when these bytes arrive. It is ready only after the" "A2060C receives a data strobe from the LWDAQ driver. We use the XON" "and XOFF characters (decimal 17 amd 19 respectively) to tell the" "device on the other end of the RS-232 connection when it can transmit" "bytes and have them received correctly by the A2060C." "As part of the XON and XOFF protocol, the A2060C sends out an XON over" "the RS-232 interface, using the RS-232 Transmitter, when it receives" "the first LWDAQ data strobe after a receive command. A receive command" "sets DC5. At that point, the RS-232 Transmitter starts waiting for DS" "When it receives DS, it transmits an XON. Our assumption is that the" "A2060C sent an XOFF character earlier, using a transmit command." [tcd0,tcd1].clk=CK; [tcd0,tcd1].aclr=RESET; TCDC=(tcd0==^hFF); TCDZ=(tcd==0); when (tcd==tcd_end_count) then tcd:=0; else { tcd0:=tcd0+1; when TCDC then tcd1:=tcd1+1 else tcd1:=tcd1; } "The state machine that controls the transmission of bits." sts.clk=CK; sts.aclr=RESET; state_diagram sts; state 0: if NCS & DC6 then 1; if NCS & DC5 then 12; if !NCS # (!DC5 & !DC6) then 0; state 1:if TCDZ then 2 else 1;"wait for symbol clock" state 2:if TCDZ then 3 else 2;"start bit" state 3:if TCDZ then 4 else 3;"bit 0" state 4:if TCDZ then 5 else 4; state 5:if TCDZ then 6 else 5; state 6:if TCDZ then 7 else 6; state 7:if TCDZ then 8 else 7; state 8:if TCDZ then 9 else 8; state 9:if TCDZ then 10 else 9; state 10:if TCDZ then 11 else 10;"bit 7" state 11:if TCDZ then 0 else 11;"stop bit" state 12: if NCS & DC6 then 1; else { if !DC5 then 0; if DC5 & DS then 1; if DC5 & !DS then 12; } equations "The logic that determines each serial bit. Here we choose" "between command bits DC9..DC16 when DC6 is set, or an XON" "character when DC5 is set. XON is decimal 17, which is" "binary 00010001." SOUT=(sts==0) #(sts==1) #(sts==3)&DC9&DC6 # (sts==3)&DC5 #(sts==4)&DC10&DC6 #(sts==5)&DC11&DC6 #(sts==6)&DC12&DC6 #(sts==7)&DC13&DC6 # (sts==7)&DC5 #(sts==8)&DC14&DC6 #(sts==9)&DC15&DC6 #(sts==10)&DC16&DC6 #(sts==11); "RS-232 Receiver" "===============" SSIN.clk=CK; SSIN:=SIN; [rcd0,rcd1].clk=CK; [rcd0,rcd1].aclr=RESET; RCDC=(rcd0==^hFF); RCDZ=(rcd==0); when (rcd==rcd_end_count) then rcd:=0; else { when (srs==0) & (SSIN) then rcd:=rcd_half_count; else { rcd0:=rcd0+1; when RCDC then rcd1:=rcd1+1 else rcd1:=rcd1; } } srs.clk=CK; srs.aclr=RESET; state_diagram srs; state 0:if !SSIN then 1 else 0;"waiting for start bit" state 1:if RCDZ then 2 else 1;"start bit" state 2:if RCDZ then 3 else 2;"bit 0" state 3:if RCDZ then 4 else 3; state 4:if RCDZ then 5 else 4; state 5:if RCDZ then 6 else 5; state 6:if RCDZ then 7 else 6; state 7:if RCDZ then 8 else 7; state 8:if RCDZ then 9 else 8; state 9:if RCDZ then 10 else 9;"bit 7" state 10:if RCDZ then 0 else 10;"stop bit" equations rd.clk=CK; rd.aclr=RESET; when (srs>=2) & (srs<=9) then { when RCDZ then [RD0..RD7]:=[RD1..RD7,SSIN]; else rd:=rd; } else { rd:=rd; } "LWDAQ Data Transmit" "===================" bd.clk=CK; bd.aclr=RESET; when (srs==10) then bd:=rd; else bd:=bd; dts.clk=CK; dts.aclr=RESET; state_diagram dts; state 0:if NCS & DC5 then 1 else 0; state 1: if DS then 2; if !DS & DC5 then 1; if !DS & !DC5 then 0; state 2: if (srs!=10) then 3; if (srs==10) & DC5 then 2; if (srs==10) & !DC5 then 0; state 3: if (srs==10) then 4; if (srs!=10) & DC5 then 3; if (srs!=10) & !DC5 then 0; 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; state 11:goto 12; state 12:goto 13; state 13:goto 14; state 14:goto 15; state 15:goto 16; state 16:goto 17; state 17:goto 18; state 18:goto 19; state 19:goto 20; state 20:goto 21; state 21:goto 22; state 22:goto 23; state 23:goto 1; equations when DC5 then { B=(dts==0)#(dts==1)#(dts==2)#(dts==3) #(dts==6)&BD7#(dts==7)&BD7 #(dts==8)&BD6#(dts==9)&BD6 #(dts==10)&BD5#(dts==11)&BD5 #(dts==12)&BD4#(dts==13)&BD4 #(dts==14)&BD3#(dts==15)&BD3 #(dts==16)&BD2#(dts==17)&BD2 #(dts==18)&BD1#(dts==19)&BD1 #(dts==20)&BD0#(dts==21)&BD0 #(dts==22)#(dts==23); } "Indicators and Test Pins" "========================" [LED1..LED9] = [DC1..DC9]; [LED9..LED16] = [BD0..BD7]; TP1 = DTS0; TP2 = DTS1; TP3 = DS; TP4 = B; end