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