数字IC面试手撕代码(四)

在某个群看到某个大佬,面试海康数字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


这个代码仿真过了,功能基本没什么问题。数字IC面试手撕代码(四)_第1张图片
就是值的注意的是,在通过flag计数的时候,最后的结果减1才是真正的有效数据结果。因为如上图中16’h000f和16’h87ff其实是无效的的,因为有效的数据段是在这两组数据的中间,所以应该减去2。但是为什么只会减去1呢?这是因为如下图在这里插入图片描述
有什么问题,请指出来,大家一块讨论。

你可能感兴趣的:(数字IC,面试)