题解 | #输入序列不连续的序列检测#
输入序列不连续的序列检测
https://www.nowcoder.com/practice/f96d0e94ec604592b502b0f1800ed8aa
//此题的解决方法为状态机,选用的还是n+1位,1位为起始位,不同的是在本次中还需加入一个无效等待位,和上一个题一致, //对于这个等待位,只要数据无效就进入状态,所以在状态机的第二段中,有效位是关键,需要进行两个判断,一个是数据有效位的判断,另一个是跳转条件的判断 //在进入等待位后,状态的跳转变得复杂,主要集中在需要知道上一个跳转时的状态,寄存上一个状态简单,但是要是上一个状态是等待,那么就还需要知道上上个,这样就陷入了死循环中 //所以不对状态进行寄存,而是对输入进行寄存,将移位寄存器法结合起来,只需判断其最低的两位,就能知道下一个状态应该往哪跳和本身状态是啥,而寄存器是受数据有效位控制的,所以无效的数没有进来,故之前的就没有等待位, //而是最后一个等待位之前的跳转位,这样就能把等待位给忽略掉,只需控制有效的数据进来就行 //输出可以直接在状态4输出,因为没延时 //由本题的输出可知,没有延时,所以在第二段组合逻辑中,nex采用组合控制,不使用时序控制 `timescale 1ns/1ns module sequence_detect( input clk, input rst_n, input data, input data_valid, output reg match ); //此题的解决方法为状态机,选用的还是n+1位,1位为起始位,不同的是在本次中还需加入一个无效等待位,和上一个题一致, //对于这个等待位,只要数据无效就进入状态,所以在状态机的第二段中,有效位是关键,需要进行两个判断,一个是数据有效位的判断,另一个是跳转条件的判断 //在进入等待位后,状态的跳转变得复杂,主要集中在需要知道上一个跳转时的状态,寄存上一个状态简单,但是要是上一个状态是等待,那么就还需要知道上上个,这样就陷入了死循环中 //所以不对状态进行寄存,而是对输入进行寄存,将移位寄存器法结合起来,只需判断其最低的两位,就能知道下一个状态应该往哪跳和本身状态是啥,而寄存器是受数据有效位控制的,所以无效的数没有进来,故之前的就没有等待位, //而是最后一个等待位之前的跳转位,这样就能把等待位给忽略掉,只需控制有效的数据进来就行 //输出可以直接在状态4输出,因为没延时 //由本题的输出可知,没有延时,所以在第二段组合逻辑中,nex采用组合控制,不使用时序控制 localparam IDEL_st = 6'b00_0001; localparam One_st = 6'b00_0010; localparam Two_st = 6'b00_0100; localparam Thre_st = 6'b00_1000; localparam Four_st = 6'b01_0000; localparam Wait_st = 6'b10_0000; reg [5:0] cur_state; reg [5:0] nex_state; reg [3:0] data_reg; always@(posedge clk or negedge rst_n) begin if(!rst_n) data_reg <= 4'b0; else if(data_valid) data_reg <= {data_reg[2:0] , data}; else data_reg <= data_reg; end always@(posedge clk or negedge rst_n) begin if(!rst_n) cur_state <= IDEL_st; else cur_state <= nex_state; end always@(*) begin if(!rst_n) nex_state = IDEL_st; else begin nex_state = IDEL_st; case(cur_state) IDEL_st : nex_state = ((data_valid) && (!data)) ? One_st : ((data_valid) ? IDEL_st : Wait_st); One_st : nex_state = ((data_valid) && (data)) ? Two_st : ((data_valid) ? One_st : Wait_st); Two_st : nex_state = ((data_valid) && (data)) ? Thre_st : ((data_valid) ? One_st : Wait_st); Thre_st : nex_state = ((data_valid) && (!data)) ? Four_st : ((data_valid) ? IDEL_st : Wait_st); Four_st : nex_state = ((data_valid) && (!data)) ? One_st : ((data_valid) ? Two_st : Wait_st); Wait_st : begin case(data_reg[1:0]) 2'b00 : nex_state = ((data_valid) && (data)) ? Two_st : ((data_valid) ? One_st : Wait_st); 2'b01 : nex_state = ((data_valid) && (data)) ? Thre_st : ((data_valid) ? One_st : Wait_st); 2'b10 : nex_state = ((data_valid) && (data)) ? Two_st : ((data_valid) ? One_st : Wait_st); 2'b11 : nex_state = ((data_valid) && (!data)) ? Four_st : ((data_valid) ? IDEL_st : Wait_st); default : nex_state = Wait_st; endcase end endcase end end always@(posedge clk or negedge rst_n) begin if(!rst_n) match <= 1'b0; else begin if(nex_state == Four_st) match <= 1'b1; else match <= 1'b0; end end endmodule