介绍
-
目的:在数据流中检测出一定的序列;
此处数据流在.vt文件中给data,通过移位来一个个赋值给x;例化.v文件,把x传给.v文件,在.v文件中编写二段式状态机转移程序,检测有无序列10010
-
波形图示例
新用到Timegen软件画波形;
评价:波形确实好画,还可以画时序图,就是标0101有点麻烦,不好操作。
示例中out的第二个脉冲就是容易漏掉的地方
转移图
序列检测器一开始看到很容易出错(对于我而言吧):会漏掉一些情况,如转移图中红色、黑色部分。仔细多想
程序
它的程序还是很简单,就是几个状态的切换(前提是转移图画对了~ )发现这个时候转移图真好用(真香~)
这里用的是二段式状态机
- SequenceDetector.v
module SequenceDetector ( input clk, input rst, input x, output reg z ); reg [2:0] state; reg [2:0] next_state; parameter IDLE =3'd0; parameter A =3'd1; parameter B =3'd2; parameter C =3'd3; parameter D =3'd4; parameter E =3'd5; always @(posedge clk or posedge rst) begin if(rst) state <= IDLE; else state <= next_state; end always @(*) begin case(state) IDLE: begin if(x) begin next_state = A; z = 1'd0; end else begin next_state= IDLE; z = 1'd0; end end A: begin if(x) begin next_state = A; z = 1'd0; end else begin next_state= B; z = 1'd0; end end B: begin if(x) begin next_state = A; z = 1'd0; end else begin next_state= C; z = 1'd0; end end C: begin if(x) begin next_state = D; z = 1'd0; end else begin next_state= IDLE; z = 1'd0; end end D: begin if(x) begin next_state = A; z = 1'd0; end else begin next_state= E; z = 1'd1; end end E: begin if(x) begin next_state = A; z = 1'd0; end else begin next_state= C; z = 1'd0; end end default: begin next_state= IDLE; z = 1'd0; end endcase end endmodule
仿真信号
- SequenceDetector.vt
球球你别写testbench时忘了分号了~自动仿真又检测不出来,波形出不来还一直等哈哈
`timescale 1 ns/ 1 ns module SequenceDetector_vlg_tst(); reg clk; reg rst; reg x; wire z; reg [23:0] data; SequenceDetector i1 ( .clk(clk), .rst(rst), .x(x), .z(z) ); initial begin #0 clk = 1'b0; #0 rst = 1'b0; #3 rst = 1'b1; #3 rst = 1'b0; #1 data = 24'b1100_1001_0000_1001_1100_1001;//一开始多打了一位 $display("Running testbench"); end always #10 begin clk = ~clk; end always @(posedge clk) begin data <= data<<1; x <= data[23]; end endmodule
- 仿真结果
- 几点注意
1. 写的是clk上升沿进行data的移位,所以别被那些长长短短的波形弄糊涂,看沿处;
2. 其实这里x的变化是比data[23]慢一个clk的:在always中进行非阻塞赋值,所以此always完后x赋值的是上一个data[23],而当前data[23]实际上等于data[22]
重点补充
-
之前说到.v的input(默认为input wire)在.vt中必须要为reg(1),其实不是这样的,只是说一般这样用,这样用没问题。
(1)法.vt 的x输出是有锁存的,而(2)法是没有的;
从使用的理解上,(1)法更清晰(因为我也没理解(2)法的原理哈哈)
1. 这里对.vt 修改,如下:.v的input(默认为input wire)在.vt 中用wire(2)wire x; assign x = data[23];//assign赋值左边必须得为wire型 always @(posedge clk) begin data <= data<<1; end
2. 波形
且assign是阻塞赋值,data一边输出x就会改变,不会慢一个clk
注意这里看波形图:由于写initial时里面的延时是随便设置的,所以这里x的第一个“1”码时间很短,但不是没有;