一、设计要求(鲲鲲指定的就直接贴过来)
设计序列信号检测器:当输入码流为111000或101110时输出信号为1,否则输出0,然后对后续序列重新检测。如给定序列1011100010,输出只会拉高一次,对应红色序列段,而下划线序列段并不会使输出拉高。
从设计指标中可以得出,鲲鲲让我们做的是双序列都可以触发且非重复检测。
二、序列检测器原理
实际上并没有想象中的复杂,序列检测器的典型设计方法就是三段式状态机,不论是我们学过的静电1101序列检测器、10110序列检测器还是我们这次设计的双序列检测器,没有本质区别,不同的只是状态转移的状态数和转移的复杂度。
通过题目,我们就能得到以下状态转移图:(dot生成)
dot源码
digraph Moore_FSM{
bgcolor = "lavender";
//起始状态
IDLE[label = "IDLE",shape = "circle",style="",color="lightgoldenrod1"];
//中间状态
S0[label = "S0",shape = "circle",color="lime"];
S1_1[label = "S1_1",shape = "circle",color="lime"];
S2_1[label = "S2_1",shape = "circle",color="lime"];
S3_1[label = "S3_1",shape = "circle",color="lime"];
S4_1[label = "S4_1",shape = "circle",color="lime"];
S1_2[label = "S1_2",shape = "circle",color="lime"];
S2_2[label = "S2_2",shape = "circle",color="lime"];
S3_2[label = "S3_2",shape = "circle",color="lime"];
S4_2[label = "S4_2",shape = "circle",color="lime"];
//输出结果
TEST[label = "TEST",shape = "circle",color="seagreen1"];
//开始连线
IDLE -> S0[label = "1/0"];
IDLE -> IDLE[label = "0/0"];
S0 -> S1_1[label = "1/0"];
S0 -> S1_2[label = "0/0"];
S1_1 -> S2_1[label = "1/0"];
S1_1 -> S1_2[label = "0/0"];
S2_1 -> S3_1[label = "0/0"];
S2_1 -> S1_1[label = "1/0"];
S3_1 -> S4_1[label = "0/0"];
S3_1 -> S2_2[label = "1/0"];
S4_1 -> TEST[label = "0/0"];
S4_1 -> S0[label = "1/0"];
S1_2 -> S2_2[label = "1/0"];
S1_2 -> IDLE[label = "0/0"];
S2_2 -> S3_2[label = "1/0"];
S2_2 -> S1_2[label = "0/0"];
S3_2 -> S4_2[label = "1/0"];
S3_2 -> IDLE[label = "0/0"];
S4_2 -> TEST[label = "0/0"];
S4_2 -> S2_1[label = "1/0"];
TEST -> IDLE[label = "/1"];
}
三、Verilog实现与仿真
1、Verilog代码:
应用三段式状态机思想,状态机由状态寄存器、状态转移逻辑、输出控制逻辑组成,具体代码如下:
module seq_dector(
input clk,
input rst_n,
input data_in,
output reg data_out
);
//定义状态寄存器
reg [10:0]current_state,next_state;
//状态定义:独热码
parameter IDLE = 11'b00000000001;
parameter S0 = 11'b00000000010;
parameter S1_1 = 11'b00000000100;
parameter S1_2 = 11'b00000001000;
parameter S2_1 = 11'b00000010000;
parameter S2_2 = 11'b00000100000;
parameter S3_1 = 11'b00001000000;
parameter S3_2 = 11'b00010000000;
parameter S4_1 = 11'b00100000000;
parameter S4_2 = 11'b01000000000;
parameter TEST = 11'b10000000000;
//同步时序逻辑控制状态的切换
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
//组合逻辑判断状态转移条件
always@(*)
begin
if(!rst_n)
begin
next_state = IDLE;
end
else
begin
case(current_state)
IDLE:
begin
if(data_in == 1'b1)
next_state = S0;
else
next_state = IDLE;
end
S0:
begin
if(data_in == 1'b1)
next_state = S1_1;
else
next_state = S1_2;
end
S1_1:
begin
if(data_in == 1'b1)
next_state = S2_1;
else
next_state = S1_2;
end
S1_2:
begin
if(data_in == 1'b1)
next_state = S2_2;
else
next_state = IDLE;
end
S2_1:
begin
if(data_in == 1'b0)
next_state = S3_1;
else
next_state = S2_2;
end
S2_2:
begin
if(data_in == 1'b1)
next_state = S3_2;
else
next_state = S1_2;
end
S3_1:
begin
if(data_in == 1'b0)
next_state = S4_1;
else
next_state = S2_2;
end
S3_2:
begin
if(data_in == 1'b1)
next_state = S4_2;
else
next_state = IDLE;
end
S4_1:
begin
if(data_in == 1'b0)
next_state = TEST;
else
next_state = IDLE;
end
S4_2:
begin
if(data_in == 1'b0)
next_state = TEST;
else
next_state = S2_1;
end
TEST:
begin
next_state = IDLE;
end
endcase
end
end
//同步逻辑描述状态的输出
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data_out <= 1'b0;
end
else
begin
if(next_state == TEST)
data_out <= 1'b1;
else
data_out <= 1'b0;
end
end
endmodule
2、testbench
module testbench;
// Inputs
reg clk;
reg rst_n;
reg data_in;
// Outputs
wire data_out;
// Instantiate the Unit Under Test (UUT)
seq_dector uut (
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.data_out(data_out)
);
initial begin
// Initialize Inputs
clk = 0;
rst_n = 0;
data_in = 0;
// Wait 100 ns for global reset to finish
#20;
rst_n = 1'b1;
// Add stimulus here
data_in = 1'b0;
#20
data_in = 1'b1;
#20
data_in = 1'b0;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b0;
#20
data_in = 1'b0;
#20
data_in = 1'b0;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b0;
#20
data_in = 1'b0;
#20
data_in = 1'b0;
#20
data_in = 1'b1;
#20
data_in = 1'b0;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b1;
#20
data_in = 1'b0;
$finish;
end
always #10 clk = ~clk;
endmodule
3、仿真结果
设计测试激励序列:0-101110_00-111000-101110
理论上结果: 00000000100000000010000001
仿真结果:
由于状态机由上升沿触发,所以从上图可以看出:在第一个有效序列101110到来的时候,在上升沿的时刻输出信号1,持续到下一个时钟上升沿。后来的111000和101110也是如此。
并且完成了非重复性检测的要求,序列检测器在遇到10111000的时候只产生一次检测信号。