// 第一段:组合逻辑,状态转移 always @(*) begin case (state) LEFT: begin // 左边有障碍物,或者两边都有,就向右走 if ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; endelsebegin next_state = LEFT; end end RIGHT: begin // 右边有障碍物,或者两边都有,就向左走 if ((bump == 2'b01) || (bump == 2'b11)) begin next_state = LEFT; endelsebegin next_state = RIGHT; end end default: begin next_state = LEFT; end endcase end
// 第二段:时序逻辑,状态更新(异步复位) always @(posedge clk orposedge areset) begin if (areset) begin state <= LEFT; // 复位时向左走 endelsebegin state <= next_state; end end
// 第一段:组合逻辑,状态转移 always @(*) begin case (state) LEFT: begin if (ground == 1'b0) begin next_state = AH_LEFT; // 地面没了,开始掉落,记住方向 endelseif ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; // 碰到障碍,右转 endelsebegin next_state = LEFT; end end RIGHT: begin if (ground == 1'b0) begin next_state = AH_RIGHT; // 地面没了,开始掉落,记住方向 endelseif ((bump == 2'b01) || (bump == 2'b11)) begin next_state = LEFT; // 碰到障碍,左转 endelsebegin next_state = RIGHT; end end AH_LEFT: begin if (ground == 1'b0) begin next_state = AH_LEFT; // 还在掉落,继续保持 endelsebegin next_state = LEFT; // 回到地面,继续向左走 end end AH_RIGHT: begin if (ground == 1'b0) begin next_state = AH_RIGHT; // 还在掉落,继续保持 endelsebegin next_state = RIGHT; // 回到地面,继续向右走 end end default: begin next_state = LEFT; end endcase end
// 第二段:时序逻辑,状态更新(异步复位) always @(posedge clk orposedge areset) begin if (areset) begin state <= LEFT; endelsebegin state <= next_state; end end
// 第一段:组合逻辑,状态转移 always @(*) begin case (state) LEFT: begin if (ground == 1'b0) begin next_state = FALL_LEFT; // 优先级最高:掉落 endelseif (dig == 1'b1) begin next_state = DIG_LEFT; // 次之:挖掘 endelseif ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; // 最后:改变方向 endelsebegin next_state = LEFT; end end RIGHT: begin if (ground == 1'b0) begin next_state = FALL_RIGHT; endelseif (dig == 1'b1) begin next_state = DIG_RIGHT; endelseif ((bump == 2'b01) || (bump == 2'b11)) begin next_state = LEFT; endelsebegin next_state = RIGHT; end end DIG_LEFT: begin if (ground == 1'b0) begin next_state = FALL_LEFT; // 挖掘时也可能掉落! endelsebegin next_state = DIG_LEFT; // 继续挖掘 end end DIG_RIGHT: begin if (ground == 1'b0) begin next_state = FALL_RIGHT; endelsebegin next_state = DIG_RIGHT; end end FALL_LEFT: begin if (ground == 1'b0) begin next_state = FALL_LEFT; // 继续掉落 endelsebegin next_state = LEFT; // 回到地面 end end FALL_RIGHT: begin if (ground == 1'b0) begin next_state = FALL_RIGHT; endelsebegin next_state = RIGHT; end end default: begin next_state = LEFT; end endcase end
// 第二段:时序逻辑,状态更新 always @(posedge clk orposedge areset) begin if (areset) begin state <= LEFT; endelsebegin state <= next_state; end end
// 第一段:组合逻辑,状态转移 always @(*) begin case (state) LEFT: begin if (ground == 1'b0) begin next_state = FALL_LEFT; endelseif (dig == 1'b1) begin next_state = DIG_LEFT; endelseif ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; endelsebegin next_state = LEFT; end end
RIGHT: begin if (ground == 1'b0) begin next_state = FALL_RIGHT; endelseif (dig == 1'b1) begin next_state = DIG_RIGHT; endelseif ((bump == 2'b01) || (bump == 2'b11)) begin next_state = LEFT; endelsebegin next_state = RIGHT; end end
DIG_LEFT: begin if (ground == 1'b0) begin next_state = FALL_LEFT; endelsebegin next_state = DIG_LEFT; end end
DIG_RIGHT: begin if (ground == 1'b0) begin next_state = FALL_RIGHT; endelsebegin next_state = DIG_RIGHT; end end
FALL_LEFT: begin if ((ground == 1'b0) && (cycle_count < 5'd20)) begin next_state = FALL_LEFT; // 还在掉落,时间不够20 endelseif ((ground == 1'b0) && (cycle_count >= 5'd20)) begin next_state = SPLATTER; // 还在掉落,时间够20了 endelsebegin next_state = LEFT; // 回到地面,还没死 end end
FALL_RIGHT: begin if ((ground == 1'b0) && (cycle_count < 5'd20)) begin next_state = FALL_RIGHT; endelseif ((ground == 1'b0) && (cycle_count >= 5'd20)) begin next_state = SPLATTER; endelsebegin next_state = RIGHT; end end
SPLATTER: begin if (ground == 1'b1) begin next_state = DEAD; // 落地了,彻底死亡 endelsebegin next_state = SPLATTER; // 还没落地,继续splatter end end
DEAD: begin next_state = DEAD; // 死了就不动了 end
default: begin next_state = LEFT; end endcase end
// 第二段:时序逻辑,状态更新 always @(posedge clk orposedge areset) begin if (areset) begin state <= LEFT; endelsebegin state <= next_state; end end
// 第三段:计数器逻辑 always @(posedge clk orposedge areset) begin if (areset) begin cycle_count <= 5'd0; endelseif ((next_state == FALL_LEFT) || (next_state == FALL_RIGHT)) begin cycle_count <= cycle_count + 1'b1; // 继续掉落,计数+1 endelsebegin cycle_count <= 5'd0; // 不是掉落状态,清零 end end
// 只定义了LEFT和RIGHT,忘记定义掉落状态 parameter LEFT = 1'b0; parameter RIGHT = 1'b1; // 缺少AH_LEFT和AH_RIGHT!
错误原因:
没有仔细分析需求,每个”动作+方向”的组合都需要独立状态
比如”掉落且记得向左”和”掉落且记得向右”是两个不同的状态
正确做法:
列出所有可能的场景
每个场景都分配一个独立状态
画状态转移图帮助理清思路
错误2:状态转移优先级搞反
错误表现:
1 2 3 4 5 6 7
LEFT: begin if ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; // 先判断碰撞 endelseif (ground == 1'b0) begin next_state = AH_LEFT; // 后判断掉落!这是错的! end end
错误原因:
题目明确说了优先级:fall > dig > switch direction
地面都没了,还管什么碰撞!
正确做法:
1 2 3 4 5 6 7 8 9
LEFT: begin if (ground == 1'b0) begin// 先判断掉落(最高优先级) next_state = FALL_LEFT; endelseif (dig == 1'b1) begin// 再判断挖掘 next_state = DIG_LEFT; endelseif ((bump == 2'b10) || (bump == 2'b11)) begin next_state = RIGHT; // 最后判断方向 end end
错误3:计数器逻辑错误
错误表现:
1 2 3 4 5 6 7 8 9 10
// 计数器看当前状态而不是下一状态 always @(posedge clk) begin if (areset) begin cycle_count <= 5'd0; endelseif ((state == FALL_LEFT) || (state == FALL_RIGHT)) begin cycle_count <= cycle_count + 1'b1; // 会延迟一个周期! endelsebegin cycle_count <= 5'd0; end end