题目
正常情况下数据包由起始码(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
波形