序列检测器的逻辑功能:
序列检测是将一个指定的序列从数字码流中识别出来。本项目要检测的序列是:10010。
设X是“数字码流的输入”,Z是“检出标记输出”;高电平是“实现指定序列”;低电平是“没有发现指定序列”。码流如下表所示。
由上述码流可知:该序列检测器可实现重复性检测,由此可得如下状态转移图,如图1所示:
结合表1码流序列和图1状态转换,可编写如下RTL代码
//
// 可检测重复的序列
module seqdet(
input i_clk,
input x,
input i_rst,
output z,
output reg [7:0] state
);
// 独热码来做参数
parameter IDLE = 8'b0000_0001; // 1, 1
parameter A = 8'b0000_0010; // 2, 2
parameter B = 8'b0000_0100; // 3, 4
parameter C = 8'b0000_1000; // 4, 8
parameter D = 8'b0001_0000; // 5, 16
parameter E = 8'b0010_0000; // 6, 32
parameter F = 8'b0100_0000; // 7, 64
parameter G = 8'b1000_0000; // 8, 128
assign z = (state==D && x==0) ? 1 : 0;
// 当x序列 10010 最后一个 0刚到时刻,时钟沿立刻将状态变为E,此时z应该变为高
// assign z = (state == E) ? 1 : 0;
// 当完成 "10010" 状态的检测,即输出1.
always@(posedge i_clk or negedge i_rst) begin
if(!i_rst)
state <= IDLE;
else
case(state)
IDLE: if(x == 1) // 下
state <= A;
else
state <= IDLE;
A: if(x == 0) // 下
state <= B;
else
state <= A;
B: if(x == 0) // 下
state <= C;
else
state <= F;
C: if(x == 1) // 下
state <= D;
else
state <= G;
D: if(x == 0) // 输出
state <= E;
else
state <= A;
E: if(x == 0)
state <= C;
else
state <= A;
F: if(x == 1)
state <= A;
else
state <= B;
G: if(x == 1)
state <= F;
else
state <= G;
default:
state <= IDLE;
endcase
end
endmodule
// 测试模块
module tb_seqdet;
// `define halfperiod 20 宏定义
// 注意",宏定义的位置放哪都行。
reg i_clk, i_rst;
reg [23:0] data;
wire [7:0] state;
wire z, x;
assign x = data[23];
always #10 i_clk = ~i_clk;
always@(posedge i_clk)
data <= {data[22:0], data[23]};
// 形成数据向左移环形流,最高位与x连接
initial begin
i_clk = 1; i_rst = 1;
#2; i_rst = 0;
#30; i_rst = 1;
data = 24'b0000_1100_1001_0000_1001_0100;
#480; $stop;
end
seqdet u1_seqdet(
.i_clk (i_clk ),
.i_rst (i_rst ),
.x (x ),
.z (z ),
.state (state )
);
endmodule
从波形中可看出,程序代码正确地完成了所要设计的逻辑功能。另外,seqdet.v的编写采用了可综合的Verilog HDL风格,它可以把通过综合器的综合转换为FPGA或ASIC网表,再通过布局布线工具在FPGA或ASIC上实现。