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

波形


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM