//***************************************************************
//Simplified FT2232 emulator.
//
//One fifo 245 channel implemented. For FT2232 emulation
//instantiate the code for fifo A and B.
//
//jb/august2018 v1.0
//***************************************************************
`timescale 1ns/1ps

module FT2232 
      (      
       input               rst_in,
       input               clk,
       input  wire[7:0]    NUM_WORDS,
		
       //host(USB) side of the interface
       //up to 8 bytes are transfered
       input  wire [319:0] data_to_FPGA,
       output  reg [319:0] data_from_FPGA,
       input               fifo_op_type,    //0-data from host to FPGA, 1-data from FPGA to host
       input               start_fifo_op,
       output  reg         op_done,
 

       //245 fifo signals
       inout wire    [7:0] DATA,  //fifo A DATA
       output              RXF,   //low active: data available in FIFO
       output              TXE,   //low active: data can be written into FIFO
       input               RD,    //ReaD enable,  low to high transition
       input               WR     //WRite enable, high to low transition

       );
 //variables
 reg        fifo_op_in_progress;
 reg  [7:0] byte_count;
 wire [7:0] data_out_mux;
 reg        byte_tranfer;
 reg        fe_wr_reg, le_rd_reg;
 reg        fe_WR, le_RD; 
 
 

 //operation if progress flag
 always@(posedge clk)
 begin
 
  if      (rst_in)                                         fifo_op_in_progress <= 1'b0;
  else if (start_fifo_op)                                  fifo_op_in_progress <= 1'b1;
  else if ((byte_count==(NUM_WORDS-8'h01)) & byte_tranfer) fifo_op_in_progress <= 1'b0;
 
 
  if      (rst_in)                                         op_done <= 1'b0;
  else if (start_fifo_op)                                  op_done <= 1'b0;
  else if ((byte_count==(NUM_WORDS-8'h01)) & byte_tranfer) op_done <= 1'b1;
 

 //byte counter
  if     (rst_in )              byte_count <= 8'h00;
  else if(start_fifo_op)        byte_count <= 8'h00;
  else if(byte_tranfer)         byte_count <= byte_count + 8'h01;
  else if(~fifo_op_in_progress) byte_count <= 8'h00;

  if     (rst_in)                       byte_tranfer <= 1'b0;
  else if( fifo_op_type & ~TXE & fe_WR) byte_tranfer <= 1'b1;
  else if(~fifo_op_type & ~RXF & le_RD) byte_tranfer <= 1'b1;
  else if(byte_tranfer)                 byte_tranfer <= 1'b0;

  fe_wr_reg <=  WR;
  fe_WR     <= fe_wr_reg & ~WR;
 
  le_rd_reg <=  RD;
  le_RD     <= ~le_rd_reg & RD;
 end
 
 
 //output data mux
assign data_out_mux  =  (byte_count[5:0]==6'h00) ? data_to_FPGA[  7:  0] :
                         (byte_count[5:0]==6'h01) ? data_to_FPGA[ 15:  8] :
                         (byte_count[5:0]==6'h02) ? data_to_FPGA[ 23: 16] :
                         (byte_count[5:0]==6'h03) ? data_to_FPGA[ 31: 24] :
                         (byte_count[5:0]==6'h04) ? data_to_FPGA[ 39: 32] :
                         (byte_count[5:0]==6'h05) ? data_to_FPGA[ 47: 40] :
                         (byte_count[5:0]==6'h06) ? data_to_FPGA[ 55: 48] : 
                         (byte_count[5:0]==6'h07) ? data_to_FPGA[ 63: 56] :
                         (byte_count[5:0]==6'h08) ? data_to_FPGA[ 71: 64] :
                         (byte_count[5:0]==6'h09) ? data_to_FPGA[ 79: 72] :
                         (byte_count[5:0]==6'h0a) ? data_to_FPGA[ 87: 80] :
                         (byte_count[5:0]==6'h0b) ? data_to_FPGA[ 95: 88] :
                         (byte_count[5:0]==6'h0c) ? data_to_FPGA[103: 96] :
                         (byte_count[5:0]==6'h0d) ? data_to_FPGA[111:104] :
                         (byte_count[5:0]==6'h0e) ? data_to_FPGA[119:112] : 
                         (byte_count[5:0]==6'h0f) ? data_to_FPGA[127:120] :
						 
                         (byte_count[5:0]==6'h10) ? data_to_FPGA[135:128] :
                         (byte_count[5:0]==6'h11) ? data_to_FPGA[143:136] :
                         (byte_count[5:0]==6'h12) ? data_to_FPGA[151:144] :
                         (byte_count[5:0]==6'h03) ? data_to_FPGA[159:152] :
                         (byte_count[5:0]==6'h14) ? data_to_FPGA[167:160] :
                         (byte_count[5:0]==6'h15) ? data_to_FPGA[175:168] :
                         (byte_count[5:0]==6'h16) ? data_to_FPGA[183:176] : 
                         (byte_count[5:0]==6'h17) ? data_to_FPGA[191:184] :
                         (byte_count[5:0]==6'h18) ? data_to_FPGA[199:192] :
                         (byte_count[5:0]==6'h19) ? data_to_FPGA[207:200] :
                         (byte_count[5:0]==6'h1a) ? data_to_FPGA[215:208] :
                         (byte_count[5:0]==6'h1b) ? data_to_FPGA[223:216] :
                         (byte_count[5:0]==6'h1c) ? data_to_FPGA[231:224] :
                         (byte_count[5:0]==6'h1d) ? data_to_FPGA[239:232] :
                         (byte_count[5:0]==6'h1e) ? data_to_FPGA[247:240] : 
                         (byte_count[5:0]==6'h1f) ? data_to_FPGA[255:248] :
						 
                         (byte_count[5:0]==6'h20) ? data_to_FPGA[263:256] :
                         (byte_count[5:0]==6'h21) ? data_to_FPGA[271:264] :
                         (byte_count[5:0]==6'h22) ? data_to_FPGA[279:272] :
                         (byte_count[5:0]==6'h23) ? data_to_FPGA[287:280] :
                         (byte_count[5:0]==6'h24) ? data_to_FPGA[295:288] :
                         (byte_count[5:0]==6'h25) ? data_to_FPGA[303:296] :
                         (byte_count[5:0]==6'h26) ? data_to_FPGA[311:304] : 
                         (byte_count[5:0]==6'h27) ? data_to_FPGA[319:312] :
                         (byte_count[5:0]==6'h28) ? data_to_FPGA[327:320] :
                         (byte_count[5:0]==6'h29) ? data_to_FPGA[335:328] :
                         (byte_count[5:0]==6'h2a) ? data_to_FPGA[343:336] :
                         (byte_count[5:0]==6'h2b) ? data_to_FPGA[351:344] :
                         (byte_count[5:0]==6'h2c) ? data_to_FPGA[359:352] :
                         (byte_count[5:0]==6'h2d) ? data_to_FPGA[367:360] :
                         (byte_count[5:0]==6'h2e) ? data_to_FPGA[375:368] : 
                         (byte_count[5:0]==6'h2f) ? data_to_FPGA[383:376] : 8'h00;
 
reg [7:0] DATA_del;
always@(DATA) #1 DATA_del = DATA;
 //mux for data from FPGA
 always@(negedge WR or posedge rst_in)
  begin
   if (rst_in) data_from_FPGA <= {64{1'b0}};
   else if (fifo_op_in_progress &  fifo_op_type)
    begin	 
	 if                (byte_count[5:0]==6'h00)   data_from_FPGA[  7:  0] <= DATA_del;
     else if           (byte_count[5:0]==6'h01)   data_from_FPGA[ 15:  8] <= DATA_del;
     else if           (byte_count[5:0]==6'h02)   data_from_FPGA[ 23: 16] <= DATA_del;
     else if           (byte_count[5:0]==6'h03)   data_from_FPGA[ 31: 24] <= DATA_del;
     else if           (byte_count[5:0]==6'h04)   data_from_FPGA[ 39: 32] <= DATA_del;
     else if           (byte_count[5:0]==6'h05)   data_from_FPGA[ 47: 40] <= DATA_del;
     else if           (byte_count[5:0]==6'h06)   data_from_FPGA[ 55: 48] <= DATA_del; 
     else if           (byte_count[5:0]==6'h07)   data_from_FPGA[ 63: 56] <= DATA_del;
     else if           (byte_count[5:0]==6'h08)   data_from_FPGA[ 71: 64] <= DATA_del;
     else if           (byte_count[5:0]==6'h09)   data_from_FPGA[ 79: 72] <= DATA_del;
     else if           (byte_count[5:0]==6'h0a)   data_from_FPGA[ 87: 80] <= DATA_del;
     else if           (byte_count[5:0]==6'h0b)   data_from_FPGA[ 95: 88] <= DATA_del;
     else if           (byte_count[5:0]==6'h0c)   data_from_FPGA[103: 96] <= DATA_del;
     else if           (byte_count[5:0]==6'h0d)   data_from_FPGA[111:104] <= DATA_del;
     else if           (byte_count[5:0]==6'h0e)   data_from_FPGA[119:112] <= DATA_del; 
     else if           (byte_count[5:0]==6'h0f)   data_from_FPGA[127:120] <= DATA_del;
						 
     else if           (byte_count[5:0]==6'h10)   data_from_FPGA[135:128] <= DATA_del;
     else if           (byte_count[5:0]==6'h11)   data_from_FPGA[143:136] <= DATA_del;
     else if           (byte_count[5:0]==6'h12)   data_from_FPGA[151:144] <= DATA_del;
     else if           (byte_count[5:0]==6'h03)   data_from_FPGA[159:152] <= DATA_del;
     else if           (byte_count[5:0]==6'h14)   data_from_FPGA[167:160] <= DATA_del;
     else if           (byte_count[5:0]==6'h15)   data_from_FPGA[175:168] <= DATA_del;
     else if           (byte_count[5:0]==6'h16)   data_from_FPGA[183:176] <= DATA_del; 
     else if           (byte_count[5:0]==6'h17)   data_from_FPGA[191:184] <= DATA_del;
     else if           (byte_count[5:0]==6'h18)   data_from_FPGA[199:192] <= DATA_del;
     else if           (byte_count[5:0]==6'h19)   data_from_FPGA[207:200] <= DATA_del;
     else if           (byte_count[5:0]==6'h1a)   data_from_FPGA[215:208] <= DATA_del;
     else if           (byte_count[5:0]==6'h1b)   data_from_FPGA[223:216] <= DATA_del;
     else if           (byte_count[5:0]==6'h1c)   data_from_FPGA[231:224] <= DATA_del;
     else if           (byte_count[5:0]==6'h1d)   data_from_FPGA[239:232] <= DATA_del;
     else if           (byte_count[5:0]==6'h1e)   data_from_FPGA[247:240] <= DATA_del; 
     else if           (byte_count[5:0]==6'h1f)   data_from_FPGA[255:248] <= DATA_del;
						 
     else if           (byte_count[5:0]==6'h20)   data_from_FPGA[263:256] <= DATA_del;
     else if           (byte_count[5:0]==6'h21)   data_from_FPGA[271:264] <= DATA_del;
     else if           (byte_count[5:0]==6'h22)   data_from_FPGA[279:272] <= DATA_del;
     else if           (byte_count[5:0]==6'h23)   data_from_FPGA[287:280] <= DATA_del;
     else if           (byte_count[5:0]==6'h24)   data_from_FPGA[295:288] <= DATA_del;
     else if           (byte_count[5:0]==6'h25)   data_from_FPGA[303:296] <= DATA_del;
     else if           (byte_count[5:0]==6'h26)   data_from_FPGA[311:304] <= DATA_del; 
     else if           (byte_count[5:0]==6'h27)   data_from_FPGA[319:312] <= DATA_del;
     else if           (byte_count[5:0]==6'h28)   data_from_FPGA[327:320] <= DATA_del;
     else if           (byte_count[5:0]==6'h29)   data_from_FPGA[335:328] <= DATA_del;
     else if           (byte_count[5:0]==6'h2a)   data_from_FPGA[343:336] <= DATA_del;
     else if           (byte_count[5:0]==6'h2b)   data_from_FPGA[351:344] <= DATA_del;
     else if           (byte_count[5:0]==6'h2c)   data_from_FPGA[359:352] <= DATA_del;
     else if           (byte_count[5:0]==6'h2d)   data_from_FPGA[367:360] <= DATA_del;
     else if           (byte_count[5:0]==6'h2e)   data_from_FPGA[375:368] <= DATA_del; 
     else if           (byte_count[5:0]==6'h2f)   data_from_FPGA[383:376] <= DATA_del;	 
   end
  end
 

 //FIFO 245 interface signals
 assign RXF = ~(fifo_op_in_progress & ~fifo_op_type);
 assign TXE = ~(fifo_op_in_progress &  fifo_op_type); 
 
 assign DATA = (fifo_op_in_progress & ~fifo_op_type & (~RD | le_RD)) ? data_out_mux : 8'bZZZZZZZZ;
 
endmodule