//given a spi_item, and read or write reg_mems.
class spi_rw;

  function rw(ref spi_item spi_pkg);
    int len = spi_pkg.data.size();
    int max_len =  0;
    bit [24:0] start;
    bit [19:0] addr ;
    int i = 0;

    start = spi_pkg.addr;
    case(start[24:20])
	5'h00	:	max_len = 32;
	5'h01	:	max_len = (start[9:8]==2'b01) ? 52 :
				  (start[9:8]==2'b10) ? 16 :
				  (start[9:8]==2'b11) ? 44 :
				  0;
	5'h02	:	max_len =  32768;
	5'h03	:	max_len =  32768;
	5'h04	:	max_len =   1024;
	5'h05	:	max_len = 524288;
	5'h06	:	max_len = 524288;
	5'h07	:	max_len =  32768;
	5'h08	:	max_len =  32768;
	5'h09	:	max_len =     80;
	5'h0A	:	max_len =   1024;
	5'h0B	:	max_len = 262144;
	5'h1F	:	max_len =     16;
    endcase
    for(i=0;i<len;i++) begin
	if(start[24:20] == 5'b01) begin
	  addr = (start[7 :0] + (i[7 :0]<<2)) % (max_len) + {{start[19: 8]}, 8'b0};
	end
	else begin
	  addr = (start[19:0] + (i[19:0]<<2)) % (max_len) ;
	end
	$display("start:%h\taddr:%h",start,addr);
	if(spi_pkg.cmd) begin
	  //$display("rd_data:%h",single_read(spi_pkg.addr + 4*i));
	  spi_pkg.data[i] = single_read(start, addr);
	end
	else begin
	  single_write(start, addr, spi_pkg.data[i]);
	end
    end
  endfunction

  function bit[31:0] single_read(bit[24: 0] start, bit[19: 0] addr);
    bit[31:0]	s_data;//,temp;
    //$display("spi read the addr:%h",addr);
    //$display(reg_mems::match_filter.data[int'(addr[19: 0]) +: 4]);
    //temp={<<byte {reg_mems::match_filter.data[int'(addr[19: 0]) +: 4]}};
    //$display("temp=%h",temp);
    case(start[24:20])
	5'h00	:	s_data = reg_mems::sys_regfile.data[int'(addr[19: 2])];
	5'h01	:	s_data = (start[9:8]==2'b01) ? reg_mems::dac_regfile.data[int'(addr[7:2])] :
				 (start[9:8]==2'b10) ? reg_mems::adc_regfile.data[int'(addr[7:2])] :
				 (start[9:8]==2'b11) ? reg_mems::pll_regfile.data[int'(addr[7:2])] :
				 32'b0;
	5'h02	:	s_data = {<<byte {reg_mems::daq_inst_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h03	:	s_data = {<<byte {reg_mems::daq_data_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h04	:	s_data = reg_mems::daq_regfile.data[int'(addr[19: 2])];
	5'h05	:	s_data = {<<byte {reg_mems::match_filter.data[int'(addr[19: 0]) +: 4]}};
	5'h06	:	s_data = {<<byte {reg_mems::read_out_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h07	:	s_data = {<<byte {reg_mems::awg_inst_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h08	:	s_data = {<<byte {reg_mems::awg_data_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h09	:	s_data = reg_mems::awg_regfile.data[int'(addr[19: 2])];
	5'h0A	:	s_data = {<<byte {reg_mems::env_indx_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h0B	:	s_data = {<<byte {reg_mems::env_data_ram.data[int'(addr[19: 0]) +: 4]}};
	5'h1F	:	s_data = reg_mems::clk_regfile.data[int'(addr[19: 2])];
    endcase
    //$display("s_data=%h",s_data);
    return s_data;
  endfunction

  function single_write(bit[24: 0] start, bit[19: 0] addr, bit[31: 0] s_data);
    //$display("single_write: addr=%h, s_data=%h",addr,s_data);
    case(start[24:20])
	5'h00	:	reg_mems::sys_regfile.data[int'(addr[19: 2])] = s_data;
	5'h01	:	case(start[9:8])
			  2'b01 : reg_mems::dac_regfile.data[int'(addr[7:2])] = s_data;
			  2'b10 : reg_mems::adc_regfile.data[int'(addr[7:2])] = s_data;
			  2'b11 : reg_mems::pll_regfile.data[int'(addr[7:2])] = s_data;
			endcase
	5'h02	:	begin
			  reg_mems::daq_inst_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::daq_inst_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::daq_inst_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::daq_inst_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h03	:	begin
			  reg_mems::daq_data_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::daq_data_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::daq_data_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::daq_data_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h04	:	reg_mems::daq_regfile.data[int'(addr[19: 2])] = s_data;
	5'h05	:	begin
			  reg_mems::match_filter.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::match_filter.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::match_filter.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::match_filter.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h06	:	begin
			  reg_mems::read_out_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::read_out_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::read_out_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::read_out_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h07	:	begin
			  reg_mems::awg_inst_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::awg_inst_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::awg_inst_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::awg_inst_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h08	:	begin
			  reg_mems::awg_data_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::awg_data_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::awg_data_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::awg_data_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h09	:	reg_mems::awg_regfile.data[int'(addr[19: 2])] = s_data;
	5'h0A	:	begin
			  reg_mems::env_indx_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::env_indx_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::env_indx_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::env_indx_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h0B	:	begin
			  reg_mems::env_data_ram.data[int'(addr[19: 0])+3] = s_data[31:24];
			  reg_mems::env_data_ram.data[int'(addr[19: 0])+2] = s_data[23:16];
			  reg_mems::env_data_ram.data[int'(addr[19: 0])+1] = s_data[15: 8];
			  reg_mems::env_data_ram.data[int'(addr[19: 0])+0] = s_data[7 : 0];
			end
	5'h1F	:	reg_mems::clk_regfile.data[int'(addr[19: 2])] = s_data;
    endcase
  endfunction

  function new();
  endfunction
  
 endclass
