FPGA 序列检测器(上篇)—— 使用摩尔状态机实现
前几天参加了一场面试,选择题净是关于实际开发的关键知识,对于没有项目经验的我而言,完全不知所云。在看不到成功的希望的同时,最后的序列检测本应该是手到擒拿,结果以翻车结束。这里吃一堑长一智,避免下次出现类似的悲剧。
题目是检测序列 11001,使用三段时状态机:
这里约定以下信号,
- 时钟 clk
- 复位(低电平有效) rst_n
- 数据输入 dat_in
- 检测结果输出(检测到了就置位) check
- 启动信号 go
这里约定使用摩尔状态机,米里机的在下一章:
检测方式,遇到这样包含重复序列的信号的话就直接忽略后面的序列(xxxx110011001xxx)
首先是检测表(姑且就这么叫吧),数学上叫二叉树、二叉表,但是我呢,比较任性。
Start |
|||||||||||||||||||||||||||||||
0 |
1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00 |
01 |
10 |
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
000 |
001 |
010 |
011 |
100 |
101 |
110 |
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0000 |
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
1101 |
1110 |
1111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00000 |
00001 |
00010 |
00011 |
00100 |
00101 |
00110 |
00111 |
01000 |
01001 |
01010 |
01011 |
01100 |
01101 |
01110 |
01111 |
10000 |
10001 |
10010 |
10011 |
10100 |
10101 |
10110 |
10111 |
11000 |
11001 |
11010 |
11011 |
11100 |
11101 |
11110 |
11111 |
这个表很重要,它展示了信息分类的结果,每一步都只有两个选择,在表中红色的表示正确的序列,黄色的表示还可以继续检测的序列,而黑色的表示必须回到开始的序列。
在这个表中,存在很多判断结构,比如第四行第八列的值为 111,它包含两个正确的 11,状态机应该回到上一步。
这里约定状态
Start: 初始状态,go 信号置位,进入状态 S0
S0: 有零个正确值 ,
S1: 有一个正确值 11
S2: 有两个正确值 11
S3: 有三个正确值 110
S4: 有四个正确值 1100
S5: 有五个正确值 11001
状态转移图如下:
状态机的输出就比较简单了,摩尔机的输出只与现态有关:
仅仅状态 S5 的时候输出 1,其他情况输出 0。
Word 写文件多好,面试非要用笔,本来期望答案写的像小学语文作业,结果弄的像医生的处方一样。
开始经典的三段式状态机:
代码如下:
仿真结果如下:
时序报告:
可以看到,这个三段式状态机大概能跑 730MHz,似乎速度还不错。
较高的速度也拜良好的编码习惯所赐。
下一章描述米里状态机。毕竟知识也需要经常温习,避免忘记。