Verilog HDL设计——电梯控制器模块

设计一个10层楼的电梯控制器模块,要求:(1) 以按键的时间先后优先级进行设计;(2) 以楼层最短位置先后优先级进行设计。
电梯运行规则:
当电梯处在上升模式时,只响应比电梯所在位置高的上楼请求,由下向上逐个执行,直到最后一个上楼请求执行完毕。如果高层有下楼请求,直接升到有下楼请求的最高楼层,然后进入下降模式。下降模式类似。
定义每层楼的状态,可扩展至任意楼层。
UP(IN):XXXXXXXXXX(10~1楼;1有效,0无效),上楼请求
DOWN(IN):XXXXXXXXXX(10~1楼;1有效,0无效),下楼请求
其中1层只能有上楼请求,10层只能有下楼请求,同一层不能既有上楼请求又有下楼请求。上楼或下楼请求被响应后对应位清零。
BUTTON(IN):XXXXXXXXXX(10~1楼;1有效,0无效),要去往的楼层
到达要去往的楼层后对应位清零。
POSITION(OUT):XXXX(当前楼层)
FLOOR:XXXXXXXXXX(10~1楼;1有效,0无效),电梯需要停下并开关门的楼层
电梯处在上升模式时,FLOOR=UP|BUTTON;电梯处在下降模式时,FLOOR=DOWN|BUTTON。
UP_DOWN:X(0上升模式,1下降模式)

状态图

状态图
仿真流程图

仿真流程图
Design Block:

module elevator (CLK,RESET,UP,DOWN,BUTTON,POSITION);
 input CLK,RESET;
 input [10:1] UP,DOWN,BUTTON;
 output reg [3:0] POSITION;
 reg [3:0] P;
 reg [10:1] FLOOR;
 reg UP_DOWN;
 reg tmp,flag;
 integer temp;
 reg [8:0] CurrentState,NextState;
 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) CurrentState<=S0;
  else CurrentState<=NextState;
 end

 always @ (RESET or CurrentState 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;
   flag=0;
  end
  else
  begin
   if(flag==0) FLOOR=UP_DOWN?DOWN|BUTTON:UP|BUTTON;
   case(CurrentState)
    S0:
    begin
     POSITION=P;
     if(FLOOR==10'b0) NextState=S0;
     else
      begin
       if(UP_DOWN==0)
        begin
         if(P==4'b1010) UP_DOWN=1;
         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];
            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
       NextState=S1;
      end
    end
    S1:
     NextState=S2;
    S2:
     NextState=S3;
    S3:
     NextState=S4;
    S4:
    begin
     if(UP_DOWN==0) NextState=S5;
     else NextState=S6;
    end
    S5:
    begin
     if(FLOOR==10'b0) NextState=S0;
     else
      begin
       P=P+1'b1;
       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;
           NextState=S0;
          end
         else
          NextState=S7;     
        end
       else
        begin
         if(FLOOR[P]) NextState=S0;
         else NextState=S7;
        end 
      end
    end
    S6:
    begin
     if(FLOOR==10'b0) NextState=S0;
     else
      begin
       P=P-1'b1;
       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;
           NextState=S0;
          end
         else
          NextState=S8;     
        end
       else
        begin
         if(FLOOR[P]) NextState=S0;
         else NextState=S8;
        end 
      end
    end
    S7:
     NextState=S5;
    S8:
     NextState=S6;
   endcase
  end
 end
endmodule

Test Bench:

`timescale 1ns/1ns
module Test_elevator;
 reg CLK,RESET;
 reg [10:1] UP,DOWN,BUTTON;
 wire [3:0] POSITION;
 elevator U0(CLK,RESET,UP,DOWN,BUTTON,POSITION);
 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

仿真波形图:

在这里插入图片描述
总结

这个题目去年做过,今年回过头来看有了一些新的思考。相比之前在每层楼增加了上下楼请求按钮(UP、DOWN),在电梯里增加了要去往的楼层按键(BUTTON),将FLOOR变成中间变量,表示电梯需要停下并开关门的楼层。整个系统功能完善了许多,也更具备实用性。

  • 14
    点赞
  • 139
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
基于FPGA设计的智能电梯控制器设计WORD文档+quartus13.0工程Verilog源码文件,可以做为你的课程设计参考。 1.1 设计要求 ① 楼层的高度大于等于6,根据降低运行成本的原则,设计并实现一个以方向优先电梯调度算法。 ②要求能够使用按键模拟对电梯的控制,为了便于观察,将电梯所在的楼层(1~6)用数码管显示出来,将电梯的上下楼状态(上,下,开门,关门,静止)用发光管或数码管显示出来,并且能够实现对电梯实现锁定禁止运行。 ③ 画出电梯控制器的状态机,写出状态编码方案。 ④ 用Verilog语言对设计进行描述,并下载到实验板上调试成功,适当增加比较符合现实的控制限制。 ⑤ 写出设计性实验报告,并打印各层次的源文件和仿真波形,然后作简要说明。 并谈谈此次实验的收获、感想及建议 1.2 设计思路 我把电梯的状态分为三种:上升、下降、停留(其中包括开门、关门、禁止),状态分别编码为00、01、10来识别。楼层设计为六层,一般的电梯在每层外面都有上下请求的按钮,还有电梯内部的一楼到六楼的请求,以及持续开门、关门的请求。我们可以通过按键的输入对各种变量进行赋值,代表不同的请求,然后用case语句分各个楼层进行条件判断,每层分为两大块的响应,即本层有无需求,若有需求,则进行开门动作,若无需求,则分上升的状态和下降和停留的状态,分别又有不同的请求(除第一层和第六层特殊,只有上升的或下降的请求),上升下降分别作不同的响应(主要对i值进行变化)即可 输入主要用按键实现(六个楼层加向上向下两个,共八个),电梯的状态分为4种,上升,下降,停留,禁止分别用4个LED灯来表示,用数码管显示电梯所在楼层。对电梯的锁定操作,是同时按上下两个按键,电梯锁定的操作是电梯自动回到一楼,并对请求无任何响应。 之后对该系统进行了改进,对于开门与关门的区别,我采用LCD显示,主要是对停留状态进行进一步分解,停留时对LCD显示进行控制,从而显示开门关门状态。 module dianti(ledup,leddown,ledforbid,ledstay,A,B,c1,c2,c3,c4,c5,c6,clock,out,LCD_DATA,LCD_EN, LCD_RS, LCD_RW, LCD_ON, LCD_BLON,test); output ledup,leddown,ledstay,ledforbid; output [6:0]out; output LCD_EN, LCD_RS, LCD_RW, LCD_ON, LCD_BLON; output [1:0]test;//用于测试开门关门状态 input A,B,clock,c1,c2,c3,c4,c5,c6; inout [7:0]LCD_DATA; //.输入输出变量的声明 reg [4:0] floor1; reg [5:1] floor2; reg [5:0] floor3; reg [3:0] i; reg [1:0] s; reg [6:0]out; reg [3:0]t; reg [1:0]control; //寄存器变量 wire clk_out;//分频后的输出时钟 wire [1:0]test; reg ledup,leddown,ledforbid,ledstay; assign test=control; Clock c(clock,clk_out); //分频 LCD d(clock,control,LCD_DATA,LCD_EN, LCD_RS, LCD_RW, LCD_ON, LCD_BLON);//LCD显示 always @(posedge clk_out) begin t<=t+4'b0001; ledup<=(s==2'b01 &&!(A==1 && B==1) ); //电梯上升中 leddown<=(s==2'b10 &&!(A==1 && B==1));//电梯下降中 ledforbid<=(A==1 && B==1);// 电梯处于锁定 ledstay<=(s==2'b00&&!(A==1 && B==1));//电梯停留 if( A==1 && B==0) begin // request up if(c5==1) floor1[4]<=1; if(c4==1) floor1[3]<=1; if(c3==1) floor1[2]<=1;
序列检测器是一种电路,用于检测输入信号序列是否符合某种特定的模式。在Verilog HDL语言中,可以使用状态机来实现序列检测器。以下是一个简单的序列检测器的Verilog HDL代码示例: ```verilog module sequence_detector( input clk, // 时钟信号 input reset, // 复位信号 input data, // 输入数据信号 output reg match // 匹配信号 ); // 定义状态 typedef enum logic [1:0] { STATE_IDLE, // 空闲状态 STATE_S1, // 状态1 STATE_S2, // 状态2 STATE_S3 // 状态3 } state_t; // 定义状态转移表 parameter [3:0] TRANS_TABLE [0:3] = '{4'b0000, 4'b0001, 4'b0010, 4'b0100}; // 定义当前状态变量和下一个状态变量 reg [1:0] state, next_state; // 初始化状态为IDLE initial begin state = STATE_IDLE; end // 定义状态机逻辑 always @ (posedge clk, posedge reset) begin if (reset) begin state <= STATE_IDLE; end else begin state <= next_state; end end // 定义状态转移逻辑 always @ (*) begin case (state) STATE_IDLE: begin if (data) begin next_state = STATE_S1; end else begin next_state = STATE_IDLE; end end STATE_S1: begin if (!data) begin next_state = STATE_IDLE; end else if (data) begin next_state = STATE_S2; end end STATE_S2: begin if (!data) begin next_state = STATE_IDLE; end else if (data) begin next_state = STATE_S3; end end STATE_S3: begin if (!data) begin next_state = STATE_IDLE; match = 1; end else begin next_state = STATE_S3; end end endcase end endmodule ``` 这个序列检测器可以检测输入数据信号是否符合“1101”这个模式。输入数据信号通过data端口输入,匹配结果通过match端口输出。当输入数据信号符合“1101”这个模式时,match信号会被置为1。如果输入数据信号不符合模式,match信号会保持为0。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值