FPGA基础——序列识别器(FSM)
(1)
我们想要创建一个计时器:
- 在检测到特定模式(1101)时启动,
- 再移动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