水箱问题(Exams/ece241 2013 q4)
一个大水库的水为几个用户服务。为了保持足够高的水位,三个传感器以5英寸的间隔垂直放置。当水位高于最高传感器S3时,输入流量应为零。当液位低于最低传感器(Si)时,流量应处于最大(公称流量阀和补充流量阀均打开)。当水位在上下两个传感器之间时,流量由两个因素决定:水位和上次传感器变化前的水位。每个水位都有一个与之相关的名义流量,如下表所示。如果传感器的变化表明以前的水平低于当前水平,则应该发生名义流量。如果之前的水平高于当前水平,应通过打开补充流量阀(由AFR控制)来增加流量。画出水库控制器的摩尔模型状态图。清楚地指出每个状态的所有状态转换和输出。FSM的输入是S1, S2和S3;输出为FR1,FR2,FR3和△FR。
还包括一个高电平有效同步复位,可将状态机复位到与水位长时间处于低位时相当的状态(未置位传感器,并且所有四个输出均置位)。
模块声明
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
题目解析
对于本题来说,主要的关键就是设计状态转移图,然后理清输出的逻辑即可完成整体设计。对于水箱的状态,从上图中的状态可以看出对应状态的输出,对于水箱的水位状态,例如处于低于S1时,此时的状态可能为持续低于S1或者水位上升将水位处于S1和S2之间。其余状态同理,状态变化为低于当前、高于当前或者保持不变。对于输出状态dfr,如果之前的水平高于当前水平dfr置位为高。
答案
module top_module (
input clk,
input reset,
input [3:1] s,
output fr3,
output fr2,
output fr1,
output dfr
);
reg [2-1:0] state=0;
reg [2-1:0] next_state=0;
localparam
BL_S1 = 0,
BW_S1andS2 = 1,
BW_S2andS3 = 2,
AB_S3 = 3;
always @(posedge clk)
begin
// State flip-flops with synchronous reset
if(reset=='b1)
state<=BL_S1;
else
state<=next_state;
end
wire below_S1=(s==3'b000);
wire between_S1_S2=(s==3'b001);
wire between_S2_S3=(s==3'b011);
wire above_S3=(s==3'b111);
always @(*)
begin
case(state)
BL_S1:
begin
if (below_S1)
begin
next_state = BL_S1;
end
else if (between_S1_S2)
begin
next_state = BW_S1andS2;
end
else
begin
next_state = state;
end
end
BW_S1andS2:
begin
if (between_S1_S2)
begin
next_state = BW_S1andS2;
end
else if (between_S2_S3)
begin
next_state = BW_S2andS3;
end
else if (below_S1)
begin
next_state = BL_S1;
end
else
begin
next_state = state;
end
end
BW_S2andS3:
begin
if (between_S2_S3)
begin
next_state = BW_S2andS3;
end
else if (between_S1_S2)
begin
next_state = BW_S1andS2;
end
else if (above_S3)
begin
next_state = AB_S3;
end
else
begin
next_state = state;
end
end
AB_S3:
begin
if (between_S2_S3)
begin
next_state = BW_S2andS3;
end
else if (above_S3)
begin
next_state = AB_S3;
end
else
begin
next_state = state;
end
end
endcase
end
//判断dfr
reg lower_flag = 0;
always@(posedge clk)
begin
if(reset==1)
lower_flag<=1;
else if(state < next_state)
lower_flag<=0;
else if(state > next_state)
lower_flag<=1;
end
assign dfr=lower_flag;
always@(*)
begin
if(state == BL_S1)
begin
fr1=1;
fr2=1;
fr3=1;
end
else if(state == BW_S1andS2)
begin
fr1=1;
fr2=1;
fr3=0;
end
else if(state == BW_S2andS3)
begin
fr1=1;
fr2=0;
fr3=0;
end
else
begin
fr1=0;
fr2=0;
fr3=0;
end
end
endmodule
Lemmings1
游戏旅鼠涉及大脑相当简单的小动物。如此简单,以至于我们将使用有限状态机对其进行建模。
在莱明斯的2D世界中,旅鼠可以处于两种状态之一:向左行走或向右行走。如果它撞到障碍物,它会改变方向。特别是,如果旅鼠在左边撞到,它会向右走。如果它在右边撞到,它会向左走。如果它同时在两侧碰撞,它仍然会改变方向。
实现具有两个状态、两个输入和一个输出的 Moore 状态机,用于模拟此行为。
模块声明
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right);
答案:
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
output walk_left,
output walk_right);
parameter LEFT=0, RIGHT=1;
reg state, next_state;
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset==1)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
always @(*) begin
// State transition logic
case (state)
LEFT:begin
if (bump_left==1) begin
next_state = RIGHT;
end else begin
next_state = LEFT;
end
end
RIGHT:begin
if (bump_right==1) begin
next_state = LEFT;
end else begin
next_state = RIGHT;
end
end
endcase
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
endmodule
Lemmings2
除了左右行走之外,如果地面消失在它们下面,旅鼠还会摔倒(大概会“啊!”)。
除了左右行走并在碰撞时改变方向外,当地面=0时,旅鼠会摔倒并说“啊!当地面重新出现(地面=1)时,旅鼠将恢复以与坠落前相同的方向行走。跌倒时被撞不会影响行走方向,在与地面相同的周期内被撞到消失(但尚未下落),或者地面在仍然下落时再次出现时,也不会影响行走方向。
构建一个对此行为进行建模的有限状态机。
状态转移图示例如下:
模块声明
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
答案
module top_module(
input clk,
input areset, // Freshly brainwashed Lemmings walk left.
input bump_left,
input bump_right,
input ground,
output walk_left,
output walk_right,
output aaah );
parameter LEFT=0, RIGHT=1, FALL_LEFT=2,FALL_RIGHT=3;
reg [1:0] state;
reg [1:0] next_state;
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset==1)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
always @(*) begin
// State transition logic
case (state)
LEFT:begin
if(ground==0)begin
next_state = FALL_LEFT;
end
else if (bump_left==1) begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground==0)begin
next_state = FALL_RIGHT;
end
else if (bump_right==1) begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
FALL_LEFT:begin
if(ground==1)begin
next_state = LEFT;
end
else begin
next_state = FALL_LEFT;
end
end
FALL_RIGHT:begin
if(ground==1)begin
next_state = RIGHT;
end
else begin
next_state = FALL_RIGHT;
end
end
endcase
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign aaah = (state == FALL_RIGHT)||(state == FALL_LEFT);
endmodule
Lemmings3
除了行走和跌倒之外,有时还可以告诉旅鼠做有用的事情,比如挖掘(当 dig=1
时开始挖掘)。如果旅鼠目前在地面上行走(地面=1
并且没有掉落),则可以挖掘,并且将继续挖掘,直到到达另一侧(地面=0
)。在这一点上,由于没有地面,它会掉下来(啊啊!),然后一旦它再次落地,就继续向原来的方向走。与跌倒一样,在挖掘时被撞到没有影响,并且在跌倒或没有地面时被告知要挖掘会被忽略。
换句话说,行走的旅鼠可以跌倒、挖掘或改变方向。如果满足这些条件中的多个,则下降的优先级高于挖掘,挖掘的优先级高于切换方向。
时序示意图如下:
根据题目给出示意状态转移图如下:
模块声明
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 );
答案
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=0, RIGHT=1, FALL_LEFT=2,FALL_RIGHT=3,DIG_L=4,DIG_R=5;
reg [2:0] state;
reg [2:0] next_state;
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset==1)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
always @(*) begin
// State transition logic
case (state)
LEFT:begin
if(ground==0)begin
next_state = FALL_LEFT;
end
else if (dig==1) begin
next_state = DIG_L;
end
else if (bump_left==1) begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground==0)begin
next_state = FALL_RIGHT;
end
else if (dig==1) begin
next_state = DIG_R;
end
else if (bump_right==1) begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
FALL_LEFT:begin
if(ground==1)begin
next_state = LEFT;
end
else begin
next_state = FALL_LEFT;
end
end
FALL_RIGHT:begin
if(ground==1)begin
next_state = RIGHT;
end
else begin
next_state = FALL_RIGHT;
end
end
DIG_L:begin
if(ground==0)begin
next_state = FALL_LEFT;
end
else begin
next_state = DIG_L;
end
end
DIG_R:begin
if(ground==0)begin
next_state = FALL_RIGHT;
end
else begin
next_state = DIG_R;
end
end
default:begin
next_state = LEFT;
end
endcase
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign digging = (state == DIG_R)||(state == DIG_L);
assign aaah = (state == FALL_RIGHT)||(state == FALL_LEFT);
endmodule
lemmings4
虽然旅鼠可以走路、跌倒和挖掘,但旅鼠并非无懈可击。如果旅鼠跌落时间过长然后着地,它可能会飞溅。特别是,如果旅鼠掉落超过 20 个时钟周期然后撞到地面,它将飞溅并停止行走、跌落或挖掘(所有 4 个输出都变为 0),永远(或直到 FSM 重置)。旅鼠在落地前可以下落多远没有上限。旅鼠只有在落地时才飞溅;它们不会在半空中飞溅。
扩展有限状态机以对此行为进行建模。跌落 20 个周期以内是可以生存的:
跌落 21 个周期会导致飞溅死亡:
根据题目描述的状态转移图如下图所示:
模块声明
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 );
答案
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=0, RIGHT=1, FALL_LEFT=2,FALL_RIGHT=3,DIG_L=4,DIG_R=5,SPLAT=6;
reg [2:0] state;
reg [2:0] next_state;
always @(posedge clk, posedge areset) begin
// State flip-flops with asynchronous reset
if(areset==1)begin
state<=LEFT;
end
else begin
state<=next_state;
end
end
always @(*) begin
// State transition logic
case (state)
LEFT:begin
if(ground==0)begin
next_state = FALL_LEFT;
end
else if (dig==1) begin
next_state = DIG_L;
end
else if (bump_left==1) begin
next_state = RIGHT;
end
else begin
next_state = LEFT;
end
end
RIGHT:begin
if(ground==0)begin
next_state = FALL_RIGHT;
end
else if (dig==1) begin
next_state = DIG_R;
end
else if (bump_right==1) begin
next_state = LEFT;
end
else begin
next_state = RIGHT;
end
end
FALL_LEFT:begin
if(timeout==1&&ground==1)begin
next_state = SPLAT;
end
else if(ground==1)begin
next_state = LEFT;
end
else begin
next_state = FALL_LEFT;
end
end
FALL_RIGHT:begin
if(timeout==1&&ground==1)begin
next_state = SPLAT;
end
else if(ground==1)begin
next_state = RIGHT;
end
else begin
next_state = FALL_RIGHT;
end
end
SPLAT:begin
next_state = SPLAT;
end
DIG_L:begin
if(ground==0)begin
next_state = FALL_LEFT;
end
else begin
next_state = DIG_L;
end
end
DIG_R:begin
if(ground==0)begin
next_state = FALL_RIGHT;
end
else begin
next_state = DIG_R;
end
end
default:begin
next_state = LEFT;
end
endcase
end
// Output logic
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign digging = (state == DIG_R)||(state == DIG_L);
assign aaah = (state == FALL_RIGHT)||(state == FALL_LEFT);
//aaah计数
reg [4:0] aaah_cnt=0;
always @(posedge clk) begin
if(aaah==1)begin
aaah_cnt<=aaah_cnt+1;
end
else begin
aaah_cnt<=0;
end
end
reg timeout=0;
always @(*) begin
if(areset==1)
timeout=0;
else if(aaah_cnt==20)
timeout=1;
else
timeout=timeout;
end
endmodule
Fsm onehot
给定以下具有 1 个输入和 2 个输出的状态机:
假设此状态机使用独热编码,其中状态 [0] 到 state[9] 分别对应于状态 S0 到 S9。除非另有说明,否则输出为零。
实现状态机的状态转换逻辑和输出逻辑部分(但不是状态触发器)。给定状态 [9:0] 中的当前状态,并且必须生成 next_state[9:0] 和两个输出。通过检查(假设独热编码)推导出逻辑方程。(测试平台将使用非一个热输入进行测试,以确保您不会尝试做更复杂的事情)。
模块声明
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
答案
module top_module(
input in,
input [9:0] state,
output [9:0] next_state,
output out1,
output out2);
parameter S0 = 'd0,S1 = 'd1,S2 = 'd2,S3 = 'd3,
S4 = 'd4,S5 = 'd5,S6 = 'd6,S7 = 'd7,
S8 = 'd8,S9 = 'd9;
assign next_state[0] = ~in & (state[S0] | state[S1] | state[S2] | state[S3] | state[S4] | state[S7] | state[S8] | state[S9]);
assign next_state[1] = in & (state[S0] | state[S8] | state[S9]);
assign next_state[2] = in & state[S1];
assign next_state[3] = in & state[S2];
assign next_state[4] = in & state[S3];
assign next_state[5] = in & state[S4];
assign next_state[6] = in & state[S5];
assign next_state[7] = in & (state[S6] | state[S7]);
assign next_state[8] = ~in & state[S5];
assign next_state[9] = ~in & state[S6];
assign out1 = (state[S8])||(state[S9]);
assign out2 = (state[S7])||(state[S9]);
endmodule
Fsm ps2
PS/2 鼠标协议发送长度为三个字节的消息。但是,在连续字节流中,消息的开始和结束位置并不明显。唯一的指示是每个三个字节消息的第一个字节始终具有 bit[3]=1(但其他两个字节的 bit[3] 可能是 1 或 0,具体取决于数据)。
我们想要一个有限状态机,当给定输入字节流时,它将搜索消息边界。我们将使用的算法是丢弃字节,直到我们看到 bit[3]=1 的字节。然后,我们假设这是消息的第 1 字节,并在收到所有 3 个字节(完成)后发出接收消息的信号。
FSM 应在成功接收每条消息的第三个字节后立即在循环中发出完成信号。
一些时序图来解释所需的行为,在无错误条件下,每三个字节形成一条消息:
发生错误时,搜索字节 1:
请注意,这与 1xx
序列识别器不同。此处不允许重叠序列:
模块声明
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done);
答案
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output done); //
parameter BYTE1 = 'd0,BYTE2 = 'd1,BYTE3 = 'd2,DONE = 'd3;
reg [1:0] state;
reg [1:0] next_state;
// State flip-flops (sequential)
always @(posedge clk) begin
if(reset==1)begin
state<=BYTE1;
end
else begin
state<=next_state;
end
end
// State transition logic (combinational)
always @(*) begin
case (state)
BYTE1:begin
if(in[3]==0)begin
next_state = BYTE1;
end
else begin
next_state = BYTE2;
end
end
BYTE2:begin
next_state = BYTE3;
end
BYTE3:begin
next_state = DONE;
end
DONE:begin
if(in[3]==0)begin
next_state = BYTE1;
end
else begin
next_state = BYTE2;
end
end
default:next_state = BYTE1;
endcase
end
// Output logic
assign done = (state == DONE);
endmodule
Fsm ps2data
现在您有一个状态机来识别 PS/2 字节流中的三字节消息,请添加一个数据路径,该数据路径也将在收到数据包时输出 24 位(3 字节)消息(out_bytes[23:16] 是第一个字节,out_bytes[15:8] 是第二个字节,依此类推)。
每当断言完成信号时,out_bytes都需要有效。你可以在其他时间输出任何东西(即,不在乎)。
模块声明
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done);
答案
module top_module(
input clk,
input [7:0] in,
input reset, // Synchronous reset
output [23:0] out_bytes,
output done); //
parameter BYTE1 = 'd0,BYTE2 = 'd1,BYTE3 = 'd2,DONE = 'd3;
reg [1:0] state;
reg [1:0] next_state;
// State flip-flops (sequential)
always @(posedge clk) begin
if(reset==1)begin
state<=BYTE1;
end
else begin
state<=next_state;
end
end
// State transition logic (combinational)
always @(*) begin
case (state)
BYTE1:begin
if(in[3]==0)begin
next_state = BYTE1;
end
else begin
next_state = BYTE2;
end
end
BYTE2:begin
next_state = BYTE3;
end
BYTE3:begin
next_state = DONE;
end
DONE:begin
if(in[3]==0)begin
next_state = BYTE1;
end
else begin
next_state = BYTE2;
end
end
default:next_state = BYTE1;
endcase
end
reg [7:0] in_r0;
reg [7:0] in_r1;
reg [7:0] in_r2;
always @(posedge clk ) begin
in_r0<=in;
in_r1<=in_r0;
in_r2<=in_r1;
end
// Output logic
assign done = (state == DONE);
always @(*) begin
if(done==1)
out_bytes={in_r2,in_r1,in_r0};
end
endmodule