Verilog的序列信号检测器实现及其testbench仿真

  终于迈向了testbench的学习,第一个就拿简单的练练手,没想这都遇到了好几个问题,在一番折腾下,终于把问题调试完毕,趁热乎过来写下本人的第一篇博客。。序列信号检测器对串行输出进行检测,如果检测到连续的1001,则输出1,否则输出0。

  程序采用两段式状态机写法。两段式状态机即:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移,另外一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出。状态机编码方式采用独热码方式,《Verilog数字系统设计与FPGA应用》【赵倩、林丽萍】一书中说:“CPLD器件更多地提供组合逻辑资源,而FPGA器件更多的提供触发器资源,所以对于CPLD的数字系统设计多使用格雷码编码,而基于FPGA的数字系统设计多使用独热码编码。”代码如下:

  Detected_1001.v

 1 module Detected_1001(Data_in,Clock,Reset,Detected);
 2 
 3 input Data_in,Clock,Reset;
 4 output Detected;
 5 reg Detected;
 6 reg [4:0]state;
 7 parameter s0=5'b10000,
 8           s1=5'b01000,
 9           s2=5'b00100,
10           s3=5'b00010,
11           s4=5'b00001;
12 always@(state)
13 begin
14 case(state)
15 s0:
16   Detected=1'b0;
17 s1:
18   Detected=1'b0;
19 s2:
20   Detected=1'b0;
21 s3:
22   Detected=1'b0;
23 s4:
24   Detected=1'b1;
25   
26 default:Detected=1'b0;
27 endcase
28 end
29 /*assign Detected=(state==s4)?1:0;*/
30 always@(posedge Clock or negedge Reset)
31 begin
32 if(!Reset)
33   begin
34   state<=s0;
35   end
36 else
37   case(state)
38     s0:if(Data_in==1'b0)state<=s0;
39        else state<=s1;
40        
41     s1:if(Data_in==1'b0)state<=s2;
42        else state<=s0;
43        
44     s2:if(Data_in==1'b0)state<=s3;
45        else state<=s0;
46        
47     s3:if(Data_in==1'b0)state<=s0;
48        else state<=s4;
49        
50     s4:if(Data_in==1'b0)state<=s0;
51        else state<=s1;
52     
53     default:state<=s0;
54   endcase
55   end
56 endmodule
View Code

   Detected_1001_tb.v

 1 `timescale 1ns/1ps
 2 module Detected_1001_tb;
 3 reg Clock,Reset,Data_in;
 4 wire Detected;
 5 reg [4:0] i;
 6 parameter sequence=18'b001_00100100_1101001;
 7 
 8 Detected_1001 U(
 9 .Clock(Clock),
10 .Reset(Reset),
11 .Data_in(Data_in),
12 .Detected(Detected)
13 );
14 
15 initial 
16 begin
17   i=0;Data_in=0;
18   Reset=0;Clock=0; #4 Reset=1;#4 Clock=0;
19   forever #2 Clock=~Clock;
20 end
21 
22 always@(posedge Clock or negedge Reset)
23 begin
24   if(~Reset)
25     begin
26     i<=5'b0;
27     end
28   else if(i<=5'd17)
29     begin
30       Data_in<=sequence[i];
31       i<=i+5'd1;
32     end
33   else
34     i<=5'b0;
35 end    
36 
37 endmodule    
38         
39   
View Code

  仿真波形:

  过程中遇到的问题及解决方法:

  1、输出Detected始终为0。

  解决方法及出现原因:在Detected_1001.v中对时钟沿的检测处,改错之前是always@(Clock),指生成组合逻辑电路,改正为always@(posedge Clock)后错误消除,指触发器的状态仅在时钟上升沿或下降沿发生跳变的同步时序逻辑电路。

  2、输出Detected初始状态不定。

  解决方法及出现原因:Detected_1001.v中对时钟沿的检测处,改错之前是always@(posedge Clock),改错后为always@(posedge Clock or negedge Reset),在Reset里把初始状态设置为s0,而一开始在测试文件里Clock是保持0值的,因此此条always语句未动作,所以Detected出现不定状态。

  3、高电平出现时刻分析:

  以时间点的概念来理解。在T4时刻,状态机模块检测到的输入是T4时刻以前的值,即Data_in=0,故在T4的将来时刻,state决定跳转到状态s3,也即Detected=0。同样的道理,在T5时刻,状态机模块检测到的输入是T5时刻以前的值,即Data_in=1,故在T5的将来时刻,state决定跳转到状态s4,也即Detected=1。

  (详细说来:该实验当中,TB作为激励给.v文件Data_in输入。当上升沿来临时,TB赋值给Data_in,同一时刻的上升沿状态机对Data_in的值进行判断,但是判断的是此时刻以前的值。这就是为什么检测输出要比Data_in的赋值完成慢一拍的原因。)

  

原文地址:https://www.cnblogs.com/fkl523/p/3405402.html