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图设计数字系统,可以很容易将语言描述的设计问题变成时序流程图的描述。根据时序流程图就可以得到电路的状态图和输出函数,从而得出相应的硬件电路。在设计的过程中体会到了它的便利之处。

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

目录
相关文章
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的1024QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的1024QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同SNR条件下的性能测试。1024QAM调制将10比特映射到复平面上的1024个星座点之一,实现高效数据传输。硬件测试结果表明,在SNR=32dB和40dB时,系统表现出良好的性能。Verilog核心程序展示了各模块的连接与功能实现。
364 7
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的MSK调制解调系统系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于FPGA实现MSK调制解调系统,采用Verilog开发,包含同步模块、高斯信道模拟、误码率统计等功能。相比仿真版本,新增ILA数据采集与VIO在线SNR设置模块。通过硬件测试验证,展示不同SNR(如10dB和16dB)下的性能表现。研究聚焦软件无线电领域,优化算法复杂度以适应硬件限制,利用MSK恒定包络、相位连续等特性提升频谱效率。核心代码实现信号生成、调制解调、滤波及误码统计,提供完整的硬件设计与分析方案。
499 19
|
数据采集 移动开发 算法
【硬件测试】基于FPGA的QPSK调制+软解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于FPGA实现QPSK调制与软解调系统,包含Testbench、高斯信道、误码率统计模块,并支持不同SNR设置。硬件版本新增ILA在线数据采集和VIO在线SNR设置功能,提供无水印完整代码及测试结果。通过VIO分别设置SNR为6dB和12dB,验证系统性能。配套操作视频便于用户快速上手。 理论部分详细解析QPSK调制原理及其软解调实现过程,涵盖信号采样、相位估计、判决与解调等关键步骤。软解调通过概率估计(如最大似然法)提高抗噪能力,核心公式为*d = d_hat / P(d_hat|r[n])*,需考虑噪声对信号点分布的影响。 附Verilog核心程序代码及注释,助力理解与开发。
408 5
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的4ASK调制解调系统的硬件测试版本,该系统包括testbench、高斯信道模块和误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置功能。通过VIO设置不同SNR(如15dB和25dB),实现了对系统性能的实时监测与调整。4ASK是一种通过改变载波幅度表示数据的数字调制方式,适用于多种通信场景。FPGA平台的高效性和灵活性使其成为构建高性能通信系统的理想选择。
361 17
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的16QAM调制+软解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于之前开发的16QAM调制与软解调系统,增加了硬件测试功能。该系统包含FPGA实现的16QAM调制、软解调、高斯信道、误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置模块。通过硬件测试,验证了不同SNR条件下的系统性能。16QAM软解调通过比较接收信号采样值与16个调制点的距离,选择最近的调制点来恢复原始数据。核心Verilog代码实现了整个系统的功能,包括SNR设置、信号处理及误码率统计。硬件测试结果表明系统在不同SNR下表现良好,详细操作步骤可参考配套视频。
348 13
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4FSK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于之前的文章《基于FPGA的4FSK调制解调系统》,增加了ILA在线数据采集模块和VIO在线SNR设置模块,实现了硬件测试版本。通过VIO设置不同SNR(如10dB和20dB),并展示了ILA采集的数据结果。四频移键控(4FSK)是一种数字调制方法,利用四个不同频率传输二进制数据,具有较高的频带利用率和抗干扰性能。输入的二进制数据分为两组,每组两个比特,对应四个频率f1、f2、f3、f4,分别代表二进制组合00、01、10、11。调制过程中选择相应频率输出,并进行幅度调制以增强抗干扰能力。接收端通过带通滤波器提取信号并还原为原始二进制数据。
352 7
|
数据采集 算法 数据处理
【硬件测试】基于FPGA的256QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的256QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同信噪比(如30dB和40dB)的仿真测试,并提供配套操作视频。256QAM调制方案每个符号携带8比特信息,通过复数值星座图映射实现高效传输。Verilog代码展示了核心模块设计,包括SNR设置、数据处理和ILA测试分析,确保系统在实际硬件环境中的稳定性和性能。
339 2
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的16QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的16QAM基带通信系统硬件测试版本。该系统在仿真基础上增加了ILA在线数据采集和VIO在线SNR设置模块,支持不同信噪比(如15dB、25dB)的测试。16QAM是一种正交幅度调制方式,通过两路4ASK信号叠加实现,每个符号包含4比特信息。系统采用正交调幅法生成16QAM信号,并通过DAC转换为模拟信号。解调时使用正交相干解调,经低通滤波器恢复电平信号。开发板内完成发射与接收,无需定时同步模块。代码可移植至其他开发板,具体步骤见配套文档。
311 2
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的2ASK调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍基于FPGA的2ASK调制解调系统,涵盖仿真效果、理论知识、Verilog核心程序及开发板使用说明。系统包含testbench、高斯信道模块和误码率统计模块,支持不同SNR设置。硬件测试版本增加了ILA在线数据采集和VIO在线SNR设置功能。2ASK调制通过改变载波振幅传输二进制信号,FPGA实现包括系统设计、Verilog编码、仿真测试和硬件部署。详细操作步骤见配套视频,代码适用于多种开发板,提供移植方法。
329 1
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的64QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的64QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集模块和vio在线SNR设置模块,支持不同SNR条件下的仿真与测试。通过设置SNR为25dB和30dB进行测试,验证了系统的可行性和性能。此外,本文详细阐述了64QAM调制解调的工作原理,包括信号生成、调制、解调及误码率测试等环节,并提供了Verilog核心程序代码。
273 0

热门文章

最新文章