// module controls the DAC unit on the Analog_Testboard
// v1.0 jb/march/2019
//
//
//**************************************************************************
//
//  DAC (with external reference) is controled by SPI interface.
//
//
//  ******DAC9881_cntrl data format******
// DAC9881_cntrl[23:0]  SPI instruction register (see the datasheet)
//
// DAC9881_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'
//
// DAC9881_cntrl[31:26]      reserved
//
//**************************************************************************

//
//
module dac
 (  
  //module state machine inputs
  input clk,
  input rst,
  input op_start,
  input wire[31:0] DAC9881_cntrl,
		  
  //DAC control signals
  output     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 dara
  output reg[23:0] DAC9881_data_back
 );
		


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





always @(posedge clk or posedge rst)	
begin	
	if (rst) begin
     op_done       <= 1'b1; 
	  SPI_instr_reg <= {24{1'b0}};
     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; //SPI command detected
               op_starts    <= ~op_start_reg & op_start;
               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[23:0] <= DAC9881_cntrl[23:0];
               else if (next_cycle)  SPI_instr_reg[23:0] <= {SPI_instr_reg[22: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[23];                 
				
               // bit number register
               if (op_starts)       bit_num[4:0] <= 5'b10111;//23 decimal
               else if (next_cycle) bit_num[4:0] <= bit_num[4:0] - 5'b00001;
				
               //next cycle flag
               if (cph[11] & ~(bit_num==5'b00000)) next_cycle <= 1'b1;
               else                                next_cycle <= 1'b0;

               //operation done flag
               if (op_starts)                         op_done <= 1'b0;	
               else if ((bit_num==5'b00000)& 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					
               // DAC9881_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      (op_start          & DAC9881_cntrl[25]   ==1'b1 )  DAC_LDAC_b <= DAC9881_cntrl[24];
					else if (op_done & cph[11] & DAC9881_cntrl[25]   ==1'b1 )  DAC_LDAC_b <= 1'b1;  
               else if (op_start          & DAC9881_cntrl[25:24]==2'b00)  DAC_LDAC_b <= 1'b1;  
					else if (op_start          & DAC9881_cntrl[25:24]==2'b01)  DAC_LDAC_b <= 1'b1; 				
               else if (le_done[2]        & DAC9881_cntrl[25:24]==2'b01)  DAC_LDAC_b <= 1'b0;
               else if (DAC_LDAC_b==1'b0  & cph[11]==1'b1 & DAC9881_cntrl[25:24]==2'b01)      DAC_LDAC_b <= 1'b1;

     end	
end


//
//on the board the DAC_RESET_b is wired as CS_b!!!!
//
assign DAC_RESET_b = op_done;

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


  

endmodule				