Verilog-数据包检测器

目录

题目

正常情况下数据包由起始码(16bit)、数据段(n byte<256)、结束码(16bit)3部分组成。起始码为0xFF00,结束码为0xFF01.在一个完整的数据包中,数据段部分不会出现起始码和结束码,请设计一个电路在码流中检测完整且有效的数据包,并输出当前数据包的有效数据长度n。

代码

`timescale 1ns / 1ps

module data_packet_detect(
	input clk,
	input rstn,
	
	input [7:0] din,
	input din_vld,
	
	output [7:0] data_cnt,
	output data_cnt_vld
    );

localparam IDLE = 0;
localparam START = 1;
localparam DATA = 2;
localparam OVER = 3;

reg [1:0] state,next_state;
reg [7:0] data_cnt_reg;
reg flag_FF;  // 此标志位为数据包将结束时收到的FF

always @(posedge clk or negedge rstn) begin
	if(!rstn) state <= IDLE;
	else state <= next_state;
end

always @(*) begin
	case(state)
		IDLE:
			begin
				if(din_vld && din == 8‘hFF) next_state = START;
				else next_state = IDLE;
			end
		START:
			begin
				if(din_vld && din == 8‘h00) next_state = DATA;
				else next_state = IDLE;
			end
		DATA:
			begin
				if(din_vld && din == 8‘h01 && flag_FF) next_state = OVER;  //收到FF01
				else next_state = DATA;
			end
		OVER:
			begin
				next_state = IDLE;
			end
		default: next_state = IDLE;
	endcase
end

always @(posedge clk or negedge rstn) begin
	if(!rstn) data_cnt_reg <= 8‘d0;
	else begin
		if(state == DATA) data_cnt_reg <= data_cnt_reg + 1‘b1;
		else if(state == OVER) data_cnt_reg <= 8‘d0;
		else data_cnt_reg <= data_cnt_reg;
	end
end

always @(posedge clk or negedge rstn) begin
	if(!rstn) flag_FF <= 1‘b0;
	else begin
		if(din_vld && state == DATA && din == 8‘hFF) flag_FF <= 1‘b1;
		else flag_FF <= 1‘b0;
	end
end

assign data_cnt_vld = (state == OVER)? 1‘b1 : 1‘b0;
assign data_cnt = data_cnt_reg - 2‘d2;  // 实际数据包长度需要减去结束标志位的2个字节

endmodule

测试激励

`timescale 1ns / 1ps

module data_packet_detect_tb;

	// Inputs
	reg clk;
	reg rstn;
	reg [7:0] din;
	reg din_vld;

	// Outputs
	wire [7:0] data_cnt;
	wire data_cnt_vld;

	// Instantiate the Unit Under Test (UUT)
	data_packet_detect uut (
		.clk(clk), 
		.rstn(rstn), 
		.din(din), 
		.din_vld(din_vld), 
		.data_cnt(data_cnt), 
		.data_cnt_vld(data_cnt_vld)
	);

	initial begin
		// Initialize Inputs
		clk = 0;
		rstn = 0;
		din = 0;
		din_vld = 0;

		// Wait 100 ns for global reset to finish
		#100;
		
		@(negedge clk);
		rstn = 1;
		
		@(negedge clk);
		din_vld = 1;
		din = 8‘h01;
		
		@(posedge clk);
		din = 8‘h02;

		@(posedge clk);
		din = 8‘hFF;

		@(posedge clk);
		din = 8‘h03;

		@(posedge clk);
		din = 8‘hFF;

		@(posedge clk);
		din = 8‘h00;

		@(posedge clk);
		din = 8‘h01;	

		@(posedge clk);
		din = 8‘h02;

		@(posedge clk);
		din = 8‘h03;

		@(posedge clk);
		din = 8‘hFF;

		@(posedge clk);
		din = 8‘h03;

		@(posedge clk);
		din = 8‘hFF;

		@(posedge clk);
		din = 8‘h01;	

		@(posedge clk);
		din_vld = 0;
        
		// Add stimulus here

	end
	
	always #20 clk = ~clk;
      
endmodule

波形

Verilog-数据包检测器