FPGA设计电梯控制器模块

举报
timerring 发表于 2022/07/29 22:00:03 2022/07/29
【摘要】 设计一个10层楼的电梯控制器模块1. 实验内容与原理说明要求:(1) 以按键的时间先后优先级进行设计;或者 (2) 以楼层最短位置先后优先级进行设计.由题意可知,因为每层楼设有上下两个按钮,其中1层只能有上楼请求,10层只能有下楼请求,同一层不能既有上楼请求又有下楼请求。上楼或下楼请求被响应后对应位清零。当有其中一层的按钮按下时,电梯前往;根据时间优先级,可以设置先按下的请求先响应;根据位置...

设计一个10层楼的电梯控制器模块

1. 实验内容与原理说明

要求:(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

3. 波形仿真图

编辑

4.门级电路图

编辑

设计模块所占用器件的资源情况如下所示:

编辑

【实验结果及思考】

此次实验有关有限状态机的设计,包括一个交通红绿灯控制器模块,实现主干道和支路之间红绿黄灯的信号转换,小轿车尾灯控制器模块以及设计一个10层楼的电梯控制器模块。总体来说是上学期数电中有关状态机的实际应用,但是给我思路上的启发是巨大的,帮助我从实践的角度理解Mealy状态图和Moore状态图。也帮助我捋清了状态机的设计步骤,即:

1)依据具体的设计原则,确定采用Moore状态机还是Mealy状态机。

2)分析设计要求列出状态机的所有状态,并对每一个状态进行状态编码

3)根据状态转移关系和输出函数画出状态图。

4)根据所画的状态图,采用硬件描述语言对状态机进行描述。


对状态机的各个状态赋予一组特定的二进制数称为状态编码。在状态机的编码中,我尝试了自然二进制编码、格雷编码和One-Hot编码。通过占用情况可以很明显地看出自然二进制码和格雷码的编码方案使用的触发器较少,其编码效率较高,但负责根据当前状态和状态转换条件进行译码的组合电路会比较复杂,其逻辑规模也较大,使得次态逻辑在传输过程中需要经过多级逻辑,从而影响电路的工作速度。在设计的过程中,我也在实践中复习了ASM的相关知识。通过ASM图设计数字系统,可以很容易将语言描述的设计问题变成时序流程图的描述。根据时序流程图就可以得到电路的状态图和输出函数,从而得出相应的硬件电路。在设计的过程中体会到了它的便利之处。

理论与实际相结合是很重要的,只有把所学的理论知识与实践相结合起来,从理论中得出结论、验证结论,才能真正提高自己的实际动手和独立思考的能力。在设计的过程中遇到问题,通过查阅资料、查阅手册及共同讨论的方式,最终解决了遇到的难关。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。