题解 | 不重叠序列检测

1、示意图显示结果需在本组数据传完的下一个周期立即得出,所以必须是组合逻辑,但题目给的reg型,故需使用always@(*)

2、需要比较数据结果,故需新建变量check用于储存一组数据;同时需一个计数器记录周期;时钟同步;

3、题目要求用状态机:

A:将结果与状态绑定:因为结果需要在6次传输完成才能判断,而次态的判断需要在前一状态内确定,所以【结果态】和【读数态】不能直接相连,所以需要添加一个过渡态。

B:将结果与状态分离:那么只需要读数和判断两种状态就行。

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
   
   
// 状态定义
parameter READ = 0, WAIT=1, MATCH = 2, NOT_MATCH = 3;

wire R2W,W2M,W2N,C2R;

reg  [1:0] state_c;  // 当前状态
reg  [1:0] state_n;  // 下一个状态

reg [3:0] cnt    ;
reg [5:0] check  ;

// 状态更新逻辑:每个时钟上升沿或复位信号有效时更新当前状态
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state_c <= READ;  // 复位时回到空闲状态
    end else begin
        state_c <= state_n;  // 更新为下一个状态
    end
end

always @(posedge clk or negedge rst_n) begin
      if (~rst_n) begin
         cnt      <= 4'd0  ;
      end else if (cnt == 4'd5) begin
         cnt      <= 4'd0  ;
      end else begin
         cnt      <= cnt + 1'b1;            
      end
   end

always @(posedge clk or negedge rst_n) begin
      if (~rst_n) begin
         check    <= 6'd0  ;
      end else begin
         check    <= {check[4:0],data};
      end
   end


// 状态转移逻辑:根据当前状态和条件计算下一个状态
always @(*) begin
    case (state_c)
        READ: begin
            if (R2W) begin
                state_n = WAIT; 
            end else begin
                state_n = state_c;  
            end
        end
        WAIT: begin
            if (W2M) begin
                state_n = MATCH;
            end else if (W2N) begin
                state_n = NOT_MATCH;
            end else begin
                state_n = state_c;  
            end
        end
        MATCH: begin
            if (C2R) begin
                state_n = READ;
            end else begin
                state_n = state_c;  
            end
        end       
        NOT_MATCH: begin
            if (C2R) begin
                state_n = READ;
            end else begin
                state_n = state_c;  
            end
        end  
        default: begin
                state_n = READ;  
        end
    endcase
end

// 状态转移条件定义
assign R2W = cnt == 4'd5;  
assign W2M = check == 6'b011100;
assign W2N = check != 6'b011100;
assign C2R = cnt == 4'd1;  //因为判断状态需要被捕获,所以需要持续一个时钟周期,即cnt==0由WAIT开始MATCH/NOT_MATCH收尾;cnt在边沿之后,所以state_n的状态变化也会在边沿之后;

// 输出逻辑:根据当前状态生成输出信号
always @(*) begin
    if (!rst_n) begin
         match = 1'b0;
         not_match = 1'b0;
    end else begin
         match = state_n == MATCH;  //此处不能用 state_c,因为需要即时出结果,而此时state_c == WAIT;
         not_match = state_n == NOT_MATCH;
	end
end

endmodule
`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
   
   
// 状态定义
parameter READ = 0, CHECK = 1;
wire R2C,C2R;

reg  state_c;  // 当前状态
reg  state_n;  // 下一个状态

reg [3:0] cnt    ;
reg [5:0] check  ;

// 状态更新逻辑:每个时钟上升沿或复位信号有效时更新当前状态
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state_c <= READ;  // 复位时回到空闲状态
    end else begin
        state_c <= state_n;  // 更新为下一个状态
    end
end

always @(posedge clk or negedge rst_n) begin
      if (~rst_n) begin
         cnt      <= 4'd0  ;
      end else if (cnt == 4'd5) begin
         cnt      <= 4'd0  ;
      end else begin
         cnt      <= cnt + 1'b1;            
      end
   end

always @(posedge clk or negedge rst_n) begin
      if (~rst_n) begin
         check    <= 6'd0  ;
      end else begin
         check    <= {check[4:0],data};
      end
   end


// 状态转移逻辑:根据当前状态和条件计算下一个状态
always @(*) begin
    case (state_c)
        READ: begin
            if (R2C) begin
                state_n = CHECK;  
            end else begin
                state_n = state_c;  
            end
        end
        CHECK: begin
            if (C2R) begin
                state_n = READ;
            end else begin
                state_n = state_c;  
            end
        end       

        default: begin
                state_n = READ;  
        end
    endcase
end

// 状态转移条件定义
assign R2C = cnt == 4'd5;  
assign C2R = cnt == 4'd0;  

// 输出逻辑:根据当前状态生成输出信号
always @(*) begin
    if (!rst_n) begin
         match = 1'b0;
         not_match = 1'b0;
    end else begin
         match = (state_c == CHECK) & (check == 6'b011100);
         not_match = (state_c == CHECK) & (check != 6'b011100);
	end
end

endmodule

写完了,还是两种状态的划分简单点啊~不过这两种实际上都有点像骡子了,都用计数器了,再搞个状态机。。。。这题目设计有点怪怪的,强行要求状态机,分0-6的状态实际上也是个计数器嘛

全部评论

相关推荐

点赞 评论 收藏
分享
03-06 20:09
贵州大学 Java
King987:你这个学历找个中大厂刷实习经历都是可以的,但是项目要有亮点才行,这个什么外卖就不要做了,去找找最新的项目,至少涉及高并发或者是新型的AI技术mcp rag啥的 ,我在出简历点评,但是你这个没什么好点评的,内容太少,而且含金量太低。自己改一改吧,或者看一下我的项目地址中,那里有大厂最近做过的实习项目
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务