//将各上升请求信号实时地合并(6楼为顶层,无上升请求,考虑到通用性,将第4位填零)
always @(call_up_1 or call_up_2 or call_up_3 or call_up_4 or call_up_5)
up_all={1'b0, call_up_5, call_up_4, call_up_3, call_up_2, call_up_1};
//将各下降请求信号实时地合并(1楼为底层,无下降请求,考虑到通用性,将第1位填零)
always @(call_down_2 or call_down_3 or call_down_4 or call_down_5 or call_down_6)
down_all={call_down_6, call_down_5, call_down_4, call_down_3, call_down_2, 1'b0};
//将各停靠请求信号实时地合并
always @(request_1 or request_2 or request_3 or request_4 or request_5 or request_6)
request_all={request_6, request_5, request_4, request_3, request_2, request_1};
//display which floor the elevator is....
display_decode h1(cp_50M,PosOut,out,over_alarm);
display_decode_count h2(cp_50M,count,count_out);
// finite state machine in the style of three segments ,三段式
//1st StateShift always block,sequential state transition,有限状态机第一段
always @(posedge real_clk or posedge reset)
if(reset)
begin
LiftState<=WAIT;
end
else
LiftState<=NextState;
//2nd StateShift always block,combinational condition judgement,有限状态机第二段
always @(LiftState or up_all or down_all or request_all or pos or count or UpDnFlag)
case(LiftState)
WAIT:
begin
if(request_all>0)//有停靠请求否
begin
if((request_all&pos)>0)//停靠请求中有当前楼层停靠请求否
NextState=OPENDOOR;//有当前楼层请求,则下一状态转开门
else if(request_all>pos)//有当前楼层之上的停靠请求否(优先向上的请求)
NextState=UP;//有则,下一状态转上升
else
NextState=DOWN;//只有当前楼层之下的停靠请求,下一状态转下降
end
else if((up_all&pos)||(down_all&pos))//上下请求中有当前楼层请求否
begin
NextState=OPENDOOR;
end
else if((up_all>pos)||(down_all>pos))//上下请求中有当前楼层之上的请求否
NextState=UP;
else if(up_all||down_all)//上下请求中有当前楼层之下的请求否
NextState=DOWN;
else
NextState=WAIT;//无任何请求,继续处于WAIT模式
end
UP:
begin
if((request_all&pos)||(up_all&pos))//停靠或上升请求中有当前楼层的请求否
NextState=UPSTOP;//有,下一状态转为UPSTOP(停靠后要1s才开门,UPSTOP即为这1s的过渡期)
else if((request_all>pos)||(up_all>pos))//停靠或上升请求中有当前楼层之上的请求否
NextState=UP;
else if(down_all>0)//有下降请求否
begin
if((down_all>pos)&&((down_all^pos)>pos))//下降请求中有当前楼层的请求否
NextState=UP;
else if((down_all&pos)||(pos<FLOOR6)) //其实这样做意义不大,只是使上下标志提前变化
NextState=UPSTOP;
else if((down_all&pos)&&(pos==FLOOR6))//事实上不满足第一条件的话,电梯根本不会到达第四层
NextState=DOWNSTOP;
else//下降请求中只有当前楼层之下的请求
NextState=DOWN;
end
else if(request_all||up_all)//只有当前楼层之上的停靠或上升请求否
NextState=DOWN;
else
NextState=WAIT;//无任何请求,转为WAIT模式
end
else if(up_all>0)
begin
if(((up_all&FLOOR1)<pos&&(up_all&FLOOR1))||((up_all&FLOOR2)<pos&&(up_all&FLOOR2))||((up_all&FLOOR3)<pos&&(up_all&FLOOR3))||((up_all&FLOOR4)<pos&&(up_all&FLOOR4))||((up_all&FLOOR5)<pos&&(up_all&FLOOR5))||((up_all&FLOOR6)<pos&&(up_all&FLOOR6)))
NextState=DOWN;
else if((up_all&pos)&&(pos>FLOOR1))
NextState=DOWNSTOP;
else if((up_all&pos)&&(pos==FLOOR1))
NextState=UPSTOP;
else
NextState=UP;
end
else if(request_all||down_all)
NextState=UP;
else
NextState=WAIT;
end
UPSTOP:
begin
NextState=OPENDOOR;//停靠1时钟周期后开门
end
DOWNSTOP:
begin
NextState=OPENDOOR;//停靠1时钟周期后开门
end
OPENDOOR:
begin
if(count<5)//开门不足5周期,则继续转移到开门状态
NextState=OPENDOOR;
else
NextState=CLOSEDOOR;//开门5周期后,关门
end
CLOSEDOOR:
begin
if(UpDnFlag==UPFLAG)//开门关门前电梯是处于上升状态吗
begin
if((request_all&pos)||(up_all&pos))//上升或停靠请求中有当前楼层的请求否,有可能关门的瞬间又有新的请求
NextState=OPENDOOR;
else if((request_all>pos)||(up_all>pos))//上升或停靠请求中有当前楼层之上的请求否
NextState=UP;
else if(down_all>0)//有下降请求否
begin
if((down_all>pos)&&((down_all^pos)>pos))
NextState=UP;//有当前楼层之上的下降请求,则下一状态转移上升
else if((down_all&pos)>0)//有当前楼层的下降请求信号,且更上层无下降请求
NextState=OPENDOOR;
else//只有低于当前层的下降请求
NextState=DOWN;
end
else if(request_all||up_all)//上升和停靠请求中有当前层的请求且只有当前层下的请求
NextState=DOWN;
else
NextState=WAIT;//无任何请求,转为WAIT模式
end
//请参考UpDnFlag=UPFLAG的注释
else if(UpDnFlag==DNFLAG)
begin
if((request_all&pos)||(down_all&pos))
NextState=OPENDOOR;
else if(((request_all&FLOOR1)<pos&&(request_all&FLOOR1))||((request_all&FLOOR2)<pos&&(request_all&FLOOR2))||((request_all&FLOOR3)<pos&&(request_all&FLOOR3))||((request_all&FLOOR4)<pos&&(request_all&FLOOR4))||((request_all&FLOOR5)<pos&&(request_all&FLOOR5))||((request_all&FLOOR6)<pos&&(request_all&FLOOR6)))
NextState=DOWN;
else if(((down_all&FLOOR1)<pos&&(down_all&FLOOR1))||((down_all&FLOOR2)<pos&&(down_all&FLOOR2))||((down_all&FLOOR3)<pos&&(down_all&FLOOR3))||((down_all&FLOOR4)<pos&&(down_all&FLOOR4))||((down_all&FLOOR5)<pos&&(down_all&FLOOR5))||((down_all&FLOOR6)<pos&&(down_all&FLOOR6)))
NextState=DOWN;
else if(up_all>0)
begin
if(((up_all&FLOOR1)<pos&&(up_all&FLOOR1))||((up_all&FLOOR2)<pos&&(up_all&FLOOR2))||((up_all&FLOOR3)<pos&&(up_all&FLOOR3))||((up_all&FLOOR4)<pos&&(up_all&FLOOR4))||((up_all&FLOOR5)<pos&&(up_all&FLOOR5))||((up_all&FLOOR6)<pos&&(up_all&FLOOR6)))
NextState=DOWN;
else if((up_all&pos)>0)
NextState=OPENDOOR;
else
NextState=UP;//
end
else if(request_all||down_all)
NextState=UP;
else
NextState=WAIT;//
end
//请参考WAIT模式的注释
else
begin
if(request_all>0)
begin
if((request_all&pos)>0)
NextState=OPENDOOR;
else if(request_all>pos)
NextState=UP;
else
NextState=DOWN;
end
else if((up_all&pos)||(down_all&pos))
begin
NextState=OPENDOOR;
end
else if((up_all>pos)||(down_all>pos))
NextState=UP;
else if(up_all||down_all)
NextState=DOWN;
else
begin
NextState=WAIT;
end
end
end
default:
NextState=WAIT;
endcase
//3rd StateShift always block,the sequential FSM output,有限状态机第三段
always @(posedge real_clk or posedge reset)//output
if(reset)
//复位后初始化当前楼层为第一层,门是关闭的,电梯是静止的
begin
pos<=FLOOR1;
DoorFlag<=CLOSED;
UpDnFlag<=STATIC;
end
else
begin
PosOut<=pos;//PosOut的输出慢pos一个时钟周期
case(NextState)
WAIT:
//状态为WAIT时,楼层不变,门是关闭的,电梯是静止的,其他模式的情况请大家自己推导
begin
pos<=pos;
DoorFlag<=CLOSED;
UpDnFlag<=STATIC;
end
UP:
begin
pos<=pos<<1;
DoorFlag<=CLOSED;
UpDnFlag<=UPFLAG;
end
DOWN:
begin
pos<=pos>>1;
DoorFlag<=CLOSED;
UpDnFlag<=DNFLAG;
end
UPSTOP:
begin
pos<=pos;
DoorFlag<=CLOSED;
UpDnFlag<=UPFLAG;
end
DOWNSTOP:
begin
pos<=pos;
DoorFlag<=CLOSED;
UpDnFlag<=DNFLAG;
end
OPENDOOR:
begin
pos<=pos;
DoorFlag<=OPEN;
UpDnFlag<=UpDnFlag;
end
CLOSEDOOR:
begin
pos<=pos;
DoorFlag<=CLOSED;
UpDnFlag<=UpDnFlag;
end
default:
//默认情况
begin
pos<=FLOOR1;
DoorFlag<=CLOSED;
UpDnFlag<=STATIC;
end
endcase
end
endmodule
/////////////////////////////////////////////
// Only write to LCD, bypass iRS to LCD_RS
assign LCD_DATA = iDATA;
assign LCD_RW = 1'b0;
assign LCD_RS = iRS;
/////////////////////////////////////////////
always@(posedge iCLK or negedge iRST_N)
begin
if(!iRST_N)
begin
oDone <= 1'b0;
LCD_EN <= 1'b0;
preStart<= 1'b0;
mStart <= 1'b0;
Cont <= 0;
ST <= 0;
end
else
begin
////// Input Start Detect ///////
preStart<= iStart;
if({preStart,iStart}==2'b01)
begin
mStart <= 1'b1;
oDone <= 1'b0;
end
//////////////////////////////////
if(mStart)
begin
case(ST)
0: ST <= 1; // Wait Setup
1: begin
LCD_EN <= 1'b1;
ST <= 2;
end
2: begin
if(Cont<CLK_Divide)
Cont <= Cont+1;
else
ST <= 3;
end
3: begin
LCD_EN <= 1'b0;
mStart <= 1'b0;
oDone <= 1'b1;
Cont <= 0;
ST <= 0;
end
endcase
end
end
end
always@(posedge iCLK or negedge iRST_N)
begin
if(!iRST_N)
begin
LUT_INDEX <= 0;
mLCD_ST <= 0;
mDLY <= 0;
mLCD_Start <= 0;
mLCD_DATA <= 0;
mLCD_RS <= 0;
end
else
begin
if(LUT_INDEX<LUT_SIZE)
begin
case(mLCD_ST)
0: begin
mLCD_DATA <= LUT_DATA[7:0];
mLCD_RS <= LUT_DATA[8];
mLCD_Start <= 1;
mLCD_ST <= 1;
end
1: begin
if(mLCD_Done)
begin
mLCD_Start <= 0;
mLCD_ST <= 2;
end
end
2: begin
if(mDLY<18'h00008)
mDLY <= mDLY+1;
else
begin
mDLY <= 0;
mLCD_ST <= 3;
end
end
3: begin
LUT_INDEX <= LUT_INDEX+1;
mLCD_ST <= 0;
end
endcase
end