FPGA基础——序列识别器(FSM)

(1)

我们想要创建一个计时器:

  1. 在检测到特定模式(1101)时启动,
  2. 再移动4位来确定延迟时间,
  3. 等计数器数完,然后
  4. 通知用户并等待用户确认计时器。

在这个问题中,只实现控制计时器的有限状态机。这里不包括数据路径(计数器和一些比较器)。

 

串行数据在数据输入引脚上可用。当接收到模式1101时,状态机必须断言输出shift_ena为4个时钟周期。

 

在此之后,状态机将断言其计数输出,以表明它正在等待计数器,并等待输入done_count达到最大值。

 

此时,状态机必须断言done,以通知用户计时器超时,并等待直到输入ack为1,然后重置,以寻找下一个启动序列(1101)的出现。

 

状态机应该重新设置为开始搜索输入序列1101的状态。

 

下面是预期输入和输出的示例。“x”状态可能会让人读起来有点困惑。它们表明FSM不应该关心这个周期中特定的输入信号。例如,一旦检测到1101模式,FSM就不再查看输入的数据,直到它在其他所有事情都完成之后继续搜索。

其状态转移图如下:

 

 

 1 module top_module (
 2     input clk,
 3     input reset,      // Synchronous reset
 4     input data,
 5     output shift_ena,
 6     output counting,
 7     input done_counting,
 8     output done,
 9     input ack );
10     parameter S=4'd0,S1=4'd1,S11=4'd2,S110=4'd3;
11     parameter B0=4'd4,B1=4'd5,B2=4'd6,B3=4'd7;
12     parameter Count=4'd8,Wait=4'd9;
13     reg [3:0] state,next;
14     
15     always@(posedge clk)
16         if(reset)
17             state <= S;
18         else
19             state <= next;
20     
21     always@(*)begin
22         case(state)
23             S:
24                 next <= data?S1:S;
25             S1:
26                 next <= data?S11:S;
27             S11:
28                 next <= data?S11:S110;
29             S110:
30                 next <= data?B0:S;
31             B0:
32                 next <= B1;
33             B1:
34                 next <= B2;
35             B2:
36                 next <= B3;
37             B3:
38                 next <= Count;
39             Count:
40                 next <= done_counting?Wait:Count;
41             Wait:
42                 next <= ack?S:Wait;
43             default:
44                 next <= S;
45         endcase
46     end
47     
48     assign shift_ena = (state==B0 || state==B1 || state==B2 || state==B3);
49     assign counting = state==Count;
50     assign done = state==Wait;   
51     
52 endmodule

 (2)

串行数据在数据输入引脚上可用。当模式1101被接收时,电路必须在接下来的4位中移位,最有效位先移位。这4位决定定时器延迟的持续时间。我把这称为延迟[3:0]。

在此之后,状态机将断言其计数输出,以表明它正在计数。状态机必须精确计算(delay[3:0] + 1) * 1000个时钟周期。例如,delay=0表示计数1000个周期,delay=5表示计数6000个周期。也输出当前剩余时间。这应该等于延迟1000个循环,然后延迟-1为1000个循环,以此类推,直到它为0为1000个循环。当电路不计数时,count[3:0]输出是不关心的(任何值方便你实现)。

在这一点上,电路必须断言done以通知用户计时器超时,并等待直到输入ack为1才被重置,以寻找下一个开始序列(1101)的出现。

电路应复位到开始寻找输入序列1101的状态。

下面是预期输入和输出的示例。“x”状态可能会让人读起来有点困惑。它们表明FSM不应该关心这个周期中特定的输入信号。例如,一旦1101和delay[3:0]被读取,电路就不再查看输入的数据,直到它在其他所有事情都完成之后恢复搜索。在这个例子中,电路计数2000个时钟周期,因为延迟[3:0]值是4'b0001。最后几个周期开始另一个计数,延时[3:0]= 4'b1110,计数为15000个周期。

 

 

  1 module top_module (
  2     input clk,
  3     input reset,      // Synchronous reset
  4     input data,
  5     output [3:0] count,
  6     output counting,
  7     output done,
  8     input ack );
  9     
 10     parameter S=4'd0,S1=4'd1,S11=4'd2,S110=4'd3;
 11     parameter B0=4'd4,B1=4'd5,B2=4'd6,B3=4'd7;
 12     parameter Count=4'd8,Wait=4'd9;
 13     reg [3:0] state,next;
 14     reg [3:0] delay;
 15     reg [3:0] a;
 16     reg [15:0]    counter;
 17     wire done_counting;
 18     
 19     always@(posedge clk)
 20         if(reset)
 21             state <= S;
 22         else
 23             state <= next;
 24     
 25     always@(posedge clk)
 26         if(reset)
 27             counter <= 0;
 28         else if(next==Wait)
 29             counter <= 0;
 30            else if(next==Count)
 31             counter <= counter+1'b1;
 32     
 33     always@(*)begin
 34         if(counter <= 1000)begin
 35             a = 4'd0;
 36         end
 37         else if(counter > 1000 && counter <= 2000)begin
 38             a = 4'd1;
 39         end
 40         else if(counter > 2000 && counter <= 3000)begin
 41             a = 4'd2;
 42         end
 43         else if(counter > 3000 && counter <= 4000)begin
 44             a = 4'd3;
 45         end
 46         else if(counter > 4000 && counter <= 5000)begin
 47             a = 4'd4;
 48         end
 49         else if(counter > 5000 && counter <= 6000)begin
 50             a = 4'd5;
 51         end
 52         else if(counter > 6000 && counter <= 7000)begin
 53             a = 4'd6;
 54         end
 55         else if(counter > 7000 && counter <= 8000)begin
 56             a = 4'd7;
 57         end
 58         else if(counter > 8000 && counter <= 9000)begin
 59             a = 4'd8;
 60         end
 61         else if(counter > 9000 && counter <= 10000)begin
 62             a = 4'd9;
 63         end
 64         else if(counter > 10000 && counter <= 11000)begin
 65             a = 4'd10;
 66         end
 67         else if(counter > 11000 && counter <= 12000)begin
 68             a = 4'd11;
 69         end
 70         else if(counter > 12000 && counter <= 13000)begin
 71             a = 4'd12;
 72         end
 73         else if(counter > 13000 && counter <= 14000)begin
 74             a = 4'd13;
 75         end
 76         else if(counter > 14000 && counter <= 15000)begin
 77             a = 4'd14;
 78         end
 79         else begin
 80             a = 4'd15;
 81         end
 82     end 
 83     
 84     always@(*)begin
 85         case(state)
 86             S:
 87                 next <= data?S1:S;
 88             S1:
 89                 next <= data?S11:S;
 90             S11:
 91                 next <= data?S11:S110;
 92             S110:
 93                 next <= data?B0:S;
 94             B0:begin
 95                 next <= B1;
 96                 delay[3] <= data;
 97             end
 98             B1:begin
 99                 next <= B2;
100                 delay[2] <= data;
101             end
102             B2:begin
103                 next <= B3;
104                 delay[1] <= data;
105             end
106             B3:begin
107                 next <= Count;
108                 delay[0] <= data;
109             end
110             Count:
111                 next <= done_counting?Wait:Count;
112             Wait:
113                 next <= ack?S:Wait;
114             default:
115                 next <= S;
116         endcase
117     end
118     
119     assign done_counting = (counter==(delay+1)*1000)?1'b1:1'b0;
120     assign count = (state == Count) ? delay-a : 0;
121     assign counting = state==Count;
122     assign done = state==Wait;   
123     
124 endmodule

 

posted on 2021-04-21 17:05  一曲挽歌  阅读(723)  评论(0编辑  收藏  举报

导航