module T_control(clk,reset,sink_valid,sink_sop,sink_eop,fifo_full,Realdata_in,Imagdata_in,
Rfifodata_in,Ififodata_in,state,ADD,ADD_WN,Realdata_out,Imagdata_out,rdata_out,idata_out,
source_valid,source_eop,source_sop,sink_ready,source_valid_Tcontrol,rdreq_fifo,aclr_rom,cnt);

input clk,reset,sink_valid,sink_sop,sink_eop,fifo_full;
input [1:0]state;
input[17:0] Realdata_in,Imagdata_in,Rfifodata_in,Ififodata_in;
output source_valid,source_eop,source_sop,sink_ready,source_valid_Tcontrol,rdreq_fifo,aclr_rom;
output[15:0] Realdata_out,Imagdata_out,rdata_out,idata_out;
output[5:0]ADD;
output[4:0]ADD_WN;
output[6:0]cnt;

parameter level_total=4'b0110;
parameter idle=3'b000,sink=3'b001,Pro_read=3'b011,Pro_write=3'b111,source=3'b110,Wait=3'b101;
parameter scale=10'b0001000000;

reg[2:0] current_state,next_state;
reg[2:0] level,next_level;
reg[6:0] i;
reg[6:0] cnt,next_cnt;
reg[5:0]  k;
reg[5:0] add[scale-1:0];
reg[4:0] add_wn[31:0];//存放旋转因子地址值 

wire[17:0]Rdata_in,Idata_in,Rdata_out,Idata_out;
wire[5:0] ADD;
wire[4:0]ADD_WN;
wire WR;

always@(current_state or sink_valid or sink_eop or sink_sop or cnt or level or fifo_full)begin
	case(current_state)
		idle:	if(sink_valid==1&sink_sop==1)begin
					next_state=sink;
					next_cnt=1;
					next_level=level;
					end
				else begin
					next_state=idle;
					next_cnt=0;
					next_level=level;
					end
		sink:	if(sink_valid==1&sink_eop==1)begin
						next_state=Pro_read;
						next_cnt=0;
						next_level=level;
						end
					else begin
						next_state=sink;
						next_level=level;
						if(cnt>scale-1)
							next_cnt=0;
						else
							next_cnt=cnt+7'b0000_001;
						end
	   Pro_read: if(cnt<scale+1)	begin
						next_state=Pro_read;
						next_cnt=cnt+7'b0000_001;
						next_level=level;
						end
				else begin
						next_state=Wait;
						next_cnt=0;
						next_level=level;
					end
		Wait:	if(fifo_full==1)begin
						next_state=Pro_write;
						next_cnt=0;
						next_level=level;
						end
				else	begin
						next_state=Wait;
						next_cnt=0;
						next_level=level;
						end
		Pro_write:if(cnt<scale-1)	begin
					next_state=Pro_write;
					next_cnt=cnt+7'b0000_001;
					next_level=level;
					end
				else if(level<level_total-1)	begin
						next_state=Pro_read;
						next_cnt=0;
						next_level=level+3'b001;
					end
					else	begin
						next_state=source;
						next_cnt=0;
						next_level=0;
					end
		source:	if(cnt>scale)begin
					next_state=idle;
					next_cnt=0;
					next_level=level;
				end
				else begin
					next_state=source;
					next_cnt=cnt+7'b0000_001;
					next_level=level;
				end
		default: begin
					next_state=idle;
					next_cnt=0;
					next_level=level;
					end
	endcase
end
	
always@(posedge clk or negedge reset)begin
if(!reset)begin
		current_state<=idle;
		level<=0;
		cnt<=0;
	end
else begin		
		current_state<=next_state;
		level<=next_level;
		cnt<=next_cnt;
	end
end

always@(level)begin//address of butterfly
	case(level)
		0:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[0],i[5],i[4],i[3],i[2],i[1]};
		1:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[0],i[4],i[3],i[2],i[1]};			
		2:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[4],i[0],i[3],i[2],i[1]};
		3:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[4],i[3],i[0],i[2],i[1]};
		4:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[4],i[3],i[2],i[0],i[1]};
		5:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[4],i[3],i[2],i[1],i[0]};
	default:for(i=7'b0000_000;i<scale;i=i+7'b0000_001)
				add[i]={i[5],i[4],i[3],i[2],i[1],i[0]};
	endcase		
end

always@(level)begin//address of butterfly
	case(level)
		0:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]=k[4:0];
		1:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]={k[3:0],1'b0};	//the theory	
		2:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]={k[2:0],2'b00};
		3:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]={k[1:0],3'b000};
		4:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]={k[0],4'b0000};
		5:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]=5'b00000;
	default:for(k=6'b0000_00;k<32;k=k+6'b0000_01)
				add_wn[k]=5'b00000;
	endcase		
end






lpm_ram_dq0 ram1(.clock(clk), .address(ADD), .wren(WR), .data(Rdata_in),.q(Rdata_out));
lpm_ram_dq0 ram2(.clock(clk), .address(ADD), .wren(WR), .data(Idata_in),.q(Idata_out));//RAM慢两拍！

assign ADD=(next_state==sink||current_state==sink)?cnt[5:0]:
		   (current_state==Pro_read||current_state==Pro_write)?add[cnt]:
		   (current_state==source)?{cnt[0],cnt[1],cnt[2],cnt[3],cnt[4],cnt[5]}:6'b0000_00;//bit-reversed
assign Rdata_in=(next_state==sink||current_state==sink)?Realdata_in:
				(current_state==Pro_write)?Rfifodata_in:18'b0000_0000_0000_000000;
assign Idata_in=(next_state==sink||current_state==sink)?Imagdata_in:
				(current_state==Pro_write)?Ififodata_in:18'b0000_0000_0000_000000;
assign WR=(next_state==sink||current_state==sink||current_state==Pro_write)?1'b1:1'b0;
assign ADD_WN=(current_state==Pro_read&&cnt<scale)?add_wn[cnt[5:1]]:5'b0000_0;

assign aclr_rom=(current_state==Pro_read&&cnt<scale+1)?1'b0:1'b1;
assign source_valid=(current_state==source&&cnt>1)?1'b1:1'b0;
assign source_sop=(current_state==source&&cnt==2)?1'b1:1'b0;
assign source_eop=(next_state==idle&&cnt==scale+1)?1'b1:1'b0;
assign Imagdata_out=(current_state==source&&cnt>1)?
						(state==2'b00)?Idata_out[15:0]:
						(state==2'b01)?Idata_out[16:1]:
						(state==2'b10)?Idata_out[17:2]:16'b0000_0000_0000_0000:16'b0000_0000_0000_0000;
assign Realdata_out=(current_state==source&&cnt>1)?
						(state==2'b00)?Rdata_out[15:0]:
						(state==2'b01)?Rdata_out[16:1]:
						(state==2'b10)?Rdata_out[17:2]:16'b0000_0000_0000_0000:16'b0000_0000_0000_0000;
assign sink_ready=(!reset)?1'b0:(current_state==idle||current_state==sink)?1'b1:1'b0;
assign source_valid_Tcontrol=(!reset)?1'b0:(current_state==Pro_read&&cnt>1)?1'b1:1'b0;
assign rdata_out=(!reset)?16'b0000_0000_0000_0000:(current_state==Pro_read&&cnt>1)?//attention
						(state==2'b00)?Rdata_out[15:0]:
						(state==2'b01)?Rdata_out[16:1]:
						(state==2'b10)?Rdata_out[17:2]:16'b0000_0000_0000_0000:16'b0000_0000_0000_0000;
assign idata_out=(!reset)?16'b0000_0000_0000_0000:(current_state==Pro_read&&cnt>1)?
						(state==2'b00)?Idata_out[15:0]:
						(state==2'b01)?Idata_out[16:1]:
						(state==2'b10)?Idata_out[17:2]:16'b0000_0000_0000_0000:16'b0000_0000_0000_0000;
assign rdreq_fifo=(!reset)?1'b0:(next_state==Pro_write)?1'b1:1'b0;

endmodule




