FPGA设计电梯控制器模块

简介: 本文介绍了FPGA设计电梯控制器模块的具体方法

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

  1. 实验内容与原理说明

要求:(1) 以按键的时间先后优先级进行设计;

或者 (2) 以楼层最短位置先后优先级进行设计.

由题意可知,因为每层楼设有上下两个按钮,其中1层只能有上楼请求,10层只能有下楼请求,同一层不能既有上楼请求又有下楼请求。上楼或下楼请求被响应后对应位清零。当有其中一层的按钮按下时,电梯前往;根据时间优先级,可以设置先按下的请求先响应;根据位置优先级,可以设置距离近的请求先响应。可以设置clk,reset,up1-up9,down2-down10共计20个端口,用来输入时钟信号、复位信号和每层楼的上下请求。

有限状态机共stopon1,dooropen,doorclose,wait1, wait2, wait3, wait4, up, down, stop十个状态,分别对应停在一楼、开门、关门、等待(共4s)、上、下、停止十个工作状态。

image.png

由上分析,可以绘制其仿真的状态图如下:

 image.png

整体仿真的流程图如下:
image.png

 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

  1. 波形仿真图

image.png

4.门级电路图
image.png

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

image.png

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

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

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

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

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

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

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

目录
相关文章
|
2月前
|
数据采集 传感器 监控
如何在LabVIEW中使用FPGA模块
如何在LabVIEW中使用FPGA模块
43 1
|
9天前
|
算法 测试技术 开发工具
基于FPGA的QPSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
该系统在原有的QPSK调制解调基础上,新增了高斯信道和误码率统计模块,验证了不同SNR条件下的QPSK误码性能。系统包括数据生成、QPSK调制与解调等模块,使用Vivado 2019.2进行仿真,展示了SNR分别为15dB、10dB、5dB和1dB时的误码情况。系统采用Verilog语言实现,具有高效、可靠的特点。
25 3
|
2月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误码率统计模块
升级版FPGA MSK调制解调系统集成AWGN信道模型,支持在Vivado 2019.2中设置不同SNR仿真误码率。示例SNR值从0到15,结果展示解调质量随SNR提升。MATLAB仿真验证了MSK性能,图片显示了仿真结果。 ### 理论概要 研究聚焦于软件无线电中的MSK调制解调,利用Verilog实现。MSK是一种相位连续、恒包络的二进制调制技术,优点包括频谱效率高。系统采用无核设计,关键模块包括调制器、解调器和误码检测。复位、输入数据、中频信号等关键信号通过Verilog描述,并通过Chipscope在线观察。
55 6
基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误码率统计模块
|
1月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的BPSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本系统基于Vivado2019.2,在原有BPSK调制解调基础上新增高斯信道及误码率统计模块,可测试不同SNR条件下的误码性能。仿真结果显示,在SNR=0dB时误码较高,随着SNR增至5dB,误码率降低。理论上,BPSK与2ASK信号形式相似,但基带信号不同。BPSK信号功率谱仅含连续谱,且其频谱特性与2ASK相近。系统采用Verilog实现,包括调制、加噪、解调及误码统计等功能,通过改变`i_SNR`值可调整SNR进行测试。
25 1
|
1月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的2FSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本系统基于FSK调制解调,通过Vivado 2019.2仿真验证了不同信噪比(SNR)下的误码率表现。加入高斯信道与误码统计模块后,仿真结果显示:SNR=16dB时误码极少;随SNR下降至0dB,误码逐渐增多。FSK利用频率变化传输信息,因其易于实现且抗干扰性强,在中低速通信中有广泛应用。2FSK信号由连续谱与离散谱构成,相位连续与否影响功率谱密度衰减特性。Verilog代码实现了FSK调制、加性高斯白噪声信道及解调功能,并计算误码数量。
34 5
|
2月前
|
异构计算
FPGA进阶(3):SDRAM读写控制器的设计与验证(二)
FPGA进阶(3):SDRAM读写控制器的设计与验证(二)
23 0
|
2月前
|
异构计算 内存技术
FPGA进阶(3):SDRAM读写控制器的设计与验证(一)
FPGA进阶(3):SDRAM读写控制器的设计与验证
50 0
|
算法 异构计算
m基于FPGA的256QAM调制信号产生模块verilog实现,包含testbench
m基于FPGA的256QAM调制信号产生模块verilog实现,包含testbench
290 0
|
算法 异构计算
m基于FPGA的1024QAM调制信号产生模块verilog实现,包含testbench
m基于FPGA的1024QAM调制信号产生模块verilog实现,包含testbench
360 0
|
算法 异构计算
基于FPGA的控制参数在线实时调整的自适应PI控制器设计,包含testbench测试程序
基于FPGA的控制参数在线实时调整的自适应PI控制器设计,包含testbench测试程序
201 0

热门文章

最新文章