设计一个10层楼的电梯控制器模块
- 实验内容与原理说明
要求:(1) 以按键的时间先后优先级进行设计;
或者 (2) 以楼层最短位置先后优先级进行设计.
由题意可知,因为每层楼设有上下两个按钮,其中1层只能有上楼请求,10层只能有下楼请求,同一层不能既有上楼请求又有下楼请求。上楼或下楼请求被响应后对应位清零。当有其中一层的按钮按下时,电梯前往;根据时间优先级,可以设置先按下的请求先响应;根据位置优先级,可以设置距离近的请求先响应。可以设置clk,reset,up1-up9,down2-down10共计20个端口,用来输入时钟信号、复位信号和每层楼的上下请求。
有限状态机共stopon1,dooropen,doorclose,wait1, wait2, wait3, wait4, up, down, stop十个状态,分别对应停在一楼、开门、关门、等待(共4s)、上、下、停止十个工作状态。
由上分析,可以绘制其仿真的状态图如下:
整体仿真的流程图如下:
2. 实验模块程序代码和激励代码
(1)设计模块代码
module Lift(CLK,RESET,up,down,button,pos);
//定义时钟和复位信号
input CLK,RESET;
//定义10位上、下楼请求信号和选择的楼层输入信号
input [10:1] up,down,button;
//4位的当前楼层的输出信号
output reg [3:0] pos;
reg [3:0] P;
//定义10位的电梯需要停下开门的楼层的信号
reg [10:1] FLOOR;
//定义上下楼指示信号
reg up_down;
//定义tmp为楼层指示信号,flag为非同相的请求
reg tmp,flag;
integer temp;
//使用one-hot码编码的状态指示信号
reg [8:0] CState,NState;
parameter S0=9'b000000001,S1=9'b000000010,S2=9'b000000100,S3=9'b000001000,S4=9'b000010000,S5=9'b000100000,S6=9'b001000000,S7=9'b010000000,S8=9'b100000000;//使用独热码对状态进行编码
//定义状态转换代码段
always@(posedge CLK or negedge RESET)
begin
if(~RESET)
CState<=S0;//复位到S0
else
CState<=NState;//调整到下一个状态
end
//定义状态转换条件模块
always@(RESET or CState or up_down or up or down or button or P or flag)
begin
//若复位信号有效
if(~RESET) begin
up_down=0;//将上升下降信号复位
FLOOR=10'b0;//将要开门的楼层的指示信号复位
P=4'b0001;//复位在1楼
flag=0;//复位为没有非同向请求
end
else begin//若复位信号无效,开始正常运行
if(flag==0)//如果没有非同向请求
FLOOR=up_down?down|button:up|button;
//在上楼时,要开门的楼层就是有上楼请求信号的楼层和电梯内要去的楼层.
case(CState)
S0://定义停驻状态
begin
pos=P;
//输出当前所在的楼层位置
if(FLOOR==10'b0)
NState=S0;
//如果要开门的楼层信号为空,则次态仍为等待状态
else begin
//如果要开门的楼层的信号不为空,也就是在运行或有请求信号
if(up_down==0) begin//如果正在上升
if(P==4'b1010)
up_down=1;//在10楼时,由于无法上升,因此将模式改为下降
else begin//若非顶层
case(P)
4'b0001:
tmp=FLOOR[2] | FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];//如果要去当前层以上的任意一层,tmp为1
4'b0010:
tmp=FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0011:
tmp=FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0100:
tmp=FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0101:
tmp=FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0110:
tmp=FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0111:
tmp=FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b1000:
tmp=FLOOR[9] | FLOOR[10];
4'b1001:
tmp=FLOOR[10];
endcase
if(tmp==0) begin
FLOOR=down|button;
case(P)
4'b0001:
tmp=FLOOR[2] | FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0010:
tmp=FLOOR[3] | FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0011:
tmp=FLOOR[4] | FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0100:
tmp=FLOOR[5] | FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0101:
tmp=FLOOR[6] | FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0110:
tmp=FLOOR[7] | FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b0111:
tmp=FLOOR[8] | FLOOR[9] | FLOOR[10];
4'b1000:
tmp=FLOOR[9] | FLOOR[10];
4'b1001:
tmp=FLOOR[10];
endcase
if(tmp==0) up_down=1;
else begin
flag=1;
up_down=0;
end
end
end
end
else begin
if(P==4'b0001) up_down=0;
else begin
case(P)
4'b1010:
tmp=FLOOR[9] | FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b1001:
tmp=FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b1000:
tmp=FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0111:
tmp=FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0110:
tmp=FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0101:
tmp=FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0100:
tmp=FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0011:
tmp=FLOOR[2] | FLOOR[1];
4'b0010:
tmp=FLOOR[1];
endcase
if(tmp==0) begin
FLOOR=up|button;
case(P)
4'b1010:
tmp=FLOOR[9] | FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b1001:
tmp=FLOOR[8] | FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b1000:
tmp=FLOOR[7] | FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0111:
tmp=FLOOR[6] | FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0110:
tmp=FLOOR[5] | FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0101:
tmp=FLOOR[4] | FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0100:
tmp=FLOOR[3] | FLOOR[2] | FLOOR[1];
4'b0011:
tmp=FLOOR[2] | FLOOR[1];
4'b0010:
tmp=FLOOR[1];
endcase
if(tmp==0) up_down=0;
else begin
flag=1;
up_down=1;
end
end
end
end
NState=S1;
end
end
S1:
NState=S2;
S2:
NState=S3;
S3:
NState=S4;
S4:
begin
if(up_down==0) NState=S5;
else NState=S6;
end
S5:
begin
if(FLOOR==10'b0) NState=S0;
else begin
P=P+1;
if(flag==1) begin: B1
integer i;
temp=0;
for(i=10;i>0&&temp==0;i=i-1)
if(FLOOR[i]==1)
temp=i;
if(P==temp) begin
flag=0;
up_down=1;
NState=S0;
end
else
NState=S7;
end
else begin
if(FLOOR[P])
NState=S0;
else
NState=S7;
end
end
end
S6:
begin
if(FLOOR==10'b0)
NState=S0;
else begin
P=P-1;
if(flag==1) begin:B2
integer i;
temp=0;
for(i=1;i<11&&temp==0;i=i+1)
if(FLOOR[i]==1)
temp=i;
if(P==temp) begin
flag=0;
up_down=0;
NState=S0;
end
else
NState=S8;
end
else begin
if(FLOOR[P])
NState=S0;
else
NState=S8;
end
end
end
S7:
NState=S5;
S8:
NState=S6;
endcase
end
end
endmodule
(2)激励模块代码
// Verilog Test Bench template for design : Lift
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module Lift_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg CLK;
reg RESET;
reg [10:1] button;
reg [10:1] down;
reg [10:1] up;
// wires
wire [3:0] pos;
// assign statements (if any)
Lift i1 (
// port map - connection between master ports and signals/registers
.CLK(CLK),
.RESET(RESET),
.button(button),
.down(down),
.pos(pos),
.up(up)
);
always begin
CLK=1'b0;
#5 CLK=1'b1;
#5;
end
initial begin
RESET=1'b0;
#10 RESET=1'b1;
#790 $stop;
end
initial begin
up=10'b0;
#10 up=10'b0000010001;
#40 up=10'b0000010000;
#160 up=10'b0;
end
initial begin
down=10'b0;
#210 down=10'b1100000000;
#180 down=10'b0100000000;
#60 down=10'b0;
#120 down=10'b0000100000;
#40 down=10'b0;
end
initial begin
button=10'b0;
#10 button=10'b0000001000;
#140 button=10'b0;
#20 button=10'b0010000000;
#140 button=10'b0;
#40 button=10'b0000100000;
#200 button=10'b0;
#20 button=10'b0000000001;
#180 button=10'b0;
end
endmodule
- 波形仿真图
4.门级电路图
设计模块所占用器件的资源情况如下所示:
【实验结果及思考】
此次实验有关有限状态机的设计,包括一个交通红绿灯控制器模块,实现主干道和支路之间红绿黄灯的信号转换,小轿车尾灯控制器模块以及设计一个10层楼的电梯控制器模块。总体来说是上学期数电中有关状态机的实际应用,但是给我思路上的启发是巨大的,帮助我从实践的角度理解Mealy状态图和Moore状态图。也帮助我捋清了状态机的设计步骤,即:
1)依据具体的设计原则,确定采用Moore状态机还是Mealy状态机。
2)分析设计要求列出状态机的所有状态,并对每一个状态进行状态编码
3)根据状态转移关系和输出函数画出状态图。
4)根据所画的状态图,采用硬件描述语言对状态机进行描述。
对状态机的各个状态赋予一组特定的二进制数称为状态编码。在状态机的编码中,我尝试了自然二进制编码、格雷编码和One-Hot编码。通过占用情况可以很明显地看出自然二进制码和格雷码的编码方案使用的触发器较少,其编码效率较高,但负责根据当前状态和状态转换条件进行译码的组合电路会比较复杂,其逻辑规模也较大,使得次态逻辑在传输过程中需要经过多级逻辑,从而影响电路的工作速度。在设计的过程中,我也在实践中复习了ASM的相关知识。通过ASM图设计数字系统,可以很容易将语言描述的设计问题变成时序流程图的描述。根据时序流程图就可以得到电路的状态图和输出函数,从而得出相应的硬件电路。在设计的过程中体会到了它的便利之处。
同时,这次实验让我懂得了理论与实际相结合是很重要的,只有上课所学到的理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论、验证结论,才能真正提高自己的实际动手和独立思考的能力。在设计的过程中遇到问题,通过查阅资料、查阅手册及共同讨论的方式,最终解决了遇到的难关。