👉注:本文所用的代码均已编译通过,详情在文末。
👉注:更多精彩请看: 面试常问的verilog代码汇总 一文
简介
序列检测器顾名思义是用于检测一段给定的信号。可以使用状态机来直接描述,也可以采用移位寄存器的方式进行检测。
简单的序列检测器
这里用最简单的 ”111“序列检测器,当电路输入X出现三个或三个以上为1时,电路输出Z为1,否则输出为0。下面介绍2种代码形式,分别采取:状态机直接描述和使用移位寄存器检测。
1.采用直接的状态描述方式
首先,需要画出它的状态转移图,如下:
状态描述:
- A表示出现0个1时的状态;
- B表示出现一个1时的状态;
- C表示连续出现两个1时的状态;
- D表示出现三个或三个以上1时的状态。
根据状态图,我们就可以轻松写出状态机了,如下:
module check_sequence(z,x,clk,rst_n);
output z;
input x,clk,rst_n;
reg[1:0] state,next_state;//四个状态,需要两位状态寄存器表示
wire z;
parameter A=2'b00;
parameter B=2'b01;
parameter C=2'b10;
parameter D=2'b11;
assign z = (state == D) ? 1 : 0;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state <= A;
next_state <= A;
end
else begin
state <= next_state;
end
end
always@(x,state)begin
case(state)
A: if(x) next_state <= B;
else next_state <= A;
B:if(x) next_state <= C;
else next_state <= A;
C:if(x) next_state <= D;
else next_state <= A;
D:if(x) next_state <= D;
else next_state <= A;
//因为转态编码都全部case了,不需要使用default
endcase
end
endmodule
当然,上面转态转移图还能进一步化简,先根据状态转移图划出卡诺图并化简,最后可以写出输出方程和状态方程。详细可以回顾数字电路。
2.使用移位寄存器
使用3位移位寄存器,把输入X作为移位寄存器的输入,当寄存器中为111时,输出Z为1。
module check_sequence3(z,x,clk,rst_n);
output z;
input x,clk,rst_n;
reg[2:0] q;
reg z;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
q <= 0;
z <= 0;
end
else begin
q <= {q[1:0],x};//移位寄存
end
end
always@(posedge clk or negedge rst_n)begin
if(q==3'b111) z <= 1;
else z <= 0;
end
endmodule
稍复杂的序列检测器
“11010”序列检测器。当出现序列“11010”时,输出Y为1,否则Y为0。
1.状态机描述
不多逼逼,直接上状态转移图。如下:
module check_sequence(dout,din,clk,rst_n);
output dout;
input din,clk,rst_n;
reg[2:0] state,next_state;//六个状态,需要3位状态寄存器表示
wire dout;
parameter IDLE=3'b000,A=3'b001,B=3'b010,C=3'b011,D=3'b100,E=3'b101;
assign dout = (state == E) ? 1 : 0;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state <= 3'b000;
next_state <= 3'b000;
end
else begin
state <= next_state;
end
end
always@(state or din)begin
case(state)
IDLE:if(din) next_state <= A;
else next_state <= IDLE;
A:if(din) next_state <= B;
else next_state <= IDLE;
B:if(din) next_state <= B;
else next_state <= C;
C:if(din) next_state <= D;
else next_state <= IDLE;
D:if(din) next_state <= B;
else next_state <= E;
E:if(din) next_state <= A;
else next_state <= IDLE;
default: next_state <= IDLE;
endcase
end
endmodule
2.使用移位寄存器
也可以使用5位移位寄存器来检测序列,和3位很类似,这里就不赘述了。
代码编译
PS:以上三组代码均通过编译,分别命名为check_sequence、check_sequence1和check_sequence2