07 串行数据流特定序列循环检测器的设计与功能验证(附源码)

写在前面,昨天一网友问了我关于状态机的问题,借此做一个记录:设计一个可循环检测的序列检测器记录,该模块使用moore型状态机实现,使用独热码编码。


虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击直达
应用工具:vcs 和 verdi



一、Demand

  模块功能是检测串行数据流中,一个5位数二进制10010出现的情况,实现循环检测(检测到10010之后,如果后续数据输入为010),即序列为10010010xxx,需检测到出现2次该序列,搭建测试平台进行功能验证。

二、Spec

(1)Analyze

  依需求可知,需检测的序列宽度为5,那么算上IDLE状态,状态机一共有6个状态,可设定为IDLE,S1,S2,S3,S4,S5。采用独热码编码。每检测到一次序列,输出一个信号,并且计数器自加1,以此记录一共检测到多少次。

在低速系统中,状态机中状态的个数 < 4个,使用二进制码编码
在低速系统中,状态机中状态的个数在4~24个,使用独热码编码
在低速系统中,状态机中状态的个数>24个,使用格雷码编码

(2)Interface Description

Signal NameWidthDirectionDescription
clk1inputSystem clk signal, xxMhz
rst1inputSystem reset signal
data1inputDetected data
result1outputDetection result signal
res_cnt2outputThe number of occurrences of the sequence

(3)FSM

在这里插入图片描述

三、Design and Functional Verification

(1)RTL

//-- modified by xlinxdu, 2022/04/24
module check #(
  parameter WIDHT = 2
)(
  input                   clk_i    ,
  input                   rst_n_i  ,

  //-- interface
  input                   data_i   ,
  output reg              result_o ,
  output reg [WIDHT-1:0]  res_cnt_o //(sum)
);

//-- state define
parameter  IDLE = 6'b00_0001;
parameter  S1   = 6'b00_0010;
parameter  S2   = 6'b00_0100;
parameter  S3   = 6'b00_1000;
parameter  S4   = 6'b01_0000;
parameter  S5   = 6'b10_0010;

reg  [5:0] cur_state;//current state
reg  [5:0] nxt_state;//next state

wire       result_s ;//sum
reg        nres_cnt ;//


/*-----------------------------------------------\
 -----------  updata of current state  ----------
\-----------------------------------------------*/

always @ (posedge clk_i or negedge rst_n_i) begin
  if (!rst_n_i) begin
    cur_state <= 6'b0;
  end
  else begin
    cur_state <= nxt_state;
  end
end


/*-----------------------------------------------\
 --------------  transfer of state  -------------
\-----------------------------------------------*/

always @ (*) begin
  case(cur_state) 
    IDLE: if(data_i) nxt_state = S1  ;
          else       nxt_state = IDLE;

    S1  : if(data_i) nxt_state = S1  ;
          else       nxt_state = S2  ; 

    S2  : if(data_i) nxt_state = S1  ;
          else       nxt_state = S3  ;

    S3  : if(data_i) nxt_state = S4  ;
          else       nxt_state = IDLE;

    S4  : if(data_i) nxt_state = S1  ;
          else       nxt_state = S5  ;

    S5  : if(data_i) nxt_state = S1  ;
          else       nxt_state = S3  ;

    default:         nxt_state = IDLE;
  endcase
end

/*-----------------------------------------------\
 ---------  updata of result counter  -----------
\-----------------------------------------------*/
always @ (*) begin
  if(nxt_state == S5) begin
    nres_cnt = 1'b1;
  end
  else begin
    nres_cnt = 1'b0;//clear 
  end
end

always @ (posedge clk_i or negedge rst_n_i) begin
  if (!rst_n_i) begin
    res_cnt_o <= 2'b0;
  end
  else begin
    res_cnt_o <= res_cnt_o + nres_cnt;
  end
end

/*-----------------------------------------------\
 ---------- updata of result_o   ----------
\-----------------------------------------------*/

//assign result_s = (cur_state == S4) ? 1'b1 : 1'b0;
assign result_s = (nxt_state == S5) ? 1'b1 : 1'b0;

always @ (posedge clk_i or negedge rst_n_i) begin
  if (!rst_n_i) begin
    result_o <= 1'b0;
  end
  else begin
    result_o <= result_s;
  end
end

endmodule

(2)Test Bench

module tb_check;
  reg         clk_i    ;
  reg         rst_n_i  ;
  reg         data_i   ;

  wire        result_o ;
  wire  [1:0] res_cnt_o;

reg [17:0] data_check;

initial begin
  clk_i = 0 ;
  rst_n_i = 1;
  data_i = 0;
  data_check = 18'b10_1001_0001_0010_0100;

  #5 rst_n_i = 0;
  #10 rst_n_i = 1;
end

always begin
  data_i = data_check[17];
  #60 data_check = (data_check << 1'b1);
end


check tb_check(
               .clk_i    (clk_i    ),
               .rst_n_i  (rst_n_i  ),
               .data_i   (data_i   ),
               .result_o (result_o ),
               .res_cnt_o(res_cnt_o)
);

always begin
  #30 clk_i = ~clk_i;
end



initial begin
  #2000 $finish;
  
  $fsdbDumpfile("check.fsdb");
  $fsdbDumpvars            ;
  $fsdbDumpMDA             ;
end

endmodule

四、Result

在这里插入图片描述
  在测试平台中,输入的数据为data_check = 18’b10_1001_0001_0010_0100,转换成串行数据流输入到被测试模块DUT中,见上图三个框,10010出现了三次。功能实现了在每检测一次输出一个信号,记一次数,保证了模块基本的数据通路。


作者:xlinxdu
版权:本文是作者原创,版权归作者所有。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

  • 94
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、实验目的: 1、深入了解与掌握同步时序逻辑电路的设计过程; 2、了解74LS74、74LS08、74LS32及74LS04芯片的功能; 3、能够根据电路图连接好实物图,并实现功能。学会设计过程中的检验与完善。 二、实验内容描述: 题目:“1 1 1”序列检测器。 原始条件:使用D触发器( 74 LS 74 )、“与”门 ( 74 LS 08 )、“或”门( 74 LS 32 )、非门 ( 74 LS 04 ),设计“1 1 1”序列检测器。 集成电路引脚图: D触发器( 74 LS 74 ) “与”门 ( 74 LS 08 ) “或........ 三、实验设计过程: 第1步,画出原始状态图和状态表。 根据任务书要求,设计序列检测器有一个外部输入x和一个外部输出Z。输入和输出的逻辑关系为:当外部输入x第一个为“1”,外部输出Z为“0”;当外部输入x第二个为“1”,外部输出Z为“0”;当外部输入x第三个为“1”,外部输出Z才为“1”。假定有一个外部输入x序列以及外部输出Z为: 输入x: 0 1 0 1 1 1 0 1 1 1 1 0 1 输出Z: 0 0 0 0 0 1 0 0 0 1 1 0 0 要判别序列检测器是否连续接收了“111”,电路必须用不同的状态记载外部输入x的值。假设电路的初始状态为A,x输入第一个“1”,检测器状态由A装换到B,用状态B记载检测器接受了111序列的第一个“1”,这时外部输出Z=0;x输入第二个“1”,检测器状态由B装换到C,用状态C记载检测器接受了111序列的第二个“1”,外部输出Z=0;x输入第三个“1”,检测器状态由C装换到D,外部输出Z=1。然后再根据外部输入及其他情况时的状态转移,写出相应的输出。以上分析了序列检测器工作,由此可画出图7-1所示的原始状态图。根据原始状态图可列出原始状态表,如表7-2所示。 现态 次态/输出 x = 0 x = 1 A A / 0 B / 0 B A / 0 C / 0 C A / 0 D / 1 D A / 0 D / 1 (表 7-2 原始状态表) (图

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xlinxdu

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值