在某个群看到某个大佬,面试海康数字IC实习的时候让手撕代码。现在也把这个题目复现一下。
题目正常情况下数据包由起始码(16bit)、数据段(n bytes n < 256 )、结束码(16bit)三部分组成。起始码为0xFF00、结束码为0xFF01。在一个完整的数据包中,数据段部分不会出现起始码和结束码。请设计一个电路在码流中检测完整且有效的数据包,并输出当前数据包的有效长度n。输入接口in:clk、rst_n、din[7:0]、din_vld
输出接口out:data_cnt[7:0]、data_cnt_vld。
刚开始看了这个题目,也没有仔细多想,看了那个大佬的描述之后,应该注意:异常检测(结束码还没出现的时候如果超过255bytes的数据要报异常、如果中间出现起始码要报异常)。所以应该在上面的输出端口上加上两个异常标志位。
接下来就是我对这个题目的代码的书写:
module data(
input clk,
input rst_n,
input [7:0] din,
input din_vld,
output reg [7:0] data_cnt_1,
output data_cnt_vld,
output error_start,
output error_cnt
);
reg [15:0] temp_data;
reg [7:0] data_cnt;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
temp_data <= 16'd0;
end
else if(din_vld) begin
temp_data <= {temp_data[7:0],din};
end
end
reg flag;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
flag <= 1'b0;
end
else if(din_vld) begin
if(temp_data==16'hff00) begin
flag <= 1'b1;
end
else if(temp_data==16'hff01) begin
flag <= 1'b0;
end
end
end
//error_start
/*
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
error_start <= 1'b0;
end
else if(flag && (temp_data==16'hff00)) begin
error_start <= 1'b1;
end
else begin
error_start <= 1'b0;
end
end*/
assign error_start = (flag && (temp_data==16'hff00)) ? 1'b1 : 1'b0;
//error_cnt
/* always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
error_cnt <= 1'b0;
end
else if(flag && data_cnt==8'd255 && temp_data!=16'hff01) begin
error_cnt <= 1'b1;
end
else begin
error_cnt <= 1'b0;
end
end */
assign error_cnt = (flag && (data_cnt==8'd254) && temp_data!=16'hff01) ? 1'b1 : 1'b0;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt <= 8'd0;
end
else if(error_start || error_cnt) begin
data_cnt <= 8'd0;
end
else if(flag && temp_data==16'hff01) begin
data_cnt <= 8'd0;
end
else if(flag && din_vld) begin
data_cnt <= data_cnt + 1'b1;
end
end
/* always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt_vld <= 1'b0;
end
else if(flag && temp_data==16'hff01) begin
data_cnt_vld <= 1'b1;
end
else begin
data_cnt_vld <= 1'b0;
end
end */
assign data_cnt_vld = (flag && temp_data==16'hff01) ? 1'b1 : 1'b0;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt_1 <= 8'd0;
end
else if(flag && temp_data==16'hff01)begin
data_cnt_1 <= data_cnt-1;
end
end
endmodule
这个代码仿真过了,功能基本没什么问题。
就是值的注意的是,在通过flag计数的时候,最后的结果减1才是真正的有效数据结果。因为如上图中16’h000f和16’h87ff其实是无效的的,因为有效的数据段是在这两组数据的中间,所以应该减去2。但是为什么只会减去1呢?这是因为如下图
有什么问题,请指出来,大家一块讨论。