使用Verilog实现FPGA双列电梯控制系统

简介: 设计目的及要求 实现2个8层电梯升降控制设计,该设计模拟完成8层楼的载客服务,同时示电梯运行情况和电梯外请求信息,具体要求如下: 1)       每层电梯设有请求开关,电梯可响应按键操作,到达指定楼层; 2)       当有请求时,该楼层的指示灯亮; 3)       电梯运行时,各楼层有运行模式指示,显示目前电梯是上升或下降。

设计目的及要求

实现28层电梯升降控制设计,该设计模拟完成8层楼的载客服务,同时示电梯运行情况和电梯外请求信息,具体要求如下:

1)       每层电梯设有请求开关,电梯可响应按键操作,到达指定楼层;

2)       当有请求时,该楼层的指示灯亮;

3)       电梯运行时,各楼层有运行模式指示,显示目前电梯是上升或下降。

4)       各楼层均有电梯楼层显示,告知等待者电梯当前处于哪一层楼;

5)       响应动作完成后,即电梯到达该楼层后该楼层的指示灯灭,完成一次响应操作。

6)       可以通过相关显示模块提示升降信息。

 

总体设计思路

根据系统设计要求,并考虑到系统的可检验性,结合实际情况,双列电梯控制的相对于单列电梯控制的主要区别也是设计难点在于两列电梯的相互配合,在多个请求触发的情况下能够尽可能快的完成响应,减少乘客等待时间。针对这一设计需求,对双列电梯做了主从电梯区分,融合优先级响应控制的方法,完成电梯的自主判断。

 

3硬件设计思路

3.1电源电路 

改电源电路是给按键电路供电电路,输出为3.3V。

1 电源电路

 

3.2按键电路

根据设计需要,本设计硬件电路一共包含16个外接按键,分别是一栋八层的电梯内置楼层选择按键KEY[108...101];二栋八层的电梯内置楼层选择按键KEY[208...201];通过上拉电阻接入3.3V电压,芯片引脚检测到按键低电平有效。设计原理图如图2

3.3指示灯电路

根据设计需要,本设计硬件电路一共包含20个外接LED灯,分别是一栋八层的电梯外部楼层响应指示灯LED[1_8...1_1];二栋八层的电梯外部楼层响应指示灯LED[2_8...2_1];电梯上行指示灯两个,和电梯下行指示灯两个。通过查阅EP2C8Q208C8N开发板芯片手册,芯片引脚输出电压达到3.3V,输出电流为20mA,所以可以直接给LED高电平来点亮LED。设计原理图如图3

2 按键电路                                                                                 3 指示灯电路

4 硬件实物图


软件设计分析

4.1程序框图

1. 按键扫描,当有键按下时,先判断主电梯繁忙标志位,从而选择电梯工作。

2. 判断上升、下降标志位,根据情况控制流水灯移位方向,指示灯亮灭,及数码管显示楼层。

3. 当目标楼层等于当前楼层时,标志位都清零,流水灯停止移位,开始闪烁,指示灯全灭,数码管显示当前楼层。

5 程序流程图

4.2接口参数

@param(in)rst(复位信号),CLOCK(基础时钟信号),key(按键信号输入);

@param(out)DIG(段选信号),SEL(位选信号),

         LED1(一栋指示灯),LED2(二栋指示灯),

         BUZZER(蜂鸣器输出信号);

         sign_up(一栋电梯上行信号),sign_down(一栋电梯下行信号),

         sign_up2(一栋电梯上行信号),sign_down2(一栋电梯下行信号);

4.3部分代码


4.3.1主程序

/***********************************************/
/*                双列八层电梯设计           
/*  实现功能:                           
/*      %每层电梯设有请求开关,按键到达指定楼层 
/*      %当有请求时,指定楼层灯亮             
/*      %电梯运行时,各楼层有运行状态指示      
/*      %各楼层均有电梯楼层显示               
/*      %电梯到达楼层后,该楼层指示灯灭        
/***********************************************/
module elevator_sun(rst,CLOCK,key,
                    DIG,SEL,LED1,LED2,
                    BUZZER,
                    sign_up,sign_down,sign_up2,sign_down2
                    );
	input rst;                 //复位信号
	input CLOCK;               //时钟信号
    input [23:0]key;
    
    output [7:0]LED1;          //指示灯信号
    output [7:0]LED2;          //指示灯信号
	output [7:0]SEL;           //位选信号
	output [6:0]DIG;           //段选信号
    output BUZZER;
    output sign_up,sign_down;
    output sign_up2,sign_down2;
	
    wire count_clk;            //分频新时钟
    wire c_clk;		           //扫描时钟
	wire [3:0]data;            //计数传递寄存器
    wire [3:0]level;           //计数传递寄存器
    wire [3:0]level2;          //计数传递寄存器
    wire [3:0]number;          //计数传递寄存器
    wire [3:0]number2;         //计数传递寄存器

    
	parameter N_1S=10000,N_SCAN=10000000;
                //N_1S 秒分频系数,分出周期为一秒的时钟信号
                //N_SCAN 扫描分频系数,分出数码管扫描的时钟信号
                
	clock #(N_1S) a1(CLOCK,rst,count_clk);                                                       //调用分频器,一秒时钟信号
    clock #(N_SCAN) a2(CLOCK,rst,c_clk);                                                         //调用分频器,扫描时钟信号
	display a3(number,number2,count_clk,DIG,SEL);                                                //调用数码管显示函数
    key_test a4(CLOCK,c_clk,rst,key,level,sign_up,sign_down,level2,sign_up2,sign_down2);         //调用按键预置函数
    control a5(c_clk,level,LED1,number,sign_up,sign_down);                                       //调用楼层控制函数
    control a6(c_clk,level2,LED2,number2,sign_up2,sign_down2);                                   //调用楼层控制函数
endmodule

4.3.2分频器

module clock(CLOCK,rst,out_clock);
    parameter flag;          //计数标志
	input CLOCK;             //时钟信号
	input rst;               //复位信号
	output out_clock;        //时钟输出
	reg [30:0] count=0;      //计数寄存器 
	reg out_clock_reg=0;     //时钟输出寄存器
   
	
	assign out_clock = out_clock_reg;    //链接时钟信号
	
	always@(posedge CLOCK or negedge rst)
	begin
	
		if(!rst)
			begin
				count<=0;
				out_clock_reg<=0;
			end
		else
			begin
				count<=count+1'b1;
			if(count==flag)                         //当时钟寄存器数值等于计数标志
				begin
					out_clock_reg<=~out_clock_reg;  //时钟输出电平反转
					count<=0;
				end
			end

	end
Endmodule

4.3.3显示

module display(in,in2,c_clk,DIG,SEL);
	input [3:0] in;          //楼层1输入
    input [3:0] in2;         //楼层2输入
	input c_clk;             //扫描时钟
	output [7:0] SEL;        //位选信号
	output [6:0] DIG;        //段选信号
    
	reg [7:0] SEL_R;         //位选信号寄存器
	reg [6:0] DIG;           //段选信号寄存器
    reg [3:0] nature;        //显示数字寄存器
	
	assign SEL = SEL_R;      //链接位选信号

    reg [2:0]count=0;             //计数寄存器赋初值
			
	always@(posedge c_clk)   //产生扫描信号
		begin
			count<=count+1'b1;
		end
		
	always@(count)
		begin
			case(count)
				//0:begin nature<=10;  SEL_R<=8'b1111_1110; end
                1:begin nature<=in; SEL_R<=8'b1111_1101; end
                2:begin nature<=9;  SEL_R<=8'b1111_1011; end
                //3:begin nature<=0; SEL_R<=8'b1111_0111; end
                //4:begin nature<=10;  SEL_R<=8'b1110_1111; end
				5:begin nature<=in2;SEL_R<=8'b1101_1111; end
                6:begin nature<=9;  SEL_R<=8'b1011_1111; end
                //7:begin nature<=0; SEL_R<=8'b0111_1111; end
			endcase
		end
     
	always@(nature)
		begin                //数码管显示数码
			case(nature)
				0:DIG=7'b1001_110;//(
                1:DIG=7'b1111_001;//1
				2:DIG=7'b0100_100;//2
				3:DIG=7'b0110_000;//3
				4:DIG=7'b0011_001;//4
				5:DIG=7'b0010_010;//5
				6:DIG=7'b0000_010;//6
				7:DIG=7'b1111_000;//7
				8:DIG=7'b0000_000;//8
				9:DIG=7'b0001_110;//F
                10:DIG=7'b1110_001;//)
			endcase
		end
		
Endmodule

4.3.4按键

含按键消抖及busy标志位判断,选择赋值

module key_test(CLOCK,c_clk,rst,key,level,sign_up,sign_down,level2,sign_up2,sign_down2);
    input CLOCK,c_clk,rst;
    input [23:0]key;
    input sign_up,sign_down;
    input sign_up2,sign_down2;
    	
    output reg[3:0] level = 1;
    output reg[3:0] level2 = 1;
    
    reg busy;
    reg busy2;
    reg [3:0]state;  //状态寄存器
    reg [3:0]keyr;

    wire key1;
    wire key_neg = ~keyr[2] & keyr[3];                                                          //有按键按下
    wire key_pos = keyr[2] & ~keyr[3];                                                          //有按键释放 
    assign key1 =   !key[23]&!key[22]&!key[21]&!key[20]&!key[19]&!key[18]&!key[17]&!key[16]&
                    !key[15]&!key[14]&!key[13]&!key[12]&!key[11]&!key[10]&!key[9]&!key[8]&
                    !key[7]&!key[6]&!key[5]&!key[4]&!key[3]&!key[2]&!key[1]&!key[0];            //所有按键相与判断是否有按键触发
    
    always @ (posedge CLOCK or negedge rst)
        if(!rst) keyr <= 3'b111;
        else keyr <= {keyr[2:0],key1};
    
    //定时计数逻辑,对按键消抖判断
    reg[19:0] cnt;
	//定时计数器
    always @ (posedge CLOCK or negedge rst )
        if(!rst) cnt <= 20'd0;
        else if(key_neg || key_pos) cnt <= 20'd0;
        else if(cnt < 20'd999_999) cnt <= cnt + 1'b1;
        else cnt <= 20'd0;
	
    //定时采集按键值
    reg [23:0] key_v [1:0];
    always @ (posedge CLOCK or negedge rst)
        if (!rst) begin
            key_v[0] <= 24'b1111_1111_1111_1111_1111_1111;
            key_v[1] <= 24'b1111_1111_1111_1111_1111_1111;
        end
        else begin 
            key_v[1] <= key_v[0];		
            if(cnt == 20'd999_999) key_v[0] <= key;	//定时键值采集
            else key_v[0] <= key_v[0];	
        end    
    wire [23:0] key_out = key_v[1] & ~key_v[0];  //消抖后按键变化值
        
    always @ (posedge CLOCK or negedge rst )
        if (!rst) busy = 0;
        else if(!(sign_up||sign_down))  busy = 0;
        else busy =1;
    
    always @ (posedge CLOCK or negedge rst )
        if (!rst) busy2 = 0;
        else if(!(sign_up2||sign_down2))  busy2 = 0;
        else busy2 =1;    
        
    always @ (posedge CLOCK)    //楼层请求
    begin
        if (!rst) 
            begin 
                level <= 1;
                level2 <= 1; 
            end
        else if(key_out[0])
            begin
                if(busy==0) level<=1;
                else if((busy2==0)&&(busy==1)) level2<=1;
            end
        else if(key_out[1]) 
            begin 
                if(busy==0) level<=2;
                else if((busy2==0)&&(busy==1)) level2<=2;
            end
        else if(key_out[2]) 
            begin 
                if(busy==0) level<=3;
                else if((busy2==0)&&(busy==1)) level2<=3;                	
            end
        else if(key_out[3]) 
            begin 
                if(busy==0) level<=4;
                else if((busy2==0)&&(busy==1)) level2<=4;
            end
        else if(key_out[4]) 
            begin 
                if(busy==0) level<=5;
                else if((busy2==0)&&(busy==1)) level2<=5;
            end
        else if(key_out[5]) 
            begin 
                if(busy==0) level<=6;
                else if((busy2==0)&&(busy==1)) level2<=6;
            end
        else if(key_out[6]) 
            begin 
                if(busy==0) level<=7;
                else if((busy2==0)&&(busy==1)) level2<=7;
            end
        else if(key_out[7]) 
            begin 
                if(busy==0) level<=8;
                else if((busy2==0)&&(busy==1)) level2<=8;
            end
    end    
Endmodule

4.3.5楼层控制

比较目标楼层与当前楼层,控制显示外设的工作。

module control(c_clk,number_new,
                LED,number_old,sign_up,sign_down);
    input c_clk;
    input [3:0]number_new;
    output [7:0] LED;
    output number_old;
    output sign_up,sign_down;
    reg [3:0]number_old=1;
    reg [7:0]LED_reg=8'b0000_0001;
    reg sign_up_reg = 0;
    reg sign_down_reg = 0; 
    assign LED = LED_reg;
    assign sign_up = sign_up_reg;
    assign sign_down = sign_down_reg;
    
    always@(negedge c_clk)
        begin
            if(number_new>number_old)
                begin
                    sign_up_reg<=1;
                    sign_down_reg<=0;
                    LED_reg <= LED_reg << 1'b1;
                    number_old<=number_old+'b1;
                end
            else if(number_new<number_old)
                begin
                    sign_up_reg<=0;
                    sign_down_reg<=1;
                    LED_reg <= LED_reg >> 1'b1;
                    number_old<=number_old-1'b1;
                end
            else
                begin
                    sign_up_reg<=0;
                    sign_down_reg<=0; 
                    LED_reg[number_new-1] <= ~LED_reg[number_new-1]; 
                end
        end
endmodule

5设计结果与分析

      此双列电梯能根据电梯运作情况来选择电梯响应,有流水灯显示、指示灯显示及数码管显示来标明电梯工作情况,两列电梯共用一套按键,节省硬件,更加智能。

        不足之处:

1.       未能实现电梯运作工程中对同一方向需求的按键判断;

2.       两电梯都空闲时,未能根据时间最短原则选择电梯响应请求。

 

6 实际运行图


目录
相关文章
|
6月前
|
机器学习/深度学习 算法 异构计算
m基于FPGA的多通道FIR滤波器verilog实现,包含testbench测试文件
本文介绍了使用VIVADO 2019.2仿真的多通道FIR滤波器设计。展示了系统RTL结构图,并简述了FIR滤波器的基本理论,包括单通道和多通道的概念、常见结构及设计方法,如窗函数法、频率采样法、优化算法和机器学习方法。此外,还提供了Verilog核心程序代码,用于实现4通道滤波器模块,包含时钟、复位信号及输入输出接口的定义。
176 7
|
6月前
|
算法 异构计算
基于FPGA的ECG信号滤波与心率计算verilog实现,包含testbench
基于FPGA的ECG信号滤波与心率计算verilog实现,包含testbench
|
6月前
|
算法 异构计算
m基于FPGA的电子钟verilog实现,可设置闹钟,包含testbench测试文件
该文介绍了基于FPGA的电子钟设计,利用Vivado2019.2平台进行开发并展示测试结果。电子钟设计采用Verilog硬件描述语言,核心包括振荡器、分频器和计数器。时间显示为2个十进制格式,闹钟功能通过存储器和比较器实现,当当前时间等于设定时间时触发。文中给出了Verilog核心程序示例,展示了时钟信号、设置信号及输出的交互。
195 2
|
6月前
|
编解码 算法 异构计算
基于FPGA的NC图像质量评估verilog实现,包含testbench和MATLAB辅助验证程序
在Vivado 2019.2和Matlab 2022a中测试的图像质量评估算法展示了效果。该算法基于NC指标,衡量图像与原始图像的相似度,关注分辨率、色彩深度和失真。提供的Verilog代码段用于读取并比较两个BMP文件,计算NC值。
|
6月前
|
算法 异构计算
m基于FPGA的MPPT最大功率跟踪算法verilog实现,包含testbench
该内容包括三部分:1) 展示了Vivado 2019.2和Matlab中关于某种算法的仿真结果图像,可能与太阳能光伏系统的最大功率点跟踪(MPPT)相关。2) 简述了MPPT中的爬山法原理,通过调整光伏电池工作点以找到最大功率输出。3) 提供了一个Verilog程序模块`MPPT_test_tops`,用于测试MPPT算法,其中包含`UI_test`和`MPPT_module_U`两个子模块,处理光伏电流和电压信号。
68 1
|
4月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误码率统计模块
升级版FPGA MSK调制解调系统集成AWGN信道模型,支持在Vivado 2019.2中设置不同SNR仿真误码率。示例SNR值从0到15,结果展示解调质量随SNR提升。MATLAB仿真验证了MSK性能,图片显示了仿真结果。 ### 理论概要 研究聚焦于软件无线电中的MSK调制解调,利用Verilog实现。MSK是一种相位连续、恒包络的二进制调制技术,优点包括频谱效率高。系统采用无核设计,关键模块包括调制器、解调器和误码检测。复位、输入数据、中频信号等关键信号通过Verilog描述,并通过Chipscope在线观察。
101 6
基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误码率统计模块
|
6月前
|
算法 异构计算
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
m基于FPGA的RS+卷积级联编译码实现,RS用IP核实现,卷积用verilog实现,包含testbench测试文件
63 0
|
4月前
|
C语言 芯片 异构计算
FPGA新起点V1开发板(六-语法篇)——verilog简介+基础语法
FPGA新起点V1开发板(六-语法篇)——verilog简介+基础语法
|
5月前
|
存储 算法 编译器
课程设计——基于FPGA的交通红绿灯控制系统(源代码)
课程设计——基于FPGA的交通红绿灯控制系统(源代码)
|
5月前
|
算法 计算机视觉 异构计算
基于FPGA的图像一维FFT变换IFFT逆变换verilog实现,包含tb测试文件和MATLAB辅助验证
```markdown ## FPGA 仿真与 MATLAB 显示 - 图像处理的 FFT/IFFT FPGA 实现在 Vivado 2019.2 中仿真,结果通过 MATLAB 2022a 展示 - 核心代码片段:`Ddddddddddddddd` - 理论:FPGA 实现的一维 FFT/IFFT,加速数字信号处理,适用于高计算需求的图像应用,如压缩、滤波和识别 ```

热门文章

最新文章