data/full_repos/permissive/42803760/ftl/Dynamic_Controller/code/Cmd_Analysis.v
1: b'%Error: data/full_repos/permissive/42803760/ftl/Dynamic_Controller/code/Cmd_Analysis.v:28: Cannot find include file: Dynamic_Controller_Parameters.vh\n`include"Dynamic_Controller_Parameters.vh" \n        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/42803760/ftl/Dynamic_Controller/code,data/full_repos/permissive/42803760/Dynamic_Controller_Parameters.vh\n             data/full_repos/permissive/42803760/ftl/Dynamic_Controller/code,data/full_repos/permissive/42803760/Dynamic_Controller_Parameters.vh.v\n             data/full_repos/permissive/42803760/ftl/Dynamic_Controller/code,data/full_repos/permissive/42803760/Dynamic_Controller_Parameters.vh.sv\n             Dynamic_Controller_Parameters.vh\n             Dynamic_Controller_Parameters.vh.v\n             Dynamic_Controller_Parameters.vh.sv\n             obj_dir/Dynamic_Controller_Parameters.vh\n             obj_dir/Dynamic_Controller_Parameters.vh.v\n             obj_dir/Dynamic_Controller_Parameters.vh.sv\n%Error: Exiting due to 1 error(s)\n'
module Cmd_Analysis(
clk,fifo_rd_clk,clk_83M,rst_n,
Cmd_In_En,Cmd_In,Finished_Cmd_FIFO_Empty,Finished_Cmd_Out_En,Finished_Cmd_Out,Data_In_En,Data_In,Cmd_Available,Data_2_host_en,Data_2_host,ControllerIdle,
Set_Empty,Set_Empty_ID,FIFO_rd_en,FIFO_addr,FIFO_empty,Cmd_Out,RAM_Unit_ID,Finished_cmd_wr_en,Finished_cmd_FIFO_full,Chips_Ready,
Rd_RAM_Data_en,Data_Out,DataFromFlash_en,DataFromFlash,RD_data_FIFO_full
    );

`include"Dynamic_Controller_Parameters.vh"
	 
input clk;
input fifo_rd_clk;
input clk_83M;
input rst_n; 

input Cmd_In_En;
input [ 127 : 0 ] Cmd_In;
output Finished_Cmd_FIFO_Empty;

input Finished_Cmd_Out_En;
output [ 127 : 0 ] Finished_Cmd_Out;
input Data_In_En;
input [ 255 : 0 ] Data_In;
output reg Cmd_Available;
input Data_2_host_en;
output [255:0] Data_2_host;
output reg ControllerIdle;

input Set_Empty;
input [3:0] Set_Empty_ID;
input FIFO_rd_en;
input [2:0] FIFO_addr;
output FIFO_empty;
output [ 127: 0] Cmd_Out;

input [3:0] RAM_Unit_ID;
input Finished_cmd_wr_en;
output Finished_cmd_FIFO_full;
input Chips_Ready;

input Rd_RAM_Data_en;
output [7:0]  Data_Out;

input DataFromFlash_en;
input [15:0] DataFromFlash;
output RD_data_FIFO_full;


parameter IDLE             = 3'h0;
parameter RD_FIRST_CMD     = 3'h1;
parameter RD_SECOND_CMD    = 3'h2;
parameter WR_FIRST_CMD     = 3'h3;
parameter WR_SECOND_CMD    = 3'h4;
parameter ER_FIRST_CMD     = 3'h5;
parameter ER_SECOND_CMD    = 3'h6;


 reg [6:0] wr_data_counter;
 reg during_wr_data;

reg [9:0] wr_address;
reg [14:0] rd_address;

reg [3:0] Current_ID;
wire [3:0] FE_ID_w;
wire Avaliable_w;

reg [7:0] empty;

reg cmd_arrived;
reg cmd_write_en;
reg cmd_read_en;
reg cmd_erase_en;
reg [127:0] Command_Temp;
reg [2:0] Target_Addr;


reg [2:0] cmd_curr_state;
reg [2:0] cmd_next_state;
reg cmd_fifo_wr_en;
reg [127:0] cmd_data_in;
reg cmd_write_en_clr;
reg cmd_read_en_clr;
reg cmd_erase_en_clr;

wire [7:0] wr_en_w;
wire [127:0] din0_w;
wire [127:0] din1_w;
wire [127:0] din2_w;
wire [127:0] din3_w;
wire [127:0] din4_w;
wire [127:0] din5_w;
wire [127:0] din6_w;
wire [127:0] din7_w;

wire [7:0] rd_en_w;
wire [7:0] almost_full_w;
wire [7:0] FIFO_empty_w;

wire rd_en0_w;
wire rd_en1_w;
wire rd_en2_w;
wire rd_en3_w;
wire rd_en4_w;
wire rd_en5_w;
wire rd_en6_w;
wire rd_en7_w;

wire [127:0] dout0_w;
wire [127:0] dout1_w;
wire [127:0] dout2_w;
wire [127:0] dout3_w;
wire [127:0] dout4_w;
wire [127:0] dout5_w;
wire [127:0] dout6_w;
wire [127:0] dout7_w;

wire fifo_rst;
assign fifo_rst=~rst_n;	



always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    ControllerIdle<=1'b0;
	Cmd_Available<=1'b0;
  end
  else
  begin
    ControllerIdle<=(&FIFO_empty_w) & Chips_Ready;
	Cmd_Available <= (~|almost_full_w) & (|FE_ID_w) & (~cmd_arrived) &(~during_wr_data);
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    cmd_write_en<=1'b0;
	cmd_read_en<=1'b0;
	cmd_erase_en<=1'b0;
	Target_Addr<=3'b0;
	Current_ID<=4'b0;
	cmd_arrived<=1'b0;
  end
  else
  begin
	 if(Cmd_In_En&Cmd_Available)
	 begin
	   Command_Temp<=Cmd_In;
	 
		cmd_arrived<=1'b1;
	   case(Cmd_In[127:126])
		2'b00:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b1;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=Cmd_In[66:64];
		end
		2'b01:begin
		   Current_ID<=FE_ID_w;
		   cmd_write_en<=1'b1;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=Cmd_In[66:64];
		end
		2'b11:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b1;
		   Target_Addr<=Cmd_In[2:0];
		end
		default:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=3'b0;
		end
	    endcase
     end 
    else if(cmd_write_en_clr)
	 begin
      cmd_write_en<=1'b0;
		cmd_arrived<=1'b0;
	 end
	else if (cmd_read_en_clr)
	begin
	  cmd_read_en<=1'b0;
	  cmd_arrived<=1'b0;
	end
	else if (cmd_erase_en_clr)
	begin
	   cmd_erase_en<=1'b0;
		cmd_arrived<=1'b0;
	end
  end
end



always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    empty<=8'hff;
  end
  else
  begin
    if(Set_Empty)
	begin
		case(Set_Empty_ID)
	  	4'h1:empty[0]<=1'b1;
		4'h2:empty[1]<=1'b1;
		4'h3:empty[2]<=1'b1;
		4'h4:empty[3]<=1'b1;
		4'h5:empty[4]<=1'b1;
		4'h6:empty[5]<=1'b1;
		4'h7:empty[6]<=1'b1;
		4'h8:empty[7]<=1'b1;
		default:empty<=empty;
	   endcase
	end
    else if(cmd_write_en)
	begin
  		case(Current_ID)
		     4'h1:empty[0]<=1'b0;
		     4'h2:empty[1]<=1'b0;
		     4'h3:empty[2]<=1'b0;
		     4'h4:empty[3]<=1'b0;
		     4'h5:empty[4]<=1'b0;
		     4'h6:empty[5]<=1'b0;
		     4'h7:empty[6]<=1'b0;
		     4'h8:empty[7]<=1'b0;
			 default:empty<=empty;
		   endcase
    end
	
  end
end


always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
     cmd_curr_state<='b0;
  end  
  else
  begin
    cmd_curr_state<=cmd_next_state;
  end
end  

always@(*)
begin

	case(cmd_curr_state) 
	IDLE:begin
	  if(cmd_write_en)
	    cmd_next_state=WR_FIRST_CMD;
	  else if (cmd_read_en)
	    cmd_next_state=RD_FIRST_CMD;
	  else if (cmd_erase_en)
	    cmd_next_state=ER_FIRST_CMD;
	  else
	    cmd_next_state=IDLE;
	end
	RD_FIRST_CMD:begin
	    cmd_next_state=RD_SECOND_CMD;
	end
	RD_SECOND_CMD:begin
	     cmd_next_state=IDLE;
	end
	WR_FIRST_CMD:begin
	   cmd_next_state=WR_SECOND_CMD;
	end
	WR_SECOND_CMD:begin
	   cmd_next_state=IDLE;
	end
	ER_FIRST_CMD:begin
	   cmd_next_state=ER_SECOND_CMD;
	end
	ER_SECOND_CMD:begin
	   cmd_next_state=IDLE;
	end
	default:begin
	  cmd_next_state=IDLE;
	end
	endcase
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
	  cmd_fifo_wr_en<=1'b0;
      cmd_data_in<=128'b0;
	  cmd_write_en_clr<=1'b0;
      cmd_read_en_clr<=1'b0;
      cmd_erase_en_clr<=1'b0;
	end
	else
	begin
	  case(cmd_next_state)
	  IDLE:begin
	     cmd_fifo_wr_en<=1'b0;
         cmd_data_in<=128'b0;
	     cmd_write_en_clr<=1'b0;
         cmd_read_en_clr<=1'b0;
         cmd_erase_en_clr<=1'b0;
	  end
	  
	  RD_FIRST_CMD:begin
	    cmd_read_en_clr<=1'b1;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  RD_SECOND_CMD:begin
	    cmd_read_en_clr<=1'b0;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  
	  WR_FIRST_CMD:begin
	    cmd_write_en_clr<=1'b1;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:123],Current_ID,Command_Temp[118:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  WR_SECOND_CMD:begin
	  	  cmd_write_en_clr<=1'b0;
	     cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:123],Current_ID,Command_Temp[118:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  ER_FIRST_CMD:begin
	     cmd_erase_en_clr<=1'b1;
		 cmd_fifo_wr_en<=1'b1;
         cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  ER_SECOND_CMD:begin
		 cmd_erase_en_clr<=1'b0;
		 cmd_fifo_wr_en<=1'b1;
       cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};     
	  end 
	  default:begin
	    cmd_erase_en_clr<=1'b0;
		 cmd_fifo_wr_en<=1'b0;
       cmd_data_in<=128'b0;
	  end
	  endcase
	end
end




always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
		  wr_address<=10'b0;
  end  
  else
  begin
       if(Data_In_En)
		  wr_address<=wr_address+1'b1;
	   else if(wr_data_counter==0)
		  wr_address<=(Current_ID-1'b1)*'h80;
	   else
	      wr_address<=wr_address;
		  
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    wr_data_counter<=7'b0;
  end
  else
  begin
     if(Data_In_En)
	   wr_data_counter<=wr_data_counter+1'b1;
	 else
	    wr_data_counter<=wr_data_counter;
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    during_wr_data<=1'b0;
  end
  else
  begin
    if(cmd_write_en)
      during_wr_data<=1'b1;
    else if (wr_data_counter=='h7f)
      during_wr_data<=1'b0;
  end
end



always@(posedge fifo_rd_clk or negedge rst_n)
begin
  if(!rst_n)
  begin
     rd_address<=15'b0;
  end  
  else
  begin
       if(Rd_RAM_Data_en)
		    rd_address<=rd_address+1'b1;
		 else
		    rd_address<=(RAM_Unit_ID-1'b1)*'h1000;
  end
end

wire [255:0] data_in;

reg data_in_en;
reg [15:0] data0 ;
reg [15:0] data1 ;
reg [15:0] data2 ;
reg [15:0] data3 ;
reg [15:0] data4 ;
reg [15:0] data5 ;
reg [15:0] data6 ;
reg [15:0] data7 ;
reg [15:0] data8 ;
reg [15:0] data9 ;
reg [15:0] data10;
reg [15:0] data11;
reg [15:0] data12;
reg [15:0] data13;
reg [15:0] data14;
reg [15:0] data15;
reg [3:0] counter;


assign data_in={data0,data1,data2,data3,data4,data5,data6,data7,data8,data9,data10,data11,data12,data13,data14,data15};
RD_DATA_FIFO rd_data_fifo_inst1 (
  .rst(fifo_rst),
  .wr_clk(clk_83M),
  .rd_clk(clk),
  .din(data_in),
  .wr_en(data_in_en),
  .rd_en(Data_2_host_en),
  .dout(Data_2_host),
  .full(),
  .empty(),
  .prog_full(RD_data_FIFO_full)
);
reg [6:0] rd_data_in_counter;
always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     rd_data_in_counter<='b0;
  end
  else
  begin
     if(data_in_en)
	    rd_data_in_counter<=rd_data_in_counter+1'b1;
	  else
	    rd_data_in_counter<=rd_data_in_counter;
  end
end

always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin

    data_in_en<=1'b0;
  end
  else
  begin

    if(counter=='hf)
	  data_in_en<=1'b1;
	else
	  data_in_en<=1'b0;
  end
end
always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     data0 <=16'b0;
     data1 <=16'b0;
     data2 <=16'b0;
     data3 <=16'b0;
     data4 <=16'b0;
     data5 <=16'b0;
     data6 <=16'b0;
     data7 <=16'b0;
     data8 <=16'b0;
     data9 <=16'b0;
     data10<=16'b0;
     data11<=16'b0;
     data12<=16'b0;
     data13<=16'b0;
     data14<=16'b0;
     data15<=16'b0;
  end  
  else
  begin
     if(DataFromFlash_en)
	 begin
        data0 <= DataFromFlash;
        data1 <= data0        ;
        data2 <= data1        ;
        data3 <= data2        ;
        data4 <= data3        ;
        data5 <= data4        ;
        data6 <= data5        ;
        data7 <= data6        ;
        data8 <= data7        ;
        data9 <= data8        ;
        data10<= data9        ;
        data11<= data10       ;
        data12<= data11       ;
        data13<= data12       ;
        data14<= data13       ;
        data15<= data14       ;
	 end
  end
end

always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     counter<=4'b0;
  end
  else
  begin       
    if(DataFromFlash_en)
	     counter<=counter+1'b1;
  end
end



RAM_WRITE ram_write_inst (
  .clka(clk),
  .wea(Data_In_En),
  .addra(wr_address),
  .dina(Data_In),
  .douta(),
  .clkb(fifo_rd_clk),
  .web(1'b0),
  .addrb(rd_address),
  .dinb(8'b0),
  .doutb(Data_Out)
);
Valid_Monitor  valid_monitor_inst(.clk(clk), 
                                  .rst_n(rst_n), 
											 .Valid(empty), 
											 .FE_ID(FE_ID_w)
											  );


MUX1_8 mux1_8_inst( .address(Target_Addr),
               .wr_en(cmd_fifo_wr_en),
			   .din(cmd_data_in),
               .wr_en0(wr_en_w[0]),
			   .wr_en1(wr_en_w[1]),
			   .wr_en2(wr_en_w[2]),
			   .wr_en3(wr_en_w[3]),
			   .wr_en4(wr_en_w[4]),
			   .wr_en5(wr_en_w[5]),
			   .wr_en6(wr_en_w[6]),
			   .wr_en7(wr_en_w[7]),
               .din0(din0_w)  ,
			   .din1(din1_w)  ,
			   .din2(din2_w)  ,
			   .din3(din3_w)  ,
			   .din4(din4_w)  ,
			   .din5(din5_w)  ,
			   .din6(din6_w)  ,
			   .din7(din7_w) 
    );

TargetCmdFIFO target_fifo_inst0 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din0_w),
  .wr_en(wr_en_w[0]),
  .rd_en(rd_en0_w),
  .dout(dout0_w),
  .full(),
  .almost_full(almost_full_w[0]),
  .empty(FIFO_empty_w[0])
);
TargetCmdFIFO target_fifo_inst1 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din1_w),
  .wr_en(wr_en_w[1]),
  .rd_en(rd_en1_w),
  .dout(dout1_w),
  .full(),
  .almost_full(almost_full_w[1]),
  .empty(FIFO_empty_w[1])
);
TargetCmdFIFO target_fifo_inst2 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din2_w),
  .wr_en(wr_en_w[2]),
  .rd_en(rd_en2_w),
  .dout(dout2_w),
  .full(),
  .almost_full(almost_full_w[2]),
  .empty(FIFO_empty_w[2])
);
TargetCmdFIFO target_fifo_inst3 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din3_w),
  .wr_en(wr_en_w[3]),
  .rd_en(rd_en3_w),
  .dout(dout3_w),
  .full(),
  .almost_full(almost_full_w[3]),
  .empty(FIFO_empty_w[3])
);
TargetCmdFIFO target_fifo_inst4 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din4_w),
  .wr_en(wr_en_w[4]),
  .rd_en(rd_en4_w),
  .dout(dout4_w),
  .full(),
  .almost_full(almost_full_w[4]),
  .empty(FIFO_empty_w[4])
);
TargetCmdFIFO target_fifo_inst5 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din5_w),
  .wr_en(wr_en_w[5]),
  .rd_en(rd_en5_w),
  .dout(dout5_w),
  .full(),
  .almost_full(almost_full_w[5]),
  .empty(FIFO_empty_w[5])
);
TargetCmdFIFO target_fifo_inst6 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din6_w),
  .wr_en(wr_en_w[6]),
  .rd_en(rd_en6_w),
  .dout(dout6_w),
  .full(),
  .almost_full(almost_full_w[6]),
  .empty(FIFO_empty_w[6])
);
TargetCmdFIFO target_fifo_inst7 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din7_w),
  .wr_en(wr_en_w[7]),
  .rd_en(rd_en7_w),
  .dout(dout7_w),
  .full(),
  .almost_full(almost_full_w[7]),
  .empty(FIFO_empty_w[7])
);

MUX8_1 mux8_1_inst(
                   .address(FIFO_addr),

                   .rd_en0(rd_en0_w),
                   .rd_en1(rd_en1_w),
                   .rd_en2(rd_en2_w),
                   .rd_en3(rd_en3_w),
                   .rd_en4(rd_en4_w),
                   .rd_en5(rd_en5_w),
                   .rd_en6(rd_en6_w),
                   .rd_en7(rd_en7_w),
                   .dout0(dout0_w),
                   .dout1(dout1_w),
                   .dout2(dout2_w),
                   .dout3(dout3_w),
                   .dout4(dout4_w),
                   .dout5(dout5_w),
                   .dout6(dout6_w),
                   .dout7(dout7_w),
				       .empty0(FIFO_empty_w[0]),
                   .empty1(FIFO_empty_w[1]),
                   .empty2(FIFO_empty_w[2]),
                   .empty3(FIFO_empty_w[3]),
                   .empty4(FIFO_empty_w[4]),
                   .empty5(FIFO_empty_w[5]),
                   .empty6(FIFO_empty_w[6]),
                   .empty7(FIFO_empty_w[7]),

                   .rd_en(FIFO_rd_en),
				   .empty(FIFO_empty),
                   .dout(Cmd_Out)
    );
	

Finished_Cmd_FIFO finished_cmd_fifo_inst1(.clk(clk),
                                          .rst(fifo_rst),
														.din(Cmd_Out),
														.wr_en(Finished_cmd_wr_en),
														.rd_en(Finished_Cmd_Out_En),
														.dout(Finished_Cmd_Out),
														.full(Finished_cmd_FIFO_full),
														.empty(Finished_Cmd_FIFO_Empty)
														);

endmodule
module Cmd_Analysis(
clk,fifo_rd_clk,clk_83M,rst_n,
Cmd_In_En,Cmd_In,Finished_Cmd_FIFO_Empty,Finished_Cmd_Out_En,Finished_Cmd_Out,Data_In_En,Data_In,Cmd_Available,Data_2_host_en,Data_2_host,ControllerIdle,
Set_Empty,Set_Empty_ID,FIFO_rd_en,FIFO_addr,FIFO_empty,Cmd_Out,RAM_Unit_ID,Finished_cmd_wr_en,Finished_cmd_FIFO_full,Chips_Ready,
Rd_RAM_Data_en,Data_Out,DataFromFlash_en,DataFromFlash,RD_data_FIFO_full
    );


`include"Dynamic_Controller_Parameters.vh"
	 
input clk;
input fifo_rd_clk;
input clk_83M;
input rst_n; 

input Cmd_In_En;
input [ 127 : 0 ] Cmd_In;
output Finished_Cmd_FIFO_Empty;

input Finished_Cmd_Out_En;
output [ 127 : 0 ] Finished_Cmd_Out;
input Data_In_En;
input [ 255 : 0 ] Data_In;
output reg Cmd_Available;
input Data_2_host_en;
output [255:0] Data_2_host;
output reg ControllerIdle;

input Set_Empty;
input [3:0] Set_Empty_ID;
input FIFO_rd_en;
input [2:0] FIFO_addr;
output FIFO_empty;
output [ 127: 0] Cmd_Out;

input [3:0] RAM_Unit_ID;
input Finished_cmd_wr_en;
output Finished_cmd_FIFO_full;
input Chips_Ready;

input Rd_RAM_Data_en;
output [7:0]  Data_Out;

input DataFromFlash_en;
input [15:0] DataFromFlash;
output RD_data_FIFO_full;


parameter IDLE             = 3'h0;
parameter RD_FIRST_CMD     = 3'h1;
parameter RD_SECOND_CMD    = 3'h2;
parameter WR_FIRST_CMD     = 3'h3;
parameter WR_SECOND_CMD    = 3'h4;
parameter ER_FIRST_CMD     = 3'h5;
parameter ER_SECOND_CMD    = 3'h6;


 reg [6:0] wr_data_counter;
 reg during_wr_data;

reg [9:0] wr_address;
reg [14:0] rd_address;

reg [3:0] Current_ID;
wire [3:0] FE_ID_w;
wire Avaliable_w;

reg [7:0] empty;

reg cmd_arrived;
reg cmd_write_en;
reg cmd_read_en;
reg cmd_erase_en;
reg [127:0] Command_Temp;
reg [2:0] Target_Addr;


reg [2:0] cmd_curr_state;
reg [2:0] cmd_next_state;
reg cmd_fifo_wr_en;
reg [127:0] cmd_data_in;
reg cmd_write_en_clr;
reg cmd_read_en_clr;
reg cmd_erase_en_clr;

wire [7:0] wr_en_w;
wire [127:0] din0_w;
wire [127:0] din1_w;
wire [127:0] din2_w;
wire [127:0] din3_w;
wire [127:0] din4_w;
wire [127:0] din5_w;
wire [127:0] din6_w;
wire [127:0] din7_w;

wire [7:0] rd_en_w;
wire [7:0] almost_full_w;
wire [7:0] FIFO_empty_w;

wire rd_en0_w;
wire rd_en1_w;
wire rd_en2_w;
wire rd_en3_w;
wire rd_en4_w;
wire rd_en5_w;
wire rd_en6_w;
wire rd_en7_w;

wire [127:0] dout0_w;
wire [127:0] dout1_w;
wire [127:0] dout2_w;
wire [127:0] dout3_w;
wire [127:0] dout4_w;
wire [127:0] dout5_w;
wire [127:0] dout6_w;
wire [127:0] dout7_w;

wire fifo_rst;
assign fifo_rst=~rst_n;	



always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    ControllerIdle<=1'b0;
	Cmd_Available<=1'b0;
  end
  else
  begin
    ControllerIdle<=(&FIFO_empty_w) & Chips_Ready;
	Cmd_Available <= (~|almost_full_w) & (|FE_ID_w) & (~cmd_arrived) &(~during_wr_data);
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    cmd_write_en<=1'b0;
	cmd_read_en<=1'b0;
	cmd_erase_en<=1'b0;
	Target_Addr<=3'b0;
	Current_ID<=4'b0;
	cmd_arrived<=1'b0;
  end
  else
  begin
	 if(Cmd_In_En&Cmd_Available)
	 begin
	   Command_Temp<=Cmd_In;
	 
		cmd_arrived<=1'b1;
	   case(Cmd_In[127:126])
		2'b00:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b1;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=Cmd_In[66:64];
		end
		2'b01:begin
		   Current_ID<=FE_ID_w;
		   cmd_write_en<=1'b1;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=Cmd_In[66:64];
		end
		2'b11:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b1;
		   Target_Addr<=Cmd_In[2:0];
		end
		default:begin
		   cmd_write_en<=1'b0;
	       cmd_read_en<=1'b0;
	       cmd_erase_en<=1'b0;
		   Target_Addr<=3'b0;
		end
	    endcase
     end 
    else if(cmd_write_en_clr)
	 begin
      cmd_write_en<=1'b0;
		cmd_arrived<=1'b0;
	 end
	else if (cmd_read_en_clr)
	begin
	  cmd_read_en<=1'b0;
	  cmd_arrived<=1'b0;
	end
	else if (cmd_erase_en_clr)
	begin
	   cmd_erase_en<=1'b0;
		cmd_arrived<=1'b0;
	end
  end
end



always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    empty<=8'hff;
  end
  else
  begin
    if(Set_Empty)
	begin
		case(Set_Empty_ID)
	  	4'h1:empty[0]<=1'b1;
		4'h2:empty[1]<=1'b1;
		4'h3:empty[2]<=1'b1;
		4'h4:empty[3]<=1'b1;
		4'h5:empty[4]<=1'b1;
		4'h6:empty[5]<=1'b1;
		4'h7:empty[6]<=1'b1;
		4'h8:empty[7]<=1'b1;
		default:empty<=empty;
	   endcase
	end
    else if(cmd_write_en)
	begin
  		case(Current_ID)
		     4'h1:empty[0]<=1'b0;
		     4'h2:empty[1]<=1'b0;
		     4'h3:empty[2]<=1'b0;
		     4'h4:empty[3]<=1'b0;
		     4'h5:empty[4]<=1'b0;
		     4'h6:empty[5]<=1'b0;
		     4'h7:empty[6]<=1'b0;
		     4'h8:empty[7]<=1'b0;
			 default:empty<=empty;
		   endcase
    end
	
  end
end


always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
     cmd_curr_state<='b0;
  end  
  else
  begin
    cmd_curr_state<=cmd_next_state;
  end
end  

always@(*)
begin

	case(cmd_curr_state) 
	IDLE:begin
	  if(cmd_write_en)
	    cmd_next_state=WR_FIRST_CMD;
	  else if (cmd_read_en)
	    cmd_next_state=RD_FIRST_CMD;
	  else if (cmd_erase_en)
	    cmd_next_state=ER_FIRST_CMD;
	  else
	    cmd_next_state=IDLE;
	end
	RD_FIRST_CMD:begin
	    cmd_next_state=RD_SECOND_CMD;
	end
	RD_SECOND_CMD:begin
	     cmd_next_state=IDLE;
	end
	WR_FIRST_CMD:begin
	   cmd_next_state=WR_SECOND_CMD;
	end
	WR_SECOND_CMD:begin
	   cmd_next_state=IDLE;
	end
	ER_FIRST_CMD:begin
	   cmd_next_state=ER_SECOND_CMD;
	end
	ER_SECOND_CMD:begin
	   cmd_next_state=IDLE;
	end
	default:begin
	  cmd_next_state=IDLE;
	end
	endcase
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
	  cmd_fifo_wr_en<=1'b0;
      cmd_data_in<=128'b0;
	  cmd_write_en_clr<=1'b0;
      cmd_read_en_clr<=1'b0;
      cmd_erase_en_clr<=1'b0;
	end
	else
	begin
	  case(cmd_next_state)
	  IDLE:begin
	     cmd_fifo_wr_en<=1'b0;
         cmd_data_in<=128'b0;
	     cmd_write_en_clr<=1'b0;
         cmd_read_en_clr<=1'b0;
         cmd_erase_en_clr<=1'b0;
	  end
	  
	  RD_FIRST_CMD:begin
	    cmd_read_en_clr<=1'b1;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  RD_SECOND_CMD:begin
	    cmd_read_en_clr<=1'b0;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  
	  WR_FIRST_CMD:begin
	    cmd_write_en_clr<=1'b1;
	    cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:123],Current_ID,Command_Temp[118:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  WR_SECOND_CMD:begin
	  	  cmd_write_en_clr<=1'b0;
	     cmd_fifo_wr_en<=1'b1;
        cmd_data_in<={Command_Temp[127:123],Current_ID,Command_Temp[118:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  ER_FIRST_CMD:begin
	     cmd_erase_en_clr<=1'b1;
		 cmd_fifo_wr_en<=1'b1;
         cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b0,Command_Temp[63+ADDR_WIDTH:0]};
	  end
	  ER_SECOND_CMD:begin
		 cmd_erase_en_clr<=1'b0;
		 cmd_fifo_wr_en<=1'b1;
       cmd_data_in<={Command_Temp[127:65+ADDR_WIDTH],1'b1,Command_Temp[63+ADDR_WIDTH:0]};     
	  end 
	  default:begin
	    cmd_erase_en_clr<=1'b0;
		 cmd_fifo_wr_en<=1'b0;
       cmd_data_in<=128'b0;
	  end
	  endcase
	end
end




always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
		  wr_address<=10'b0;
  end  
  else
  begin
       if(Data_In_En)
		  wr_address<=wr_address+1'b1;
	   else if(wr_data_counter==0)
		  wr_address<=(Current_ID-1'b1)*'h80;
	   else
	      wr_address<=wr_address;
		  
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    wr_data_counter<=7'b0;
  end
  else
  begin
     if(Data_In_En)
	   wr_data_counter<=wr_data_counter+1'b1;
	 else
	    wr_data_counter<=wr_data_counter;
  end
end

always@(posedge clk or negedge rst_n)
begin
  if(!rst_n)
  begin
    during_wr_data<=1'b0;
  end
  else
  begin
    if(cmd_write_en)
      during_wr_data<=1'b1;
    else if (wr_data_counter=='h7f)
      during_wr_data<=1'b0;
  end
end



always@(posedge fifo_rd_clk or negedge rst_n)
begin
  if(!rst_n)
  begin
     rd_address<=15'b0;
  end  
  else
  begin
       if(Rd_RAM_Data_en)
		    rd_address<=rd_address+1'b1;
		 else
		    rd_address<=(RAM_Unit_ID-1'b1)*'h1000;
  end
end

wire [255:0] data_in;

reg data_in_en;
reg [15:0] data0 ;
reg [15:0] data1 ;
reg [15:0] data2 ;
reg [15:0] data3 ;
reg [15:0] data4 ;
reg [15:0] data5 ;
reg [15:0] data6 ;
reg [15:0] data7 ;
reg [15:0] data8 ;
reg [15:0] data9 ;
reg [15:0] data10;
reg [15:0] data11;
reg [15:0] data12;
reg [15:0] data13;
reg [15:0] data14;
reg [15:0] data15;
reg [3:0] counter;


assign data_in={data0,data1,data2,data3,data4,data5,data6,data7,data8,data9,data10,data11,data12,data13,data14,data15};
RD_DATA_FIFO rd_data_fifo_inst1 (
  .rst(fifo_rst),
  .wr_clk(clk_83M),
  .rd_clk(clk),
  .din(data_in),
  .wr_en(data_in_en),
  .rd_en(Data_2_host_en),
  .dout(Data_2_host),
  .full(),
  .empty(),
  .prog_full(RD_data_FIFO_full)
);
reg [6:0] rd_data_in_counter;
always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     rd_data_in_counter<='b0;
  end
  else
  begin
     if(data_in_en)
	    rd_data_in_counter<=rd_data_in_counter+1'b1;
	  else
	    rd_data_in_counter<=rd_data_in_counter;
  end
end

always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin

    data_in_en<=1'b0;
  end
  else
  begin

    if(counter=='hf)
	  data_in_en<=1'b1;
	else
	  data_in_en<=1'b0;
  end
end
always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     data0 <=16'b0;
     data1 <=16'b0;
     data2 <=16'b0;
     data3 <=16'b0;
     data4 <=16'b0;
     data5 <=16'b0;
     data6 <=16'b0;
     data7 <=16'b0;
     data8 <=16'b0;
     data9 <=16'b0;
     data10<=16'b0;
     data11<=16'b0;
     data12<=16'b0;
     data13<=16'b0;
     data14<=16'b0;
     data15<=16'b0;
  end  
  else
  begin
     if(DataFromFlash_en)
	 begin
        data0 <= DataFromFlash;
        data1 <= data0        ;
        data2 <= data1        ;
        data3 <= data2        ;
        data4 <= data3        ;
        data5 <= data4        ;
        data6 <= data5        ;
        data7 <= data6        ;
        data8 <= data7        ;
        data9 <= data8        ;
        data10<= data9        ;
        data11<= data10       ;
        data12<= data11       ;
        data13<= data12       ;
        data14<= data13       ;
        data15<= data14       ;
	 end
  end
end

always@(posedge clk_83M or negedge rst_n )
begin
  if(!rst_n)
  begin
     counter<=4'b0;
  end
  else
  begin       
    if(DataFromFlash_en)
	     counter<=counter+1'b1;
  end
end



RAM_WRITE ram_write_inst (
  .clka(clk),
  .wea(Data_In_En),
  .addra(wr_address),
  .dina(Data_In),
  .douta(),
  .clkb(fifo_rd_clk),
  .web(1'b0),
  .addrb(rd_address),
  .dinb(8'b0),
  .doutb(Data_Out)
);
Valid_Monitor  valid_monitor_inst(.clk(clk), 
                                  .rst_n(rst_n), 
											 .Valid(empty), 
											 .FE_ID(FE_ID_w)
											  );


MUX1_8 mux1_8_inst( .address(Target_Addr),
               .wr_en(cmd_fifo_wr_en),
			   .din(cmd_data_in),
               .wr_en0(wr_en_w[0]),
			   .wr_en1(wr_en_w[1]),
			   .wr_en2(wr_en_w[2]),
			   .wr_en3(wr_en_w[3]),
			   .wr_en4(wr_en_w[4]),
			   .wr_en5(wr_en_w[5]),
			   .wr_en6(wr_en_w[6]),
			   .wr_en7(wr_en_w[7]),
               .din0(din0_w)  ,
			   .din1(din1_w)  ,
			   .din2(din2_w)  ,
			   .din3(din3_w)  ,
			   .din4(din4_w)  ,
			   .din5(din5_w)  ,
			   .din6(din6_w)  ,
			   .din7(din7_w) 
    );

TargetCmdFIFO target_fifo_inst0 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din0_w),
  .wr_en(wr_en_w[0]),
  .rd_en(rd_en0_w),
  .dout(dout0_w),
  .full(),
  .almost_full(almost_full_w[0]),
  .empty(FIFO_empty_w[0])
);
TargetCmdFIFO target_fifo_inst1 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din1_w),
  .wr_en(wr_en_w[1]),
  .rd_en(rd_en1_w),
  .dout(dout1_w),
  .full(),
  .almost_full(almost_full_w[1]),
  .empty(FIFO_empty_w[1])
);
TargetCmdFIFO target_fifo_inst2 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din2_w),
  .wr_en(wr_en_w[2]),
  .rd_en(rd_en2_w),
  .dout(dout2_w),
  .full(),
  .almost_full(almost_full_w[2]),
  .empty(FIFO_empty_w[2])
);
TargetCmdFIFO target_fifo_inst3 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din3_w),
  .wr_en(wr_en_w[3]),
  .rd_en(rd_en3_w),
  .dout(dout3_w),
  .full(),
  .almost_full(almost_full_w[3]),
  .empty(FIFO_empty_w[3])
);
TargetCmdFIFO target_fifo_inst4 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din4_w),
  .wr_en(wr_en_w[4]),
  .rd_en(rd_en4_w),
  .dout(dout4_w),
  .full(),
  .almost_full(almost_full_w[4]),
  .empty(FIFO_empty_w[4])
);
TargetCmdFIFO target_fifo_inst5 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din5_w),
  .wr_en(wr_en_w[5]),
  .rd_en(rd_en5_w),
  .dout(dout5_w),
  .full(),
  .almost_full(almost_full_w[5]),
  .empty(FIFO_empty_w[5])
);
TargetCmdFIFO target_fifo_inst6 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din6_w),
  .wr_en(wr_en_w[6]),
  .rd_en(rd_en6_w),
  .dout(dout6_w),
  .full(),
  .almost_full(almost_full_w[6]),
  .empty(FIFO_empty_w[6])
);
TargetCmdFIFO target_fifo_inst7 (
  .clk(clk),
  .rst(fifo_rst),
  .din(din7_w),
  .wr_en(wr_en_w[7]),
  .rd_en(rd_en7_w),
  .dout(dout7_w),
  .full(),
  .almost_full(almost_full_w[7]),
  .empty(FIFO_empty_w[7])
);

MUX8_1 mux8_1_inst(
                   .address(FIFO_addr),

                   .rd_en0(rd_en0_w),
                   .rd_en1(rd_en1_w),
                   .rd_en2(rd_en2_w),
                   .rd_en3(rd_en3_w),
                   .rd_en4(rd_en4_w),
                   .rd_en5(rd_en5_w),
                   .rd_en6(rd_en6_w),
                   .rd_en7(rd_en7_w),
                   .dout0(dout0_w),
                   .dout1(dout1_w),
                   .dout2(dout2_w),
                   .dout3(dout3_w),
                   .dout4(dout4_w),
                   .dout5(dout5_w),
                   .dout6(dout6_w),
                   .dout7(dout7_w),
				       .empty0(FIFO_empty_w[0]),
                   .empty1(FIFO_empty_w[1]),
                   .empty2(FIFO_empty_w[2]),
                   .empty3(FIFO_empty_w[3]),
                   .empty4(FIFO_empty_w[4]),
                   .empty5(FIFO_empty_w[5]),
                   .empty6(FIFO_empty_w[6]),
                   .empty7(FIFO_empty_w[7]),

                   .rd_en(FIFO_rd_en),
				   .empty(FIFO_empty),
                   .dout(Cmd_Out)
    );
	

Finished_Cmd_FIFO finished_cmd_fifo_inst1(.clk(clk),
                                          .rst(fifo_rst),
														.din(Cmd_Out),
														.wr_en(Finished_cmd_wr_en),
														.rd_en(Finished_Cmd_Out_En),
														.dout(Finished_Cmd_Out),
														.full(Finished_cmd_FIFO_full),
														.empty(Finished_Cmd_FIFO_Empty)
														);

endmodule