(电子科技大学 数字系统实验二 结课验收项目 fpga板 veriolg语言))
第一次写,实属小白,写的不好请见谅。就对这个设计提供自己的一点思路看法
题目要求:
板子了一般都是学校发的板子,我用的板子就是学校发的。(电子科技大学自主研发的板子)
正文:
对于这个项目,我将之分为顶层文件,时钟分频模块,电梯模块,矩阵键盘模块,动态显示模块。
顶层文件(代码):
module top(
input clk,
input set, //T9启动信号
input reset, //f3 复位信号
input [3:0]col,
output [3:0]row,
output [3:0]led,
output [5:0]dig,
output [7:0]seg
);
wire clk_1k;
wire clk_50;
wire clk_4s;
fenpin u1(.clk(clk),
.clk_1k(clk_1k),
.clk_50(clk_50),
.clk_4s(clk_4s));
wire k0;
wire k4;
wire k3;
wire k7;
keyboard u2(
.clk_1k(clk_1k),//键盘扫描
.clk_50(clk_50),//按键消抖
.col(col),
.row(row),//行初值
.upButton(k0),//对应一楼按键
.downButton(k4),//对应二楼按键
.upstair(k3),
.downstair(k7));//对应电梯内1 2按键
wire [1:0]state;
wire [1:0]floor;
dian_ti u3(
.clk(clk),
.set(set),
.reset(reset),
.key0(k0),
.key4(k4),
.key7(k7),
.key3(k3),
.led(led),//指示灯
.state(state),//00待机状态 01上行状态 10下机状态
.floor(floor) ); //楼层 01一楼 10二楼
dynamic_led2 u4(
.floor(floor),
.state(state),
.clk(clk_1k),
.seg(seg),
.dig(dig)
);
endmodule
分频模块:初始时钟源即板上时钟源为50Mhz, 这里有个失误,4s的分频时钟这里没用到,设计的时候多余了
module fenpin(clk,clk_1k,clk_50,clk_4s);
inout clk;
output reg clk_1k=0;
output reg clk_50=0;
output reg clk_4s=0;
reg[24:0] clk_div_cnt0=0;
reg[24:0] clk_div_cnt1=0;
reg[24:0] clk_div_cnt2=0;
//1khz
always @ (posedge clk)
begin
if (clk_div_cnt0==25000)//分频
begin
clk_1k=~clk_1k;
clk_div_cnt0=0;
end
else
clk_div_cnt0=clk_div_cnt0+1;
end
//50hz
always @ (posedge clk)
begin
if (clk_div_cnt1==499999)//分频
begin
clk_50=~clk_50;
clk_div_cnt1=0;
end
else
clk_div_cnt1=clk_div_cnt1+1;
end
//4s
always @ (posedge clk)
begin
if (clk_div_cnt2==9999999)//分频
begin
clk_4s=~clk_4s;
clk_div_cnt2=0;
end
else
clk_div_cnt2=clk_div_cnt2+1;
end
endmodule
矩阵键盘:进行按键扫描后进行按键消抖,这里对16个按键都进行了扫描,但由于只用四个按键所以只对四个按键进行消抖
module keyboard(
input clk_1k,//键盘扫描
input clk_50,//按键消抖
input [3:0]col,
output reg [3:0]row=4'b0001,//行初值
output upButton,//对应一楼按键
output downButton,//对应二楼按键
output upstair,
output downstair);//对应电梯内1 2按键
reg [15:0] btn=0;//初始化为0
always @ (posedge clk_1k)
begin
if (row[3:0]==4'b1000)
row[3:0]=4'b0001;//到了1000,下一个是0001
else
row[3:0]=row[3:0]<<1; //向左移一位。0001-0010-0100-1000-0001
end
always @ (negedge clk_1k)
begin
case (row[3:0])
4'b0001:
begin
btn[3:0]=col; //列输入值存至4位寄存器
end
4'b0010:
begin
btn[7:4]=col;
end
4'b0100:
begin
btn[11:8]=col;
end
4'b1000:
begin
btn[15:12]=col;
end
default:btn=0;
endcase
end
ajxd u0(
.btn_in(btn[0]),
.clk(clk_50),
.btn_out(upButton)
);
ajxd u1(
.btn_in(btn[4]),
.clk(clk_50),
.btn_out(downButton)
);
ajxd u2(
.btn_in(btn[3]),
.clk(clk_50),
.btn_out(upstair)
);
ajxd u3(
.btn_in(btn[7]),
.clk(clk_50),
.btn_out(downstair)
);
endmodule
按键消抖:
module ajxd(
input btn_in,
input clk,
output btn_out
);
reg btn0=0;//定义了btn0寄存器
reg btn1=0;//定义了btn1寄存器
reg btn2=0;//定义了btn2寄存器
reg[24:0] clk_div_cnt=0;
reg btn_clk=0;
always@ (posedge clk)
begin
btn0<=btn_in;
btn1<=btn0;
btn2<=btn1;
end
assign btn_out=(btn2&btn1&btn0)|(~btn2&btn1&btn0);
endmodule
电梯模块:就实验要求的效果,算是实现了(gate信号是电梯开关门信号,这里不用管,没用到)
module dian_ti(
input clk,
input set,
input reset,
input key0,
input key4,
input key3,
input key7,
output reg [3:0]led=0,//指示灯
output reg [1:0]state=0,//00待机状态 01上行状态 10下机状态
output reg [1:0]floor=1 //楼层 01一楼 10二楼
);
reg gate;//关门状态
reg [2:0] num;
reg [27:0]clk_count=0;
always@(posedge clk)
begin
if(!reset)
begin
led=4'b0000;
state=0;
floor=1;
gate=0;
end
else if(set)
begin
if(led)
begin
if(clk_count==199999999)
begin
clk_count=0;
if((floor==1)) begin floor=floor+1; end
else begin floor=floor-1; end
state=0;
led=4'b0000;
end
else clk_count=clk_count+1;
end
else if((key0)&&state==0) //一楼按下key0且电梯待机
begin
if(floor==2)
begin
led[0]=1; //一楼电梯外灯亮
state=2; //下行状态
end
gate=1; //到达一楼 打开门
end
else if((key4)&&state==0)
begin
if(floor==1)
begin
led[1]=1;//二楼电梯外灯亮
state=1;//上行
end
gate=1;//到达二楼,门开
end
else if((key3)&&floor==1) //在一楼 电梯内按下 且门是开的
begin
led[2]=1;
gate=0; //关电梯门
state=1; //电梯上行
end
else if((key7)&&floor==2) //在二楼 电梯内按上 且门是开的
begin
led[3]=1;
gate=0; //关电梯门
state=2; //电梯下行
end
end
end
endmodule
动态显示模块:结果显示在最右边的两位数码管上
module dynamic_led2(
input [1:0]floor,//楼层
input [1:0]state,//状态
input gate,//门
input clk,
output reg [7:0] seg,
output reg [5:0] dig
);
reg [1:0] num=0;
always @ (posedge clk)
begin
if (num>=1)
num=0;
else
num=num+1;
end
//译码器
always @ (num)
begin
case(num)
0:dig=6'b111110;
1:dig=6'b111101;
//3:dig=6'b111011;
default: dig=0;
endcase
end
//选择器,确定显示数据
reg [3:0] disp_data;
always @ (num)
begin
case(num)
0:disp_data=floor;
1:disp_data=state+3'b011;
//2:disp_data=gate+6;
//3:disp_data=
default: disp_data=0;
endcase
end
//显示译码器
always@(disp_data)
begin
case(disp_data)
4'h1: seg=8'h06;
4'h2: seg=8'h5b;
4'h3: seg=8'h40;//待机
4'h4: seg=8'h01;//上行
4'h5: seg=8'h08;//下行
//4'h6: seg=8'h06;//关门
//4'h7: seg=8'h09;
default: seg=0;
endcase
end
endmodule
这个演示图片太大了,懒得去弄了,大概就这样了。