HDLBits|HDLBits练习-有限状态机FSM

Exams/ece241 2013 q4-水位问题 1、输入是什么?
2、现态是什么?
3、次态是什么?
4、转换条件是什么?
5、输出是什么?
HDLBits|HDLBits练习-有限状态机FSM
文章图片

在这个问题中,输入是3个传感器,现态和次态是4个水位状态(water level),转换条件是3个传感器的值是什么情况,输出是水阀的开关状态。其中水阀分两类,一类是固定水阀(nominal flow),一类是辅助水阀(supplemental flow)。

module top_module ( input clk, input reset, //同步复位,高有效 input [3:1] s, output fr3, output fr2, output fr1, output dfr ); parameter a=1,b=2,c=3,d=4; reg[2:0] state,state_n; //状态转换 always@(posedge clk)begin if(reset) state <= a; else state <= state_n; end//转换条件 always@(*)begin case(state) a:state_n = s[1]? b:a; b:state_n = s[2]? c:(s[1]? b:a); c:state_n = s[3]? d:(s[2]? c:b); d:state_n = s[3]? d:c; endcase end//输出结果 always@(*)begin case(state) a:{fr3,fr2,fr1} = 3'b111; b:{fr3,fr2,fr1} = 3'b011; c:{fr3,fr2,fr1} = 3'b001; d:{fr3,fr2,fr1} = 3'b000; endcase endalways@(posedge clk)begin if(reset) dfr <= 1; else begin if(state > state_n) dfr <= 1; else if(state

其中,辅助水阀的开关取决于当前状态和前一状态的值,所以用时序逻辑+比较器实现。如果现在的状态是a,下一状态是b。那么当下一个时钟来临时,a就变成了上一个状态,b就变成了当前状态,再通过比较得出水是上升还是下降,从而实现dfr的赋值。
答案中给出的程序如下:
module top_module ( input clk, input reset, input [3:1] s, output reg fr3, output reg fr2, output reg fr1, output reg dfr ); // Give state names and assignments. I'm lazy, so I like to use decimal numbers. // It doesn't really matter what assignment is used, as long as they're unique. // We have 6 states here. parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5; reg [2:0] state, next; // Make sure these are big enough to hold the state encodings. // Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset. always @(posedge clk) begin if (reset) state <= A2; else state <= next; end// Combinational always block for state transition logic. Given the current state and inputs, // what should be next state be? // Combinational always block: Use blocking assignments. always@(*) begin case (state) A2: next = s[1] ? B1 : A2; B1: next = s[2] ? C1 : (s[1] ? B1 : A2); B2: next = s[2] ? C1 : (s[1] ? B2 : A2); C1: next = s[3] ? D1 : (s[2] ? C1 : B2); C2: next = s[3] ? D1 : (s[2] ? C2 : B2); D1: next = s[3] ? D1 : C2; default: next = 'x; endcase end // Combinational output logic. In this problem, a procedural block (combinational always block) // is more convenient. Be careful not to create a latch. always@(*) begin case (state) A2: {fr3, fr2, fr1, dfr} = 4'b1111; B1: {fr3, fr2, fr1, dfr} = 4'b0110; B2: {fr3, fr2, fr1, dfr} = 4'b0111; C1: {fr3, fr2, fr1, dfr} = 4'b0010; C2: {fr3, fr2, fr1, dfr} = 4'b0011; D1: {fr3, fr2, fr1, dfr} = 4'b0000; default: {fr3, fr2, fr1, dfr} = 'x; endcase end endmodule

答案中直接分配了6个状态,包括了上升和下降的信息(b1b2,c1c2),所以结构更为精简。这里给出了状态机的默认值‘x。

Lemmings1 碰到左边就往右走,碰到右边就往左走。
所以状态只有两个:向右、向左;输入为碰左边、碰右边。
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 @(*) begin // State transition logic case(state) LEFT:next_state = bump_left? RIGHT:LEFT; RIGHT:next_state = bump_right? LEFT:RIGHT; default:next_state = 'x; endcase endalways @(posedge clk, posedge areset) begin // State flip-flops with asynchronous reset if(areset) state <= LEFT; else state <= next_state; end// Output logic assign walk_left = (state == LEFT); assign walk_right = (state == RIGHT); endmodule

Lemmings2 比上面多了一个“坠落”的效果,并会发出“aaah”,掉落时不再受碰撞影响,地重新出现的时候继续上一方向。
新状态:坠落;转入条件:ground=0;输出: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 WL=0,WR=1,WLF=2,WRF=3; reg [1:0] state,state_n; always@(posedge clk or posedge areset)begin if(areset) state <= WL; else state <= state_n; endalways@(*)begin case(state) WL:state_n = ground? (bump_left? WR:WL):WLF; WR:state_n = ground? (bump_right? WL:WR):WRF; WLF:state_n = ground? WL:WLF; WRF:state_n = ground? WR:WRF; endcase endassign walk_left = (state == WL); assign walk_right = (state == WR); assign aaah = (state == WRF)||(state == WLF); endmodule

Lemmings3 新增状态:挖洞
转入条件:ground=1&&dig=1
转出条件:ground=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 ); parameter WR=0,WL=1,WLF=2,WRF=3,DIGL=4,DIGR=5; reg [2:0] state,state_n; always@(posedge clk or posedge areset)begin if(areset) state <= WL; else state <= state_n; endalways@(*)begin case(state) WL:state_n = ground? (dig? DIGL:(bump_left? WR:WL)):WLF; WR:state_n = ground? (dig? DIGR:(bump_right? WL:WR)):WRF; WLF:state_n = ground? WL:WLF; WRF:state_n = ground? WR:WRF; DIGL:state_n = ground? DIGL:WLF; DIGR:state_n = ground? DIGR:WRF; endcase endassign walk_left = state == WL; assign walk_right = state == WR; assign aaah = (state == WLF)||(state == WRF); assign digging = (state == DIGR)||(state == DIGL); endmodule

Lemmings4 新增状态:飞溅
转入条件:下落时间>20clk && 有地面出现
输出:全部输出为0

通过debug我发现,aaah是在下落过程中一直出现,并不会在splatter的状态下终止。这就意味着在下落过程中,只有t>20且ground=1时,输出才会改变。
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 WL=0,WR=1,DIGL=2,DIGR=3,WLF=4,WRF=5,SPL=6,OVER=7; reg [3:0] state,state_n; reg [4:0] cnt_20; wireadd_cnt_20; wireend_cnt_20; wirefull_cnt_20; always@(posedge clk or posedge areset)begin if(areset)begin cnt_20 = 5'b0; full_cnt_20 = 0; end else begin if(add_cnt_20)begin if(end_cnt_20)begin cnt_20 = 5'b0; full_cnt_20 = 1; end else begin cnt_20 = cnt_20 + 1; full_cnt_20 = full_cnt_20; end end else begin cnt_20 = 5'b0; //无地计数,有地清零 full_cnt_20 = 0; end end endassign add_cnt_20 = ~ground; assign end_cnt_20 = add_cnt_20 && cnt_20 == 20; always@(posedge clk or posedge areset)begin if(areset) state = WL; else state = state_n; endalways@(*)begin case(state) WL:state_n = ground?(dig?DIGL:(bump_left?WR:WL)):WLF; WR:state_n = ground?(dig?DIGR:(bump_right?WL:WR)):WRF; DIGL:state_n = ground?DIGL:WLF; DIGR:state_n = ground?DIGR:WRF; WLF:state_n = ground?(full_cnt_20?OVER:WL):WLF; WRF:state_n = ground?(full_cnt_20?OVER:WR):WRF; OVER:state_n = OVER; endcase endassign walk_left = state == WL; assign walk_right = state == WR; assign aaah = state == WLF || state == WRF ; assign digging = state == DIGL || state == DIGR; endmodule



Fsm onehot HDLBits|HDLBits练习-有限状态机FSM
文章图片

只写状态转换逻辑和输出
module top_module( input in, input [9:0] state, output [9:0] next_state, output out1, output out2); assign next_state[0] = (state & 10'b1110011111)&&(~in); assignnext_state[1] = (state[0] & in) | (state[8] & in)|(state[9] & in); assignnext_state[2] = (state[1] & in); assignnext_state[3] = (state[2] & in); assignnext_state[4] = (state[3] & in); assignnext_state[5] = (state[4] & in); assignnext_state[6] = (state[5] & in); assignnext_state[7] = (state[7] & in) | state[6] & (in); assignnext_state[8] =state[5] & (~in); assignnext_state[9] =state[6] & (~in); assignout1 = (state[8] | state[9]) ? 1:0; assignout2 = (state[9] | state[7]) ? 1:0; endmodule

我发现除了s5s6,其他状态下当in=0时,都会回到s0。所以将state输入按位与,消去s5s6的影响,再逻辑与上~in,只要其他位有1,则状态回到s0。
其他状态与之前的独热码状态机无差别,独热码的使用让逻辑转换式更加简单,利于消除毛刺。

Fsm ps2 HDLBits|HDLBits练习-有限状态机FSM
文章图片

这里的BYTE1、BYTE2、BYTE3,对应每一组信号的bit[3]、bit[2]、bit[1]
HDLBits|HDLBits练习-有限状态机FSM
文章图片

这里in[3]的数据只表示第3位,即标志位。当in[3]=1时,输出3位数据,完成后标志位done=1。这里最下面一行的byte1、byte2、byte3对应的是输出信号,不是done。
HDLBits|HDLBits练习-有限状态机FSM
文章图片

这里一组信号输出完成后,下一个in[3]还未来临,所以状态维持在byte1,;当in[3]=1时,下一状态变成byte2.
module top_module( input clk, input [7:0] in, input reset,// Synchronous reset output done); //reg[3:0] state,state_n; parameterBYTE1=0,BYTE2=1,BYTE3=2,DONE=3; // State transition logic (combinational) always@(*)begin case(state) BYTE1:state_n = in[3]?BYTE2:BYTE1; BYTE2:state_n = BYTE3; BYTE3:state_n = DONE; DONE: state_n = in[3]?BYTE2:BYTE1; endcase end// State flip-flops (sequential) always@(posedge clk)begin if(reset) state = BYTE1; else state = state_n; end// Output logic assign done = (state == DONE)? 1:0; endmodule

Fsm ps2data 与上一题的主要区别在于提供了数据的存储路径,这里的思路是当下一状态改变时,意味着数据满足要求,在下一个时钟到来的时候,一方面state=state_n;一方面输入数据被存储起来。
module top_module( input clk, input [7:0] in, input reset,// Synchronous reset output [23:0] out_bytes, output done); //// FSM from fsm_ps2 reg[3:0] state,state_n; parameterBYTE1=0,BYTE2=1,BYTE3=2,DONE=3; // State transition logic (combinational) always@(*)begin case(state) BYTE1:state_n = in[3]?BYTE2:BYTE1; BYTE2:state_n = BYTE3; BYTE3:state_n = DONE; DONE: state_n = in[3]?BYTE2:BYTE1; endcase end// State flip-flops (sequential) always@(posedge clk)begin if(reset) state = BYTE1; else state = state_n; end// Output logic assign done = (state == DONE); // New: Datapath to store incoming bytes. //下一状态为BYTE2时,BYTE1记录完成; //下一状态为BYTE3时,BYTE2记录完成; //下一状态为DONE时,BYTE3记录完成; reg [23:0] out_reg; always@(posedge clk)begin if(reset) out_reg <= 24'b0; else case(state_n) BYTE2:out_reg[23:16] <= in[7:0]; BYTE3:out_reg[15:8]<= in[7:0]; DONE: out_reg[7:0]<= in[7:0]; default:out_reg[23:0]<= 24'b0; endcase endassign out_bytes = (state == DONE)?out_reg[23:0]:24'b0; endmodule


【HDLBits|HDLBits练习-有限状态机FSM】

    推荐阅读