序列发生器(两类序列、三种设计方法和两种发生模式|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

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti