//************************************************************************
//
// module loads/reads 40 bits of control information to/from COLUTA chip
// v1.0 jb/june/2017
//
//************************************************************************
//
//  COLUATA scan chain module has two registers 
//  (both of them are tripple redundant):
//  40 bit shift register will shift control data
//  from scan_chain_cntrl register (software supplied).
//  Control data register contains controll signals for the whole COLUTA
//  chip.
//
//  ******scan_chain_cntrl data format******
//  scan_chain_cntrl[39:0]  data to be loaded into the scan shift register
//  scan_chain_cntrl  [40]  enable flag; 
//  scan_chain_cntrl  [41]  load flag; 
//
//  Operations between shift-register and data-register are 
//  defined by the following two flags:
//
//      load   enable
//       0       0    nop
//       0       1    shift operation only
//       1       0    shift operation and load data into control register
//       1       1    load shift register with the data from data register
//                    and shift them out to FPGA (scan_chain_back register)
//
//
//
//  ********read back data format***
//  scan_chain_back[39: 0]  data from scan chain
//  scan_chain_back[63:40]  SEU counter from scan chain logic
//
//************************************************************************
module scan_chain
     (  
       input clk,
       input rst,
       input op_start,
       input wire[41:0] scan_chain_cntrl,


       //scan_chain interface to COLUTA chip
        output reg SCAN_CLK,      
        output reg SCAN_ENABLE,   
        output reg SCAN_IN,   
        output reg SCAN_LOAD,
        output reg SCAN_RESET,
        input      SCAN_OUT,
        input      SEU_COUNT,
        //
        output reg[63:0]scan_chain_back,
        //
        output reg op_done
      );
		
		
//variables
reg        op_starts, op_start_reg, cycle_start, scan_en_flg;
reg        scan_load_flg, scan_clk_flg, next_cycle;
reg  [6:0] cph;
reg [41:0] scan_dat_reg;
reg  [5:0] bit_num;


//*****************************Main Body********************************


always @(posedge clk or posedge rst)	
begin	
	if (rst) 
         begin
          SCAN_CLK    <= 1'b0;      
          SCAN_ENABLE <= 1'b0; 
          SCAN_IN     <= 1'b0;  
          SCAN_LOAD   <= 1'b0;
          SCAN_RESET  <= 1'b1;
          cph[6:0]    <= 6'b000000;
          op_done     <= 1'b0;
         end
	else 
         begin
               //basic bit cycle
               op_start_reg <= op_start;
               op_starts    <= ~op_start_reg & op_start;
               cycle_start  <=  op_starts | next_cycle; 
               cph[6:0]     <= {cph[5:0], cycle_start};
	
               //scan chain control signals
               SCAN_ENABLE  <= scan_en_flg       &   (cph[1] | cph[2] | cph[3] | cph[4 | cph[5]]);
               SCAN_CLK     <= scan_clk_flg      &   (         cph[2] | cph[3] | cph[4]         );
               SCAN_IN      <= scan_dat_reg[39]  &   (cph[1] | cph[2] | cph[3] | cph[4 | cph[5]]);	
               SCAN_LOAD    <= scan_load_flg     &   (cph[1] | cph[2] | cph[3] | cph[4 | cph[5]]);

               //data register
               if (op_starts)       scan_dat_reg[41:0] <= scan_chain_cntrl[41:0];
               else if (next_cycle) scan_dat_reg[39:0] <= {scan_dat_reg[38:0], 1'b0};
				
               // bit number register
               if (op_starts)        bit_num[5:0] <= 6'b101000;//40 decimal
               else if (next_cycle)  bit_num[5:0] <= bit_num[5:0] - 6'b000001;
				
               //next cycle flag
               if (cph[6] & ~(bit_num==6'b000000)) next_cycle <= 1'b1;
               else                                next_cycle <= 1'b0;
				
               //scan_en_flag 
               scan_en_flg   <= ((scan_dat_reg[41] | scan_dat_reg[40]) & ~(bit_num==6'b000000)) |
                                ((scan_dat_reg[41] & scan_dat_reg[40]) &  (bit_num==6'b000000)) ;
				
               //scan_clk_flg
               scan_clk_flg  <= scan_dat_reg[41] | scan_dat_reg[40];
				
               //
               scan_load_flg  <= ((bit_num==6'b000000) & scan_dat_reg[41] & ~scan_dat_reg[40])  |
                                 ((bit_num==6'b101000) & scan_dat_reg[41] &  scan_dat_reg[40])    ;
               SCAN_RESET     <= 1'b0;

               // operation done flag
               if (op_start & ~op_start_reg)           op_done <= 1'b0;	
               else if ((bit_num==6'b000000)& cph[6])  op_done <= 1'b1;
           end	
end



//read back register
always @(posedge SCAN_CLK)
  begin
   scan_chain_back[39:0] <= {scan_chain_back[38:0], SCAN_OUT};
  end

  
  
// SUE counter - preliminary logic
// this counter counts positive edges of SEU_COUNT signal
always @(posedge clk or posedge rst)	
begin	
	if (rst) 
         begin
			                scan_chain_back[63:40] <= {24{1'b0}};
			end
   else if (SEU_COUNT)   scan_chain_back[63:40] <= scan_chain_back[63:40] + 24'h000001;
			
end			
 
//****************************end*****************************************

endmodule		