一、要求
设计一个序列检测同步时序逻辑电路,要实现的功能如下:
当已有输入码流出现序列111000或101110时输出检测信号为1,否则输出为0。在时序上检测到完整序列的下一个时钟周期输出检测结果。输入信号有效为1时表示当前输入有效,否则表示无效。之前输入依旧计入序列中并不清零,即允许序列重叠检测。例如:
输入码流(设输入数据均有效)和输出检测为
[I] 0 0 1 1 1 0 0 0 1 1 0 1 1 1 0 0 0 0
[O] 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1
模块输入输出功能定义:
名称 |
方向 |
位宽 |
描述 |
clk |
I |
1 |
系统时钟 |
rst_n |
I |
1 |
异步复位,低电平有效 |
din_vld |
I |
1 |
输入数据有效指示 |
din |
I |
1 |
输入数据 |
result |
O |
1 |
输出检测结果 |
二、实现
1.移位寄存器比较法
/*模块端口定义*/
module seq_detect(
input clk,
input rst_n,
input din_vld,
input din,
output reg result
);
reg [5:0] tmp = 6'd0;
/*移位寄存器*/
always @(posedge clk or negedge rst_n) begin
if(!rst_n) tmp <= 6'd0;
else if(din_vld) tmp[5:0] <= {tmp[4:0],din};
end
/*条件判断产生输出*/
always @(posedge clk or negedge rst_n) begin
if(!rst_n) result <= 1'b0;
else if(tmp == 6'b111000 || tmp == 6'b101110) result <= 1'b1;
else result <= 1'b0;
end
endmodule
testbench:
`timescale 1ns / 1ps
module tb_seq_detect();
reg clk;
reg rst_n;
reg din_vld;
reg din;
wire result;
initial begin
clk = 1'b0;
rst_n = 1'b0;
din_vld = 1'b0;
#10
din = 1'd0;
#100
rst_n = 1'b1;
din_vld = 1'b1;
end
always #50 clk = ~clk; //10MHz
always #2000 din_vld = ~din_vld;
/*产生随机输入*/
always @(posedge clk) begin
din <= {$random}%2;
end
/*实例化测试模块*/
seq_detect u_seq_detect(
.clk(clk),
.rst_n(rst_n),
.din(din),
.din_vld(din_vld),
.result(result)
);
endmodule
仿真结果:
可见对于输入的随机序列,在rst_n = 1且din_vld = 1的条件下,满足连续输入的6bit为111000和101110时,输出result = 1。din_vld = 0时输入无效,tmp保持原状态。
2、有限状态机FSM
/*
三段式状态机:三个always模块
1.同步时序描述状态转移;
2.组合逻辑判断状态转移条件;
3.描述状态输出
*/
/*模块端口定义*/
module seq_detect(
input clk,
input rst_n,
input din_vld,
input din,
output reg result
);
reg [3:0] state, next_state;
/*
分析: 共有12个状态,对应输入如下:
idle:0 s1:1 s2:11 s3:111 s4 :1110 s5 :11100 s6:111000
s7:10 s8:101 s9:1011 s10:10111 s11:101110
*/
/*状态编码*/
parameter idle = 4'd0, s1 = 4'd1, s2 = 4'd2, s3 = 4'd3, s4 = 4'd4, s5 = 4'd5,
s6 = 4'd6, s7 = 4'd7, s8 = 4'd8, s9 = 4'd9, s10 = 4'd10, s11 = 4'd11;
/*状态转移*/
always @(posedge clk or negedge rst_n) begin
if(!rst_n) state <= idle;
else if (din_vld) state <= next_state;
else state <= state;
end
/*转移条件判断*/
always @(*) begin
case(state)
idle: next_state = din ? s1 : idle;
s1: next_state = din ? s2 : s7;
s2: next_state = din ? s3 : s7;
s3: next_state = din ? s3 : s4;
s4: next_state = din ? s8 : s5;
s5: next_state = din ? s1 : s6;
s6: next_state = din ? s1 : idle;
s7: next_state = din ? s8 : idle;
s8: next_state = din ? s9 : s7;
s9: next_state = din ? s10 : s7;
s10: next_state = din ? s3 : s11;
s11: next_state = din ? s8 : s5;
default: next_state = idle;
endcase
end
/*输出描述*/
always @(posedge clk or negedge rst_n) begin
if(!rst_n) result <= 1'b0;
else if(state == s6 || state == s11) result <= 1'b1;
else result <= 1'b0;
end
endmodule
testbench同上。
仿真结果:
可见输入为连续的101110和111000时,在下一个时钟周期有result = 1。
综合结果:
文章来源:https://www.toymoban.com/news/detail-457211.html
2022/1/17 1:32 文章来源地址https://www.toymoban.com/news/detail-457211.html
到了这里,关于序列检测器的verilog实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!