名称:基于FPGA的停车场设计Verilog代码Quartus仿真
软件:Quartus
语言:Verilog
代码功能:
假设停车场只有一个入口和一个出口,利用两对光电传感器检测车辆的进出情况,如图5.11所示。当有车辆处在接收器与发射器中间时,相应的输出位置为有效即置1.通过检查光电传感器可以确定是否有车辆进出活动或者只是行人穿过。例
如,车辆进入会发生如下事件
1.最开始两个传心都未被遮挡(ab值为00
2.传感器a被遮挡(ab值为"10)
3.两个传感器都被遮挡(ab值为"11”)
4.传感器a未被遮挡(ab值为01”)
5.两个传感器都未被遮挡(ab值为"00”)
因此,可以按一下步骤设计一个停车场计时器
1.设计一个带有输2输入(a、b)、2输出( enter、exit)的有限状态机。当车辆进入、开出停车场时,分别将
enter、exit置一个周期的有效电平
2根据有限状态机写出HDL代码。
3.设计一个带有两个控制信号 (inc, dec)的计数器,当信号有效时加1或减1:写出HDL代码
结合计数器,有限状态机和LED复用显示电路,用俩个带去抖电路的按键代替光电传感器的输入,验证停车场计数器的功能
1. 工程文件
2. 程序文件
3. 程序编译
4. Testbench
5. 仿真图
部分代码展示:
`timescale 1ns / 1ps // // module park_station( input clk,//输入时钟 input a,//入口 input b,//出口 output reg [3:0] weixuan,//数码管位选 output reg [7:0] duanxuan//数码管段选 ); parameter idle_in = 3'd0;//空闲状态 parameter idle_out = 3'd5;//空闲状态 parameter car_in = 3'd1;//有车进入状态 parameter car_in_wait = 3'd2;//有车进入维持状态 parameter car_out = 3'd3;//有车离开状态 parameter car_out_wait = 3'd4;//有车离开维持状态 //parameter car_inout = 3'd5;//同时有车进入离开状态 reg [2:0] state_a='d0; reg [2:0] state_b='d0; //两段式状态机第一段,状态转换 always@(posedge clk) begin case(state_a) idle_in:if(a==1) state_a<=car_in;//有车进入 else state_a<=idle_in;//无车保持空闲状态 car_in: state_a<=car_in_wait;//有车进入维持状态 car_in_wait:if(a==1) state_a<=car_in_wait;//有车进入维持状态 else state_a<=idle_in;//车完全驶入 default:state_a<=idle_in; endcase case(state_b) idle_out:if(b==1) state_b<=car_out;//有车离开 else state_b<=idle_out;//无车保持空闲状态 car_out: state_b<=car_out_wait;//有车离开维持状态 car_out_wait:if(b==1) state_b<=car_out_wait;//有车离开维持状态 else state_b<=idle_out;//车完全离开 default:state_b<=idle_out; endcase end reg enter=0;//进入脉冲 reg exit=0;//离开脉冲 //两段式状态机第二段,状态对应操作 always@(posedge clk) begin if(state_a==car_in) enter<=1; else enter<=0; if(state_b==car_out) exit<=1; else exit<=0; end wire [1:0] detect;//车辆驶入驶出组合情况 assign detect={enter,exit}; reg inc=0;//车辆增加 reg dec=0;//车辆减少 reg [7:0] car_num='d0;//车辆总数 always@(posedge clk) begin if(detect==2'b00)begin//没有驶入驶出 inc<=0; dec<=0; end else if(detect==2'b01)begin//驶出 inc<=0; dec<=1; end else if(detect==2'b10)begin//驶入 inc<=1; dec<=0; end else if(detect==2'b10)begin//同时驶入驶出 inc<=0; dec<=0; end end always@(posedge clk) begin if(inc==1) if(car_num=='d255)//停车场满 car_num<=car_num;//不再驶入 else car_num<=car_num+1;//驶入 else if(dec==1) if(car_num=='d0) car_num<=car_num;//不再驶出 else car_num<=car_num-1;//驶出 else car_num<=car_num; end wire [3:0] one,ten; wire [3:0] hun; wire count; wire shift_reg; //将二进制的car_num转换为个位,十位,百位,BCD码便于数码管显示 assign hun=car_num/100;//除以100 assign ten=car_num/10%10;//除以10,再除以10取余数 assign one=car_num%10;//除以10取余数 //以下为数码管显示 reg [3:0] jishu='d0; reg [3:0] data='d0; always@(posedge clk)//为数码管动态扫描的时间间隔作准备 begin if(jishu==4'b1111) jishu<=0; else jishu<=jishu+1; end always@(posedge clk) begin case(jishu[3:2])//位值读取;每一个时间间隔读取一个位(个位、十位、百位...) 2'd0:data<=hun; 2'd1:data<=ten; 2'd2:data<=one; default:data<=one; endcase end always@(posedge clk) begin case(jishu[3:2]) 3'd0: weixuan<=4'b0001; 3'd1: weixuan<=4'b0010; 3'd2: weixuan<=4'b0100; default:weixuan<=4'b0000; endcase case(data)//段选 endmodule
源代码
扫描文章末尾的公众号二维码