module transparport(ClkToFPGA, Reset, DataValidToFPGA, DataToFPGA, DataValidFromFPGA, DataFromFPGA);
   input ClkToFPGA;
   input Reset;
   input DataValidToFPGA;
   input DataToFPGA;
   output DataValidFromFPGA;
   output DataFromFPGA;

   parameter state0 = 3'b000;
   parameter state1 = 3'b001;
   parameter state2 = 3'b010;
   parameter state3 = 3'b011;
   parameter state4 = 3'b100;
	
   wire ClkToFPGA, Reset, DataValidToFPGA;
   wire DataValidFromFPGA;
   wire DataFromFPGA;

   (* signal_encoding = "user" *)
   reg [2:0] cur_state;
   reg [2:0] next_state;
   reg [9:0] mem_addr;
   reg [9:0] last_addr;
   reg [31:0] mem_in;
   wire [31:0] mem_out;
   reg [4:0] bit_pos;
   wire data_out_done;
   wire inc_serial_addr;
   wire inc_mem_addr;
   reg mem_write_en;

// Memory Core
   memcore memory (
	.addr(mem_addr), // Bus [9 : 0] 
	.clk(ClkToFPGA),
	.din(mem_in), // Bus [31 : 0] 
	.dout(mem_out), // Bus [31 : 0] 
	.we(mem_write_en));

   assign data_out_done = (mem_addr == last_addr) ? 1'b1 : 1'b0;
   assign DataValidFromFPGA = (cur_state == state3 || cur_state == state4) ? 1'b1 : 1'b0;
   assign DataFromFPGA = mem_out[bit_pos]; 
   assign inc_serial_addr = (cur_state == state1 || cur_state == state4) ? 1'b1 : 1'b0; 
   assign inc_mem_addr = (cur_state == state1 && bit_pos == 5'b11111) || 
             (cur_state == state4 && bit_pos == 5'b11110) ? 1'b1 : 1'b0; 

   always @(posedge ClkToFPGA or posedge Reset)
      if (Reset == 1'b1) 
         mem_in <= 32'b0000_0000_0000_0000_0000_0000_0000_0000;
      else if (DataValidToFPGA == 1'b1) 
         mem_in[bit_pos] <= DataToFPGA;

   always @(negedge ClkToFPGA or posedge Reset)
      if (Reset == 1'b1) 
         bit_pos <= 5'b00000;
      else if (inc_serial_addr == 1'b1)
         bit_pos <= bit_pos + 1;

   always @(posedge ClkToFPGA)
      if (cur_state == state1 && bit_pos == 5'b11111)
         mem_write_en <= 1'b1;
      else
         mem_write_en <= 1'b0;

   always @(negedge ClkToFPGA or posedge Reset)
      if (Reset == 1'b1) 
         mem_addr <= 10'b0000000000;
      else if (cur_state == state2) 
         mem_addr <= 10'b0000000000;
      else if (inc_mem_addr == 1'b1)
         mem_addr <= mem_addr + 1;

   always @(posedge ClkToFPGA or posedge Reset)
      if (Reset == 1'b1)
         last_addr <= 10'b0000000000;
      else if (cur_state == state1)
         last_addr <= mem_addr;

   always @(posedge ClkToFPGA or posedge Reset) // State transition logic
      if (Reset == 1'b1) cur_state <= state0;
      else cur_state <= next_state;

   always @(cur_state or DataValidToFPGA or data_out_done) // Next state combinational logic
      begin
         case (cur_state)
            state0:
               if (DataValidToFPGA == 0)
                  next_state <= state0;
               else 
                  next_state <= state1;
            state1:
               if (DataValidToFPGA == 1)
                  next_state <= state1;
               else 
                  next_state <= state2;
            state2:
               next_state <= state3;
            state3:
               next_state <= state4;
            state4:
               if (data_out_done == 0)
                  next_state <= state4;
               else 
                  next_state <= state0;
            default: next_state <= state0;
         endcase
      end

endmodule
