//
//
// module controls the AD5689 dual DAC unit on the COLUTA tester board
// v2.0 jb/august/2018
//
//
//**************************************************************************
//
//  AD5689 dual DAC (with external reference) is controled by SPI interface.
//  SPI interaface allows to write user data into input register
//  for both channels.
//  Input register is loaded to the DAC register using LDAC signal
//  or SPI instruction.
//  Reset pulse will update DAC registers with zero scale or midscale,
//  depending on the state of the RSTSEL pin
//
//  ******AD5689_cntrl data format******
//  AD5689_cntrl[23:0]  first SPI instruction register (see the datasheet)
//
//  AD5689_cntrl[25:24] LDAC control 
//                      00   no LDAC is generated
//                      01   LDAC is generated after current SPI instruction
//                      10   LDAC is permanently at '0'
//                      11   LDAC is permanently at '1'
//
//  AD5689_cntrl[26]    Reset control (1 reset pulse generated)
//  AD5689_cntrl[27]    RSTSEL signal state
//  AD5689_cntrl[28]    SPI command length (0 - 24 bit   1 - 48 bit)
//
//  AD5689_cntrl[52:29] second SPI instruction register (see the datasheet)
//  AD5689_cntrl[55:53] reserved
//
//**************************************************************************
//
//


module dac
     (  
        //module state machine inputs
        input clk,
		  input rst,
		  input op_start,
		  input wire[55:0] AD5689_cntrl,
		  
		  //DAC control signals
		  output reg DAC_RSTSEL,
		  output reg DAC_RESET_b,
		  output reg DAC_SCLK,
		  output reg DAC_SYNC_b,
		  output reg DAC_SDIN,
		  input      DAC_SDO,
		  output reg DAC_LDAC_b,
		  
		  //read back data
		  output reg[47:0] AD5689_data_back
		);
		


//variables			
reg        op_starts, rst_starts, op_start_reg, 
           rst_start_reg, cycle_start, next_cycle,
			  op_done;
reg [11:0] cph, rst_cph;
reg [47:0] SPI_instr_reg;
reg  [5:0] bit_num;
reg  [2:0] le_done;

//
// this is the main state machine
//
always @(posedge clk or posedge rst)	
begin	
	if (rst) begin
                  DAC_RSTSEL  <= 1'b0;      
	               DAC_RESET_b <= 1'b1; 
	               DAC_SCLK    <= 1'b0;  
                  DAC_SYNC_b  <= 1'b1;
                  DAC_SDIN    <= 1'b0;
                  DAC_LDAC_b  <= 1'b1;
                 end
else 
         begin
//******************************SPI operation*****************************************
               //basic bit cycle
               op_start_reg <= op_start & ~AD5689_cntrl[26]; //SPI command detected (no RESET command)
               op_starts    <= ~op_start_reg & op_start & ~AD5689_cntrl[26];
               cycle_start  <=  op_starts | next_cycle | le_done[2]; 
               cph[11:0]    <= {cph[10:0], cycle_start};

               //SPI instruction register
               if      (op_starts )  SPI_instr_reg[47:0] <= {AD5689_cntrl[23:0], AD5689_cntrl[52:29]};
               else if (next_cycle)  SPI_instr_reg[47:0] <= {SPI_instr_reg[46:0] , 1'b0};
		
               //SYNC signal
               if (op_starts)    DAC_SYNC_b <= 1'b0;
               else if (op_done) DAC_SYNC_b <= 1'b1;

               //SCLK signal
               if     (cph[5]  & ~op_done) DAC_SCLK  <=  1'b1;
               else if(cph[10] & ~op_done) DAC_SCLK  <=  1'b0; 

               //SPI SDIN signal 
               DAC_SDIN <= SPI_instr_reg[47];               
				
               // bit number register
               if      (op_starts & ~AD5689_cntrl[28]) bit_num[5:0] <= 6'b010111;//SPI instr lenght is 23
					else if (op_starts &  AD5689_cntrl[28]) bit_num[5:0] <= 6'b101111;//SPI instr lenght is 47
               else if (next_cycle)                    bit_num[5:0] <= bit_num[5:0] - 6'b000001;
				
               //next cycle flag
               if (cph[11] & ~(bit_num==6'b000000)) next_cycle <= 1'b1;
               else                                 next_cycle <= 1'b0;

               //operation done flag
               if (op_starts)                          op_done <= 1'b0;	
               else if ((bit_num==6'b000000)& cph[11]) op_done <= 1'b1;
					
               //leading edge of operation done 
               le_done[1:0] <= {le_done[0], DAC_SYNC_b};
               le_done[2]   <= ~le_done[1] & le_done[0];
					
               //  LDAC					
               //  AD5689_cntrl[25:24] LDAC control 
               //                      00   no LDAC is generated
               //                      01   LDAC is generated after current SPI instruction
               //                      10   LDAC is permanently at '0'
               //                      11   LDAC is permanently at '1'
               if      (AD5689_cntrl[25]==1'b1)               DAC_LDAC_b <= AD5689_cntrl[24];
               else if (le_done[2] & AD5689_cntrl[24])        DAC_LDAC_b <= 1'b0;
               else if ((DAC_LDAC_b==1'b0) & (cph[11]==1'b1)) DAC_LDAC_b <= 1'b1;
					
					
//******************************RESET operation*****************************************
//  AD5689_cntrl[26]     Reset control (1 reset pulse generated)
//  AD5689_cntrl[27]     RSTSEL signal state
               //basic bit cycle
               rst_start_reg <= op_start & AD5689_cntrl[26]; //RESET command detected
               rst_starts    <= ~rst_start_reg & op_start & AD5689_cntrl[26];
               rst_cph[11:0] <= {rst_cph[10:0], rst_starts};
					
               //RSTSEL signal
               DAC_RSTSEL <= AD5689_cntrl[27];

               //RESET signal
               if (rst_starts)       DAC_RESET_b <= 1'b0;
               else if (rst_cph[11]) DAC_RESET_b <= 1'b1;
         end	
end

//read back register
always @(negedge DAC_SCLK)
  begin
   if (DAC_SYNC_b==1'b0) AD5689_data_back[47:0] <= {AD5689_data_back[46:0], DAC_SDO};
  end


  

endmodule				