检测输入的数据是否是连续的3个8'h23。
一、问题
检测输入的数据是否是连续的3个8’h23(在成功检测3个之后重新开始计数)
二、思路
1、使用计数器,在reset的情况下计数器的默认值是1。
2、如果成功检测到frame_i信号并且data_i等于8‘h23时计数器加1,否则计数器的值保持默认值1。
3、如果成功检测到frame_i信号并且data_i等于8‘h23时计数器再加1,否则计数器的值变成默认值1。
4、按照步骤3继续检测,待计数器的值等于3,frame_i信号有效并且data_i的值为8’h23是输出一个pulse。
5、计数器的值又变成1,重新开始检测。
三、代码如下
module frame
#(
parameter DATA_WIDTH = 8,
parameter COUNTER_NUM = 3,
parameter DATA_VALUE = 8'h23
)
(
input clk_i ,
input rst_n_i ,
input frame_i ,
input [DATA_WIDTH-1:0] data_i ,
output logic flag_o
);
logic [$clog2(COUNTER_NUM)-1:0] cnt_r;
always_ff @(posedge clk_i or negedge rst_n_i) begin
if(!rst_n_i) begin
cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
end
else if(cnt_r >= COUNTER_NUM && frame_i && data_i == DATA_VALUE) begin
cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
end
else if(frame_i) begin
if(data_i == DATA_VALUE) begin
cnt_r <= cnt_r + 1'b1;
end
else begin
cnt_r <= {{($clog2(COUNTER_NUM)-1){1'b0}},1'b1};
end
end
end
assign flag_o = (cnt_r == COUNTER_NUM) && frame_i && (data_i == DATA_VALUE);
//**********************************************************************
//Assertion
//**********************************************************************
property check_flag;
@(posedge clk_i)
disable iff(!rst_n_i)
flag_o |-> (data_i == DATA_VALUE) && $past(data_i == DATA_VALUE,1,frame_i) && $past(data_i == DATA_VALUE,2,frame_i);
endproperty
a_check_flag : assert property(check_flag());
c_check_flag : cover property(check_flag());
endmodule
四、testbench如下
module frame_tb;
parameter DATA_WIDTH = 8 ;
parameter COUNTER_NUM = 3 ;
parameter DATA_VALUE = 8'h23 ;
logic clk_i ;
logic rst_n_i ;
logic frame_i ;
logic [DATA_WIDTH-1:0] data_i ;
logic flag_o ;
logic [1:0][DATA_WIDTH-1:0] data_random; //这个变量主要是用来产生8'h23和非8'h23的随机数
assign data_random[0] = DATA_VALUE;
frame
#(
.DATA_WIDTH (DATA_WIDTH ),
.COUNTER_NUM (COUNTER_NUM),
.DATA_VALUE (DATA_VALUE )
)
(
.clk_i (clk_i ),
.rst_n_i (rst_n_i ),
.frame_i (frame_i ),
.data_i (data_i ),
.flag_o (flag_o )
);
always #5 clk_i = ~clk_i;
task rst;
begin
rst_n_i = 1'b0;
#101;
rst_n_i = 1'b1;
end
endtask
task frame_input;
begin
logic random_a;
logic random_b;
data_random[1] = $urandom;
random_a = $urandom_range(0,1);
random_b = $urandom_range(0,1);
@(posedge clk_i);
frame_i <= random_a;
data_i <= {DATA_WIDTH{random_a}} & data_random[random_b];
end
endtask
initial
begin
clk_i = 1'b0;
frame_i = 1'b0;
data_i = 'h0 ;
rst();
repeat(1000) begin
frame_input();
end
$stop;
end
endmodule
五、仿真结果如下
过去最远的延伸正是此刻,未来最早的起点就在此刻。