Verilog -- 並行2bit輸入序列檢測器
@(verilog)
樂鑫2020筆試題:
描述:模塊輸入口是並行的2bit,實現對\((1011001)_2\)的序列檢測,輸入數據順序為高位2bit先輸入,當檢測到序列時輸出一拍高電平脈沖,用verilg描述。
方法一:狀態機
采用狀態機描述,先列出狀態轉移表,跟單bit輸入不同的是,這里的輸入是並行的2bit:
state\input | 00 | 01 | 10 | 11 |
---|---|---|---|---|
0 | 0 | 1 | 10 | 1 |
1 | 0 | 101 | 10 | 1 |
10 | 0 | 1 | 10 | 1011 |
101 | 0 | 101 | 10110 | 1 |
1011 | 101100 | 101 | 10 | 1 |
10110 | 0 | 1011001 | 10 | 1011 |
101100 | 0 | 1 | 10 | 1 |
0 | 101 | 10 | 1 |
以及輸出的狀態轉移表:
state\input | 00 | 01 | 10 | 11 |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 |
10 | 0 | 0 | 0 | 0 |
101 | 0 | 0 | 0 | 0 |
1011 | 0 | 0 | 0 | 0 |
10110 | 0 | 1 | 0 | 0 |
101100 | 0 | 0 | 1 | 1 |
0 | 0 | 0 | 0 |
通過分析可以發現,1011001和1狀態是完全等價的,因此可以歸並,並且其他狀態的轉移也有相同的,也可以放到一起:
狀態轉移表:
state\input | 00 | 01 | 10 | 11 |
---|---|---|---|---|
0\101100 | 0 | 1 | 10 | 1 |
1 | 0 | 101 | 10 | 1 |
10\10110 | 0 | 1 | 10 | 1011 |
101 | 0 | 101 | 10110 | 1 |
1011 | 101100 | 101 | 10 | 1 |
輸出轉移表:
state\input | 00 | 01 | 10 | 11 |
---|---|---|---|---|
0\1\10\101\1011 | 0 | 0 | 0 | 0 |
10110 | 0 | 1 | 0 | 0 |
101100 | 0 | 0 | 1 | 1 |
Verilog代碼:
`timescale 1ns/1ps
module two_bit_input_seq_detector
(
input clk,
input rst_n,
input [1:0] data,
output reg success
);
reg [2:0] current_state;
reg [2:0] next_state;
parameter S0 = 3'b000,
S1 = 3'b001,
S10 = 3'b011,
S101 = 3'b010,
S1011 = 3'b110,
S10110 = 3'b111,
S101100 = 3'b101;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) current_state <= 3'b0;
else current_state <= next_state;
end
always @(*)
case(current_state)
S0,S101100:
case(data)
2'b00: next_state = S0;
2'b01: next_state = S1;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
S1: case(data)
2'b00: next_state = S0;
2'b01: next_state = S101;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
S10,S10110:
case(data)
2'b00: next_state = S0;
2'b01: next_state = S1;
2'b10: next_state = S10;
2'b11: next_state = S1011;
endcase
S101: case(data)
2'b00: next_state = S0;
2'b01: next_state = S101;
2'b10: next_state = S10110;
2'b11: next_state = S1;
endcase
S1011: case(data)
2'b00: next_state = S101100;
2'b01: next_state = S101;
2'b10: next_state = S10;
2'b11: next_state = S1;
endcase
default: next_state = S0;
endcase
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
success <= 0;
end else begin
case(current_state)
S0,S1,S10,S101,S1011: success <= 0;
S10110 : if(data == 2'b01) success <= 1;
else success <= 0;
S101100: if(data[1] == 1'b1) success <= 1;
else success <= 0;
default: success <= 0;
endcase
end
end
endmodule
testbench:
`timescale 1ns/1ps
module two_bit_input_seq_detector_tb();
reg clk;
reg rst_n;
reg [1:0] data;
wire success;
reg [127:0] seq;
always #1 clk = ~clk;
initial begin
clk = 0;
data = 0;
rst_n = 1;
#4 rst_n = 0; #2 rst_n = 1;
seq = 0;
while(1) begin
@(posedge clk) begin
data <= $random%4;
seq <= (seq<<2) + data;
end
end
end
two_bit_input_seq_detector U_2BIT_INPUT_SEQ_DETECTOR_0
( .clk ( clk ),
.rst_n ( rst_n ),
.data ( data ),
.success ( success ));
initial begin
$fsdbDumpvars();
$fsdbDumpMDA();
$dumpvars();
#1000 $finish;
end
endmodule
波形圖:

放大來看:

可以看到,功能正確。
方法二:移位寄存器
使用移位寄存器解決序列檢測問題是真的簡單粗暴,直接上代碼:
`timescale 1ns/1ps
module two_bit_input_seq_detector_v2
(
input clk,
input rst_n,
input [1:0] data,
output success
);
parameter DETECTOR = 7'b1011001;
reg [7:0] fifo;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
fifo <= 8'b0;
end else begin
fifo <= {fifo[5:0],data};
end
end
assign success = (fifo[7:1]==DETECTOR || fifo[6:0]==DETECTOR) ? 1:0;
endmodule
testbench:
`timescale 1ns/1ps
module two_bit_input_seq_detector_v2_tb();
reg clk;
reg rst_n;
reg [1:0] data;
wire success;
reg [127:0] seq;
always #1 clk = ~clk;
initial begin
clk = 0;
data = 0;
rst_n = 1;
#4 rst_n = 0; #2 rst_n = 1;
seq = 0;
while(1) begin
@(posedge clk) begin
data <= $random%4;
seq <= (seq<<2) + data;
end
end
end
two_bit_input_seq_detector_v2 U_TWO_BIT_INPUT_SEQ_DETECTOR_V2_0
( .clk ( clk ),
.rst_n ( rst_n ),
.data ( data ),
.success ( success ));
initial begin
$fsdbDumpvars();
$fsdbDumpMDA();
$dumpvars();
#1000 $finish;
end
endmodule
仿真波形:
功能正確!