序列发生器(两类序列、三种设计方法和两种发生模式|verilog代码|Testbench|仿真结果)

本文主要是介绍序列发生器(两类序列、三种设计方法和两种发生模式|verilog代码|Testbench|仿真结果),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

序列发生器

  • 一、前言
  • 二、状态机法、寄存器法和计数器法
    • 2.1 状态机法
      • 2.1.1使用状态机生成序列1001
      • 2.1.2 Verilog代码
      • 2.1.3 Tsetbench
      • 2.1.4 仿真结果
    • 2.2移位寄存器法
      • 2.2.1使用移位寄存器生成序列1001
      • 2.2.2 Verilog代码
      • 2.2.3 Tsetbench
      • 2.2.4 仿真结果
    • 2.3计数器法
      • 2.3.1 使用计数器生成序列1001
      • 2.3.2 Verilog代码
      • 2.3.3 Tsetbench
      • 2.3.4 仿真结果
  • 三、重叠发生与非重叠发生
    • 3.1非重叠和重叠生成序列“1001”
    • 3.2 verilog代码
    • 3.3 Testbench
    • 3.4 仿真结果
  • 四、伪随机序列发生器
    • 4.1 伪随机序列发生器原理
    • 4.2 verilog代码
    • 4.3 Testbench
    • 4.4 仿真结果
  • 五、总结

在这里插入图片描述



数字IC经典电路设计
经典电路设计是数字IC设计里基础中的基础,盖大房子的第一部是打造结实可靠的地基,每一篇笔者都会分门别类给出设计原理、设计方法、verilog代码、Testbench、仿真波形。然而实际的数字IC设计过程中考虑的问题远多于此,通过本系列希望大家对数字IC中一些经典电路的设计有初步入门了解。能力有限,纰漏难免,欢迎大家交流指正。

快速导航链接如下:

个人主页链接
1.数字分频器设计
2.序列检测器设计
3.序列发生器设计
4.序列模三检测器设计
5.奇偶校验器设计
6.自然二进制数与格雷码转换



一、前言

序列发生器是一种基于数字电路中逻辑门、触发器等组件设计的模块化电路,可以按照特定的顺序生成一系列数字信号或数据。

为什么需要设计序列发生器呢?

在数字IC设计中,序列发生器通常被用于产生特定的数字序列,以用于测试和验证数字电路的正确性。序列发生器通常被用于产生随机或伪随机数字序列,以模拟实际的操作环境,并测试数字电路的各种情况下的响应。

序列发生器通常用于测试数字电路中的寄存器、计数器、状态机等模块。例如,在设计一个计数器时,需要验证计数器是否可以正确地计数,并且在达到最大计数值时是否能够正确地回滚到初始值。为了验证这些功能,需要使用一个序列发生器来产生一系列的计数值,并将这些值输入到计数器中进行测试。因此,序列发生器在数字IC设计中是一个非常重要的工具,它可以帮助设计师验证数字电路的正确性,并提高数字电路的可靠性和性能。

序列发生器有哪些发生模式呢?

以下是一些常见的序列发生器模式:

  • 简单发生器:按照固定的顺序依次输出数字序列。
  • 密码型发生器:根据特定的编码方式,产生符合要求的数字序列,如曼彻斯特编码、差分曼彻斯特编码等。
  • 伪随机序列发生器:产生看似随机的数字序列,但实际上是按照特定的算法生成的,用于加密和通信等领域。

序列发生器的设计思路同序列检测器相似,常用简单序列发生器设计有如下三种设计思路:(1)状态机法;(2)移位寄存器法;(3)计数器法。

二、状态机法、寄存器法和计数器法

2.1 状态机法

2.1.1使用状态机生成序列1001

要求:使用状态机设计一个序列发生器,可循环生成序列“1001”,要求序列不重叠

此处设计思路与序列检测器相似,且更为简单, 参考序列检测器2.1状态机部分。以生成“1001”序列为例,借用万能的状态机,设计四个状态并且依次发生状态转移,通过判断当前的状态从而输出一位对应的数字,四个状态分别对应序列“1001”的四位数字。因为有限状态机的工作原理,序列“1001”将会被逐位循环输出。

2.1.2 Verilog代码

//使用状态机设计发生“1001”的序列发生器
//可非重叠发生序列“1001”
module sequence_generator01(input	  clk, input 	  rst_n,output   reg  seq_out );//采用独热码编译四个状态,初始IDLE状态为待机状态
//独热码相比二进制码和格雷码,方便电路设计判断、状态转移,且逻辑更简单 
parameter        IDLE = 4'b0001;
parameter        S1   = 4'b0010;
parameter 	  	 S2   = 4'b0100;
parameter        S3   = 4'b1000;//定义两个寄存器表示状态机的目前状态和下一状态
reg [3:0]	 curr_state;
reg [3:0] 	 next_state;//第一段使用时序逻辑描述状态转移
always@(posedge clk or negedge rst_n) beginif(!rst_n) begincurr_state <= IDLE;endelse begincurr_state <= next_state;end
end//第二段使用组合逻辑判断状态转移条件
always@(*) beginif(!rst_n) beginnext_state <= IDLE;endelse begincase(curr_state)IDLE  :next_state = S1;S1	  :next_state = S2;S2	  :next_state = S3;S3	  :next_state = IDLE;default:next_state = IDLE;	//养成良好代码风格,不能遗漏,防生成latch,也可以通过赋初值避免endcaseend
end//第三段使用时序逻辑描述状态输出
//通过判断状态机的状态来判断当前的输出值,达到输出序列“1001”目的
always@(posedge clk or negedge rst_n) beginif(!rst_n) beginseq_out <= 1'b0;endelse begincase(next_state)IDLE  :seq_out <= 1'b1;S1	  :seq_out <= 1'b0;S2	  :seq_out <= 1'b0;S3	  :seq_out <= 1'b1;default:seq_out <= 1'b0;endcaseend
endendmodule

2.1.3 Tsetbench

`timescale 1ns/1ps		//仿真时间单位1ns 仿真时间精度1ps
module sequence_gnerator01_tb();//信号申明
reg 	clk;
reg 	rst_n;
wire 	seq_out;//生成复位信号
//为时钟信号和复位信号赋初值
initial beginclk    = 0;rst_n  = 1;#5  rst_n = 0;#10 rst_n = 1;
end//生成时钟信号
always #5  clk = ~clk;//模块实例化(将申明的信号连接起来即可)
sequence_generator01 u_sequence_generator01(.clk        	 (clk),.rst_n		     (rst_n), .seq_out		 (seq_out));endmodule

2.1.4 仿真结果

在这里插入图片描述

2.2移位寄存器法

2.2.1使用移位寄存器生成序列1001

要求:使用移位寄存器设计一个序列发生器,可循环生成序列“1001”,要求序列不重叠

此处设计思路与序列检测器相似,且更为简单, 参考序列检测器2.2移位寄存器部分。设置一个和序列等长的寄存器,且初始数值为“1001”。处于时钟上升沿时完成两步操作:首先,输出当前寄存器的缓存数据的最高位;其次是,将数据的最高位转移到数据的最低位,拼接成新的数据重新缓存到寄存器中。因为移位寄存器的工作原理,缓存在移位寄存器中的序列“1001”将会被逐位循环输出。

2.2.2 Verilog代码

//使用移位寄存器设计发生“1001”的序列发生器
//可非重叠发生序列“1001”
module sequence_generator02(input	  clk, input 	  rst_n,output   reg  seq_out );//定义一个寄存器缓存数据
reg  [3:0]  seq;//使用时序逻辑完成复位和移位寄存器移位过程
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq <= 4'b1001;		//初始赋值“1001”(此处复位不是0)endelse begin seq <= {seq[2:0],seq[3]};	//移位寄存器最高位位移至最低位end 
end //使用时序逻辑完成复位与输出
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_out <= 1'b0;endelse begin seq_out <= seq[3];	//每个时钟上升沿输出最高位end 
endendmodule

2.2.3 Tsetbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sequence_gnerator02_tb();//信号申明
reg 	clk;
reg 	rst_n;
wire 	seq_out;//复位信号生成
//时钟信号与复位信号赋初值
initial beginclk    = 0;rst_n  = 1;#5  rst_n = 0;#10 rst_n = 1;
end//生成时钟信号
always #5  clk = ~clk;//模块实例化(将申明的信号连接起来即可)
sequence_generator02 u_sequence_generator02(.clk        	 (clk),.rst_n		 	 (rst_n), .seq_out		 (seq_out));endmodule

2.2.4 仿真结果

在这里插入图片描述

2.3计数器法

2.3.1 使用计数器生成序列1001

要求:使用计数器设计一个序列发生器,可循环生成序列“1001”,要求序列不重叠

在此处借用计数器设计序列发生器思路同借用状态机设计序列发生器异曲同工,此处的计数器可以理解为“小状态机”,在2.1中状态机状态的转移相当于此处计数器的不断累加。通过判断当前计数器数值从而输出一位对应的数字,四个状态分别对应序列“1001”的四位数字。因为计数器的工作原理,序列“1001”将会被逐位循环输出。

2.3.2 Verilog代码

//使用计数器设计发生“1001”的序列发生器
//可非重叠发生序列“1001”
module sequence_generator03(input	  clk, input 	  rst_n,output   reg  seq_out );//定义一个计数器
reg  [1:0]  cnt;//计数器模块
//完成0-3的循环计数
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt <= 2'b00;endelse if(cnt == 2'b11) begincnt <= 2'b00;endelse begin cnt <= cnt + 1'b1;end 
end //根据计数器的计数逐次输出“1001” 
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_out <= 1'b0;endelse begin case(cnt)2'b00:seq_out <= 1'b1;2'b01:seq_out <= 1'b0;2'b10:seq_out <= 1'b0;2'b11:seq_out <= 1'b1;endcaseend 
endendmodule

2.3.3 Tsetbench

`timescale 1ns/1ps		//仿真时间单位1ns 仿真时间精度1ps
module sequence_gnerator03_tb();//信号申明
reg 	clk;
reg 	rst_n;
wire 	seq_out;//生成复位信号
//为时钟信号和复位信号赋初值
initial beginclk    = 0;rst_n  = 1;#5  rst_n = 0;#10 rst_n = 1;
end//生成时钟信号
always #5  clk = ~clk;//模块实例化(将申明的信号连接起来即可)
sequence_generator03 u_sequence_generator03(.clk        	 (clk),.rst_n			 (rst_n), .seq_out		 (seq_out));endmodule

2.3.4 仿真结果

在这里插入图片描述

三、重叠发生与非重叠发生

在上一篇序列检测器文章中,我们提到了关于序列检测的四种模式—重叠模式、非重叠模式、连续模式、间隔模式,在序列发生器这里同样存在重叠序列发生模式和非重叠序列发生模式。这里之所以会单独领出来讲,是因为不同的发生模式会对设计出来的电路面积存在影响,尤其以移位寄存器法设计的序列发生器触发器的数量截然不同。以下以寄存器法设计为例来阐述两种模式的差异。

3.1非重叠和重叠生成序列“1001”

要求:使用移位寄存器设计一个序列发生器,可循环生成序列“1001”,有两个输出,一个要求序列不重叠一个要求序列重叠

3.2 verilog代码

//使用移位寄存器设计发生“1001”的序列发生器
//可重叠和非重叠发生序列“1001”
module sequence_generator04(input	  clk, input 	  rst_n,output   reg  seq_out_1,output   reg  seq_out_2);//定义两个个寄存器缓存数据
//寄存器定义的位数不同:非重叠缓存数据“1001”而重叠缓存缓存数据“100”
reg  [3:0]  seq_1;
reg  [2:0]  seq_2;//非重叠序列发生器模块
//使用时序逻辑完成复位和移位寄存器移位过程
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_1 <= 4'b1001;	//非重叠缓存数据“1001”(复位不是0)endelse begin seq_1 <= {seq_1[2:0],seq_1[3]};	//移位寄存器最高位位移至最低位end 
end //使用时序逻辑完成复位与输出 
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_out_1 <= 1'b0;endelse begin seq_out_1 <= seq_1[3];	//每个时钟上升沿输出最高位end 
end//重叠序列发生器模块
//使用时序逻辑完成复位和移位寄存器移位过程 
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_2 <= 4'b100;endelse begin seq_2 <= {seq_2[1:0],seq_2[2]};end 
end //使用时序逻辑完成复位与输出 
always@(posedge clk or negedge rst_n) begin if(!rst_n) begin seq_out_2 <= 1'b0;endelse begin seq_out_2 <= seq_2[2];	//每个时钟上升沿输出最高位end 
endendmodule

3.3 Testbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sequence_gnerator04_tb();//信号申明
reg 	clk;
reg 	rst_n;
wire 	seq_out_1;
wire 	seq_out_2;//复位信号生成
//时钟信号与复位信号赋初值
initial beginclk    = 0;rst_n  = 1;#5  rst_n = 0;#10 rst_n = 1;
end//生成时钟信号
always #5  clk = ~clk;//模块实例化(将申明的信号连接起来即可)
sequence_generator04 u_sequence_generator04(.clk        	 (clk),.rst_n		 	 (rst_n), .seq_out_1		 (seq_out_1),.seq_out_2		 (seq_out_2));endmodule

3.4 仿真结果

在这里插入图片描述

四、伪随机序列发生器

4.1 伪随机序列发生器原理

要求:设计一个简单序列发生器,可随机产生序列,随机序列无额外特定要求。

这个随机序列发生器可使用一个8位的“种子”来生成随机数。在每个时钟周期上升沿时,它使用当前种子值来生成一个新的种子值,并将其用作下一个时钟周期的种子。它还将当前种子值作为输出随机数。

这个随机序列发生器使用了一个简单的XOR Shift算法来生成新的种子值。这个算法通过将当前种子值向左右移位,并将结果与原始种子值进行异或来生成新的种子值。这个算法在实现上比较简单,并且可以生成高质量的随机数序列。

4.2 verilog代码

//使用XOR—Shift算法设计伪随机序列发生器
module sequence_generator05(input		clk,input		rst_n,output reg  [7:0] seq_out);//定义一个中间寄存器“种子”
reg [7:0] seed;//使用XOR—Shift算法形成“新种子”
always@(posedge clk or posedge rst_n) beginif(!rst_n) beginseed <= 8'b1; // 初始化种子endelse beginseed <= seed ^ (seed >> 2) ^ (seed << 3) ; // 生成新种子end
endalways@(posedge clk or posedge rst_n) beginif(!rst_n) beginseq_out <= 8'b0; // 初始化随机数endelse beginseq_out <= seed; // 生成新随机数end
endendmodule

4.3 Testbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sequence_gnerator05_tb();//信号申明
reg 	clk;
reg 	rst_n;
wire 	seq_out;//复位信号生成
//时钟信号与复位信号赋初值
initial beginclk    = 0;rst_n  = 1;#5  rst_n = 0;#10 rst_n = 1;
end//生成时钟信号
always #5  clk = ~clk;//模块实例化(将申明的信号连接起来即可)
sequence_generator05 u_sequence_generator05(.clk        	 (clk),.rst_n		 	 (rst_n), .seq_out		 (seq_out));endmodule

4.4 仿真结果

在这里插入图片描述

五、总结

  • 序列发生器设计方法:常见的固定序列发生器有三种设计思路,分别是状态机法、移位寄存器法、计数器法。在设计的时候虽然都可以使用,但往往在考虑电路的面积后会采取最优的方法。设计时尽量使的电路面积最小,必须考虑采用哪种方法借用的触发器数量最少!
  • 序列重叠发生与非重叠发生:以本篇序列发生器产生无重叠序列“1001”而言:
    ①若是采用状态机且采用独热码编译状态则需要四个触发器,采用格雷码编译状态只需两个触发器;若是采用移位寄存器,则需要两个触发器;若是采用计数器,则需要两个触发器;
    ②假设本篇序列发生器产生可重叠序列“1101011”,那么触发器的数目会与无重叠序列发生器一致吗?答案是不一样的!这里变成重叠序列,也就是产生的序列可以是110101101011…,这个序列中有两个1101011,二者共用11,因此以移位寄存器法产生这样的序列只需要一个5位的移位寄存器,而不可重叠序列需要7个。
    总的来说,在对序列无特殊要求情况下,若是想减少触发器的数目,可使用状态机格雷码编译状态,且产生的序列是可重叠的。
  • 伪随机序列发生器:除了固定序列的序列发生器,还存在随机序列发生器,这种随机序列发生器有很多种,可根据实际情况采用不同的算法设计出对应的伪随机序列发生器。本篇主要介绍的是最简单的伪随机序列发生器,主要通过 XOR Shift算法实现。


以下为补充的几个问题:

Question:欲产生序列信号 11010111,则至少需要______级触发器,采用______法设计。
Answer:3;状态机

Question:欲用移位寄存器产生序列信号1101010,试分析至少需要几级触发器。
Answer:6级触发器,用6级,移位状态为110101 - 101010 - 010101 - 101011 - 010110 - 101101 - 011010 - 110101……,依次输出最高位1101010。



不定期检查、补充、纠错,欢迎随时交流纠错
最后修改日期:2023.4.27

软件版本:

仿真软件:Modelsim 10.6c
绘图软件:亿图图示
描述语言:verilog

这篇关于序列发生器(两类序列、三种设计方法和两种发生模式|verilog代码|Testbench|仿真结果)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/740909

相关文章

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Pandas统计每行数据中的空值的方法示例

《Pandas统计每行数据中的空值的方法示例》处理缺失数据(NaN值)是一个非常常见的问题,本文主要介绍了Pandas统计每行数据中的空值的方法示例,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是空值?为什么要统计空值?准备工作创建示例数据统计每行空值数量进一步分析www.chinasem.cn处

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Windows 上如果忘记了 MySQL 密码 重置密码的两种方法

《Windows上如果忘记了MySQL密码重置密码的两种方法》:本文主要介绍Windows上如果忘记了MySQL密码重置密码的两种方法,本文通过两种方法结合实例代码给大家介绍的非常详细,感... 目录方法 1:以跳过权限验证模式启动 mysql 并重置密码方法 2:使用 my.ini 文件的临时配置在 Wi

MySQL重复数据处理的七种高效方法

《MySQL重复数据处理的七种高效方法》你是不是也曾遇到过这样的烦恼:明明系统测试时一切正常,上线后却频频出现重复数据,大批量导数据时,总有那么几条不听话的记录导致整个事务莫名回滚,今天,我就跟大家分... 目录1. 重复数据插入问题分析1.1 问题本质1.2 常见场景图2. 基础解决方案:使用异常捕获3.

最详细安装 PostgreSQL方法及常见问题解决

《最详细安装PostgreSQL方法及常见问题解决》:本文主要介绍最详细安装PostgreSQL方法及常见问题解决,介绍了在Windows系统上安装PostgreSQL及Linux系统上安装Po... 目录一、在 Windows 系统上安装 PostgreSQL1. 下载 PostgreSQL 安装包2.

SQL中redo log 刷⼊磁盘的常见方法

《SQL中redolog刷⼊磁盘的常见方法》本文主要介绍了SQL中redolog刷⼊磁盘的常见方法,将redolog刷入磁盘的方法确保了数据的持久性和一致性,下面就来具体介绍一下,感兴趣的可以了解... 目录Redo Log 刷入磁盘的方法Redo Log 刷入磁盘的过程代码示例(伪代码)在数据库系统中,r

Nginx location匹配模式与规则详解

《Nginxlocation匹配模式与规则详解》:本文主要介绍Nginxlocation匹配模式与规则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、环境二、匹配模式1. 精准模式2. 前缀模式(不继续匹配正则)3. 前缀模式(继续匹配正则)4. 正则模式(大

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组