%vme bus control% subdesign vme_port4 %ADD FEB_PORT, CHANGE IN WRITE/FEB_SEND SEQUENCE 5/12/00% (clk, %40 mhz system clock% /sysrst, %/reset from vme bus% v_add[17..6], %vme addess from vme_add fpga% v_word, %module/data type recongnization strobe from vme_add fpga% v_/ds, %vme /ds from vme_add fpga, delayed ??% v_/write, %vme write strobe, image of vme /write% pureadback[31..0], %read back data from PU_port% fiforeadback[31..0], %readback data from fifo_port% FEB_STATUS[31..0], %READBACK FEB_PORT STATUS 5/11/00 % BSY[4..1] %BUSY FLAG FROM OTHER PORTs, CAN'T RECEIVE OR DELIVER NEW VME DATA % :input; vbus_data[31..0] %bidirectional vme data from vme bus% :bidir; vmedatain[31..0], %latched vme write data% vmeadd[13..6], %latched vme add as command, a[17..14] not used% dtack, r/w, %retimed vme read/write stobe to other ports of vmefpga% dirtrans, %the direction for transceivers% /tran_oe, %output enable for transceivers% vme_/rst, %VME RESET TO OTHER PORTION OF VMEFPGA% ST[15..0] %VME SEQUENCE CONTROL% :output;) variable start :node; dw :dff; %v_/write registe, set before data latch in,reset after dtack, deafult high% vmedatatri[31..0]:tri; %tri-state buffer for vme bidirectional data% vreg_a[31..0] :dffe; %vbus_di[] latch register% vreg_b[31..0] :dff; %vbus_di[]'s sync reg% syncadd[7..0] :dff; %latch and SYNC 8 BITS VME ADD TO 40 MHZ% vmerst :dff; %soft reset for vmefpga% DS13 :dff; % ONE CYCLE DELEY OF S13, AS READ DTACK% sel[4..1] :lcell; %PORT SELECTION FLAG, USED TO IDENTIFY BSY FLAG OF SELECTED PORT% S: machine of bits (sb[3..0]) with states ( S0 = B"0000", S1 = B"0001", S2 = B"0011", S3 = B"0010", S4 = B"0110", S5 = B"0111", S6 = B"0101", S7 = B"0100", S8 = B"1000", S9 = B"1001", S10 = B"1011", S11 = B"1010", S12 = B"1110", S13 = B"1100", S14 = B"1101", S15 = B"1111"); BEGIN % vme bus access control % case S is when S0 => if (!V_/ds & v_word) then S = S1; else S = S0; end if; when S1 => S=S2; %start, latch v_add, v_dat and vme_write% when S2=> S=S3; %vmeadd sync.% when S3=> s = s4; when S4=> %check bsy% if (bsy[4..1] == sel[4..1]) & !(v_/ds) & (sel[4..1] != 0) THEN %SELECTED PORT IS BSY, WAIT AT S4% S=S4; ELSIF (bsy[4..1] == sel[4..1]) & v_/ds then %vme time out, back to s0% s = s15; else S=S5; % NOT BSY, go ahead% END IF; when S5=> if(v_/write)then %vme read % S=S6; else S=S9; %vme write, ISSUE A DATACK AFTER 2 CYCLES, AT S10% end if; when S6=> % % S=S7; when S7 => s = s8; when S8 => S=S12; when S9 => S=S10; when S10 => s = s11; when S11 => %negate dtack, write operation is finished% s=s12; when S12 => %check bsy% IF V_/DS THEN %time out% S = S15; ELSIF (SEL[4..1] == BSY[4..1]) & (SEL[4..1] !=0) THEN %bsy, wait at s12% S = S12; ELSIF (SEL[4..1] != BSY[4..1]) # (sel[4..1] ==0) THEN %not bsy or vme_/reset,go ahead% S = S13; END IF; when S13 => %READBACK DATA HAS PREPARED, put the data on v_bus% IF (V_/DS) THEN S=S14; ELSE S = S13; %DATA IS PRESENTED ON V_BUS DURING V_/DS LOW% END IF; when S14 => %READ IS COMPLETED% S = S15; when S15 => S=S0; %sequence back to origine% end case; S.clk = clk; s.reset = !/sysrst; ST[15..0] = S[15..0]; start = (s == s2); ds13.clk = clk; ds13.d = s13; dtack = ds13.q; %PORT SELECTION% IF V_WORD THEN SEL[1] = (V_ADD[13..11] == 1); %PU_VME PORT IS SELECTED% SEL[2] = (V_ADD[13..11] == 2); %FIFO PORT IS SELECTED% SEL[3] = (V_ADD[13..11] == 3); %FEB PORT IS SELECTED% SEL[4] = (V_ADD[13..11] == 4); %TTC PORT IS SELECTED% ELSE sel[4..1] = GND; %NO PORT IS SELECTED% END IF; % bidirectional control to vme bus, vme data readback % vmedatatri[].oe = (s==s13) & r/w & (sel[4..1] !=0); % read back data stay on the bus until v_/ds is negated % vmedatatri[].in = SEL[1] & pureadback[31..0] # SEL[2] & fiforeadback[31..0] # SEL[3] & FEB_STATUS[31..0]; VBUS_DATA[31..0] = vmedatatri[].out; % latch vme data and sync to clk% vreg_a[31..0].clk = clk; vreg_a[].clrn = vme_/rst; vreg_a[].ena = START & !v_/write; %ENABLE VME DATA LATCH IN% vreg_a[].d = vbus_data[]; vreg_b[31..0].clk = clk; vreg_b[].clrn = vme_/rst; vreg_b[].d = vreg_a[].q; vmedatain[31..0] = vreg_b[].q; %ready to use vme input data% %latch vme address at s3% syncadd[].clk = clk; syncadd[].clrn = vme_/rst; syncadd[].d = start & v_add[13..6] # syncadd[].q & (s != s15); vmeadd[13..6] = syncadd[].q; %ready to use vme address as vme command% %reset vmefpga's reg. logic 1 in bit0 means reset, vme_/rst is low one cycle at st10 % vmerst.clk = clk; vmerst.CLRN = /sysrst; vmerst.d = !(vbus_data[0] & (v_add[13..11] == 0) & (v_add[10..6] == 9) & (s==s9)); % logic 1 IN BIT 0 means reset% vme_/rst = vmerst.q; %vme direction% /tran_oe = !(v_word & !v_/ds); dirtrans = v_/write; %vme read/write% dw.clk = clk; dw.clrn = vme_/rst; dw.d = !(V_/write) & start # (dw.q & !(ST15)); R/W = !dw.q; end;