Lemmings又多了一种状态:dig,我按照上一篇文章里大神的思路又多加了两种状态:LEFT_DIGGING与RIGHT_DIGGING,写出了如下的代码:
- module top_module(
- input clk,
- input areset, // Freshly brainwashed Lemmings walk left.
- input bump_left,
- input bump_right,
- input ground,
- input dig,
- output walk_left,
- output walk_right,
- output aaah,
- output digging );
-
- parameter LEFT=4'b000001, RIGHT=4'b000010, LEFT_FALLING=4'b000100, RIGHT_FALLING=4'b001000,
- LEFT_DIGGING=4'b010000, RIGHT_DIGGING=4'b100000;
-
- reg [3:0] state,next_state;
-
- always@(*)begin
- case(state)
- LEFT: next_state = ground?(dig?LEFT_DIGGING:(bump_left?RIGHT:LEFT)):LEFT_FALLING;
- RIGHT: next_state = ground?(dig?RIGHT_DIGGING:(bump_right?LEFT:RIGHT)):RIGHT_FALLING;
- LEFT_FALLING: next_state = ground?LEFT:LEFT_FALLING;
- RIGHT_FALLING: next_state = ground?RIGHT:RIGHT_FALLING;
- LEFT_DIGGING: next_state = ground?(dig?LEFT_DIGGING:(bump_left?RIGHT:LEFT)):LEFT_FALLING;
- RIGHT_DIGGING: next_state = ground?(dig?RIGHT_DIGGING:(bump_right?LEFT:RIGHT)):RIGHT_FALLING;
- default: next_state = LEFT;
- endcase
- end
-
- always@(posedge clk or posedge areset)begin
- if(areset)
- state <= LEFT;
- else
- state <= next_state;
- end
-
- assign walk_left = (state == LEFT);
- assign walk_right = (state == RIGHT);
- assign aaah = (state == LEFT_FALLING || state == RIGHT_FALLING);
- assign digging = (state == RIGHT_DIGGING || state == LEFT_DIGGING);
-
- endmodule
跑出来有错误,检查了时序图,发现这道题目跟我理解的不一致,我以为input中的dig一直为1时,lemming才一直挖地,原来是只要dig输入过1,lemming会一直挖地直到尽头。然后我改掉了LEFT_DIGGING和RIGHT_DIGGING的状态转换的条件,得到如下的代码:
- module top_module(
- input clk,
- input areset, // Freshly brainwashed Lemmings walk left.
- input bump_left,
- input bump_right,
- input ground,
- input dig,
- output walk_left,
- output walk_right,
- output aaah,
- output digging );
-
- parameter LEFT=4'b000001, RIGHT=4'b000010, LEFT_FALLING=4'b000100, RIGHT_FALLING=4'b001000,
- LEFT_DIGGING=4'b010000, RIGHT_DIGGING=4'b100000;
-
- reg [3:0] state,next_state;
-
- always@(*)begin
- case(state)
- LEFT: next_state = ground?(dig?LEFT_DIGGING:(bump_left?RIGHT:LEFT)):LEFT_FALLING;
- RIGHT: next_state = ground?(dig?RIGHT_DIGGING:(bump_right?LEFT:RIGHT)):RIGHT_FALLING;
- LEFT_FALLING: next_state = ground?LEFT:LEFT_FALLING;
- RIGHT_FALLING: next_state = ground?RIGHT:RIGHT_FALLING;
- LEFT_DIGGING: next_state = ground?LEFT_DIGGING:LEFT_FALLING;
- RIGHT_DIGGING: next_state = ground?RIGHT_DIGGING:RIGHT_FALLING;
- default: next_state = LEFT;
- endcase
- end
-
- always@(posedge clk or posedge areset)begin
- if(areset)
- state <= LEFT;
- else
- state <= next_state;
- end
-
- assign walk_left = (state == LEFT);
- assign walk_right = (state == RIGHT);
- assign aaah = (state == LEFT_FALLING || state == RIGHT_FALLING);
- assign digging = (state == RIGHT_DIGGING || state == LEFT_DIGGING);
-
- endmodule
仍然有错误,是在RIGHT状态下的bump_right和dig两个输入同时为1的时候出了问题,lemming一开始的反应去挖地了,没有问题,但是挖完地以后改变了方向变成了LEFT_DIGGING,而参考答案中没有改变方向是RIGHT_DIGGING。
然后检查到这里我发现一个大问题,我的parameter和和state的长度不对?!那时序图怎么跑到1940才发现错误呢?把parameter和state的长度改正之后终于success了。
按照我错误的写法,LEFT_DIGGING和RIGHT_DIGGING应该会被视为一种状态,所以只会执行case中排在前面的LEFT_DIGGING的状态转换,所以不会影响LEFT_DIGGING,只会影响RIGHT_DIGGING。因此导致了上面的错误。所以case里的条件是有顺序的,排在前面的匹配了后面的就不检查了?为了验证这个猜测,我把case里LEFT_DIGGING和RIGHT_DIGGING交换了位置,把RIGHT_DIGGING放在了前面,果然影响到了LEFT_DIGGING。