能跑就行系列。。
描述:设计一个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
有些地方不够完善,仅供参考
由于未使用消抖开关的原因,烧录后板上按键响应有时会失效,不过小心使用,过验收应该没问题
此外,本作品未考虑按键同时按下的情况,可进行相应补充
推荐阅读
- FPGA状态机
- modelsim|安路IP核仿真(testbench中加入glbl)
- 【4】7系列FPGA结构|从底层结构开始学习FPGA----分布式RAM(DRAM,Distributed RAM)
- Verilog|Verilog基本语法之条件语句(五)
- 数字ic|乘法器verilog
- FPGA|基于FPGA的VGA协议实现
- FPGA|基于FPGA的ds18b20温度传感器使用
- 硬件经验|Lightning 转 USB Type-A/Type-C 思路
- fpga开发|TDC进位链