捕获数据中的某个序列---verilog
状态变化图
先是检测序列,每当接收到cmp_equal信号时跳转到下一个状态,等待另外一个cmp_equal信号到来。
代码:
always @ * case(current_state) STATE_START: if (cmp_equal) next_state = STATE_ADF2; else next_state = STATE_START; //每当检测不到cmp_equal信号时,状态就跳转到STATE_START STATE_ADF2: if (cmp_equal) next_state = STATE_ADF3; else next_state = STATE_START; //同上 STATE_ADF3: if (cmp_equal) next_state = STATE_DID; else next_state = STATE_START; //同上 STATE_DID: if (cmp_equal) next_state = STATE_SDID; else next_state = STATE_START; //同上 STATE_SDID: if (cmp_equal) next_state = STATE_DC; else next_state = STATE_START; //同上 STATE_DC: if (cmp_equal) next_state = STATE_UDW0; else next_state = STATE_START; //同上 STATE_UDW0: next_state = STATE_UDW1; //解出所需要的数据 STATE_UDW1: next_state = STATE_UDW2; //解数据 STATE_UDW2: next_state = STATE_UDW3; //解数据 STATE_UDW3: next_state = STATE_CS; STATE_CS: next_state = STATE_START; default: next_state = STATE_START; endcase
状态机状态调转模块采用的是组合逻辑。
always @ (posedge clk or posedge rst) if (rst) current_state <= STATE_START; else if (ce) current_state <= next_state;
状态输出模块:
always @ * begin // Unless specifically assigned in the case statement, all FSM outputs // are given the values assigned here. ld_byte1 = 1'b0; //数据解码使能信号 ld_byte2 = 1'b0; ld_byte3 = 1'b0; ld_byte4 = 1'b0; ld_cs_err = 1'b0; clr_cs = 1'b0; cmp_mux_sel = MUX_SEL_000; //数据比对选择信号 case(current_state) STATE_START: clr_cs = 1'b1; //此状态比对的就是 000数据 STATE_ADF2: begin cmp_mux_sel = MUX_SEL_3FF; //此状态比对的就是 3FF数据 clr_cs = 1'b1; end STATE_ADF3: begin cmp_mux_sel = MUX_SEL_3FF; // 比对3FF clr_cs = 1'b1; end STATE_DID: cmp_mux_sel = MUX_SEL_DID; //比对DID数据 STATE_SDID: cmp_mux_sel = MUX_SEL_SDID; //比对SDID数据 STATE_DC: cmp_mux_sel = MUX_SEL_DC; //比对DC数据 STATE_UDW0: ld_byte1 = 1'b1; //数据解码使能 STATE_UDW1: ld_byte2 = 1'b1; STATE_UDW2: ld_byte3 = 1'b1; STATE_UDW3: ld_byte4 = 1'b1; STATE_CS: begin cmp_mux_sel = MUX_SEL_CS; //比对数据CS ld_cs_err = 1'b1; end endcase end
cmp_equal信号产生与数据比对模块生成代码:
always @ * //组合逻辑 case(cmp_mux_sel) MUX_SEL_000: cmp_mux = 10'h000; MUX_SEL_3FF: cmp_mux = 10'h3ff; MUX_SEL_DID: cmp_mux = 10'h241; MUX_SEL_SDID: cmp_mux = 10'h101; MUX_SEL_DC: cmp_mux = 10'h104; MUX_SEL_CS: cmp_mux = {~checksum[8], checksum}; default: cmp_mux = 10'h000; endcase assign cmp_equal = cmp_mux == vid_in; //实时监控vid_in数据,当符合条件时,产生cmp_equal信号
localparam [MUXSEL_MSB:0] MUX_SEL_000 = 0, MUX_SEL_3FF = 1, MUX_SEL_DID = 2, MUX_SEL_SDID = 3, MUX_SEL_DC = 4, MUX_SEL_CS = 5;