Verilog -- 序列模三(整除3)檢測器
描述:輸入口是1bit,每次進來一位數據,檢查當前序列是否能整除3,能則輸出1,否則輸出0.
例如:
序列=1,out=0;
序列=11,out=1;
序列=110,out=1;
序列=1101,out=0;
首先需要找一下規律,一個數被三除,只可能會有三種情況:
1.余數為0;
2.余數為1;
3.余數為2;
假設當前序列表示的數是x,商為a,余數為b, 則有:
\[3a+b = x \]
需要注意的是:當新進來1bit數據時,實際上隱含了一個條件就是序列將被左移,也就是說如果當前序列為\(x\),輸入數據為0,則此時序列表示的數是\(2x\),如果輸入是1,則此時序列表示\(2x+1\).
下面分類討論:
- 余數為0的情況,也就是\(3a=x\):
- 輸入為0,因為之前余數為0表示已經能整除3,這時輸入為0相當於序列乘上個2,仍然能被3整除,輸出為1;
- 輸入為1,則有\(6a+1=2x\),可見此時余數為1;
- 余數為1的情況,也就是\(3a+1=x\):
- 輸入為0,則有\(6a+2=2x\),可見此時余數為2;
- 輸入為1,則有\(6a+3=2x+1\),此時序列可以被三整除,可見此時余數為0,輸出為1;
- 余數為2的情況,也就是\(3a+2=x\):
- 輸入為0,則有\(6a+4=2x\),可見此時余數為4 mod 3 = 1;
- 輸入為1,則有\(6a+5=2x+1\),可見此時余數為5 mod 3 = 2;
也可以用下面的表來描述:
last_Remainder | Input | Remainder | Output |
---|---|---|---|
0 | 1 | 1 | 0 |
0 | 0 | 0 | 1 |
1 | 0 | 2 | 0 |
1 | 1 | 0 | 1 |
2 | 0 | 1 | 0 |
2 | 1 | 2 | 0 |
通過上面的分析可以發現,余數的三種情況可以作為狀態機的三種狀態,當前的狀態以及輸出只跟之前的狀態和當前的輸入有關,因此可以使用Mearly型狀態機描述。
狀態轉換表:
State\Input | 0 | 1 |
---|---|---|
0 | 0/1 | 1/0 |
1 | 2/0 | 0/1 |
2 | 1/0 | 2/0 |
表中的值表示next_state/output
Verilog代碼:
`timescale 1ns/1ps
module seq_mod3_detector
(
input clk,
input rst_n,
input data,
output reg success
);
reg [1:0] current_state;
reg [1:0] next_state;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) current_state <= 0;
else current_state <= next_state;
end
always@(*)begin
next_state = 0;
case(current_state)
2'd0: if(data) next_state = 2'd1;
else next_state = 2'd0;
2'd1: if(data) next_state = 2'd0;
else next_state = 2'd2;
2'd2: if(data) next_state = 2'd2;
else next_state = 2'd1;
default: next_state = 0;
endcase
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n) success <= 0;
else begin
case(next_state)
2'd0: if(data) success <= 0;
else success <= 1;
2'd1: if(data) success <= 1;
else success <= 0;
2'd2: if(data) success <= 0;
else success <= 0;
default: success <= 0;
endcase
end
end
endmodule
testbench:
`timescale 1ns/1ps
module seq_mod3_detector_tb();
reg clk;
reg rst_n;
reg data;
wire success;
reg [127:0] seq;
always #1 clk = ~clk;
initial begin
clk = 1;
rst_n = 1;
data = 0;
#2 rst_n <= 0;
#2 rst_n <= 1;
seq = 0;
while(1) begin
@(posedge clk) begin
data = $random%2;
seq = (seq<<1) + data;
end
end
end
seq_mod3_detector U_SEQ_MOD3_DETECTOR_0(
.clk ( clk ),
.rst_n ( rst_n ),
.data ( data ),
.success ( success )
);
initial begin
$fsdbDumpvars();
$fsdbDumpMDA();
$dumpvars();
#200 $finish;
end
endmodule
波形圖:

可以看到,功能正確。