【2023.11西南交大 数电实验】
具体要求
设计一个停车场出入口车辆自动检测计数电路。如图 1 所示,用两对光感应器 a
和 b 监测车辆的行动,车身长度大于 a 与 b 之间的距离。当一个物体出现在光感应发
射器和接收器之间时,光被阻断,相应的输出被置位为 1 。通过检测传感器 a 和 b 的
信号,确定是否有车辆进入或驶出停车场。(西南交通大学数电实验,笔者实验已被验收)
设计思路
FSM状态机思考过程:
(1)输入: 检测传感器a,b
(2)输出:是否有车出或入,变量设为Y
(3)状态:状态的设计方法比较多样,可以采用Moore也可以用Mearly,笔者将以后者进行介绍。状态分为7种
S0:a,b都没有反应 0 0
(进入状态)S1:a,b显示为1 0 S2:1 1 S3:0 1
(出去状态)S4:0 1 S5:1 1 S6:1 0
代码实现
这道题目本身不难,笔者认为考点在于如何将两种状况分开考虑并且建立在同一个FSM中以及如何判断干扰。
如何将两组状态分开考虑
二者状态的分歧点在于初始状态S0之后的输入,如果是10就是进入,如果是01就是出(不考虑干扰)所以在cs == 00 时把状态进行划分,进入S1就意味着是进车,S4就是出车,这样就将两组状态连接在了一起。
如何判断干扰
这边要先申明一下,因为这仅仅只是一个简化的管理系统,所以不能做到比较完善的去干扰能力,思维比较严谨的小伙伴们可以先不去想太深。这边只考虑一辆车子的前进、停住不动和倒退,以及一个人的经过。
行人的经过
以进入为例,行人经过时,信号是这样的:00 10 00 01 00
而对比车子的进入:00 10 11 01 00,中间存在 00的情况,那么只要判断处在状态10 01的时候,如果下一次出现的是00(处在状态10 01的时候),就可以判断是行人而退回到S0的状态。
车子的进与不进
因为处在不同的状态(前进属于正常状态就暂且不说)后退与停滞所需要做的操作其实是一样的,所以以进车时的S2 (11)状态为例,如果此时我检测到是 11说明车子没有发生移动,那么ns = S2(不变);如果我检测到是10说明车子回退了,那么ns = S1(回到上一个状态)。其他的情况下都是同理的。
以上便是我们对干扰的讨论,代码奉上
module test6_2022116384(ledin,cnter,clk,dout,seg,clr);
input [1:0]ledin;
input clk,clr;
output reg [3:0]cnter;//用来计数当前车库的车辆数
output reg [6:0]dout;//控制7段数码管内的7个管子
output [7:0] seg = 8'b00000001;// 控制8个7段数码管的显示
reg [2:0] ns,cs; // 次态和现态
parameter s0 = 3'b000,s1 = 3'b001,s2 = 3'b010,s3 = 3'b011,s4 = 3'b100,s5 = 3'b101,s6 = 3'b110;//7个状态
always @(posedge clk,negedge clr)
begin
if(~clr) //对当前的状态置零
cs <= s0;
else
cs <= ns;//更新状态
end
always @(*)
begin
case(cs)
s0: if(ledin == 2'b10) ns = s1;//进了车
else if(ledin == 2'b01) ns = s4;//出了车
else ns = s0;//其他情况的都是干扰
s1: if(ledin == 2'b11) ns = s2;//如果车身把两个信号都挡到了就是前进了一个状态
else if(ledin == 2'b10) ns = s1;//不动
else ns = s0;//00有两种情况,行人干扰和汽车回退 01也可能是行人因为车身长
s2: if(ledin == 2'b01) ns = s3;//车尾到b,要前进一个状态
else if(ledin == 2'b10) ns = s1;//车子往回退
else if(ledin == 2'b11) ns = s2;//不动
else ns = s0;//00,基本上就是行人的干扰了(从11 -> 00车子肯定做不到)
s3: if(ledin == 2'b00) ns = s0;//车身全部过去,要计数了
else if(ledin == 2'b11) ns = s2;//往回退 **也可能是后方又来了一辆车,同时挡信号
else if(ledin == 2'b01) ns = s3;//不动
else ns =s0;//10,车子做不到,肯定是干扰
s4: if(ledin == 2'b11) ns = s5;
else if(ledin == 2'b01) ns = s4;//不动
else ns = s0;
s5: if(ledin == 2'b10) ns = s6;
else if(ledin == 2'b01) ns = s4;//回退
else if(ledin == 2'b11) ns = s5;//不动
else ns = s0;
s6: if(ledin == 2'b00) ns = s0;
else if(ledin == 2'b10) ns = s6;//不动
else if(ledin == 2'b11) ns = s5;//车子往回走
else ns = s0;
default: ns = s0;
endcase
end
always @(posedge clk)
begin
if(ledin == 2'b00 && cs == s3) //如果是进车状态下,到了s3并且下一次的输入是00
begin
if(cnter < 4'd9)//不超过10
cnter <= cnter + 1;//车库车辆加一
else cnter = 0;
end
else if(ledin == 2'b00 && cs == s6)
begin
if(cnter > 0)//在车库不空的情况下就减一
cnter <= cnter - 1;
end
end
always @(*)//控制7段数码管
begin
case(cnter)
4'd0: dout = 7'b0111111;
4'd1: dout = 7'b0000110;
4'd2: dout = 7'b1011011;
4'd3: dout = 7'b1001111;
4'd4: dout = 7'b1100110;
4'd5: dout = 7'b1101101;
4'd6: dout = 7'b1111101;
4'd7: dout = 7'b0000111;
4'd8: dout = 7'b1111111;
4'd9: dout = 7'b1101111;
endcase
end
endmodule
上板子!
以下视频是笔者在实验室实录的,感兴趣的小伙伴可以看看哦!
车辆管理系统
感谢观看!