對於發送端發送送來的數據流,我們需要檢測出其幀頭來判斷一幀的開始,從而開始接收數據。
本人采用了接收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 可將狀態跳回去仿真數據流漏檢。