【 FPGA 】序列检测器的Moore状态机实现

举报
李锐博恩 发表于 2021/07/15 04:43:02 2021/07/15
【摘要】 设计一个序列检测器,检测序列1101,检测到输出1,否则输出0. 用状态机来实现序列检测器是非常合适的,下面先给出状态转移图,之后用Moore状态机来实现这个序列检测器: (注:此处所画为无重叠检测,有重叠检测只需要改变最后一个状态即可,例如本例里,有重叠检测,如果S4状态下输入为1,则需要转向S2状态,其他不变。) 图1:Moore状态机状态转移图 先给出行为仿...

设计一个序列检测器,检测序列1101,检测到输出1,否则输出0.

用状态机来实现序列检测器是非常合适的,下面先给出状态转移图,之后用Moore状态机来实现这个序列检测器:

(注:此处所画为无重叠检测,有重叠检测只需要改变最后一个状态即可,例如本例里,有重叠检测,如果S4状态下输入为1,则需要转向S2状态,其他不变。)

图1:Moore状态机状态转移图

先给出行为仿真示意图,示例代码后面贴出:

可见,每经历一个1101,输出就会是一个高脉冲,持续一个周期,也即输出是一个1.

该状态机的Verilog HDL描述为:


  
  1. `timescale 1ns / 1ps
  2. // Company:
  3. // Engineer:
  4. //
  5. // Create Date: 2019/01/04 11:16:29
  6. // Design Name:
  7. // Module Name: seq_det_moore
  8. // Project Name:
  9. // Target Devices:
  10. // Tool Versions:
  11. // Description:
  12. //
  13. // Dependencies:
  14. //
  15. // Revision:
  16. // Revision 0.01 - File Created
  17. // Additional Comments:
  18. //
  19. module seq_det_moore(
  20. input clk,
  21. input reset,
  22. input din,
  23. output reg dout
  24. );
  25. //状态声明
  26. localparam [2:0]
  27. s0 = 3'b000,
  28. s1 = 3'b001,
  29. s2 = 3'b010,
  30. s3 = 3'b011,
  31. s4 = 3'b100;
  32. reg [2:0] current_state,next_state;
  33. always @(posedge clk, posedge reset)
  34. begin
  35. if(reset)
  36. current_state <= s0;
  37. else
  38. current_state <= next_state;
  39. end
  40. always @ *
  41. begin
  42. case(current_state)
  43. s0:
  44. if(din == 1'b1) next_state = s1;
  45. else next_state = s0;
  46. s1:
  47. if(din == 1'b1) next_state = s2;
  48. else next_state = s0;
  49. s2:
  50. if(din == 1'b0) next_state = s3;
  51. else next_state = s2;
  52. s3:
  53. if(din == 1'b1) next_state = s4;
  54. else next_state = s0;
  55. s4:
  56. if(din == 1'b1) next_state = s1;
  57. else next_state = s0;
  58. default: next_state = s0;
  59. endcase
  60. end
  61. always @*
  62. begin
  63. if(current_state == s4) dout = 1;
  64. else dout = 0;
  65. end
  66. endmodule

RTL电路:

行为仿真代码:


  
  1. `timescale 1ns / 1ps
  2. // Company:
  3. // Engineer:
  4. //
  5. // Create Date: 2019/01/04 15:24:59
  6. // Design Name:
  7. // Module Name: seq_det_moore_tb
  8. // Project Name:
  9. // Target Devices:
  10. // Tool Versions:
  11. // Description:
  12. //
  13. // Dependencies:
  14. //
  15. // Revision:
  16. // Revision 0.01 - File Created
  17. // Additional Comments:
  18. //
  19. module seq_det_moore_tb;
  20. reg clk,reset;
  21. reg din;
  22. wire dout;
  23. reg [20:0] din_mid;
  24. integer i;
  25. // Note: CLK must be defined as a reg when using this method
  26. parameter PERIOD = 10;
  27. always begin
  28. clk = 1'b0;
  29. #(PERIOD/2) clk = 1'b1;
  30. #(PERIOD/2);
  31. end
  32. initial begin
  33. reset = 1'b1;
  34. din_mid = 21'b110111010110100101101;
  35. # 20
  36. reset = 1'b0;
  37. din = 1'b0;
  38. for(i = 0;i < 21;i = i + 1)
  39. begin
  40. #PERIOD
  41. din = din_mid[i];
  42. end
  43. end
  44. seq_det_moore uu1(.clk(clk),.reset(reset),.din(din),.dout(dout));
  45. endmodule

编写这个简单的程序,并非毫无意义的,包括这个Testbench文件,自己动手编写往往能发现一些小的细节问题,你可能并不懂,例如,在测试文件(testbench)中,我使用到了for循环,出现了如下问题,首先我尝试使用了generate for循环语法,可是Vivado软件总是报错!!!

之后,我直接使用for循环,可是变量i的类型是什么呢?

reg,real都不对,最后使用了integer才成功,这说明了什么问题,当然是基础知识不牢固导致的,基础知识为什么不牢固,往往是因为练习的不多,语法书读的次数再多,往往很枯燥无味,问题还是需要在实践中去寻找,Verilog语言很类似C,这导致我们往往很不情愿去仔仔细细地去学,稍微关注些可综合的语法,之后拿来就用。至今我仍不愿意去细看所有的语法。解决的办法就是实践。

第二个问题就是在测试文件中,定义了参数parameter PERIOD,可是后面为什么不能对此参数进行运算呢?例如我想延时2 * PERIOD,Vivado仍然报错。让我郁闷!

上述这些问题都出现在我的初次表写测试文件的代码中,这里给出错误的初稿代码:(供大家发现问题)


  
  1. `timescale 1ns / 1ps
  2. // Company:
  3. // Engineer:
  4. //
  5. // Create Date: 2019/01/04 15:24:59
  6. // Design Name:
  7. // Module Name: seq_det_moore_tb
  8. // Project Name:
  9. // Target Devices:
  10. // Tool Versions:
  11. // Description:
  12. //
  13. // Dependencies:
  14. //
  15. // Revision:
  16. // Revision 0.01 - File Created
  17. // Additional Comments:
  18. //
  19. module seq_det_moore_tb;
  20. reg clk,reset;
  21. reg din;
  22. wire dout;
  23. reg [20:0] din_mid;
  24. // Note: CLK must be defined as a reg when using this method
  25. parameter PERIOD = 10;
  26. always begin
  27. clk = 1'b0;
  28. #(PERIOD/2) clk = 1'b1;
  29. #(PERIOD/2);
  30. end
  31. initial begin
  32. reset = 1'b1;
  33. din_mid = 21'b110111010110100101101;
  34. #2*PERIOD
  35. reset = 1'b0;
  36. generate
  37. genvar i;
  38. for(i = 0;i < 21;i ++)
  39. begin
  40. #PERIOD
  41. din = din_mid[i];
  42. end
  43. endgenerate
  44. end
  45. seq_det_moore uu1(.clk(clk),.reset(reset),.din(din),.dout(dout));
  46. endmodule

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/85763185

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。