hdlbits之Exams/ece241 2013 q4的FSM问题

工作和学习中的事情太多,想干的事情更多,所以总感觉时间不够用。再加上自己比较懒,好久没有兴致闲下来写东西了。

之前做过hdlbits的一些题目,挺简单。但是今天被这道题给坑惨了,花费了几个小时才做出来。不是说这道题有多难,一是自己犯了一个脑袋驴踢的及其低级错误,二是题目也有出的不清楚的地方。原题目如下

 

自己犯下的极其低级和愚蠢的错误为在S0,S1,S2,S3四个状态,判断输入s的值是忘了加数据类型和位宽。这个愚蠢而又低级的错误导致无法进入正确的状态。

1             S0 : begin
2                 case(s)
3                     000 : next_state = S0;
4                     001 : next_state = S1;
5                     011 : next_state = S2;
6                     111 : next_state = S3;
7                     default: next_state = S0;
8                 endcase                
9             end

正确的应该如下所示:

1             S0 : begin
2                 case(s)
3                     3'b000 : next_state = S0;
4                     3'b001 : next_state = S1;
5                     3'b011 : next_state = S2;
6                     3'b111 : next_state = S3;
7                     default: next_state = S0;
8                 endcase                
9             end

第二个原题目中没有交代清楚的问题:题目中之说了如果之前水位低于当前水位,为正常水流(即dfr不用打开),如果之前水位大于当前水位,则需要打开dfr。没有说当之前水位与当前水位相同时怎么处理dfr。导致自己这个地方一直出错,最后观察作者的测试波形,才发现作者的愿意是这种情况dfr保持之前的值。这个地方挺坑爹的。

最后代码如下:

 1 module top_module (
 2     input clk,
 3     input reset,
 4     input [3:1] s,
 5     output fr3,
 6     output fr2,
 7     output fr1,
 8     output dfr
 9 ); 
10 
11     parameter [1:0] S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
12     reg       [1:0] current_state, next_state, last_state;
13 
14     always @(posedge clk) begin
15         if(reset) begin
16             current_state <= S0;
17             last_state    <= S0;
18         end
19         else begin
20             current_state <= next_state;
21             last_state    <= current_state;
22         end
23     end
24     
25     always @(*) begin
26         case(current_state)
27             S0 : begin
28                 case(s)
29                     3'b000 : next_state = S0;
30                     3'b001 : next_state = S1;
31                     3'b011 : next_state = S2;
32                     3'b111 : next_state = S3;
33                     default: next_state = S0;
34                 endcase                
35             end
36             S1 : begin
37                 case(s)
38                     3'b000 : next_state = S0;
39                     3'b001 : next_state = S1;
40                     3'b011 : next_state = S2;
41                     3'b111 : next_state = S3;
42                     default: next_state = S0;
43                 endcase                
44             end
45             S2 : begin
46                 case(s)
47                     3'b000 : next_state = S0;
48                     3'b001 : next_state = S1;
49                     3'b011 : next_state = S2;
50                     3'b111 : next_state = S3;
51                     default: next_state = S0;
52                 endcase                
53             end
54             S3 : begin
55                 case(s)
56                     3'b000 : next_state = S0;
57                     3'b001 : next_state = S1;
58                     3'b011 : next_state = S2;
59                     3'b111 : next_state = S3;
60                     default: next_state = S0;
61                 endcase                
62             end
63             default: next_state = S0;
64         endcase       
65     end
66     
67     always @(*) begin
68         case(current_state)
69             S0 : {fr3,fr2,fr1} = 3'b111;
70             S1 : {fr3,fr2,fr1} = 3'b011;
71             S2 : {fr3,fr2,fr1} = 3'b001;
72             S3 : {fr3,fr2,fr1} = 3'b000;
73             default: {fr3,fr2,fr1} = 3'b111;
74         endcase
75     end
76     //assign fr3 = (current_state == S0);
77     //assign fr2 = (current_state == S0) || (current_state == S1);
78     //assign fr1 = (current_state == S0) || (current_state == S1) || (current_state == S2);
79     
80     always @(*) begin
81         if(current_state == S0)
82             dfr = 1'b1;
83         else if(last_state > current_state)
84             dfr = 1'b1;
85         else if(last_state < current_state)
86             dfr = 1'b0;
87         else
88             dfr = dfr;   //will generate latch        
89     end
90     
91 endmodule

 原作者的非常简洁。主要区别在于自己的写法是以水位的状态为状态机的各种状态。这个状态机相对简单,但是dfr的情况无法在状态机中体现(即没有考虑水位从高到底的情况下dfr的值)。原作者通过细分状态的方式,简化了dfr的verilog代码逻辑。非常漂亮。原作者代码如下:

 1 module top_module (
 2     input clk,
 3     input reset,
 4     input [3:1] s,
 5     output reg fr3,
 6     output reg fr2,
 7     output reg fr1,
 8     output reg dfr
 9 );
10 
11 
12     // Give state names and assignments. I'm lazy, so I like to use decimal numbers.
13     // It doesn't really matter what assignment is used, as long as they're unique.
14     // We have 6 states here.
15     parameter A2=0, B1=1, B2=2, C1=3, C2=4, D1=5;
16     reg [2:0] state, next;        // Make sure these are big enough to hold the state encodings.
17     
18 
19 
20     // Edge-triggered always block (DFFs) for state flip-flops. Synchronous reset.    
21     always @(posedge clk) begin
22         if (reset) state <= A2;
23         else state <= next;
24     end
25 
26 
27 
28     // Combinational always block for state transition logic. Given the current state and inputs,
29     // what should be next state be?
30     // Combinational always block: Use blocking assignments.    
31     always@(*) begin
32         case (state)
33             A2: next = s[1] ? B1 : A2;
34             B1: next = s[2] ? C1 : (s[1] ? B1 : A2);
35             B2: next = s[2] ? C1 : (s[1] ? B2 : A2);
36             C1: next = s[3] ? D1 : (s[2] ? C1 : B2);
37             C2: next = s[3] ? D1 : (s[2] ? C2 : B2);
38             D1: next = s[3] ? D1 : C2;
39             default: next = 'x;
40         endcase
41     end
42     
43     
44     
45     // Combinational output logic. In this problem, a procedural block (combinational always block) 
46     // is more convenient. Be careful not to create a latch.
47     always@(*) begin
48         case (state)
49             A2: {fr3, fr2, fr1, dfr} = 4'b1111;
50             B1: {fr3, fr2, fr1, dfr} = 4'b0110;
51             B2: {fr3, fr2, fr1, dfr} = 4'b0111;
52             C1: {fr3, fr2, fr1, dfr} = 4'b0010;
53             C2: {fr3, fr2, fr1, dfr} = 4'b0011;
54             D1: {fr3, fr2, fr1, dfr} = 4'b0000;
55             default: {fr3, fr2, fr1, dfr} = 'x;
56         endcase
57     end
58     
59 endmodule

 状态图的s1s2s3排列方式不好,如果改为S3S2S1会更符合习惯。

posted on 2021-04-17 11:37  国静德远  阅读(1030)  评论(0编辑  收藏  举报

导航