// // // COLUTAV3 chip testing fpga code // // jb/september/2019 version v1.0 (with histogramming package) // // // // // // basic FPGA commands : // // FPGA status register write; // FPGA status register read; // control data register write; // control data register read; // Read "9650_ADC, COLUTA serializer, SEU_ADC" memory data // // byte status2: // b[1:0] fifo A operation type flags: // // 2'b00 no-op // 2'b01 FPGA control register write; // 2'b10 FPGA control register read; // 2'b11 Read memory data // // b[4:2] control/data register address // 3'b000 I2C // 3'b001 AD9650 // 3'b010 DAC // 3'b011 ADC121 // 3'b100 histogram control // 3'b101 AD9508 // 3'b110 Coluta // // module COLUTAV3_fpga ( input FPGA_CLK, //fpga clock, 40MHz system clock copy (LVPECL signaling) //I2C interface (1.2V) to COLUTA chip output SCL, //10 MHz I2C clock ...no pullup resistor on this line inout SDA, output RSTB, //output wire[1:0] chip_id, //fixed I2C address inside this version of COLUTA //COLUTA serializer data (LVDS signalig) input FRAME1, //serial data synchronized with 640MHz clock input DATA1, //serial data synchronized with 640MHz clock input DATA2, //serial data synchronized with 640MHz clock input DATA3, //serial data synchronized with 640MHz clock input DATA4, //serial data synchronized with 640MHz clock input DATA5, //serial data synchronized with 640MHz clock input DATA6, //serial data synchronized with 640MHz clock input DATA7, //serial data synchronized with 640MHz clock input DATA8, //serial data synchronized with 640MHz clock input FRAME8, //serial data synchronized with 640MHz clock //DRE ADC interface (1.8V signalig) output CLK_9650, //main ADC clock, LVDS signaling output SYNC, output CSB, output SCLK, inout SDIO, input ORA, input ORB, input DCOA, input DCOB, input wire [15:0] DA, input wire [15:0] DB, //DAC control signals (3.3V signaling) output DAC_RSTSEL, output DAC_RESET_b, output DAC_SCLK, output DAC_SYNC_b, output DAC_SDIN, input DAC_SDO, output DAC_LDAC_b, //dosimeter controls (1.2V signaling) output FPGA_IO1, output FPGA_IO2, //dosimeter ADC121 controls (3.3V signaling) output ADC121_CS, //chip select signal output ADC121_SCLK, //SCLK signal input ADC121_DATA1, //data from ADC#1 input ADC121_DATA2, //data from ADC#2 input ADC121_DATA3, //data from ADC#3 input ADC121_DATA4, //data from ADC#4 //AD9508 reset and sync signals output FPGA_9508_RSTB, output FPGA_9508_SYNCB, //Bunch crossing reset signal output BCRST, // USB interface signals (3.3V signaling) input RST_N, //RSTOUT# from FT2232 //fifo A inout wire [7:0] DATA_A, //fifo A DATA input RXF_A, //low active: data available in FIFO input TXE_A, //low active: data can be written into FIFO output RD_A, //ReaD enable, low to high transition output WR_A, //WRite enable, high to low transition output SI_WU_A, //SendImmediate/WakeUp //fifo B inout wire [7:0] DATA_B, //fifo B DATA input RXF_B, input TXE_B, output wire RD_B, output wire WR_B, output wire SI_WU_B, //programmable delay trigger output reg trigger, //interface to external pulser (3.3V signaling) // test points output wire TP1, output wire TP2, output wire TP_dummy //just to remove warnings about signals which do not drive logic ); //wires and registers wire [11:0] ADC121_DATA1_R, ADC121_DATA2_R, ADC121_DATA3_R, ADC121_DATA4_R; wire [7:0] I2C_rdback_mux, misc_mux; reg [639:0] I2C_cntrl; wire [639:0] I2C_shift_back; wire clk40, clk5_int, clk_40M_int; wire [7:0] dac_mux; wire [7:0] hist_cntrl_mux; reg [3:0] stw_cnt_rd, stw_cnt_wr; reg st_byte_read, st_byte_write; reg eoc_rd; reg [7:0] status1, status2, status3, status4, status5, status6; reg [23:0] AD9508_creg, AD9508_reg; reg fA_write, eoc_wr_A; reg [55:0] dac_reg, d_reg; reg [63:0] ad_reg, oc_reg; reg [31:0] hc_reg, hist_cntrl_reg; reg c_reg_load; wire [47:0] dac_back; reg [63:0] ADC121_creg, ADC121_reg; reg [17:0] fAw_cnt_rd; reg [6:0] fAw_cnt_wr; reg fA_read, eoc_rd_A; wire [7:0] Coluta_data_mux; reg status_rd_pulse, status_read_op; reg A_start_del, FIFO_A_op_start, FIFO_A_operation; reg rst, RST_N_flag; reg [4:0] rst_flg; reg [12:0] adc_counter_320; reg adc_write_op, adc_write_op_sync, eof_ADC_write, eof_enable; wire [15:0] coluta_deser_out1, coluta_deser_out2, coluta_deser_out3, coluta_deser_out4, coluta_deser_out5, coluta_deser_out6, coluta_deser_out7, coluta_deser_out8, adc9650_a_out, adc9650_b_out; wire [15:0] coluta_deser_outf1, coluta_deser_outf8; wire [47:0] adc121_out; reg start_op, dp_write_320, dp_write_320_del; wire clk320_trigger; wire last_i2c_ack, I2C_USB_done; reg adc121_done; wire pll3_locked; wire pll2_locked; wire [33:0] hist_data; // // Code body starts here // //static signals for FT2232 assign SI_WU_A = 1'b1; assign SI_WU_B = 1'b1; // static AD9650 assign SYNC = 1'b0; assign CSB = 1'b1; assign SCLK = 1'b0; assign SDIO = 1'bZ; //******************************************************************************* //***********************************CLOCKS************************************** //******************************************************************************* wire clk_40MHz_ad9650, clk_320MHz_coluta1, clk_320MHz_coluta2, clk_160MHz_dp_hist, pll0_locked, pll1_locked; // pll to create internal clocks **************** in_pll pll_0 ( .areset ( 1'b0 ), .inclk0 ( FPGA_CLK ), //40MHz input clock .c0 ( clk_40M_int ), //copy of FPGA_CLK .c1 ( clk40 ), //40 MHz clock in phase with FPGA_CLK .c2 ( clk5_int ), //5 MHz clock for COLUTA slow control and FT2232 comunication .c3 ( clk320_trigger ), //320 MHz clock for the trigger .locked ( pll0_locked ) ); //clocks for AD9650, COLUTA and Ray's ADC pll_640MHz pll_1 ( .areset ( 1'b0 ), .inclk0 ( clk_40M_int ), .c0 ( clk_40MHz_ad9650 ), // 40MHz .c1 ( clk_320MHz_coluta1 ), //320MHz .c2 ( clk_320MHz_coluta2 ), //320MHz .c3 ( clk_160MHz_dp_hist ), //160MHz for dual port memories and histogram package .locked ( pll1_locked ) ); //AD9650 clock assign CLK_9650 = clk_40MHz_ad9650; //******************************************************************************* //*******************************CLOCKS END************************************** //******************************************************************************* //******************************************************************************* //******************************FIFO B part************************************** //******************************************************************************* //FIFO B is used for status register read/write operation //this register controls all operations in the FPGA // //Status word description //byte status1: // b[7:0] "11111110" (FE, read only) // //byte status2: // b[1:0] fifo A operation type flags: // // 2'b00 no-op // 2'b01 FPGA control register write; // 2'b10 FPGA control register read; // 2'b11 Read memory data // // b[4:2] control/data register address // 3'b000 I2C // 3'b001 AD9650 // 3'b010 DAC // 3'b011 ADC121 // 3'b100 histogram control // 3'b101 AD9508 // 3'b110 Coluta // // // // b[5] resetB for COLUTA chip // b[6] reserved // b[7] reserved // //byte status3: // b[7:0] fifo A read/write byte counter (low byte) // For control data write operation it (5 least signficant bits are used) // defines the number of bytes sent to internal buffer. // // //byte status4: // b[7:0] fifo A read byte counter (high byte) // //byte status5: // b[0] start control data operation (execute data register commands) // b[1] pulse command (increment pulse delay counter) // b[2] COLUTA analog measurement start // b[3] reset trigger pulse delay // // b[4] reserved // b[5] software reset (0-1 transition starts operation) // b[6] start FIFO A operation, load FIFO A data into FPGA control register (0-1 transition starts operation) // or read FPGA control register to FIFO A // b[7] read the status word (0-1 transition starts operation) // // //byte status6: // b[7:0] all "11111111" (FF, read only) //******************************************************************************* // //status word write operation. Status data are received from fifo B // reg [3:0] rst_del; always @ (posedge clk5_int) begin //status write operation is always executed as soon as there are data //in the fifo B output //PC is the master of status comunication, it must deliver exactly 6 bytes of status !!!!!!!!!!!!!! if (RXF_B==1'b1) st_byte_write <= 1'b0; else if (st_byte_write==1'b1) st_byte_write <= 1'b0; else if (RXF_B==1'b0) st_byte_write <= 1'b1; //counter for number of status bytes to write if ((st_byte_write==1'b1) & (DATA_B[7:0]==8'b11111111)) stw_cnt_wr <= 4'b0000; else if ((st_byte_write==1'b1) & (DATA_B[7:0]==8'b11111110)) stw_cnt_wr <= 4'b0001; else if ( st_byte_write==1'b1) stw_cnt_wr <= stw_cnt_wr + 4'b0001; //reset rst_flg[4:0] <= {rst_flg[3:0],status5[5]}; //status word reset RST_N_flag <= RST_N; //reset from FTDI rst_del[0] <= !RST_N_flag | (rst_flg[3] & !rst_flg[4]); rst_del[3:1] <= rst_del[2:0]; rst <= rst_del[3]; //status registers if (st_byte_write==1'b1 & stw_cnt_wr==4'b0000) status1[7:0] <= DATA_B[7:0]; else if(st_byte_write==1'b1 & stw_cnt_wr==4'b0001) status2[7:0] <= DATA_B[7:0]; else if(st_byte_write==1'b1 & stw_cnt_wr==4'b0010) status3[7:0] <= DATA_B[7:0]; else if(st_byte_write==1'b1 & stw_cnt_wr==4'b0011) status4[7:0] <= DATA_B[7:0]; else if(st_byte_write==1'b1 & stw_cnt_wr==4'b0100) status5[7:0] <= DATA_B[7:0]; else if(st_byte_write==1'b1 & stw_cnt_wr==4'b0101) status6[7:0] <= DATA_B[7:0]; end //this is a read operation for FT2232!!!! assign RD_B = !(st_byte_write); // //status word read operation. The data are sent to fifo B // reg [5:0] stat_del; always @ (posedge clk5_int) begin //leading edge of status5[7] starts read operation //restart is posible by writing into status5[7] sequence 0 1 stat_del[0] <= status5[7]; stat_del[5:1] <= stat_del[4:0]; status_rd_pulse <= !stat_del[5] & status5[7]; if (rst==1'b1 | eoc_rd==1'b1) status_read_op <= 1'b0; else if (status_rd_pulse==1'b1) status_read_op <= 1'b1; //counter for number of status bytes to be read if (rst==1'b1 | eoc_rd==1'b1) stw_cnt_rd <= 4'b0000; else if (st_byte_read==1'b1) stw_cnt_rd <= stw_cnt_rd + 4'b0001; //status read operation is initiated by status word write operation //by setting status5[7] (read the status word flag) to 1 if (rst==1'b1 | TXE_B==1'b1) st_byte_read <= 1'b0; else if (st_byte_write==1'b1) st_byte_read <= 1'b0; else if (st_byte_read==1'b1) st_byte_read <= 1'b0; //read status is possible only after write operation is finished else if (TXE_B==1'b0 & status_read_op & stw_cnt_wr==4'b0000) st_byte_read <= 1'b1; //end of read cycle if (st_byte_read & (stw_cnt_rd==4'b0101)) eoc_rd <= 1'b1; else eoc_rd <= 1'b0; end //be carefull, this is a write operation for FT2232 !!! assign WR_B = st_byte_read; //mux for status register read assign DATA_B = (st_byte_read==1'b1 & stw_cnt_rd==4'b0000) ? status1 : (st_byte_read==1'b1 & stw_cnt_rd==4'b0001) ? status2 : (st_byte_read==1'b1 & stw_cnt_rd==4'b0010) ? status3 : (st_byte_read==1'b1 & stw_cnt_rd==4'b0011) ? status4 : (st_byte_read==1'b1 & stw_cnt_rd==4'b0100) ? status5 : (st_byte_read==1'b1 & stw_cnt_rd==4'b0101) ? status6 : 8'bZZZZZZZZ; // //******************************************************************************* //******************************FIFO A part************************************** //******************************************************************************* // fifo A is used to read/write data from/to COLUTA chip // // //send data from fifo A into FPGA // always @ (posedge clk5_int) begin //leading edge of status5[6] starts FIFO A operation A_start_del <= status5[6]; FIFO_A_op_start <= !A_start_del & status5[6]; if (rst==1'b1 | eoc_wr_A==1'b1 | eoc_rd_A==1'b1) FIFO_A_operation <= 1'b0; else if (FIFO_A_op_start==1'b1) FIFO_A_operation <= 1'b1; //counter for number of data bytes to write if (rst==1'b1 | eoc_wr_A==1'b1) fAw_cnt_wr <= 7'b0000001; else if (fA_write==1'b1) fAw_cnt_wr <= fAw_cnt_wr + 7'b0000001; //data byte write operation is initiated by PC software if (rst==1'b1 | RXF_A==1'b1 | status2[1:0]!=2'b01) fA_write <= 1'b0; else if (fA_write==1'b1) fA_write <= 1'b0; else if (RXF_A==1'b0 & FIFO_A_operation==1'b1) fA_write <= 1'b1; //end of write cycle if (FIFO_A_operation==1'b0) eoc_wr_A <= 1'b0; else if ((fAw_cnt_wr[6:0]==status3[6:0])&(status2[1:0]==2'b01)) eoc_wr_A <= 1'b1; else eoc_wr_A <= 1'b0; //64 bit scan chain control register if (FIFO_A_op_start==1'b1) I2C_cntrl <= {640{1'b0}}; else if ((status2[4:0]==5'b00001)&(fA_write==1'b1)) I2C_cntrl <= { DATA_A, I2C_cntrl[639:8] }; //AD9650 chip is working in default mode //so no control register in this FPGA code version //64 bit DAC control register if (FIFO_A_op_start==1'b1) d_reg <= {56{1'b0}}; else if ((status2[4:0]==5'b01001)&(fA_write==1'b1)) d_reg <= { DATA_A, d_reg[55:8] }; //ADC121 control register if (FIFO_A_op_start==1'b1) ADC121_reg <= {64{1'b0}}; else if ((status2[4:0]==5'b01101)&(fA_write==1'b1)) ADC121_reg <= { DATA_A, ADC121_reg[63:8] }; //64 bit histogram control register if (FIFO_A_op_start==1'b1) hc_reg <= {32{1'b0}}; else if ((status2[4:0]==5'b10001)&(fA_write==1'b1)) hc_reg <= { DATA_A, hc_reg[31:8] }; //24 bit AD9508 control register if (FIFO_A_op_start==1'b1) AD9508_reg <= {24{1'b0}}; else if ((status2[4:0]==5'b10101)&(fA_write==1'b1)) AD9508_reg <= { DATA_A, AD9508_reg[23:8] }; c_reg_load <= eoc_wr_A; if ((c_reg_load==1'b1)&(status2[4:0]==5'b01001)) dac_reg <= d_reg; if ((c_reg_load==1'b1)&(status2[4:0]==5'b10001)) hist_cntrl_reg <= hc_reg; if ((c_reg_load==1'b1)&(status2[4:0]==5'b10101)) AD9508_creg <= AD9508_reg; if ((c_reg_load==1'b1)&(status2[4:0]==5'b01101)) ADC121_creg <= ADC121_reg; end //this is a read operation for FT2232!!!! assign RD_A = !(fA_write); // //send data from FPGA into fifo A // reg fA_read_del; always @ (posedge clk5_int) begin //counter for number of status bytes to write //before you start read operation send 2'b00 to status2[1:0] if (rst==1'b1 | eoc_rd_A==1'b1 | (status2[1:0]==2'b00 | status2[1:0]==2'b01)) fAw_cnt_rd <= {18{1'b0}}; else if (fA_read==1'b1) fAw_cnt_rd <= fAw_cnt_rd + 18'b000000000000000001; //FPGA data read operation is active //as soon as status register allows it if (rst==1'b1 | status2[1:0]==2'b00 | status2[1:0]==2'b01) fA_read <= 1'b0; else if (fA_read==1'b1) fA_read <= 1'b0; else if (fA_read_del==1'b1) fA_read <= 1'b0; else if (TXE_A==1'b1) fA_read <= 1'b0; else if (TXE_A==1'b0 & FIFO_A_operation==1'b1 & eoc_rd_A== 1'b0) fA_read <= 1'b1; fA_read_del <= fA_read; // To provide delay to the counter so as to avoid extra clock cycle after EOC for reg A is issued. //end of read cycle is set to "1" if //number of bytes transmitted agrees with status word counter if ((fAw_cnt_rd=={status4[5:0],status3,4'b0000})& // 16bytes per sample (status2[1:0]==2'b10 | status2[1:0]==2'b11)) eoc_rd_A <= 1'b1; else eoc_rd_A <= 1'b0; end //this is a write operation for FT2232 !!! assign WR_A = fA_read; wire [7:0] ADC121_data_mux; wire [7:0] AD9650_data_mux, hist_data_mux; assign DATA_A = (fA_read==1'b1 & status2[4:0]==5'b00010) ? I2C_rdback_mux : (fA_read==1'b1 & status2[4:0]==5'b01010) ? dac_mux : (fA_read==1'b1 & status2[4:0]==5'b01110) ? misc_mux : (fA_read==1'b1 & status2[4:0]==5'b10010) ? hist_cntrl_mux : (fA_read==1'b1 & status2[4:0]==5'b00111) ? AD9650_data_mux : (fA_read==1'b1 & status2[4:0]==5'b01111) ? ADC121_data_mux : (fA_read==1'b1 & status2[4:0]==5'b10011) ? hist_data_mux : (fA_read==1'b1 & status2[4:0]==5'b11011) ? Coluta_data_mux : 8'bZZZZZZZZ; // // mux for control register read (to fifo A) // assign dac_mux = (fAw_cnt_rd[2:0]==3'b000) ? dac_back[ 7: 0] : (fAw_cnt_rd[2:0]==3'b001) ? dac_back[15: 8] : (fAw_cnt_rd[2:0]==3'b010) ? dac_back[23:16] : (fAw_cnt_rd[2:0]==3'b011) ? dac_back[31:24] : (fAw_cnt_rd[2:0]==3'b100) ? dac_back[39:32] : (fAw_cnt_rd[2:0]==3'b100) ? dac_back[47:40] : 8'b00000000; assign misc_mux = (fAw_cnt_rd[2:0]==3'b000) ? {1'b0, I2C_USB_done, last_i2c_ack, adc121_done, pll3_locked, pll2_locked, pll1_locked, pll0_locked } : 8'b00000000; // //reading histogram control register // assign hist_cntrl_mux = (fAw_cnt_rd[2:0]==3'b000) ? hist_cntrl_reg[ 7: 0] : (fAw_cnt_rd[2:0]==3'b001) ? hist_cntrl_reg[15: 8] : (fAw_cnt_rd[2:0]==3'b010) ? hist_cntrl_reg[23:16] : (fAw_cnt_rd[2:0]==3'b011) ? hist_cntrl_reg[31:24] : 8'b11111111; // //reading COLUTA data into fifo A // wire [12:0] dp_ADC_rdaddr; assign dp_ADC_rdaddr = fAw_cnt_rd[17:5]; assign Coluta_data_mux = (fAw_cnt_rd[4:0]==5'b00000) ? {coluta_deser_outf1[ 7: 0]} : //frame 1 (fAw_cnt_rd[4:0]==5'b00001) ? {coluta_deser_outf1[15: 8]} : (fAw_cnt_rd[4:0]==5'b00010) ? {coluta_deser_out1[ 7: 0]} : //channel 1 (fAw_cnt_rd[4:0]==5'b00011) ? {coluta_deser_out1[15: 8]} : (fAw_cnt_rd[4:0]==5'b00100) ? {coluta_deser_out2[ 7: 0]} : //channel 2 (fAw_cnt_rd[4:0]==5'b00101) ? {coluta_deser_out2[15: 8]} : (fAw_cnt_rd[4:0]==5'b00110) ? {coluta_deser_out3[ 7: 0]} : //channel 3 (fAw_cnt_rd[4:0]==5'b00111) ? {coluta_deser_out3[15: 8]} : (fAw_cnt_rd[4:0]==5'b01000) ? {coluta_deser_out4[ 7: 0]} : //channel 4 (fAw_cnt_rd[4:0]==5'b01001) ? {coluta_deser_out4[15: 8]} : (fAw_cnt_rd[4:0]==5'b01010) ? {coluta_deser_outf8[ 7: 0]} : //frame 8 (fAw_cnt_rd[4:0]==5'b01011) ? {coluta_deser_outf8[15: 8]} : (fAw_cnt_rd[4:0]==5'b01100) ? {coluta_deser_out5[ 7: 0]} : //channel 5 (fAw_cnt_rd[4:0]==5'b01101) ? {coluta_deser_out5[15: 8]} : (fAw_cnt_rd[4:0]==5'b01110) ? {coluta_deser_out6[ 7: 0]} : //channel 6 (fAw_cnt_rd[4:0]==5'b01111) ? {coluta_deser_out6[15: 8]} : (fAw_cnt_rd[4:0]==5'b10000) ? {coluta_deser_out7[ 7: 0]} : //channel 7 (fAw_cnt_rd[4:0]==5'b10001) ? {coluta_deser_out7[15: 8]} : (fAw_cnt_rd[4:0]==5'b10010) ? {coluta_deser_out8[ 7: 0]} : //channel 8 (fAw_cnt_rd[4:0]==5'b10011) ? {coluta_deser_out8[15: 8]} : 8'b00000000; //reading AD9650 ADC data into fifo A wire [12:0] dp_AD9650_rdaddr; assign dp_AD9650_rdaddr = fAw_cnt_rd[14:2]; assign AD9650_data_mux = (fAw_cnt_rd[1:0]==2'b00) ? {adc9650_a_out [ 7: 0]} : //AD9650 channel A (fAw_cnt_rd[1:0]==2'b01) ? {adc9650_a_out [15: 8]} : (fAw_cnt_rd[1:0]==2'b10) ? {adc9650_b_out [ 7: 0]} : //AD9650 channel B (fAw_cnt_rd[1:0]==2'b11) ? {adc9650_b_out [15: 8]} : 8'b00000000; // //reading histogram data into fifo A //PC will get 5 bytes for each histogram bin: // 12bits of bin number [33:22] and 22bits of bin count [21:0] // wire [12:0] dp_hist_rdaddr; assign dp_hist_rdaddr = fAw_cnt_rd[15:3]; assign hist_data_mux = (fAw_cnt_rd[2:0]==3'b000) ? { hist_data[ 7: 0]} : (fAw_cnt_rd[2:0]==3'b001) ? { hist_data[15: 8]} : (fAw_cnt_rd[2:0]==3'b010) ? { hist_data[23:16]} : (fAw_cnt_rd[2:0]==3'b011) ? { hist_data[31:24]} : (fAw_cnt_rd[2:0]==3'b100) ? {6'b111100, hist_data[33:32]} : 8'b00000000; //readind ADC121 dp memory data into fifo A wire [11:0] dp_ADC121_rdaddr; assign dp_ADC121_rdaddr = fAw_cnt_rd[14:3]; assign ADC121_data_mux = (fAw_cnt_rd[2:0]==3'b000) ? {adc121_out[ 7: 0]} : (fAw_cnt_rd[2:0]==3'b001) ? {adc121_out[15: 8]} : (fAw_cnt_rd[2:0]==3'b010) ? {adc121_out[23:16]} : (fAw_cnt_rd[2:0]==3'b011) ? {adc121_out[31:24]} : (fAw_cnt_rd[2:0]==3'b100) ? {adc121_out[39:32]} : (fAw_cnt_rd[2:0]==3'b101) ? {adc121_out[47:40]} :8'b00000000; // // mux for I2C shift register read (to fifo A) // assign I2C_rdback_mux = (fAw_cnt_rd[6:0]==7'b0000000) ? I2C_shift_back[ 7: 0] : (fAw_cnt_rd[6:0]==7'b0000001) ? I2C_shift_back[ 15: 8] : (fAw_cnt_rd[6:0]==7'b0000010) ? I2C_shift_back[ 23: 16] : (fAw_cnt_rd[6:0]==7'b0000011) ? I2C_shift_back[ 31: 24] : (fAw_cnt_rd[6:0]==7'b0000100) ? I2C_shift_back[ 39: 32] : (fAw_cnt_rd[6:0]==7'b0000101) ? I2C_shift_back[ 47: 40] : (fAw_cnt_rd[6:0]==7'b0000110) ? I2C_shift_back[ 55: 48] : (fAw_cnt_rd[6:0]==7'b0000111) ? I2C_shift_back[ 63: 56] : (fAw_cnt_rd[6:0]==7'b0001000) ? I2C_shift_back[ 71: 64] : (fAw_cnt_rd[6:0]==7'b0001001) ? I2C_shift_back[ 79: 72] : (fAw_cnt_rd[6:0]==7'b0001010) ? I2C_shift_back[ 87: 80] : (fAw_cnt_rd[6:0]==7'b0001011) ? I2C_shift_back[ 95: 88] : (fAw_cnt_rd[6:0]==7'b0001100) ? I2C_shift_back[103: 96] : (fAw_cnt_rd[6:0]==7'b0001101) ? I2C_shift_back[111: 104] : (fAw_cnt_rd[6:0]==7'b0001110) ? I2C_shift_back[119: 112] : (fAw_cnt_rd[6:0]==7'b0001111) ? I2C_shift_back[127: 120] : (fAw_cnt_rd[6:0]==7'b0010000) ? I2C_shift_back[135: 128] : (fAw_cnt_rd[6:0]==7'b0010001) ? I2C_shift_back[143: 136] : (fAw_cnt_rd[6:0]==7'b0010010) ? I2C_shift_back[151: 144] : (fAw_cnt_rd[6:0]==7'b0010011) ? I2C_shift_back[159: 152] : (fAw_cnt_rd[6:0]==7'b0010100) ? I2C_shift_back[167: 160] : (fAw_cnt_rd[6:0]==7'b0010101) ? I2C_shift_back[175: 168] : (fAw_cnt_rd[6:0]==7'b0010110) ? I2C_shift_back[183: 176] : (fAw_cnt_rd[6:0]==7'b0010111) ? I2C_shift_back[191: 184] : (fAw_cnt_rd[6:0]==7'b0011000) ? I2C_shift_back[199: 192] : (fAw_cnt_rd[6:0]==7'b0011001) ? I2C_shift_back[207: 200] : (fAw_cnt_rd[6:0]==7'b0011010) ? I2C_shift_back[215: 208] : (fAw_cnt_rd[6:0]==7'b0011011) ? I2C_shift_back[223: 216] : (fAw_cnt_rd[6:0]==7'b0011100) ? I2C_shift_back[231: 224] : (fAw_cnt_rd[6:0]==7'b0011101) ? I2C_shift_back[239: 232] : (fAw_cnt_rd[6:0]==7'b0011110) ? I2C_shift_back[247: 240] : (fAw_cnt_rd[6:0]==7'b0011111) ? I2C_shift_back[255: 248] : (fAw_cnt_rd[6:0]==7'b0100000) ? I2C_shift_back[263: 256] : (fAw_cnt_rd[6:0]==7'b0100001) ? I2C_shift_back[271: 264] : (fAw_cnt_rd[6:0]==7'b0100010) ? I2C_shift_back[279: 272] : (fAw_cnt_rd[6:0]==7'b0100011) ? I2C_shift_back[287: 280] : (fAw_cnt_rd[6:0]==7'b0100100) ? I2C_shift_back[295: 288] : (fAw_cnt_rd[6:0]==7'b0100101) ? I2C_shift_back[303: 296] : (fAw_cnt_rd[6:0]==7'b0100110) ? I2C_shift_back[311: 304] : (fAw_cnt_rd[6:0]==7'b0100111) ? I2C_shift_back[319: 312] : (fAw_cnt_rd[6:0]==7'b0101000) ? I2C_shift_back[327: 320] : (fAw_cnt_rd[6:0]==7'b0101001) ? I2C_shift_back[335: 328] : (fAw_cnt_rd[6:0]==7'b0101010) ? I2C_shift_back[343: 336] : (fAw_cnt_rd[6:0]==7'b0101011) ? I2C_shift_back[351: 344] : (fAw_cnt_rd[6:0]==7'b0101100) ? I2C_shift_back[359: 352] : (fAw_cnt_rd[6:0]==7'b0101101) ? I2C_shift_back[367: 360] : (fAw_cnt_rd[6:0]==7'b0101110) ? I2C_shift_back[375: 368] : (fAw_cnt_rd[6:0]==7'b0101111) ? I2C_shift_back[383: 376] : (fAw_cnt_rd[6:0]==7'b0110000) ? I2C_shift_back[391: 384] : (fAw_cnt_rd[6:0]==7'b0110001) ? I2C_shift_back[399: 392] : (fAw_cnt_rd[6:0]==7'b0110010) ? I2C_shift_back[407: 400] : (fAw_cnt_rd[6:0]==7'b0110011) ? I2C_shift_back[415: 408] : (fAw_cnt_rd[6:0]==7'b0110100) ? I2C_shift_back[423: 416] : (fAw_cnt_rd[6:0]==7'b0110101) ? I2C_shift_back[431: 424] : (fAw_cnt_rd[6:0]==7'b0110110) ? I2C_shift_back[439: 432] : (fAw_cnt_rd[6:0]==7'b0110111) ? I2C_shift_back[447: 440] : (fAw_cnt_rd[6:0]==7'b0111000) ? I2C_shift_back[455: 448] : (fAw_cnt_rd[6:0]==7'b0111001) ? I2C_shift_back[463: 456] : (fAw_cnt_rd[6:0]==7'b0111010) ? I2C_shift_back[471: 464] : (fAw_cnt_rd[6:0]==7'b0111011) ? I2C_shift_back[479: 472] : (fAw_cnt_rd[6:0]==7'b0111100) ? I2C_shift_back[487: 480] : (fAw_cnt_rd[6:0]==7'b0111101) ? I2C_shift_back[495: 488] : (fAw_cnt_rd[6:0]==7'b0111110) ? I2C_shift_back[503: 496] : (fAw_cnt_rd[6:0]==7'b0111111) ? I2C_shift_back[511: 504] : (fAw_cnt_rd[6:0]==7'b1000000) ? I2C_shift_back[519: 512] : (fAw_cnt_rd[6:0]==7'b1000001) ? I2C_shift_back[527: 520] : (fAw_cnt_rd[6:0]==7'b1000010) ? I2C_shift_back[535: 528] : (fAw_cnt_rd[6:0]==7'b1000011) ? I2C_shift_back[543: 536] : (fAw_cnt_rd[6:0]==7'b1000100) ? I2C_shift_back[551: 544] : (fAw_cnt_rd[6:0]==7'b1000101) ? I2C_shift_back[559: 552] : (fAw_cnt_rd[6:0]==7'b1000110) ? I2C_shift_back[567: 560] : (fAw_cnt_rd[6:0]==7'b1000111) ? I2C_shift_back[575: 568] : (fAw_cnt_rd[6:0]==7'b1001000) ? I2C_shift_back[583: 576] : (fAw_cnt_rd[6:0]==7'b1001001) ? I2C_shift_back[591: 584] : (fAw_cnt_rd[6:0]==7'b1001010) ? I2C_shift_back[599: 592] : (fAw_cnt_rd[6:0]==7'b1001011) ? I2C_shift_back[607: 600] : (fAw_cnt_rd[6:0]==7'b1001100) ? I2C_shift_back[615: 608] : (fAw_cnt_rd[6:0]==7'b1001101) ? I2C_shift_back[623: 616] : (fAw_cnt_rd[6:0]==7'b1001110) ? I2C_shift_back[631: 624] : (fAw_cnt_rd[6:0]==7'b1001111) ? I2C_shift_back[639: 632] :8'b00000000; //******************************************************************************* //******************************************************************************* //reset and start flags (common synchronization) //******************************************************************************* //******************************************************************************* reg reset_1, ad9508_reset, adc121_reset, hist_reset0, hist_reset1, hist_reset, dac_reset, i2c_reset, analog_start1, analog_start, pulser_start, ADC121_start, control_start1, usb_dac_start, usb_hist_start, usb_i2c_start, usb_adc121_start, usb_ad9508_start; reg init_read_hist, fill_hist ; reg [4:0] control_start_del, analog_start_del; always @(posedge clk40) begin reset_1 <= rst; //leading edge detected control_start_del <= (control_start_del << 1) | status5[0]; analog_start_del <= (analog_start_del << 1) | status5[2]; control_start1 <= ~control_start_del[4] & control_start_del[3]; analog_start1 <= ~analog_start_del [4] & analog_start_del [3]; end always @(posedge clk40) begin hist_reset0 <= reset_1; hist_reset1 <= hist_reset0; hist_reset <= hist_reset1; dac_reset <= reset_1; i2c_reset <= reset_1; adc121_reset <= reset_1; ad9508_reset <= reset_1; analog_start <= analog_start1; pulser_start <= analog_start1; ADC121_start <= analog_start1; usb_dac_start <= (status2[4:0]==5'b01001) & control_start1; usb_hist_start <= (status2[4:0]==5'b10001) & control_start1; usb_i2c_start <= (status2[4:0]==5'b00001) & control_start1; usb_adc121_start <= (status2[4:0]==5'b01101) & control_start1; usb_ad9508_start <= (status2[4:0]==5'b10101) & control_start1; fill_hist <= (hist_cntrl_reg[25:24]==2'b11); init_read_hist <= (hist_cntrl_reg[25:24]==2'b01) | (hist_cntrl_reg[25:24]==2'b10); end //******************************************************************************* //******************************************************************************* //******************************************************************************* //*******************COLUTA data deserializer implementation********************* //******************************************************************************* wire [4:0] data1_h, data1_l, data2_h, data2_l; reg [15:0] col_frame1, col_data_1, col_data_2, col_data_3, col_data_4, col_data_5, col_data_6, col_data_7, col_data_8, col_frame8; reg [15:0] adc_frame1, adc_data_1, adc_data_2, adc_data_3, adc_data_4, adc_frame8, adc_data_5, adc_data_6, adc_data_7, adc_data_8; reg [15:0] adc_frm1, adc_d_1, adc_d_2, adc_d_3, adc_d_4, adc_frm8, adc_d_5, adc_d_6, adc_d_7, adc_d_8; reg frame1_detected, frame8_detected; reg [15:0] adc_frame1_160, adc_data_1_160, adc_data_2_160, adc_data_3_160, adc_data_4_160, adc_frame8_160, adc_data_5_160, adc_data_6_160, adc_data_7_160, adc_data_8_160, adc_data_for_hist; reg dp_write_160; reg [12:0] adc_counter_160; reg col_meas_start, col_meas_start0, col_meas_start1, col_meas_start2; /* wire sca_empty; wire analog_start_br, analog_reset_br; //clock domain bridge start_op_bridge start_col_analog ( //start flags from USB .data ( {analog_start, analog_reset} ), .wrclk ( clk40 ), .wrreq ( 1'b1 ), .rdclk ( clk_320MHz_coluta ), .rdreq ( ~sca_empty ), .q ( {analog_start_br, analog_reset_br} ), .rdempty ( sca_empty ), .wrfull ( ) ); */ /* //Artificial COLUTA FRAME generated here //use that piece of code only if you do not have COLUTA chip reg cp40, cp40_del; wire FRAME; always @(posedge clk_320MHz_coluta) begin cp40 <= clk40; end always @(negedge clk_320MHz_coluta) begin cp40_del <= cp40; end assign FRAME = ~cp40_del & cp40; */ reg [12:0] col_start; always @(posedge clk_320MHz_coluta1) begin col_start <= {col_start[11:0], analog_start}; col_meas_start0 <= !col_start[12] & col_start[11]; col_meas_start1 <= col_meas_start0; col_meas_start2 <= col_meas_start1; col_meas_start <= col_meas_start2; end // //COLUTA data receivers working at 320MHz //both edges are used //Cyclone core cannot run at 640MHz // adc_rx adc_rx1 ( .datain ( {DATA4, DATA3, DATA2, DATA1, FRAME1} ), .inclock ( clk_320MHz_coluta1 ), .dataout_h ( data1_h[4:0] ), .dataout_l ( data1_l[4:0] ) ); adc_rx adc_rx2 ( .datain ( {DATA8, DATA7, DATA6, DATA5, FRAME8} ), .inclock ( clk_320MHz_coluta2 ), .dataout_h ( data2_h[4:0] ), .dataout_l ( data2_l[4:0] ) ); always @(posedge clk_320MHz_coluta1) begin //fast data shift registers col_frame1[15:0] <= {col_frame1[13:0], data1_l[0], data1_h[0]}; col_data_1[15:0] <= {col_data_1[13:0], data1_l[1], data1_h[1]}; col_data_2[15:0] <= {col_data_2[13:0], data1_l[2], data1_h[2]}; col_data_3[15:0] <= {col_data_3[13:0], data1_l[3], data1_h[3]}; col_data_4[15:0] <= {col_data_4[13:0], data1_l[4], data1_h[4]}; end always @(posedge clk_320MHz_coluta2) begin col_frame8[15:0] <= {col_frame8[13:0], data2_l[0], data2_h[0]}; col_data_5[15:0] <= {col_data_5[13:0], data2_l[1], data2_h[1]}; col_data_6[15:0] <= {col_data_6[13:0], data2_l[2], data2_h[2]}; col_data_7[15:0] <= {col_data_7[13:0], data2_l[3], data2_h[3]}; col_data_8[15:0] <= {col_data_8[13:0], data2_l[4], data2_h[4]}; end always @(posedge clk_320MHz_coluta1) begin frame1_detected <= (col_frame1[15:12]==4'b0010) & (col_frame1[5:0]==6'b000000) ; frame8_detected <= (col_frame8[15:12]==4'b0010) & (col_frame8[5:0]==6'b000000) ; //COLUTA data frame detected if (frame1_detected & frame8_detected) begin adc_frm1 <= col_frame1; adc_d_1 <= col_data_1; adc_d_2 <= col_data_2; adc_d_3 <= col_data_3; adc_d_4 <= col_data_4; adc_d_5 <= col_data_5; adc_d_6 <= col_data_6; adc_d_7 <= col_data_7; adc_d_8 <= col_data_8; adc_frm8 <= col_frame8; end //for better routing add one extra register //input signals are inverted adc_frame1 <= adc_frm1; adc_data_1 <= adc_d_1 ; adc_data_2 <= adc_d_2 ; adc_data_3 <= adc_d_3 ; adc_data_4 <= adc_d_4 ; adc_data_5 <= adc_d_5 ; adc_data_6 <= adc_d_6 ; adc_data_7 <= adc_d_7 ; adc_data_8 <= adc_d_8 ; adc_frame8 <= adc_frm8; //read state machine starts here if ((frame1_detected & frame8_detected) & (adc_write_op==1'b1)) dp_write_320 <= 1'b1; else dp_write_320 <= 1'b0; if (col_meas_start) adc_write_op_sync <= 1; else if (adc_write_op) adc_write_op_sync <= 0; if (adc_write_op_sync) adc_counter_320 <= {13{1'b1}}; else if (dp_write_320) adc_counter_320 <= adc_counter_320 + 13'b0000000000001; if (adc_write_op_sync & (frame1_detected & frame8_detected)) adc_write_op <= 1; else if (eof_ADC_write ) adc_write_op <= 0; if (col_meas_start) eof_enable <= 1'b0; else if (adc_counter_320=={13'b0111111111111}) eof_enable <= 1'b1; if (adc_write_op_sync) eof_ADC_write <= 0; else if (dp_write_320 & eof_enable & (adc_counter_320=={13'b1111111111111})) eof_ADC_write <= 1; dp_write_320_del <= dp_write_320; end //change the clock domain from 320MHz to 160MHz always @(posedge clk_160MHz_dp_hist) begin adc_counter_160 <= adc_counter_320; dp_write_160 <= dp_write_320 | dp_write_320_del; if (dp_write_160) begin adc_frame1_160 <= adc_frame1; adc_data_1_160 <= adc_data_1; adc_data_2_160 <= adc_data_2; adc_data_3_160 <= adc_data_3; adc_data_4_160 <= adc_data_4; adc_frame8_160 <= adc_frame8; adc_data_5_160 <= adc_data_5; adc_data_6_160 <= adc_data_6; adc_data_7_160 <= adc_data_7; adc_data_8_160 <= adc_data_8; end adc_data_for_hist <= adc_data_1; end //dual port memories to read data trough FTDI //This is 16 bit wide dual port ram for Coluta deserializer //dual port for the frame 1 dual_port_memory dp1 ( .data(adc_frame1_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_outf1) ); //dual port for channel 1 dual_port_memory dp2 ( .data(adc_data_1_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out1) ); //dual port for channel 2 dual_port_memory dp3 ( .data(adc_data_2_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out2) ); //dual port for channel 3 dual_port_memory dp4 ( .data(adc_data_3_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out3) ); //dual port for channel 4 dual_port_memory dp5 ( .data(adc_data_4_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out4) ); //dual port for the frame 8 dual_port_memory dp6 ( .data(adc_frame8_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_outf8) ); //dual port for channel 5 dual_port_memory dp7 ( .data(adc_data_5_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out5) ); //dual port for channel 6 dual_port_memory dp8 ( .data(adc_data_6_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out6) ); //dual port for channel 7 dual_port_memory dp9 ( .data(adc_data_7_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out7) ); //dual port for channel 8 dual_port_memory dp10 ( .data(adc_data_8_160), .wraddress(adc_counter_160), .wrclock (clk_160MHz_dp_hist), .wren(dp_write_160), .rdaddress(dp_ADC_rdaddr), .rdclock(clk5_int), .q(coluta_deser_out8) ); //********************************************************* //********************************************************* // * // Histogramming (COLUTA Channel 1 is histogrammed) * // * //********************************************************* reg h_op_start, hist_start0; reg [10:0] hist_start; reg [15:0] h_dat_r1; reg hrst, hrst0, hrst1; always @(posedge clk_160MHz_dp_hist) begin //histogram start flag hist_start <= {hist_start[9:0], (usb_hist_start | analog_start) }; hist_start0 <= ~hist_start[10] & hist_start[9]; h_op_start <= hist_start0 & (init_read_hist | fill_hist ) ; //an extra registers for better routing if (hist_cntrl_reg[26]==1'b0) h_dat_r1 <= adc_data_for_hist[11:0]; //adc_data_1_160; else h_dat_r1 <= adc_data_for_hist[15:4]; hrst0 <= hist_reset; hrst1 <= hrst0; hrst <= hrst1; end histogram h1 ( .rst (hrst), //master reset .clk (clk_160MHz_dp_hist), //clock .start_op (h_op_start), //pulse, hist operation start .hist_control (hist_cntrl_reg[25:0]), //control register .h_data (h_dat_r1[11:0]), //[11:0] data to be histogrammed, !!!! the width of data needs to be decided .h_rd_clk (clk5_int), //histogram memory output signals .h_rd_address (dp_hist_rdaddr[6:0]), .h_data_out (hist_data) ); //**************************************************************** // AD9650 data read operation //**************************************************************** // //AD9650 operation is synchronized with COLUTA data!!! // //channel A // wire DCOA_clk; wire clk_fifo_a_empty; wire [12:0] cha_counter; reg [15:0] ad9650_a_reg0, ad9650_a_reg; // clk_domain_bridge AD9650a_clk_domain_bridge ( .data ( {adc_counter_160, adc_write_op} ), .wrclk ( clk_160MHz_dp_hist ), .wrreq ( dp_write_160 ), .rdclk ( DCOA_clk ), .rdreq ( 1'b1 ), .q ( {cha_counter, adc_write_DCOA} ), .rdempty ( clk_fifo_a_empty ), .wrfull ( ) ); /* always @(posedge DCOA_clk) begin cha_counter <= adc_counter_160; end */ //dedicated PLL pll_40MHz pll_2 ( .inclk0 ( DCOA ), .c0 ( DCOA_clk ), //40 MHz clock .locked ( pll2_locked ) ); //input data register and dual port memory always @(posedge DCOA_clk) begin ad9650_a_reg0 <= DA; ad9650_a_reg <= ad9650_a_reg0; end dual_port_memory dpm1 ( .data(ad9650_a_reg), .wraddress(cha_counter), .wrclock (DCOA_clk), .wren(adc_write_DCOA), .rdaddress(dp_AD9650_rdaddr), .rdclock(clk5_int), .q(adc9650_a_out) ); // //channel B // wire DCOB_clk; wire clk_fifo_b_empty; wire [12:0] chb_counter; reg [15:0] ad9650_b_reg0, ad9650_b_reg; // clk_domain_bridge AD9650b_clk_domain_bridge ( .data ( {adc_counter_160, adc_write_op} ), .wrclk ( clk_160MHz_dp_hist ), .wrreq ( dp_write_160 ), .rdclk ( DCOB_clk ), .rdreq ( 1'b1 ), .q ( {chb_counter, adc_write_DCOB} ), .rdempty ( clk_fifo_b_empty ), .wrfull ( ) ); /* always @(posedge DCOB_clk) begin chb_counter <= adc_counter_160; end */ //dedicated PLL pll_40MHz pll_3 ( .inclk0 ( DCOB ), .c0 ( DCOB_clk ), //40 MHz clock .locked ( pll3_locked ) ); //input data register and dual port memory always @(posedge DCOB_clk) begin ad9650_b_reg0 <= DB; ad9650_b_reg <= ad9650_b_reg0; end dual_port_memory dpm2 ( .data(ad9650_b_reg), .wraddress(chb_counter), .wrclock (DCOB_clk), .wren(adc_write_DCOB), .rdaddress(dp_AD9650_rdaddr), .rdclock(clk5_int), .q(adc9650_b_out) ); //**************************************************************** //**************************************************************** //**************************************************************** //**************************DAC operations************************ //**************************************************************** //start flag reg[2:0] dac_start; always @(posedge clk40) begin dac_start[1:0] <= {dac_start[0], (usb_dac_start)}; dac_start[2] <= ~dac_start[1] & dac_start[0]; end dac dac1 ( .clk (clk40), .rst (dac_reset), .op_start (dac_start[2]), .AD5689_cntrl (dac_reg[55:0]), // .DAC_RSTSEL (DAC_RSTSEL), .DAC_RESET_b (DAC_RESET_b), .DAC_SCLK (DAC_SCLK), .DAC_SYNC_b (DAC_SYNC_b), .DAC_SDIN (DAC_SDIN), .DAC_SDO (DAC_SDO), .DAC_LDAC_b (DAC_LDAC_b), // .AD5689_data_back (dac_back[47:0]) ); //**************************************************************** //**************************************************************** // ***** I2C state machine ***** //**************************************************************** // procedure: // a/PC software loads control data register through fifo A // (USB control data stream) // b/PC software starts the execution of the I2C instruction // in the control data stream // c/I2C state machine(below) automaticaly ecexutes // all I2C commands in the queue // // wire [7:0] wb_dat_o,wb_dat_i; wire [2:0] wb_adr_i; wire wb_ack_o, wb_we_i, wb_stb_i, wb_cyc_i, scl_pad_o, scl_padoen_oe, sda_pad_o, sda_padoen_oe; wire scl_pad_i, sda_pad_i; //start flag reg[2:0] I2C_start; always @(posedge clk40) begin I2C_start[1:0] <= {I2C_start[0], (usb_i2c_start)}; I2C_start[2] <= ~I2C_start[1] & I2C_start[0]; end // //state machine converts USB control data stream into control sequence //for Wishbone compatible I2C master core // USB_I2C_state_machine usb_i2c_sm ( // .clk (clk40), .rst (i2c_reset), // I2C master core signals .i2c_reg_adr (wb_adr_i), .data_to_i2c (wb_dat_i), .data_from_i2c (wb_dat_o), .i2c_we (wb_we_i), .i2c_stb (wb_stb_i), .i2c_cyc (wb_cyc_i), .wb_ack_o (wb_ack_o), //USB command stream .i2c_operation_start(I2C_start[2]), .USB_cntr_in (I2C_cntrl), .USB_data_out (I2C_shift_back), .i2c_queue_done (I2C_USB_done), .last_i2c_ack (last_i2c_ack), .usb_tst1 () //test only ); //I2C interface to NevisADC chip i2c_master_top I2C ( .wb_clk_i (clk40), // master clock input .wb_rst_i (1'b0), // synchronous active high reset .arst_i (~i2c_reset), // asynchronous reset .wb_adr_i (wb_adr_i), // lower address bits (3bits) .wb_dat_i (wb_dat_i), // databus input (8bits) .wb_dat_o (wb_dat_o), // databus output (8bits) .wb_we_i (wb_we_i), // write enable input .wb_stb_i (wb_stb_i), // stobe/core select signal .wb_cyc_i (wb_cyc_i), // valid bus cycle input .wb_ack_o (wb_ack_o), // bus cycle acknowledge output .wb_inta_o (), // interrupt request signal output .scl_pad_i (scl_pad_i), //I2C bus signals .scl_pad_o (), .scl_padoen_o (scl_padoen_oe), .sda_pad_i (sda_pad_i), .sda_pad_o (sda_pad_o), .sda_padoen_o (sda_padoen_oe) ); //reg [3:0] sda_pad_o_del, sda_padoen_oe_del ; //always @(posedge clk40) // begin // sda_pad_o_del[0] <= sda_pad_o; // sda_pad_o_del[3:1] <= sda_pad_o_del[2:0]; // sda_padoen_oe_del[0] <= sda_padoen_oe; // sda_padoen_oe_del[3:1] <= sda_padoen_oe_del[2:0]; // end //I2C bus signals // assign SCL = scl_padoen_oe ? 1'bZ : scl_pad_o; //solution with no pull up resistor on SCL assign SCL = scl_padoen_oe; assign SDA = sda_padoen_oe ? 1'bZ : sda_pad_o; assign scl_pad_i = SCL; assign sda_pad_i = SDA; assign RSTB = !status2[5]; //resetB for COLUTA I2C&chip //chip_id is set inside COLUTA to "001" //assign chip_id[2:0] = {3'b001}; //chip id for COLUTA I2C protocol //*************************************************************************** //**********************Dosimeter and ADC121 code**************************** //*************************************************************************** // //this is to start ADC121 clocking sequence // wire dos_data_strobe; reg[2:0] adc_121_start; always @(posedge clk40) begin adc_121_start[1:0] <= {adc_121_start[0], (usb_adc121_start)}; adc_121_start[2] <= ~adc_121_start[1] & adc_121_start[0]; end ADC121 dos1 ( //module state machine inputs .clk (clk40), .rst (adc121_reset), .op_start (adc_121_start[2]), .ADC121_cntrl(ADC121_creg), //dosimeter controls (1.2V signaling) .SP_1p2_A(FPGA_IO1), .SP_1p2_B(FPGA_IO2), //ADC121 control signals .CS_b (ADC121_CS), .SCLK (ADC121_SCLK), .SDATA1 (ADC121_DATA1), .SDATA2 (ADC121_DATA2), .SDATA3 (ADC121_DATA3), .SDATA4 (ADC121_DATA4), //data_reg .Data1_reg (ADC121_DATA1_R), .Data2_reg (ADC121_DATA2_R), .Data3_reg (ADC121_DATA3_R), .Data4_reg (ADC121_DATA4_R), //data_strobe .data_strobe(dos_data_strobe) ); reg [2:0] dos_sampling; reg [11:0] dos_counter; reg [3:0] dos_rst_clk, dos_start_clk; reg dos_write_op; // //this is to start ADC121 data taking // always @(posedge clk40) begin dos_start_clk <= (dos_start_clk << 1) | ADC121_start; dos_rst_clk <= (dos_rst_clk << 1) | adc121_reset; if(dos_rst_clk[3]) begin dos_sampling <= 1'b0; dos_write_op <= 1'b0; adc121_done <= 1'b0; end else begin dos_sampling <= (dos_sampling << 1) | dos_start_clk[3]; if(!dos_write_op) begin if(!dos_sampling[2] && dos_sampling[1]) begin dos_counter <= {12{1'b0}}; dos_write_op <= 1'b1; adc121_done <= 1'b0; end end else begin if(dos_data_strobe) dos_counter <= dos_counter + 12'b000000000001; if(dos_counter == {12{1'b1}}) begin dos_write_op <= 1'b0; adc121_done <= 1'b1; end end end end //dual port memory #1 ADC121_dp_memory ADC121_dp1 ( .data ( {ADC121_DATA2_R[3:0], ADC121_DATA1_R[11:0]} ), .wraddress ( dos_counter ), .wrclock ( clk40 ), .wren ( dos_data_strobe ), .rdaddress ( dp_ADC121_rdaddr ), .rdclock ( clk5_int ), .q ( adc121_out[15:0] ) ); //dual port memory #2 ADC121_dp_memory ADC121_dp2 ( .data ( {ADC121_DATA3_R[7:0], ADC121_DATA2_R[11:4]} ), .wraddress ( dos_counter ), .wrclock ( clk40 ), .wren ( dos_data_strobe ), .rdaddress ( dp_ADC121_rdaddr ), .rdclock ( clk5_int ), .q ( adc121_out[31:16] ) ); //dual port memory #3 ADC121_dp_memory ADC121_dp3 ( .data ( {ADC121_DATA4_R[11:0], ADC121_DATA3_R[11:8]} ), .wraddress ( dos_counter ), .wrclock ( clk40 ), .wren ( dos_data_strobe ), .rdaddress ( dp_ADC121_rdaddr ), .rdclock ( clk5_int ), .q ( adc121_out[47:32] ) ); //*********************************************************************** //*********************************************************************** //*********************************************************************** //*******************AD9508 and Bunch crossing signal******************** //*********************************************************************** // //this is to start AD9508 sequence // reg[2:0] ad9508_start; always @(posedge clk40) begin ad9508_start[1:0] <= {ad9508_start[0], (usb_ad9508_start)}; ad9508_start[2] <= ~ad9508_start[1] & ad9508_start[0]; end //sequencer AD9508 AD9508_1 ( //module state machine inputs .clk (clk40), .rst (ad9508_reset), .op_start (ad9508_start[2]), .AD9508_cntrl(AD9508_creg), //AD9508 control signals .RSTB (FPGA_9508_RSTB), .SYNCB (FPGA_9508_SYNCB), .BCRST (BCRST) ); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //******************************************************************************* //***********external pulser interface - programmable delay trigger************** //******************************************************************************* //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! reg [3:0] delay_reg, delay_counter; reg [9:0] delay_start; reg [45:0]external_pulser_start; reg pulse_command, trigger_operation; always @ (posedge clk40) begin external_pulser_start[0] <= pulser_start; external_pulser_start[45:1] <= external_pulser_start[44:0]; //COLUTA analog measurement start if(status5[3]) delay_reg[3:0] <= 4'b1001; //reset the trigger delay counter else if (!external_pulser_start[35] && external_pulser_start[34] && status5[1]) begin delay_reg <= delay_reg - 4'b0001; //decrement delay counter end end always @ (posedge clk320_trigger) begin delay_start[0] <= external_pulser_start[2]; delay_start[9:1] <= delay_start[8:0]; if (delay_start[9]) trigger_operation <= 1'b1; else if (delay_counter[3:0]==4'b0000) trigger_operation <= 1'b0; if(!delay_start[3] && delay_start[2]) delay_counter <= delay_reg; else if(trigger_operation) delay_counter <= delay_counter - 4'b0001; if (external_pulser_start[45]) pulse_command <= 0; else if(delay_counter[3:0]==4'b0000) pulse_command <= 1; trigger <= pulse_command; end // //test points //these test points have the PCB routing // assign TP1 = SCL; assign TP2 = I2C_USB_done; // Dummy test point // just to remove warning about signals which do not drive logic // assigned pin position is T17, with io standard 3.3V CMOS // assign TP_dummy = ORA | ORB; endmodule