verilog|Verilog 四层电梯设计

能跑就行系列。。
描述:设计一个4层楼的电梯控制系统,完成电梯向上或向下移动到被请求楼层(假设电梯每移动一层需要1秒)。请求可来自每层楼的呼叫按钮,也可来自电梯内的目的楼层选择。当电梯到达被请求楼层后,打开电梯门10秒(假设该电梯内只有楼层按键,没有开门和关门按键),然后关闭电梯门前往下一个被请求楼层;如果没有请求则停在本层。电梯运行中保持电梯门关闭。当同时有多个请求时,应答的优先原则为尽可能不改变电梯运动方向且距离当前楼层最近。
【verilog|Verilog 四层电梯设计】top_module模块

module top_module( input clr,//清零端子 input clk,//时钟信号 input [3:0]in_floor,//电梯内楼层输入 input [2:0]out_up,//电梯上升信号 input [3:1]out_down,//电梯下降信号output [3:0]led,//小灯泡 output [3:0] pos, output [7:0] seg ); wire [15:0]dataBus; //数据传输 wire clk190hz; wire clk_1s; //时钟信号(1s) wire clk_10s; //时钟信号(10s)segMsgout U1(.clk190hz(clk190hz),.dataBus(dataBus),.pos(pos),.seg(seg)); counterU2(.clr(clr),.clk(clk),.clk_1s(clk_1s),.clk_10s(clk_10s)); clkDivU3(.clk100mhz(clk),.clk190hz(clk190hz)); elevator_controller U4(.clr(clr),.clk(clk),.clk_1s(clk_1s),.clk_10s(clk_10s),.in_floor(in_floor), .out_up(out_up),.out_down(out_down),.dataBus(dataBus),.led(led)); endmodule

elevator_controller模块
module elevator_controller( input clr,//清零端子 input clk,//时钟信号 input clk_1s,//时钟信号(1s) input clk_10s,//时钟信号(10s) input [3:0]in_floor,//电梯内楼层输入 input [2:0]out_up,//电梯上升信号 input [3:1]out_down,//电梯下降信号output reg [15:0]dataBus,//数据传输 output [3:0]led//小灯泡); parameter stop=2'b00,down=2'b01,up=2'b10; parameter one_stop=4'b0000,one_up=4'b0001, /* x_stop 代表电梯停止状态 x_up代表电梯向上运行状态 x_down 代表电梯向下运行状态 */ two_stop=4'b0010,two_up=4'b0011,two_down=4'b0100, three_stop=4'b0101,three_up=4'b0110,three_down=4'b0111, four_stop=4'b1000, four_down=4'b1001, Cstop=4'b1010; //Cstop 代表电梯运动过程中响应的停止状态 reg [2:0]now_floor; // 楼层号 reg [1:0]elevator; // 电梯运行状态 reg [3:0]Cstate; // 电梯控制器状态机的状态值 reg door; // 电梯门开关状态 reg [3:0]present_state; reg [3:0]next_state; initial begin now_floor=0; elevator=stop; door=0; Cstate=0; present_state=0; next_state=0; endalways@(posedge clk) //数据传输 begin dataBus[15:0]<={1'b0,now_floor[2:0]+3'b001,2'b00,elevator[1:0],Cstate[3:0],3'b000,door}; endalways@(posedge clk or posedge clr) //状态控制 begin if(clr) begin present_state<=one_stop; next_state<=one_stop; end else beginpresent_state<=next_state; //现状态转变为下一状态case(present_state) one_stop: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3])) next_state<=one_stop; else begin if(clk_10s) next_state<=one_up; elsenext_state<=next_state; end end one_up: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) begin next_state<=one_stop; end else begin if(clk_1s) begin if(out_up[1]|out_down[1]|in_floor[1]) next_state<=Cstop; else if(in_floor[0]|(out_up[0]&&!(in_floor[1]|in_floor[2]|in_floor[3]))) next_state<=one_stop; else next_state<=two_up; end elsenext_state<=next_state; end end two_stop: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3])) next_state<=two_stop; else begin if(clk_10s) begin if(out_up[1]|out_up[2]|out_down[2]|out_down[3]) next_state<=two_up; else if(out_up[0]|out_down[1]) next_state<=two_down; end elsenext_state<=next_state; end end two_up: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) next_state<=two_stop; else begin if(clk_1s) begin if(out_up[2]|out_down[2]|in_floor[2]) next_state<=Cstop; else if(in_floor[1]|(out_up[1]&&!(in_floor[2]|in_floor[3]))) next_state<=two_stop; else next_state<=three_up; end elsenext_state<=next_state; end end two_down: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) next_state<=two_stop; else begin if(clk_1s) begin if(in_floor[1]|(out_down[1]&&(~in_floor[0]))) next_state<=two_stop; else next_state<=Cstop; end elsenext_state<=next_state; end end three_stop: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3])) next_state<=three_stop; else begin if(clk_10s) begin if(out_up[2]|out_down[3]) next_state<=three_up; else if(out_up[0]|out_up[1]|out_down[1]|out_down[2]) next_state<=three_down; end elsenext_state<=next_state; end end three_up: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) next_state<=three_stop; else begin if(clk_1s) begin if(in_floor[2]|(out_up[2]&&(~in_floor[3]))) next_state<=three_stop; else next_state<=Cstop; end elsenext_state<=next_state; end end three_down: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) next_state<=three_stop; else begin if(clk_1s) begin if(out_down[1]|out_up[1]|in_floor[1]) next_state<=Cstop; else if(in_floor[2]|(out_down[2]&&!(in_floor[0]|in_floor[1]))) next_state<=three_stop; else next_state<=two_down; end elsenext_state<=next_state; end end four_stop: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3])) next_state<=four_stop; else begin if(clk_10s) next_state<=four_down; elsenext_state<=next_state; end end four_down: begin if(!(out_up[0]|out_up[1]|out_up[2]|out_down[1]|out_down[2]|out_down[3]|in_floor[0]|in_floor[1]|in_floor[2]|in_floor[3])) next_state<=four_stop; else begin if(clk_1s) begin if(out_down[2]|out_up[2]|in_floor[2]) next_state<=Cstop; else if(in_floor[3]|(out_down[3]&&!(in_floor[0]|in_floor[1]|in_floor[2]))) next_state<=four_stop; else next_state<=three_down; end elsenext_state<=next_state; end end Cstop: begin if(now_floor[2:0]==3'b000)next_state<=one_stop; else if(now_floor[2:0]==3'b001)next_state<=two_stop; else if(now_floor[2:0]==3'b010)next_state<=three_stop; else if(now_floor[2:0]==3'b011)next_state<=four_stop; end endcase end endalways@(posedge clk or posedge clr) //输出控制 begin if(clr) begin now_floor[2:0]<=3'b000; elevator[1:0]<=stop; door<=1'b0; Cstate[3:0]<=one_stop; end else if(clr!=1) begin case(present_state) //当前电梯所在的楼层、电梯运行状态、电梯门开关状态 one_stop: begin now_floor[2:0]<=3'b000; elevator[1:0]<=stop; door<=1; end one_up: begin elevator[1:0]<=up; door<=0; if(in_floor[0]==1)now_floor[2:0]<=3'b000; elsenow_floor[2:0]<=3'b001; end two_stop: begin now_floor[2:0]<=3'b001; elevator[1:0]<=stop; door<=1; end two_up: begin elevator[1:0]<=up; door<=0; if(in_floor[1]==1)now_floor[2:0]<=3'b001; elsenow_floor[2:0]<=3'b010; end two_down: begin elevator[1:0]<=down; door<=0; if(in_floor[1]==1)now_floor[2:0]<=3'b001; elsenow_floor[2:0]<=3'b000; end three_stop: begin now_floor[2:0]<=3'b010; elevator[1:0]<=stop; door<=1; end three_up: begin elevator[1:0]<=up; door<=0; if(in_floor[2]==1)now_floor[2:0]<=3'b010; elsenow_floor[2:0]<=3'b011; end three_down: begin elevator[1:0]<=down; door<=0; if(in_floor[2]==1)now_floor[2:0]<=3'b010; elsenow_floor[2:0]<=3'b001; end four_stop: begin now_floor[2:0]<=3'b011; elevator[1:0]<=stop; door<=1; end four_down: begin elevator[1:0]<=down; door<=0; if(in_floor[3]==1)now_floor[2:0]<=3'b011; elsenow_floor[2:0]<=3'b010; end default: begin now_floor[2:0]<=now_floor[2:0]; elevator[1:0]<=elevator[1:0]; door<=door; end endcasecase(next_state) //电梯控制器状态机的状态值 one_stop: Cstate[3:0]<=one_stop; one_up: Cstate[3:0]<=one_up; two_stop: Cstate[3:0]<=two_stop; two_up: Cstate[3:0]<=two_up; two_down: Cstate[3:0]<=two_down; three_stop: Cstate[3:0]<=three_stop; three_up: Cstate[3:0]<=three_up; three_down: Cstate[3:0]<=three_up; four_stop: Cstate[3:0]<=four_stop; four_down: Cstate[3:0]<=four_down; Cstop: Cstate[3:0]<=Cstop; default: Cstate[3:0]<=Cstate[3:0]; endcase end else begin now_floor[2:0]<=now_floor[2:0]; elevator[1:0]<=elevator[1:0]; door<=door; Cstate[3:0]<=Cstate[3:0]; end endassign led[0]=(now_floor[2:0]==3'b000)?1:0; assign led[1]=(now_floor[2:0]==3'b001)?1:0; assign led[2]=(now_floor[2:0]==3'b010)?1:0; assign led[3]=(now_floor[2:0]==3'b011)?1:0; endmodule

counter模块
module counter( input clk, input clr, output clk_1s, output clk_10s ); reg [13:0]cnt_first,cnt_second; reg [3:0]cnt_third; reg [13:0]cnt_second_t; initial begin cnt_second=14'd5; cnt_second_t=14'd0; endalways @(posedge clk or posedge clr) if(clr) cnt_first<=14'd0; else if(cnt_first==14'd10000) cnt_first<=14'd0; else cnt_first<=cnt_first +1'b1; always @(posedge clk or posedge clr) begin if(clr) begin cnt_second<=14'd5; cnt_second_t<=14'd0; end else if(cnt_second ==14'd10000) cnt_second<=14'd0; else if(cnt_second_t==14'd10000) cnt_second_t<=14'd0; else if(cnt_first==14'd10000) begin cnt_second<=cnt_second+1'b1; cnt_second_t<=cnt_second_t+1'b1; end end always @(posedge clk or posedge clr) begin if(clr) cnt_third<=4'd0; else if(cnt_third==4'd10) cnt_third<=4'd0; else if(cnt_second_t==14'd10000) cnt_third<=cnt_third+1'b1; end assign clk_1s=(cnt_second==14'd10000)?1'b1 : 1'b0; assign clk_10s= (cnt_third==4'd10)?1'b1 : 1'b0; endmodule

clkDiv模块
module clkDiv( input clk100mhz, output clk190hz ); reg [25:0]count=0; assign clk190hz=count[18]; always@(posedge clk100mhz) count<=count+1; endmodule

segMsgout模块
module segMsgout( input clk190hz, input [15:0] dataBus, output reg [3:0] pos, output reg [7:0] seg ); reg [1:0] posC; reg [3:0] dataP; always @(posedge clk190hz )begin case(posC) 0: begin pos<=4'b1000; dataP<=dataBus[15:12]; end 1:begin pos <=4'b0100; dataP <= dataBus[11:8]; end 2:begin pos <=4'b0010; dataP <= dataBus[7:4]; end 3:begin pos <=4'b0001; dataP <= dataBus[3:0]; end endcase posC = posC + 2'b01; end always @(dataP) case(dataP) 4'b0000:seg=8'b0011_1111; 4'b0001:seg=8'b0000_0110; 4'b0010:seg=8'b0101_1011; 4'b0011:seg=8'b0100_1111; 4'b0100:seg=8'b0110_0110; 4'b0101:seg=8'b0110_1101; 4'b0110:seg=8'b0111_1101; 4'b0111:seg=8'b0000_0111; 4'b1000:seg=8'b0111_1111; 4'b1001:seg=8'b0110_1111; 4'b1010:seg=8'b0111_0111; 4'b1011:seg=8'b0111_1100; 4'b1100:seg=8'b0011_1001; default:seg=8'b0000_1000; endcase endmodule

有些地方不够完善,仅供参考
由于未使用消抖开关的原因,烧录后板上按键响应有时会失效,不过小心使用,过验收应该没问题
此外,本作品未考虑按键同时按下的情况,可进行相应补充

    推荐阅读