题目:
翻译:
《旅鼠》这款游戏涉及大脑相当简单的动物。简单到我们要用有限状态机来建模。在《旅鼠》的2D世界中,旅鼠可以有两种状态:向左走或向右走。如果碰到障碍物,它会改变方向。特别是,如果旅鼠在左边被撞了,它会向右走。如果它在右边被撞了一下,它就会向左走。如果两边同时碰撞,它仍然会改变方向。实现具有两个状态、两个输入和一个输出的Moore状态机,以模拟此行为。
首先给出成功的 RTL 代码,以及自己额外写的 TB 代码,如果没有兴趣往后看可直接自取:
RTL 代码:
module Lemmings(
input clk,
input areset,
input bump_left,
input bump_right,
output walk_left,
output walk_right
);
reg state, next_state;
parameter left = 1'b0, right = 1'b1;
always@(posedge clk, negedge areset) begin
if(areset) begin
state <= left;
end
else begin
state <= next_state;
end
end
always@(*) begin
case(state)
left: next_state=bump_left?right:left;
right: next_state=bump_right?left:right;
default:next_state=state;
endcase
end
assign walk_left = (state == left);
assign walk_right = (state == right);
endmodule
TB代码:
module Lemmings_tb;
reg clk;
reg areset;
reg bump_left, bump_right;
wire walk_left, walk_right;
Lemmings u_Lemmings(
.clk(clk),
.areset(areset),
.bump_left(bump_left),
.bump_right(bump_right),
.walk_left(walk_left),
.walk_right(walk_right)
);
initial begin
clk = 0;
bump_left = 0;
bump_right = 0;
areset = 0;
#5 areset = 1;
#10 areset = 0;
end
always #10 clk = ~clk;
always@(posedge clk) begin
if({$random()%6} < 1) begin
bump_left = 1;
end
else begin
bump_left = 0;
end
end
always@(posedge clk) begin
if({$random()%6} < 1) begin
bump_right = 1;
end
else begin
bump_right = 0;
end
end
initial begin
#1000 $finish;
end
endmodule
波形:
本题是一个有限状态机问题,首先画出状态转移图:
根据状态图得到代码:
always@(*) begin
case(state)
left: next_state=bump_left?right:left;
right: next_state=bump_right?left:right;
default:next_state=state;
endcase
end
时钟上升沿和异步复位上升沿到来时更新状态 state:
always@(posedge clk, negedge areset) begin
if(areset) begin
state <= left;
end
else begin
state <= next_state;
end
end
为输出赋值:
assign walk_left = (state == left);
assign walk_right = (state == right);
整个代码采用三段式结构,易于修改和阅读。