1.序列检测器
序列检测器是时序数字电路中非常常见的设计之一。它的逻辑功能是将一个指定的序列从数字码流中识别出来。
2.例1:"10010"序列检测器
对串行输入的数据进行检测,检测“10010”。设X为数字码流输入,Z为检出标记输出,高电平表示“发现指定序列”,低电平表示“没有发现指定序列”。考虑码流为“1100100100001001001…"则如下表所列
时钟 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
X | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
Z | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
状态转移图如下:
设计代码:
module seqdet(
clk,
rst,
x,
z
);
input clk;
input rst;
input x;
output z;
reg [2:0] state,next;
parameter IDLE=1'b0,s0=1, s1=2,s2=3,s3=4,s4=5;
always@(posedge clk) begin
if(!rst)
state<=IDLE;
else
state<=next;
end
always @(*) begin
case(state)
IDLE:next=x?s0:IDLE;
s0:next=x?s0:s1;
s1:next=x?s0:s2;
s2:next=x?s3:IDLE;
s3:next=x?s0:s4;
s4:next=x?s0:s2;
endcase
end
assign z=(next==s4);
endmodule
testbench:
`timescale 1ns/1ns
module seqbet_tb;
reg clk,rst;
reg [23:0]data;
wire z,x;
assign x=data[23];
initial begin
clk=0;
rst=1;
#2 rst=0;
#30 rst=1;
data=24'b1100_1001_0000_1001_0100;
#500 $stop;
end
always #10 clk=~clk;
always@(posedge clk) begin
data={data[22:0],data[23]};
end
seqdet m1(
clk,
rst,
x,
z
);
endmodule
仿真波形:
3.例2:“1111”序列检测器
对串行数据进行检测,检测到连续4个1 、5个1、6个1Z输出为高电平,连续7个或者7个以以上报错,即ERRO输出高电平。
状态转移图:
设计代码:
module seqbet_1(
clk,
rst_n,
x,
z,
ERRO
);
input clk;
input rst_n;
input x;
output z;
output ERRO;
reg[7:0] state,next;
parameter IDLE=8'b00000001, s0=8'b00000010,s1=8'b00000100,
s2=8'b00001000,s3=8'b00010000,s4=8'b00100000,
s5=8'b01000000,err=8'b10000000;
always@(posedge clk) begin
if(!rst_n)
state<=IDLE;
else
state<=next;
end
always@(*) begin
case(state)
IDLE:next=x?s0:IDLE;
s0:next=x?s1:IDLE;
s1:next=x?s2:IDLE;
s2:next=x?s3:IDLE;
s3:next=x?s4:IDLE;
s4:next=x?s5:IDLE;
s5:next=x?err:IDLE;
err:next=x?err:IDLE;
endcase
end
assign z=(state==s3|state==s4|state==s5);
assign ERRO=(state==err);
endmodule
testbench:
`timescale 1ns/1ns
module seqbet_1_tb;
reg clk,rst_n;
reg [24:0]data;
wire z,x,ERRO;
assign x=data[24];
initial begin
clk=0;
rst_n=1;
#2 rst_n=0;
#30 rst_n=1;
data=25'b1100_1111_0011_1111_11111;
#1000 $stop;
end
always #10 clk=~clk;
always@(posedge clk) begin
data={data[23:0],data[24]};
end
seqbet_1 m1(
.clk(clk),
.rst_n(rst_n),
.x(x),
.z(z),
.ERRO(ERRO)
);
endmodule
仿真波形: