點擊上方藍字關注我們
一、前言
在數字電路中,序列檢測器(Sequence Detector)是指一種特殊類型的電路,用于尋找輸入信號中一定模式的子序列。該模式可以是任意模式,包括重復模式、連續模式、間隔模式等等。通常的序列檢測方法有2種:有限狀態機法(FSM);移位寄存器法。
為什么需要設計序列檢測電路呢?
在數字集成電路中,序列檢測電路可以用于檢測輸入信號序列中是否存在特定的模式和序列,以及判斷實際輸出和理論輸出是否存在差異。序列檢測器是確保數字系統的正確運行不可或缺的一部分!
那么數字IC中哪些部分需要設計呢?
數字集成電路(Digital Integrated Circuit,簡稱DIC)中需要設計序列檢測電路的部分主要包括以下幾個方面:
數據輸入端:序列檢測電路可以用于檢測輸入數據是否符合特定的格式要求,或者是否存在錯誤或干擾。在數字集成電路中,輸入數據通常是通過輸入端口輸入的,因此需要在輸入端口處設計序列檢測電路。
控制信號:數字集成電路中的控制信號通常是用于控制數字系統的操作序列,以確保系統按照預期的順序執行操作。在這種情況下,序列檢測電路可以用于檢測控制信號是否按照預期的序列進行。
數據輸出端:序列檢測電路還可以用于檢測輸出數據是否符合特定的格式要求,或者是否存在錯誤或干擾。在數字集成電路中,輸出數據通常是通過輸出端口輸出的,因此需要在輸出端口處設計序列檢測電路。
內部信號:數字集成電路中的內部信號通常是在芯片內部傳遞的信號,例如時鐘信號、地址信號、數據信號等。在這種情況下,序列檢測電路可以用于檢測內部信號是否按照預期的序列進行。
在IC設計的過程中,不同的部分的序列檢測器檢測的序列和發揮的具體作用不盡心相同。因此在數字集成電路中,需要根據具體的應用場景,針對不同的部分設計相應的序列檢測電路。
二、狀態機法和寄存器法
對于序列檢測器的設計,常規的設計方法有兩種:狀態機法和移位寄存器法。
狀態機法最重要的是明白狀態機狀態的轉移過程:在數據輸入之后判斷是否匹配,若匹配則進入下一狀態,不匹配則根據輸入的數據具體判斷進入的下一狀態(也有可能保持在原來的狀態)。狀態機設計過程一定要注重狀態的數量和狀態轉移以及狀態轉移條件,避免狀態的缺失以及狀態轉移的不合理循環。
移位寄存器法法基本原理是數據的移位和移位數據的對比:首先將對應的初始數據緩存在寄存器中作為一個數組,數據輸入后置于于數組的末尾,數組其它元素左移,把最早輸入的數據移出,每輸入一個數據后刷新一次。然后將數組和目標序列對比,如果數組和目標序列相等,則說明出現目標序列。
2.1狀態機法2.11 使用狀態機檢測“1001”
題目:設計一個序列檢測器,用來檢測序列1001,用_狀態機完成電路,可重復檢測_序列1001(即本文第三部分的重疊檢測)。
第一步,分析狀態機狀態轉移,分析如下:
IDLE: 初始狀態,代表目前沒有接收到滿足要求的數據。
seq_in = 1時,等于1001中的第一個數,進入S1狀態;
seq_in = 0時,保持狀態。
S1:代表目前已經有了1個匹配的數據。
seq_in = 0時,當前序列為10,等于1001中的前兩個數,進入S2狀態;
seq_in = 1時,當前序列為11,不是1001的前兩個數,但1是1001的第一個數,所以保持S1狀態。
S2:代表目前已經有了2個匹配的數據。
seq_in = 0時,當前序列為100,等于1001中的前三個數,進入S3狀態;
seq_in = 1時,當前序列為101,不是1001的前三個數,但1是1001的第一個數,所以進入S1狀態。
S3:代表目前已經有了3個匹配的數據。
seq_in = 1時,當前序列為1001,與要求序列匹配,進入S4狀態;
seq_in = 0時,當前序列為1000,與要求序列不配,0與初始狀態匹配,所以進入IDLE狀態。
S4:最終狀態,代表目前已經得到了匹配的序列,輸出信號翻轉。
seq_in = 1時,當前序列為10011,1與要求序列的第一個數匹配,所以進入S1狀態;
seq_in = 0時,當前序列為10010,10與要求的前兩個數匹配,所以進入S2狀態。
第二步:根據流程轉換分析畫出狀態機的狀態轉移圖,如下圖所示:
第三步:根據狀態機轉移圖用經典三段式(或者二段式)寫出verilog代碼
2.12 verilog代碼//使用狀態機設計檢測“1001”的序列檢測器
//可重疊檢測序列“1001”
module sequence_detect01(
input clk,
input rst_n,
input seq_in,
output mismatch//檢驗序列是否匹配,匹配輸出0,不匹配輸出0
);
//采用獨熱碼編譯五個狀態,初始IDLE狀態為待機狀態
//獨熱碼相比二進制碼和格雷碼,方便電路設計判斷、狀態轉移,且邏輯更簡單
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
//定義兩個寄存器表示狀態機的目前狀態和下一狀態
reg [4:0] curr_state;
reg [4:0] next_state;
//第一段使用時序邏輯描述狀態轉移
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
//第二段使用組合邏輯判斷狀態轉移條件
always@(*) begin
if(!rst_n) begin
next_state <= IDLE;
end
else begin
case(curr_state)
IDLE :next_state = seq_in?S1:IDLE;
S1 :next_state = seq_in?S1:S2;
S2 :next_state = seq_in?S1:S3;
S3 :next_state = seq_in?S4:IDLE;
S4 :next_state = seq_in?S1:S2;
default:next_state = IDLE;//養成良好代碼風格,不能遺漏,防生成latch,也可以通過賦初值避免
endcase
end
end
//第三段描述狀態輸出(可以使用組合邏輯,也可以用時序邏輯)
//此處采用組合邏輯,同時也提供時序邏輯代碼示例
assign mismatch = (curr_state ==S4) ? 1'b0 : 1'b1;//組合邏輯描述輸出
/*
//時序邏輯描述輸出
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
mismatch <= 1'b1;
end
else if(next_state == S4) begin
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;
end
end
*/
endmodule
2.13 testbench`timescale 1ns/1ps//仿真時間單位1ns 仿真時間精度1ps
module sequence_detect01_tb();
//信號申明
reg clk;
reg rst_n;
reg seq_in;
wire mismatch;
//生成復位信號
//為時鐘信號和復位信號賦初值
initial begin
clk = 0;
rst_n = 1;
seq_in = 1;
#5 rst_n = 0;
#10 rst_n = 1;
end
always #6 seq_in = $random;//生成隨機數作為信號輸入
always #5 clk = ~clk;//生成時鐘信號
//模塊實例化(將申明的信號連接起來即可)
sequence_detect01 u_sequence_detect01
(.clk (clk),
.rst_n (rst_n),
.seq_in (seq_in),
.mismatch (mismatch)
);
endmodule
2.14仿真結果
)
Testbench中采用隨機數來驗證序列檢測器的準確性,當時間來到705ns,隨機數連續輸出1001,mismatch在接收四位數字進行信號翻轉。
2.2移位寄存器法2.21 使用移位寄存器法檢測1001
題目:設計一個序列檢測器,用來檢測序列 1001,用_移位寄存器_完成電路設計。
移位寄存器方法比較簡單。設置一個和序列等長的寄存器,在數據輸入后將輸入移入寄存器的最低位,并判斷寄存器中的值是否與序列相同。因為移位寄存器的工作原理,設計出來的序列檢測器可以重疊檢測序列。
2.22 verilog代碼//使用移位寄存器設計檢測“1001”的序列檢測器
//可重疊檢測序列“1001”
module sequence_detect02(
input clk,
input rst_n,
input seq_in,
output regmismatch//時序邏輯中需要定義為reg型
);
reg [3:0] seq_in_r;//定義一個寄存器緩存數據
//使用時序邏輯完成復位和移位寄存器移位過程
always@(posedge clk or negedge rst_n) begin
if (!rst_n) begin
seq_in_r <= 4'b0;//中間寄存器復位
end
else begin
seq_in_r <= {seq_in_r[2:0],seq_in};//輸入數據置于數組右端,移位寄存器左移位
end
end
//使用時序邏輯完成復位與輸出
always@(posedge clk or negedge rst_n) begin
if (!rst_n) begin
mismatch <= 1'b1;
end
else if (seq_in_r == 4'b1001) begin//若檢測到1001則將mismatch置1,表明檢測到序列1001
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;//養成良好代碼風格,不能遺漏,防生成latch,可通過賦初值避免
end
end
endmodule
2.23 testbench`timescale 1ns/1ps//仿真時間單位1ns 仿真時間精度1ps
module sequence_detect02_tb;
//信號申明
regclk;
reg rst_n;
regseq_in;
wire mismatch;
//復位信號生成
//時鐘信號與復位信號賦初值
initial begin
clk = 0;
rst_n = 1;
seq_in = 1;
#5 rst_n = 0;
#10 rst_n = 1;
end
always #6 seq_in = $random;//生成隨機數作為信號輸入
always #5 clk = ~clk;//生成時鐘信號
//模塊實例化(將申明的信號連接起來即可)
sequence_detect01 u_sequence_detect01
(.clk (clk),
.rst_n (rst_n),
.seq_in (seq_in),
.mismatch (mismatch)
);
endmodule
2.24仿真結果
Testbench中采用隨機數來驗證序列檢測器的準確性,當時間來到705ns,隨機數連續輸出1001,mismatch在接收四位數字且在時鐘上升沿進行信號翻轉。
三、重疊檢測與非重疊檢測(檢測序列1001)
數字IC序列檢測中的重疊檢測和非重疊檢測是兩種不同的檢測方式。
重疊檢測是指在一個序列中,子序列之間會有部分重疊的情況,而重疊區域也需要進行檢測,并被判定為單獨的子序列。
非重疊檢測則是指在一個序列中,每個子序列之間沒有重疊部分,因此只需要檢測每個子序列本身是否滿足特定的條件即可。
3.1重疊檢測3.11 重疊檢測方法
題目:設計一個序列檢測器,用來檢測序列 1001,用_狀態機完成電路,可重復檢測_序列1001
第一步,分析狀態機狀態轉移,分析如下:
IDLE: 初始狀態,代表目前沒有接收到滿足要求的數據。
seq_in = 1時,等于1001中的第一個數,進入S1狀態;
seq_in = 0時,保持狀態。
S1:代表目前已經有了1個匹配的數據。
seq_in = 0時,當前序列為10,等于1001中的前兩個數,進入S2狀態;
seq_in = 1時,當前序列為11,不是1001的前兩個數,但1是1001的第一個數,所以保持S1狀態。
S2:代表目前已經有了2個匹配的數據。
seq_in = 0時,當前序列為100,等于1001中的前三個數,進入S3狀態;
seq_in = 1時,當前序列為101,不是1001的前三個數,但1是1001的第一個數,所以進入S1狀態。
S3:代表目前已經有了3個匹配的數據。
seq_in = 1時,當前序列為1001,與要求序列匹配,進入S4狀態;
seq_in = 0時,當前序列為1000,與要求序列不配,0與初始狀態匹配,所以進入IDLE狀態。
S4:最終狀態,代表目前已經得到了匹配的序列,輸出信號翻轉。
seq_in = 1時,當前序列為10011,1與要求序列的第一個數匹配,所以進入S1狀態;
seq_in = 0時,當前序列為10010,10與要求的前兩個數匹配,所以進入S2狀態。
第二步:根據流程轉換分析畫出狀態機的狀態轉移圖,如下圖所示:
第三步:根據狀態機轉移圖用經典三段式(或者二段式)寫出verilog代碼
3.12verilog代碼//使用狀態機設計檢測“1001”的序列檢測器
//可重疊檢測序列“1001”
module sequence_detect03(
inputclk ,
inputrst_n,
inputseq_in,
output reg mismatch//檢驗序列是否匹配,匹配輸出0,不匹配輸出0
);
//采用獨熱碼編譯五個狀態,初始IDLE狀態為待機狀態
//獨熱碼相比二進制碼和格雷碼,方便電路設計判斷、狀態轉移,且邏輯更簡單
parameterIDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
//定義兩個寄存器表示狀態機的目前狀態和下一狀態
reg [4:0] curr_state;
reg [4:0] next_state;
//第一段使用時序邏輯描述狀態轉移
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
//第二段使用組合邏輯判斷狀態轉移條件
always@(*) begin
if(!rst_n) begin
next_state <= IDLE;
end
else begin
case(curr_state)
IDLE :next_state = seq_in?S1:IDLE;
S1 :next_state = seq_in?S1:S2;
S2 :next_state = seq_in?S1:S3;
S3 :next_state = seq_in?S4:IDLE;
S4 :next_state = seq_in?S1:S2;
default:next_state = IDLE;//養成良好代碼風格,不能遺漏,防生成latch,也可以通過賦初值避免
endcase
end
end
//第三段描述狀態輸出(可以使用組合邏輯,也可以用時序邏輯)
//此處采用時序邏輯,同時也提供組合邏輯代碼示例
always@(posedge clk or negedge rst_n) begin//時序邏輯描述輸出
if(!rst_n) begin
mismatch <= 1'b1;
end
else if(next_state == S4) begin
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;
end
end
//assign mismatch = (curr_state ==S4) ? 1'b0 : 1'b1;//組合邏輯描述輸出
endmodule
3.13Testbench`timescale 1ns/1ps//仿真時間單位1ns 仿真時間精度1ps
module sequence_detect03_tb();
//信號申明
regclk;
regrst_n;
regseq_in;
wiremismatch;
//復位信號生成
//輸入信號生成,輸入信號為“1001001001001”
//時鐘信號與復位信號賦初值
initial begin
clk = 0;
rst_n = 1;
#5 rst_n = 0;
#10 rst_n = 1;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
end
//時鐘信號生成
always #5 clk = ~clk;
//模塊實例化(將申明的信號連接起來即可)
sequence_detect03 u_sequence_detect03(
.clk(clk),
.rst_n(rst_n),
.seq_in(seq_in),
.mismatch(mismatch)
);
endmodule
3.14仿真結果
輸入序列1001001001001,根據可重復檢測理論上可檢測四次信號翻轉,從仿真結果可以看到mismatch發生四次翻轉,且第二次翻轉的1001中的第一個1來自第一組1001中最后一個1,即發生重疊亦可檢測。
3.2非重疊檢測3.21 非重疊檢測方法
題目:設計一個序列檢測器,用來檢測序列 1001,用狀態機完成電路,可重復檢測序列1001
第一步,分析狀態機狀態轉移,分析如下:
IDLE: 初始狀態,代表目前沒有接收到滿足要求的數據。
seq_in = 1時,等于1001中的第一個數,進入S1狀態;
seq_in = 0時,保持狀態。
S1:代表目前已經有了1個匹配的數據。
seq_in = 0時,當前序列為10,等于1001中的前兩個數,進入S2狀態;
seq_in = 1時,當前序列為11,不是1001的前兩個數,但1是1001的第一個數,所以保持S1狀態。
S2:代表目前已經有了2個匹配的數據。
seq_in = 0時,當前序列為100,等于1001中的前三個數,進入S3狀態;
seq_in = 1時,當前序列為101,不是1001的前三個數,但1是1001的第一個數,所以進入S1狀態。
S3:代表目前已經有了3個匹配的數據。
seq_in = 1時,當前序列為1001,與要求序列匹配,進入S4狀態;
seq_in = 0時,當前序列為1000,與要求序列不配,0與初始狀態匹配,所以進入IDLE狀態。
S4:最終狀態,代表目前已經得到了匹配的序列,輸出信號翻轉。
seq_in = 1時,當前序列為10011,1與要求序列的第一個數匹配,所以進入S1狀態;
seq_in = 0時,當前序列為10010,10與要求的前兩個數匹配,但是要求非重疊檢測,所以進入IDLE狀態。
第二步:根據流程轉換分析畫出狀態機的狀態轉移圖,如下圖所示
第三步:根據狀態機轉移圖用經典三段式(或者二段式)寫出verilog代碼
3.22verilog代碼//使用狀態機設計檢測“1001”的序列檢測器
//非重疊檢測序列“1001”
module sequence_detect04(
inputclk ,
inputrst_n,
inputseq_in,
output reg mismatch//檢驗序列是否匹配,匹配輸出0,不匹配輸出0
);
//采用獨熱碼編譯五個狀態,初始IDLE狀態為待機狀態
//獨熱碼相比二進制碼和格雷碼,方便電路設計判斷、狀態轉移,且邏輯更簡單
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
//定義兩個寄存器表示狀態機的目前狀態和下一狀態
reg [4:0] curr_state;
reg [4:0] next_state;
//第一段使用時序邏輯描述狀態轉移
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
curr_state <= IDLE;
end
else begin
curr_state <= next_state;
end
end
//第二段使用組合邏輯判斷狀態轉移條件
always@(*) begin
if(!rst_n) begin
next_state <= IDLE;
end
else begin
case(curr_state)
IDLE :next_state = seq_in?S1:IDLE;
S1 :next_state = seq_in?S1:S2;
S2 :next_state = seq_in?S1:S3;
S3 :next_state = seq_in?S4:IDLE;
S4 :next_state = seq_in?S1:IDLE;
default:next_state = IDLE;//養成良好代碼風格,不能遺漏,防生成latch,也可以通過賦初值避免
endcase
end
end
//第三段描述狀態輸出(可以使用組合邏輯,也可以用時序邏輯)
//此處采用時序邏輯,同時也提供組合邏輯代碼示例
always@(posedge clk or negedge rst_n) begin//時序邏輯描述輸出
if(!rst_n) begin
mismatch <= 1'b1;
end
else if(next_state == S4) begin
mismatch <= 1'b0;
end
else begin
mismatch <= 1'b1;
end
end
//assign mismatch = (curr_state ==S4) ? 1'b0 : 1'b1;//組合邏輯描述輸出
endmodule
3.23Testbench`timescale 1ns/1ps//仿真時間單位1ns 仿真時間精度1ps
module sequence_detect04_tb();
//信號申明
regclk;
regrst_n;
regseq_in;
wiremismatch;
//復位信號生成
//輸入信號生成,輸入信號為“1001001001001”
//時鐘信號與復位信號賦初值
initial begin
clk = 0;
rst_n = 1;
#5 rst_n = 0;
#10 rst_n = 1;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
seq_in = 0;#10;
seq_in = 0;#10;
seq_in = 1;#10;
end
//時鐘信號生成
always #5 clk = ~clk;
//模塊實例化(將申明的信號連接起來即可)
sequence_detect04 u_sequence_detect04(
.clk(clk),
.rst_n(rst_n),
.seq_in(seq_in),
.mismatch(mismatch)
);
endmodule
3.24仿真結果
輸入序列1001001001001,根據可不重疊檢測理論上可檢測兩次信號翻轉,從仿真結果可以看到mismatch發生兩次翻轉,且第二組的1001中的第一個1來自第一組1001中最后一個1,即發生重疊不可檢測,所以相比于重疊檢測少了第二次翻轉(同理第四次翻轉同樣不可發生)。
四、總結
狀態機法序列檢測器:一句話概括就是設計復雜、不易擴展但是檢測模式靈活。相比使用移位寄存器來說的話,狀態機稍稍復雜些,主要體現在不易擴展(重新檢測不同序列需重新設計狀態轉移)和狀態機的狀態轉移判斷上;但是這樣也給狀態機帶來了優點 ,就是靈活性好,可以靈活處理輸入和輸出,因為狀態機具有可編程性。同時可以處理較為復雜的序列檢測任務,因為狀態機可以支持多個狀態和轉換。
移位寄存器法:一句話概括就是設計簡單、易于擴展但是檢測模式呆板。相比于使用狀態機來說的話,只能處理簡單的序列檢測任務,因為它沒有狀態機的多狀態和轉換功能。且輸入和輸出的靈活性差,因為寄存器序列移位寄存器是固定的,檢測模式固定。但是優勢很明顯,就是設計和開發相對簡單,只需要幾個寄存器和邏輯門。且易于擴展,如果要檢測另一個序列,只需要修改輸入數據。
模式選擇:前言部分提到了檢測模式包括重疊模式、連續模式、間隔模式等等。本文著重分析重疊與非重疊檢測模式,結論是重疊檢測模式可以用狀態機和移位寄存器設計,非重疊檢測模式可以用靈活的狀態機設計;本文都是基于默認的連續檢測模式設計,如果采用間隔檢測模式,處理方法是添加指示信號使能端,可以用狀態機和移位寄存器設計。因為設計邏輯簡單,所以這部分省略,可自行參照第二部分代碼設計。
綜上所述,狀態機序列檢測器適用于處理較為復雜的序列檢測任務,而寄存器序列移位寄存器適用于處理簡單的序列檢測任務。在實際應用中,應根據具體的需求來選擇合適的序列檢測方法。
有你想看的精彩 至芯科技FPGA就業培訓班——助你步入成功之路、8月12號西安中心開課、歡迎咨詢! FPGA學習:阻塞賦值和非阻塞賦值的可綜合性 FPGA學習:條件語句的可綜合性
掃碼加微信邀請您加入FPGA學習交流群
歡迎加入至芯科技FPGA微信學習交流群,這里有一群優秀的FPGA工程師、學生、老師、這里FPGA技術交流學習氛圍濃厚、相互分享、相互幫助、叫上小伙伴一起加入吧!
點個在看你最好看
原文標題:FPGA學習-序列檢測器
文章出處:【微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
-
FPGA
+關注
關注
1629文章
21744瀏覽量
603611
原文標題:FPGA學習-序列檢測器
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論