ASIC-WORLD Verilog(11)过程时序控制

news2024/11/17 3:54:00

写在前面

        在自己准备写一些简单的verilog教程之前,参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。

        这是网站原文:Verilog Tutorial

        这是系列导航:Verilog教程系列文章导航


过程块和时序控制(Procedural blocks and timing controls

  • 延时控制(Delay controls)
  • 边沿敏感的事件控制(Edge-Sensitive Event controls)
  • 电平敏感的事件控制(Level-Sensitive Event controls-Wait statements)
  • 特定事件控制(Named Events)

延时控制

        通过指定特定的仿真时间来达到延时的目的,一般语法是这样的:

#< time > < statement >;

        比如2个仿真时间单位后给复位信号赋值1;5个仿真时间单位后在给复位信号赋值0:

#2 reset = 1; //2个时间单位后赋值为1

#5 reset = 0; //5个时间单位后赋值为0

        下面是一个完整的例子,用来模拟一个复位,并通过 $monitor 来监控各个寄存器的值:

module clk_gen ();

reg clk, reset; 

initial begin
  $monitor ("TIME = %g RESET = %b CLOCK = %b", $time, reset, clk); //监控各个寄存器的值
  clk = 0; 
  reset = 0; 
  #2  reset = 1;  //2个单位后复位赋值为1
  #5  reset = 0;  //5个单位后复位赋值为0
  #10  $finish;
end 

always #1  clk =  ! clk; //每一个时间单位翻转一次时钟,即生成时钟信号,周期为2个时间单位

endmodule

        这是窗口的仿真结果:

 TIME = 0  RESET = 0 CLOCK = 0
 TIME = 1  RESET = 0 CLOCK = 1
 TIME = 2  RESET = 1 CLOCK = 0
 TIME = 3  RESET = 1 CLOCK = 1
 TIME = 4  RESET = 1 CLOCK = 0
 TIME = 5  RESET = 1 CLOCK = 1
 TIME = 6  RESET = 1 CLOCK = 0
 TIME = 7  RESET = 0 CLOCK = 1
 TIME = 8  RESET = 0 CLOCK = 0
 TIME = 9  RESET = 0 CLOCK = 1
 TIME = 10 RESET = 0 CLOCK = 0
 TIME = 11 RESET = 0 CLOCK = 1
 TIME = 12 RESET = 0 CLOCK = 0
 TIME = 13 RESET = 0 CLOCK = 1
 TIME = 14 RESET = 0 CLOCK = 0
 TIME = 15 RESET = 0 CLOCK = 1
 TIME = 16 RESET = 0 CLOCK = 0

        这是仿真结果的波形图:


边沿敏感的事件控制

        通过指定特定事件的边沿变化来控制时间(语句)的执行。一般语法是这样的:

@ (< posedge >|< negedge > signal) < statement >;

        通过时钟信号的 上升沿/下降沿 来控制某个事件的执行就是很经典的边沿敏感型事件控制语句。比如在enable信号的上升沿后的5个时钟单位后触发trigger信号为1:

always @ (posedge enable)begin 
   trigger = 0;
   repeat (5) begin    //重复5次
     @ (posedge clk) ; //在上升沿被触发
  end
   trigger = 1;         //触发其值为1
end

        这个代码可以拓展一下,并加上相应的测试脚本:


module edge_wait_example();

reg enable, clk, trigger;

//在每个enable上升沿的5个时钟后把trigger赋值为1
always @ (posedge enable)	
begin 
  trigger = 0;
  repeat (5) begin
    @ (posedge clk) ;
  end
  trigger = 1; 
end


initial begin
  $monitor ("TIME : %g CLK : %b ENABLE : %b TRIGGER : %b",
    $time, clk,enable,trigger);
  clk = 0;
  enable = 0;
  //通过延时语句分别对enable赋值
   #5   enable = 1;
   #1   enable = 0;
   #10  enable = 1;
   #1   enable = 0;
   #10  $finish;
end

always #1  clk = ~clk;

endmodule

        这是仿真结果:

 TIME : 0 CLK : 0 ENABLE : 0 TRIGGER : x
 TIME : 1 CLK : 1 ENABLE : 0 TRIGGER : x
 TIME : 2 CLK : 0 ENABLE : 0 TRIGGER : x
 TIME : 3 CLK : 1 ENABLE : 0 TRIGGER : x
 TIME : 4 CLK : 0 ENABLE : 0 TRIGGER : x
 TIME : 5 CLK : 1 ENABLE : 1 TRIGGER : 0
 TIME : 6 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 7 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 8 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 9 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 10 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 11 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 12 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 13 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 14 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 15 CLK : 1 ENABLE : 0 TRIGGER : 1
 TIME : 16 CLK : 0 ENABLE : 1 TRIGGER : 0
 TIME : 17 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 18 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 19 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 20 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 21 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 22 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 23 CLK : 1 ENABLE : 0 TRIGGER : 0
 TIME : 24 CLK : 0 ENABLE : 0 TRIGGER : 0
 TIME : 25 CLK : 1 ENABLE : 0 TRIGGER : 1
 TIME : 26 CLK : 0 ENABLE : 0 TRIGGER : 1

电平敏感的事件控制

        当前条件为真时才执行接下来的语句,有点类似if语句。它的一般语法是这样的:

wait (< expression >) < statement >; 

        比如当data_ready为真时,才把data_bus的值赋给data:

wait (data_ready == 1)  data = data_bus; 

        这个代码可以拓展一下,并加上相应的测试脚本:

module wait_example();

reg mem_read, data_ready;
reg [7:0] data_bus, data;

always @ (mem_read or data_bus or data_ready) begin
  data = 0;
  while (mem_read == 1'b1) begin
    wait (data_ready == 1) #1 data = data_bus;
  end
end

// Testbench Code here
initial begin
 $monitor ("TIME = %g READ = %b READY = %b DATA = %b", 
   $time, mem_read, data_ready, data);
 data_bus = 0;
 mem_read = 0;
 data_ready = 0;
 #10 data_bus = 8'hDE;
 #10 mem_read = 1;
 #20 data_ready = 1;
 #1  mem_read = 1;
 #1  data_ready = 0;
 #10 data_bus = 8'hAD;
 #10 mem_read = 1;
 #20 data_ready = 1;
 #1  mem_read = 1;
 #1  data_ready = 0;
 #10 $finish;
end

endmodule

        这是仿真结果:

 TIME = 0  READ = 0 READY = 0 DATA = 00000000
 TIME = 20 READ = 1 READY = 0 DATA = 00000000
 TIME = 40 READ = 1 READY = 1 DATA = 00000000
 TIME = 41 READ = 1 READY = 1 DATA = 11011110
 TIME = 42 READ = 1 READY = 0 DATA = 11011110
 TIME = 82 READ = 1 READY = 1 DATA = 11011110
 TIME = 83 READ = 1 READY = 1 DATA = 10101101
 TIME = 84 READ = 1 READY = 0 DATA = 10101101 


赋值内延迟语句(Intra-Assignment Timing Controls) 

        这是相对于 赋值间延迟语句(Inter-Assignment Timing Controls) 的概念,赋值间延迟语句就是我们平常最常用的延迟语句,也就是这种:

#10 rega = regb;

        这种情况下,赋值语句需要等待一定时间,然后将计算结果(右侧值)赋值给目标信号(左侧值)。 

        而赋值内延迟语句的用法则是这样的:

rega = #10 regb;

        它是先计算出右侧值,延时完成后再将结果赋给左侧。看看下面的例子:

  1 module intra_assign();
  2 
  3 reg a, b;
  4 
  5 initial begin
  6   $monitor("TIME = %g  A = %b  B = %b",$time, a , b);
  7   a = 1; 
  8   b = 0; 
  9   a = #10 0; 
 10   b = a;
 11    #20  $display("TIME = %g  A = %b  B = %b",$time, a , b);
 12   $finish;
 13 end 
 14 
 15 endmodule

        这是仿真结果:

 TIME = 0   A = 1  B = 0
 TIME = 10  A = 0  B = 0
 TIME = 30  A = 0  B = 0 

 


使用连续赋值语句对组合逻辑建模

        组合逻辑就是无论右侧的结果何时发生了变化,左侧的值都会同样立即发生改变。

例1 三态缓冲器

module tri_buf_using_assign();
reg data_in, enable;
wire pad;

assign pad = (enable) ? data_in : 1'bz;

initial begin
  $monitor ("TIME = %g ENABLE = %b DATA : %b PAD %b", 
    $time, enable, data_in, pad);
  #1 enable = 0;
  #1 data_in = 1;
  #1 enable = 1;
  #1 data_in = 0;
  #1 enable = 0;
  #1 $finish;
end

endmodule

        这个三态缓冲器也是经典的控制I2C、1-Wire等总线的一种方法。当enable为1时,就往总线上输出数据;当enable为0时,此时总线为高组态,就可以从总线上读取数据了。

        仿真结果:

 TIME = 0 ENABLE = x DATA : x PAD x
 TIME = 1 ENABLE = 0 DATA : x PAD z
 TIME = 2 ENABLE = 0 DATA : 1 PAD z
 TIME = 3 ENABLE = 1 DATA : 1 PAD 1
 TIME = 4 ENABLE = 1 DATA : 0 PAD 0
 TIME = 5 ENABLE = 0 DATA : 0 PAD z

 

例2 多路选择器

        同样的,这样还可以实现多路选择器:

module mux_using_assign();
reg data_in_0, data_in_1;
wire data_out;
reg  sel;

assign data_out = (sel) ? data_in_1 : data_in_0; 

// Testbench code here
initial begin
  $monitor("TIME = %g SEL = %b DATA0 = %b DATA1 = %b OUT = %b",
    $time,sel,data_in_0,data_in_1,data_out);
  data_in_0 = 0;
  data_in_1 = 0;
  sel = 0;
  #10 sel = 1;
  #10 $finish;
end

// Toggel data_in_0 at #1
always #1 data_in_0 = ~data_in_0;

// Toggel data_in_1 at #2
always #2 data_in_1 = ~data_in_1;

endmodule

        仿真结果很简单直观,看看就好:

 TIME = 0 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0
 TIME = 1 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1
 TIME = 2 SEL = 0 DATA0 = 0 DATA1 = 1 OUT = 0
 TIME = 3 SEL = 0 DATA0 = 1 DATA1 = 1 OUT = 1
 TIME = 4 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0
 TIME = 5 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1
 TIME = 6 SEL = 0 DATA0 = 0 DATA1 = 1 OUT = 0
 TIME = 7 SEL = 0 DATA0 = 1 DATA1 = 1 OUT = 1
 TIME = 8 SEL = 0 DATA0 = 0 DATA1 = 0 OUT = 0
 TIME = 9 SEL = 0 DATA0 = 1 DATA1 = 0 OUT = 1
 TIME = 10 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1
 TIME = 11 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1
 TIME = 12 SEL = 1 DATA0 = 0 DATA1 = 0 OUT = 0
 TIME = 13 SEL = 1 DATA0 = 1 DATA1 = 0 OUT = 0
 TIME = 14 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1
 TIME = 15 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1
 TIME = 16 SEL = 1 DATA0 = 0 DATA1 = 0 OUT = 0
 TIME = 17 SEL = 1 DATA0 = 1 DATA1 = 0 OUT = 0
 TIME = 18 SEL = 1 DATA0 = 0 DATA1 = 1 OUT = 1
 TIME = 19 SEL = 1 DATA0 = 1 DATA1 = 1 OUT = 1 

 


  •  📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/814582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【vue】vue中Mixins的用法(jeecg-boot为例):

文章目录 一、jeecg-boot本身只有JeecgListMixin.js二、使用Mixin:三、mixins详解&#xff1a;【1】由于每个项目的接口和参数不同>这里引进js进行处理&#xff0c;不在Mixin里面处理了&#xff08;Mixin只做公共数据处理&#xff09;【2】公共的页面字典【3】解决方法里面不…

2009年上半年 软件设计师 上午试卷3

●下图属于UML 中的&#xff08;46),其中&#xff0c;AccountManagement 需要&#xff08;47)。 (46)A.组件图 B.部署图 C.类图 D.对象图 (47)A.实现 IdentityVerifier 接口并被 CreditCardServices 调用 B.调用 CreditCardServices 实现的 Identity Verifier 接口 C.实现 I…

设计模式大白话——装饰者模式

装饰者模式 文章目录 装饰者模式一、概述二、应用场景三、代码示例四、小结 一、概述 ​ 装饰者模式&#xff0c;此模式最核心之处在于装饰二字&#xff0c;之所以需要装饰&#xff0c;是因为基础的功能无法满足需求&#xff0c;并且装饰是临时的&#xff0c;并不是永久的&…

基于Java+spring+springMvc+mybatis+jsp学生选课管理系统

基于JavaspringspringMvcmybatisjsp学生选课管理系统 一、系统介绍二、功能展示1.课程列表(学生)2.已选课程(学生)3.已修课程(学生)4.我的课程&#xff08;老师&#xff09;5.课程打分&#xff08;老师&#xff09;6.课程管理、学生管理、教师管理&#xff08;系统管理员&#…

python字典:怎么取出key对应的值

目录 python中的字典是什么 怎么判断key是否在字典中 怎么取出key对应的值 总结 python中的字典是什么 在Python中&#xff0c;字典&#xff08;Dictionary&#xff09;是一种无序且可变的数据类型&#xff0c;用于存储键-值&#xff08;Key-Value&#xff09;对。字典通过…

电脑卡顿反应慢怎么处理?提升反应速度的方法

电脑卡顿反应慢是很常见的问题&#xff0c;然而&#xff0c;我们可以采取一些方法来处理这个问题&#xff0c;帮助大家提升电脑反应速度。​ 一、提升电脑反应速度的方法 当电脑运行顺畅时&#xff0c;我们的工作体验也会更加愉悦。然而&#xff0c;如果电脑出现卡顿反应慢的…

【项目设计】MySQL 连接池的设计

目录 &#x1f449;关键技术点&#x1f448;&#x1f449;项目背景&#x1f448;&#x1f449;连接池功能点介绍&#x1f448;&#x1f449;MySQL Server 参数介绍&#x1f448;&#x1f449;功能实现设计&#x1f448;&#x1f449;开发平台选型&#x1f448;&#x1f449;MyS…

【雕爷学编程】MicroPython动手做(24)——掌控板之拓展掌控宝

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

【雕爷学编程】MicroPython动手做(23)——掌控板之WiFi与蓝牙2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

1400*D. Candy Box (easy version)(贪心)

3 10 9 Example input 3 8 1 4 8 4 5 6 3 8 16 2 1 3 3 4 3 4 4 1 3 2 2 2 4 1 1 9 2 2 4 4 4 7 7 7 7 output 题意&#xff1a; n个糖果&#xff0c;分为多个种类&#xff0c;要求尽可能的多选&#xff0c;并且使得不同种类的数量不能相同。 解析&#xff1a; 记录每种糖…

音视频技术开发周刊 | 304

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 更强的Llama 2开源&#xff0c;可直接商用&#xff1a;一夜之间&#xff0c;大模型格局变了 Meta 终于发布了大家期待已久的免费可商用版本 Llama 2。 6000份问卷透露出AI…

Java生成二维码——附Utils工具类

参加2023年的计算机设计大赛国赛&#xff0c;拿到了一等奖。 现在将项目中的工具类代码剥离出来&#xff0c;方便之后项目开发中复用。 实现效果&#xff1a; 代码实现&#xff1a; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import c…

挑战双面侧柱碰试验:比亚迪CTB保障高品质出行

对于用户来说&#xff0c;选择汽车时最应该重视的要素是什么&#xff1f; 第一&#xff0c;是安全&#xff1b;第二&#xff0c;是安全&#xff1b;第三&#xff0c;还是安全&#xff01; 那么作为新能源汽车的代表&#xff0c;比亚迪在保障驾乘人员的安全方面又是怎样做的呢&a…

基于SpringCloud+Vue的分布式架构网上商城系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

FPGA实现NIC 10G UDP协议栈网卡,纯verilog代码编写,提供工程源码和技术支持

目录 1、前言2、我这里已有的UDP方案3、10G网卡基本性能简介4、详细设计方案接口概述PCIe HIPDMA IFAXI总线接口时钟同步处理TXQ和RXQ队列TXCQ和RXCQ队列完成EQ MAC PHY流水线队列管理发送调度程序端口和接口数据路径以及发送和接收引擎分段内存接口 5、vivado工程详解6、上板…

国内 github.com经常打不开的解决办法

1、打开网站http://tool.chinaz.com/dns/ 2、在A类型中填写github.com,再点击监测按钮 3、复制下面任意一个ip 4、打开电脑文件C:\Windows\System32\drivers\etc下的host文件 5、在host文件的最后一刚加入刚才复制的IP 6、重新打开GitHub

对外接口签名生成方式

接口签名生成方式 前言 当某个系统对外部系统提供接口访问时&#xff0c;为提高接口请求安全性&#xff0c;往往会在接口访问时添加签名&#xff0c;当外部系统访问本系统签名验证成功时才能正常返回数据&#xff0c;一般接口提供方会与外部系统提前约定好&#xff0c;不同外…

六天入门PyTorch深度学习(1/6)

六天带你入门PyTorch深度学习(1/6) 之PyTorch初认识 Pytorch深度学习快速入门简易教程&#xff0c;适合所有新手学习打好框架基础 跟着我的节奏一步一步学&#xff0c;一周即可掌握 跟着我的节奏一步一步学&#xff0c;一周即可掌握 import torch #导入torch库&#xff0c…

django4.2 day1Django快速入门

1、创建虚拟环境 打开cmd安装virtualenv pip install virtualenvwrapper-winworkon 查看虚拟环境mkvirtualenv 创建新的虚拟环境删除虚拟环境 rmvirtualenv 进入虚拟环境 workon env 2、创建django虚拟环境并安装django 创建虚拟环境mkvirtualenv django4env进入虚拟环境安…

Mycat-Balance使用指南

MyCAT Balance是一个Java NIO的高性能负载均衡器&#xff0c;可以替代普通的硬件的交换机或其LVS类似的复杂机制&#xff0c;实现MyCAT集群的负载均衡。 MyCAT Balance的配置文件在conf目录下&#xff0c;frontend-conf.为前端配置&#xff0c;包括绑定的端口等&#xff0c;js…