题解 | #输入序列连续的序列检测#
输入序列连续的序列检测
http://www.nowcoder.com/practice/d65c2204fae944d2a6d9a3b32aa37b39
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
//0111_0001
//------Solution 1 finite state machine
parameter IDLE = 3'd0 ; //
parameter S0 = 3'd1 ; //0
parameter S1 = 3'd2 ; //01
parameter S2 = 3'd3 ; //011
parameter S3 = 3'd4 ; //0111
parameter S4 = 3'd5 ; //0111_0
parameter S5 = 3'd6 ; //0111_00
parameter S6 = 3'd7 ; //0111_000
reg [2:0] state , next_state ;
reg match_pre ;
always @( posedge clk or negedge rst_n) begin
if( !rst_n ) begin
state <= IDLE ;
end
else begin
state <= next_state ;
end
end
always @(*) begin
case (state)
IDLE : next_state = ~a ? S0 : IDLE ;
S0 : next_state = a ? S1 : S0 ;
S1 : next_state = a ? S2 : S0 ;
S2 : next_state = a ? S3 : S0 ;
S3 : next_state = ~a ? S4 : IDLE ;
S4 : next_state = ~a ? S5 : S1 ;
S5 : next_state = ~a ? S6 : S1 ;
S6 : next_state = a ? IDLE : S0 ;
default : next_state = IDLE ;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
match_pre <= 1'b0 ;
else if (state == S6 && a) //0111_0001
match_pre <= 1'b1 ;
else
match_pre <= 1'b0 ;
end
always @( posedge clk or negedge rst_n) begin
if( !rst_n ) begin
match <= 1'b0 ;
end
else begin
match <= match_pre ;
end
end
//------Solution 2 shift resister-----------------
// reg [7:0] shift;
//
// always @(posedge clk or negedge rst_n) begin
// if (!rst_n)
// shift <= 8'd0;
// else
// shift <= {shift , a};
// end
//
//
// always @( posedge clk or negedge rst_n) begin
// if( !rst_n ) begin
// match <= 1'b0 ;
// end
// else if (shift == 8'b0111_0001)begin
// match <= 1'b1 ;
// end
// else
// match <= 1'b0 ;
// end
endmodule
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
//0111_0001
//------Solution 1 finite state machine
parameter IDLE = 3'd0 ; //
parameter S0 = 3'd1 ; //0
parameter S1 = 3'd2 ; //01
parameter S2 = 3'd3 ; //011
parameter S3 = 3'd4 ; //0111
parameter S4 = 3'd5 ; //0111_0
parameter S5 = 3'd6 ; //0111_00
parameter S6 = 3'd7 ; //0111_000
reg [2:0] state , next_state ;
reg match_pre ;
always @( posedge clk or negedge rst_n) begin
if( !rst_n ) begin
state <= IDLE ;
end
else begin
state <= next_state ;
end
end
always @(*) begin
case (state)
IDLE : next_state = ~a ? S0 : IDLE ;
S0 : next_state = a ? S1 : S0 ;
S1 : next_state = a ? S2 : S0 ;
S2 : next_state = a ? S3 : S0 ;
S3 : next_state = ~a ? S4 : IDLE ;
S4 : next_state = ~a ? S5 : S1 ;
S5 : next_state = ~a ? S6 : S1 ;
S6 : next_state = a ? IDLE : S0 ;
default : next_state = IDLE ;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
match_pre <= 1'b0 ;
else if (state == S6 && a) //0111_0001
match_pre <= 1'b1 ;
else
match_pre <= 1'b0 ;
end
// 本来意图是使用3个触发器完成序列检测,所以就没有用S7=0111_0001这个状态,但好像从时序来看这么做会让match提前一拍拉起来,所以再打一拍就好了
//一直有疑惑像序列检测能不能不要用IDLE这个状态,这样就可以节省一个触发器,希望能有大佬看到后解惑
always @( posedge clk or negedge rst_n) begin
if( !rst_n ) begin
match <= 1'b0 ;
end
else begin
match <= match_pre ;
end
end
//------Solution 2 shift resister-----------------
// reg [7:0] shift;
//
// always @(posedge clk or negedge rst_n) begin
// if (!rst_n)
// shift <= 8'd0;
// else
// shift <= {shift , a};
// end
//
//
// always @( posedge clk or negedge rst_n) begin
// if( !rst_n ) begin
// match <= 1'b0 ;
// end
// else if (shift == 8'b0111_0001)begin
// match <= 1'b1 ;
// end
// else
// match <= 1'b0 ;
// end
endmodule