对于发送端发送送来的数据流,我们需要检测出其帧头来判断一帧的开始,从而开始接收数据。
本人采用了接收1011010码流的例子来讲解如何实现数据流的检测。
首先,先画好接收码流的状态图:
这里做下简单的解释:当前数据为0时,一直等待1的到来,1到后跳转S1状态(已检测数据1),在等待0的到来,如果数据为1到则返回IDLE(图上写错了)从新开始检测;此时接收了10了,状态跳转S2(已检测数据10),继续检测数据1,如果到达的数据为0则返回IDLE,为1则进入S3状态(已检测数据101),到S3状态时如果接受数据为1直接进入S4,需要注意的是,当数据为0时,此时已检测的数据为1010,状态可跳至S2,相当于把前面的10舍去了重新检测S3,S4。在S4(已检测数据1011),按照上面的方法可完成检测
verilog代码如下:
module check_data( input clk, input rst_n, input data_in, output reg data_flag1, output reg[3:0] nxt_state, output reg data_receive ); reg[3:0] cur_state; //check data 1011010 //always @(posedge clk or negedge rst_n) begin // if(!rst_n) begin // cur_state <= 0; // data_receive <= 0; // data_flag1 <= 0; // nxt_state <= 0; // end // else // cur_state <= nxt_state; //end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin data_receive <= 0; data_flag1 <= 0; nxt_state <= 0; end else begin case(nxt_state) 4'd0: begin data_receive <= 1'b0; data_flag1 <= 1'b0; if(data_in) nxt_state <= 4'd1; else nxt_state <= 4'd0; end 4'd1: if(!data_in) nxt_state <= 4'd2; else nxt_state <= 4'd0; 4'd2: if(data_in) nxt_state <= 4'd3; else nxt_state <= 4'd0; 4'd3: if(data_in) nxt_state <= 4'd4; else begin data_flag1 <= 1; nxt_state <= 4'd2; end 4'd4: if(!data_in) nxt_state <= 4'd5; else nxt_state <= 4'd1; 4'd5: if(data_in) nxt_state <= 4'd6; else nxt_state <= 4'd0; 4'd6: if(!data_in) begin nxt_state <= 4'd0; data_receive <= 1'b1; end else nxt_state <= 4'd4; default: nxt_state <= 4'd0; endcase end end endmodule
仿真tb:
module top_tb(); reg clk; reg rst_n; reg data_in; wire data_receive; initial begin clk = 1; rst_n = 0; data_in = 0; forever begin #20 clk = ~clk; end end initial begin forever begin #40 data_in = $random; end end initial begin #2000 rst_n = 1; end check_data tb( .clk(clk), .rst_n(rst_n), .data_in(data_in), .data_receive(data_receive) ); endmodule
仿真波形:
2020.12.31更新
添加了s4状态处的探测信号,看看检测数据流1011010中检测到101时检测1/0状态跳变情况,在上面已经说过了如果检测出0.则为1010 可将状态跳回去仿真数据流漏检。