//
//
// 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=1'b1, 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
		  //do not ever mess with this super ADC. read the manual!!

		  //56 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=1'b1, 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;
reg FRAME,FR1;
always @(posedge clk_320MHz_coluta1)
 begin	
  cp40   <= clk40;
  FRAME  <= FR1;    
 end
always @(negedge clk_320MHz_coluta1)
 begin
  cp40_del <= cp40;
  FR1      <= ~cp40_del & cp40;
 end 


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)
   if (FRAME) 
 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;               
    if ((FRAME) & (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;
    if      (adc_write_op_sync & (FRAME)) 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_160;
//    adc_data_for_hist <= ad9650_a_reg;
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  [11: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
//****************************************************************

//wire DCOA_A, DCOB_B;
//assign DCOA_A = clk40;
//assign DCOB_B = clk40;
//
//AD9650 operation is synchronized with COLUTA data!!!
//
//channel A		
//
wire        DCOA_clk;
wire        adc_write_DCOA;
wire        clk_fifo_a_empty;
wire [12:0] cha_counter;
reg  [15:0] ad9650_a_reg0, ad9650_a_reg;
//

//dedicated PLL
pll_40MHz	pll_2 
        (
         .inclk0 ( DCOA ),
			.areset ( ~RST_N ),
         .c0     ( DCOA_clk ),      //40 MHz clock
         .locked ( pll2_locked )
	    );	


clk_domain_bridge	AD9650a_clk 
  (
	.data    ( {adc_counter_160, adc_write_op} ),
	.wrclk   ( clk_160MHz_dp_hist ),
	.wrreq   ( dp_write_160 ),
	
	.rdclk   ( DCOA_clk ),
	.rdreq   ( ~clk_fifo_a_empty ),
	.q       ( {cha_counter, adc_write_DCOA} ),
	
	.rdempty ( clk_fifo_a_empty ),
	.wrfull  ( )
  );

/*
always @(posedge DCOA_clk)
begin
	cha_counter <= adc_counter_160;
end
*/

  
//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        adc_write_DCOB;
wire        clk_fifo_b_empty;
wire [12:0] chb_counter;
reg  [15:0] ad9650_b_reg0, ad9650_b_reg;
//

//dedicated PLL
pll_40MHz	pll_3 
        (
         .inclk0 ( DCOB ),
			.areset ( ~RST_N ),
         .c0     ( DCOB_clk ),      //40 MHz clock
         .locked ( pll3_locked )
	    );

clk_domain_bridge	AD9650b_clk 
  (
	.data    ( {adc_counter_160, adc_write_op} ),
	.wrclk   ( clk_160MHz_dp_hist ),
	.wrreq   ( dp_write_160 ),
	
	.rdclk   ( DCOB_clk ),
	.rdreq   ( ~clk_fifo_b_empty ),
	.q       ( {chb_counter, adc_write_DCOB} ),
	
	.rdempty ( clk_fifo_b_empty ),
	.wrfull  ( )
  );

/*
always @(posedge DCOB_clk)
begin
	chb_counter <= adc_counter_160;
end  
*/
  	

  
//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 =   dac_reg[28];   
   assign TP2 =   dac_reg[0]; 

//	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
