/* Coincidence Counter project See CoincidenceCounter.v for project details. HOW TO SET A COMMAND: 1) Set the command with Rcs low. 2) Set Rcs high then low to clock in the command. 3) Can now change the command again. HOW TO RUN AND COLLECT COINCIDENCES: 1) Set command 0x00 to reset everything. 2) Set Rcs high then low. 3) Set command 0x01 to run. 4) Set Rcs high then low. 5) When finished running the experiment, read counters as shown below. HOW TO READ COUNTERS WHILE RUNNING while experiment is running 1) Read counters as below. 2) Set command 0x01 to resume running. 3) Set Rcs high then low. HOW TO READ COUNTERS: 1) Set command 0x02 to pause (counters are frozen). 2) Set Rcs high then low. 3) Set command 0x05 to reset counter readback pointer 4) Set Rcs high then low. 5) Set command 0x03 to look at next counter word (not used yet). 6) Read lower 16 bits of of Counter[0] on the data bus. 7) Set Rcs high then low. 8) Read upper 16 bits of Counter[0] on the data bus. 9) Set Rcs high then low. 10) Repeat previous four steps 2047 more times for Counter[1] to Counter[2047]. Cmd. Description ==== =================================================================================== 0x00 Reset counters and readback pointer 0x01 Run 0x02 Pause 0x03 Put next partial counter on data bus 0x04 Load fixed data into counters, for testing. 0x05 Reset readback pointer 0x06 Put FPGA version:revision on data bus 0x07 ignored, future use */ //synthesis VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 module RabbitControl ( //Memory (coincidence counter array) input [31:0] MemRd, //memory read data bus B. output reg MemWrEn, //memory B write enable. output reg [10:0] MemAdd, //memory address B. output reg [31:0] MemWr, //memory write data bus B. //control... input Clk, //100HMz clock. output reg RunEn, //coincidence detection and counting enable: 0=stop, 1=run. //Rabbit... input [2:0] Rcmd, //command bus from Rabbit. input Rcs, //CS from Rabbit, active high. output reg [15:0] Rdat); //data bus to Rabbit. //Parameters... localparam VerRev = 16'h0203; //SET THE 0xVVRR VERSION:REVISION NUMBERS HERE! //Registers... reg HighWordOnBus; //0=lower half, 1=upper half of counter word to Rabbit. reg [1:0] TestDataState; //state machine for loading test data. reg LastCs; //previous state of Rcs. /****************** DATA BUS TO RABBIT EITHER UPPER OR LOWER HALF OF A COUNTER *******************/ always_comb begin if ((Rcmd == 3'd6) && Rcs) Rdat = VerRev; //read the FPGA version:revision numbers. else Rdat = (HighWordOnBus) ? MemRd[31:16] : MemRd[15:0]; //read counters. end /************************************* RABBIT COMMAND HANDLER ************************************/ always @(negedge Clk) begin if (Rcs) begin case (Rcmd) 3'd0: begin //RESET EVERYTHING. RunEn <= 0; //note: must stay in reset for >20.5uS. MemWr <= 32'd0; //for testing can change to other values. MemWrEn <= 1; MemAdd <= MemAdd + 11'd1; //continiously cycle through all counters. HighWordOnBus <= 0; end 3'd1: begin //RUN. RunEn <= 1; MemWrEn <= 0; end 3'd2: begin //PAUSE. RunEn <= 0; MemWrEn <= 0; end 3'd3: begin //PUT NEXT PARTIAL COUNTER ON DATA BUS. RunEn <= 0; MemWrEn <= 0; if (!LastCs) begin //on Rcs rising edge... LastCs <= 1; if (HighWordOnBus) begin //if high word is on data bus... HighWordOnBus <= 0; //...put low word on bus and... MemAdd <= MemAdd + 11'd1; //...goto the next counter. end else HighWordOnBus <= 1; //...else put high word on bus. end end 3'd4: begin //PUT FIXED TEST DATA INTO COUNTERS. RunEn <= 0; //note: must stay in this mode for >82uS. TestDataState <= TestDataState + 2'd1; case (TestDataState) 2'd0: MemWrEn <= 1; //write the test data. 2'd1: MemWrEn <= 0; //don't write. 2'd2: MemAdd <= MemAdd + 11'd1; //go to next counter. 2'd3: //put test data on the bus. case (MemAdd) 11'd0: MemWr <= 32'h00000000; //0. 11'd1: MemWr <= 32'h000000FF; //255. 11'd2: MemWr <= 32'h00000100; //256. 11'd3: MemWr <= 32'h0000FFFF; //65,535. 11'd4: MemWr <= 32'h00010000; //65,536. 11'd5: MemWr <= 32'h00FFFFFF; //16,777,215. 11'd6: MemWr <= 32'h01000000; //16,777,216. 11'd7: MemWr <= 32'hFFFFFFFF; //4,294,967,295. 11'd8: MemWr <= 32'd1000; //1,000. 11'd9: MemWr <= 32'd1000000; //1,000,000. 11'd10: MemWr <= 32'd1000000000; //1,000,000,000. 11'd11: MemWr <= 32'h00000001; //1. 11'd12: MemWr <= 32'h00000002; //2. 11'd13: MemWr <= 32'h00000004; //4. 11'd14: MemWr <= 32'h00000008; //8. 11'd15: MemWr <= 32'h00000010; //16. 11'd16: MemWr <= 32'h00000020; //32. 11'd17: MemWr <= 32'h00000040; //64. 11'd18: MemWr <= 32'h00000080; //128. 11'd19: MemWr <= 32'h00000100; //256. 11'd20: MemWr <= 32'h00000200; //512. 11'd21: MemWr <= 32'h00000400; //1,024. 11'd22: MemWr <= 32'h00000800; //2,048. 11'd23: MemWr <= 32'h00001000; //4,096. 11'd24: MemWr <= 32'h00002000; //8,192. 11'd25: MemWr <= 32'h00004000; //16,384. 11'd26: MemWr <= 32'h00008000; //32,768. 11'd27: MemWr <= 32'h00010000; //65,536. 11'd28: MemWr <= 32'h00020000; //131,072. 11'd29: MemWr <= 32'h00040000; //262,144. 11'd30: MemWr <= 32'h00080000; //524,288. 11'd31: MemWr <= 32'h00100000; //1,048,576. 11'd32: MemWr <= 32'h00200000; //2,097,152. 11'd33: MemWr <= 32'h00400000; //4,194,304. 11'd34: MemWr <= 32'h00800000; //8,388,608. 11'd35: MemWr <= 32'h01000000; //16,777,216. 11'd36: MemWr <= 32'h02000000; //33,554,432. 11'd37: MemWr <= 32'h04000000; //67,108,864. 11'd38: MemWr <= 32'h08000000; //134,217,728. 11'd39: MemWr <= 32'h10000000; //268,435,456. 11'd40: MemWr <= 32'h20000000; //536,870,912. 11'd41: MemWr <= 32'h40000000; //1,073,741,824. 11'd42: MemWr <= 32'h80000000; //2,147,483,648. default: MemWr <= MemAdd + 32'd10; //data is the address + 10. endcase endcase end 3'd5: begin //RESET READBACK POINTER (but don't affect running). MemAdd <= 11'd0; MemWrEn <= 0; HighWordOnBus <= 0; end 3'd6: ; //READ FPGA VER:REV (handled in combinational above). 3'd7: ; //FUTURE USE, DO NOTHING. endcase end else begin //Rcs IS NOW LOW. LastCs <= 0; MemWrEn <= 0; end end endmodule