UVM基础-Phase机制(一)

2023-10-27

1.1 function phase和task phase

       在uvm_component组件内,注册到factory机制的组件,一般内部都会有运行phase的function或task,保证在验证过程,环境能够有序执行,完成验证任务。UVM提供了两大类phase,一类是用function实现的function phase,一类是用task实现的task phase,两大类phase各有各的特点和使用场景。UVM的完整phase机制包括下图所示内容。

 

function phase主要包括:build_phase、connect_phase、end_of_elaboration_phase、start_of_simulation_phase、extact_phase、check_phase、report_phase、finial_phase。他们的主要功能:

  • build_phase主要功能为uvm树形结构的建立,组件的实例化一般在build_phase中完成,还有就是会接受一些环境变量的传递,比如driver接受vif,一般在build_phase通过config_db::get获取。
  • connect_phase主要功能为uvm树形结构的连接,主要包括组件之间基于TLM的互联等功能实现。
  • end_of_elaboration_phase主要功能是在仿真之前要做的一些操作,比如组件实例化和连接之后,要完成组件之间参数的传递等功能。
  • start_of_simulation_phase一般为环境在进入动态仿真运行之前做的一些动作,比如辅助类成员变量的初始化等。
  • extact_phase主要为环境运行过后对于一些数据的处理,比如要完成数据的运行比对之前,需要对比对数据包的处理等。
  • check_phase主要为环境的检查phase,包括数据包比对结果的检查,信息汇总等。
  • report_phase为环境汇总信息并打印的phase,一般在环境完成数据比对处理,完成TLM建模后输出的验证结果汇总,打印到log中,会从report_phase进行展示。
  • finial_phase为结束运行的phase,控制验证环境到最后的结束,可以在结束之前做一些环境的处理动作,比如判断TLM FIFO的状态等。

一般情况下,function phase不会全部使用,使用的最多的是build_phase和connect_phase,如果有需要增加的环境操作,又和build_phase以及connect_phase中的动作有冲突,一般会选择增加phase,check_phase和report_phase一般在scoreboard中会使用。

       function phase是自上而下执行的,也就是先执行build_phase,建立uvm树形结构,再执行connect_phase,建立树形结构的连接关系,然后执行到start_of_simulation_phase之后,进入task phase的运行,task_phase又包含两类主要的phase,一个是run_phase,run_phase贯穿于整个task_phase,另外一类是12个子phase,按类别分为reset phase,configuration phase,main phase,shutdown phase,每个phase又包含pre,main和post。

  • reset_phase主要执行的是验证环境在进入仿真运行之前的复位动作,将环境变量,或者interface的信号先进行复位动作,初始化。
  • configure_phase主要执行验证环境在运行时的一些配置,一般运行前需要将环境配置成场景适配的模式,也包括DUT的初始化寄存器配置任务等。
  • main_phase是主要执行仿真的phase,包括激励的发送,环境数据的处理等等
  • shutdown_phase主要控制仿真的运行停止过程,包括下电流程等。

一般12个task phase是顺序执行的,也就是运行完reset的三个phase后再执行configure的相关phase,而run_phase和12个task phase之间又是并行执行的关系,也就是说,run_phase会贯穿12个phase运行的全过程。他们之间的关系可以表达为:

1.	fork
2.	     begin
3.	             run_phase(uvm_phase phase);
4.	     end
5.	     begin
6.	             pre_reset_phase(uvm_phase phase);
7.	             reset_phase(uvm_phase phase);
8.	             post_reset_phase(uvm_phase phase);
9.	             pre_configure_phase(uvm_phase phase);
10.	             configure_phase(uvm_phase phase);
11.	             post_configure_phase(uvm_phase phase);
12.	             pre_main_phase(uvm_phase phase);
13.	             main_phase(uvm_phase phase);
14.	             post_main_phase(uvm_phase phase);
15.	             pre_shutdown_phase(uvm_phase phase);
16.	             shutdown_phase(uvm_phase phase);
17.	             post_shutdown_phase(uvm_phase phase);
18.	      end
19.	join

function_phase在uvm树形结构的建立和连接,以及验证环境静态变量的初始化过程起到作用,因此一些节点的建立,和连接,以及相应静态参数初始化,应当写在验证环境的function phase中。

task phase为验证环境运行过程的主要phase,用于操作数据,驱动激励,实现数据比对,控制仿真运行等过程,内部实现为数据的处理,激励驱动等和时间有关的功能。

2.1 function phase执行顺序

对于单个组件的phase运行顺序为顺序执行,先build phase,再执行到connect_phase,最后执行finial_phase,如下图所示:

 

        那么对于不同component之间的执行顺序是什么样的,想象一下,uvm在运行过程,需要先建立uvm树形结构,对于function phase而言,承载的任务有建立树形结构和连接组件关系的作用,因此,function phase无非只有自顶向下建立树形结构,和自底向上连接树的节点,因此,对于build_phase而言,执行规则是自顶向下的运行,也就是说先执行顶层的build_phase,例如test_case0的build_phase,再执行env的build_phase,自顶向下建立树形结构。而connect_phase,包括后续的end_of_elaboration_phase和start_of_simulation_phase,以及其他function phase,都是自底向上执行的。

       这里重点说明build_phase,自顶向下建立树形结构的过程,其实是一个树节点遍历的过程,那么同层级的节点,执行顺序是什么样的?例如agent和rm以及scoreboard之间build_phase的执行顺序是什么?实际上,同层级节点上,build_phase是按照注册到factory机制后,实例化的参数名的字典序执行,也就是说,在父节点的build_phase中,通过component::type_id::create(“component_a”,this),create函数的第一个参数表示当前节点的实例化名,那么字典序越靠前,越先执行。

       那么对于叔侄关系的节点,比如scoreboard和driver,他们的执行顺序如何,计算机体系结构中,树的遍历有广度优先和深度优先的顺序,UVM是按照深度优先序遍历执行,也就是说,如果agent和scoreboard的实例化参数名分别是“aaa”和“bbb”,那么先执行agent的build_phase,然后是driver的,monitor的,指导agent的根节点遍历完成,再执行scoreboard;那如果反过来,会先执行scoreboard,再执行agent和根节点。总结一下:

  • 同层级节点build_phase按照create函数第一个参数的字典序执行;
  • 不同层级的节点,uvm按照深度优先遍历执行。

2.2 task phase执行顺序

       上节提到,task phase是验证环境主要运行的phase,包括run phase和12个子phase,实际上,在uvm树形结构的不同节点下,或者说在验证环境的不同组件之间,task phase都是一起执行的,但是task phase往往要配合objection机制一起使用,而run_phase和12个phase之间是并行执行的,也就是说run_phase会持续到post_shutdown_phase完成后,run_phase才运行完成。本节中,我们以所有组件的相同phase内部都进行raise_objection和drop_objection为例,说明task phase在不同组件之间的运行情况,假设验证环境中只存在两个组件A和B,组件A中有如下代码:(取12个子phase中的reset_phase,configure_phase,main_phase和shutdown_phase为例):

1.	class A extends uvm_component;
2.	      `uvm_component_utils(A)
3.	       function void new(string name="A", uvm_component parent);
4.	              super.new(name, parent);
5.	       endfunction
6.	
7.	       virtual function void build_phase(uvm_phase phase);
8.	......
9.	       virtual task reset_phase(uvm_phase phase);
10.	               super.reset_phase(phase);
11.	               phase.raise_objection(this);
12.	               `uvm_info(get_type_name(), "reset_phase is begin", UVM_HIGH);
13.	               #80;
14.	               `uvm_info(get_type_name(), "reset_phase is done", UVM_HIGH);
15.	               phase.drop_objection(this);
16.	       endtask
17.	
18.	       virtual task main_phase(uvm_phase phase);
19.	               super.main_phase(phase);
20.	               phase.raise_objection(this);
21.	               `uvm_info(get_type_name(), "main_phase is begin", UVM_HIGH);
22.	               #100;
23.	               `uvm_info(get_type_name(), "main_phase is done", UVM_HIGH);
24.	               phase.drop_objection(this);
25.	       endtask
26.	
27.	       virtual task shutdown_phase(uvm_phase phase);
28.	               super.shutdown_phase(phase);
29.	               phase.raise_objection(this);
30.	               `uvm_info(get_type_name(), "shutdown_phase is begin", UVM_HIGH);
31.	               #30;
32.	               `uvm_info(get_type_name(), "shutdown_phase is done", UVM_HIGH);
33.	               phase.drop_objection(this);
34.	       endtask
35.	endclass

组件B代码:

1.	class B extends uvm_component;
2.	      `uvm_component_utils(B)
3.	       function void new(string name="B", uvm_component parent);
4.	              super.new(name, parent);
5.	       endfunction
6.	
7.	       virtual function void build_phase(uvm_phase phase);
8.	......
9.	       virtual task reset_phase(uvm_phase phase);
10.	               super.reset_phase(phase);
11.	               phase.raise_objection(this);
12.	               `uvm_info(get_type_name(), "reset_phase is begin", UVM_HIGH);
13.	               #30;
14.	               `uvm_info(get_type_name(), "reset_phase is done", UVM_HIGH);
15.	               phase.drop_objection(this);
16.	       endtask
17.	
18.	       virtual task configure_phase(uvm_phase phase);
19.	               super.configure_phase(phase);
20.	               phase.raise_objection(this);
21.	               `uvm_info(get_type_name(), "configure_phaseis begin", UVM_HIGH);
22.	               #50;
23.	               `uvm_info(get_type_name(), "configure_phaseis done", UVM_HIGH);
24.	               phase.drop_objection(this);
25.	       endtask
26.	
27.	       virtual task main_phase(uvm_phase phase);
28.	               super.main_phase(phase);
29.	               phase.raise_objection(this);
30.	               `uvm_info(get_type_name(), "main_phase is begin", UVM_HIGH);
31.	               #120;
32.	               `uvm_info(get_type_name(), "main_phase is done", UVM_HIGH);
33.	               phase.drop_objection(this);
34.	       endtask
35.	
36.	       
37.	endclass

先看reset_phase:组件A和组件B都存在reset_phase,A的reset_phase存在延时:80ns,组件B的reset_phase延时:30ns;那么A和B的reset_phase并行执行,经过30ns后,组件B的reset_phase运行结束,而组件A的reset_phase继续执行剩余50ns,此时组件B会hold住,不会继续执行后面的phase,直到组件A的reset_phase完成。

再看configure phase:组件A中不存在configure phase,而组件B存在,且内部具有延时50ns;因为task phase在12个子phase之间是顺序执行的,而在组件之间是并行执行,那么此时组件A不会执行main_phase,而是等待组件B执行完configure phase,经过50ns延时之后,在继续往下执行。

再看main_phase:组件A和B都具有main_phase,且组件A中存在延时100ns,组件B中存在延时120ns;此时组件A和B同时执行main_phase,组件A先执行完,等待组件B将剩余的120ns执行完毕,然后再进shutdown phase。

最后看shutdown_phase:组件A存在shutdown_phase,而组件B不存在,那么组件A会执行shutdown phase,而组件B会停驻等待组件A完成shutdown phase的执行,最后完成仿真的运行。

实际上,上述实例,组件A和组件B在验证环境运行的过程中,phase执行顺序其实是这样的:

       可见动态运行phase之间是并行执行的,且需要等其他组件的phase执行完之后,再执行接下来的phase。实际上,这种规则下,phase中必须结合objection机制才是这样的规则,也就是说,phase内部运行阶段被raise_objection(this),和drop_objection(this)修饰。

       那么run_phase会是什么情况?对于同一个组件来讲,如果存在run_phase,那么run_phase一定是等待post_shutdown_phase运行结束之后,才停止,假设在组件A中存在run_phase:

virtual task run_phase(uvm_phase phase);
2.	               super.run_phase(phase);
3.	               phase.raise_objection(this);
4.	               #150ns;
5.	               phase.drop_objection(this);
6.	       endtask

        那么A的run_phase一定是在时间轴运行到280ns,完成shutdown_phase之后,再退出。那么如果B中也加入run_phase,并被raise_objection和drop_objection修饰,那么就要等组件A和B的run_phase以及post_shutdown_phase都运行结束,才结束整个task phase的运行。

        对于这个规则,实际上需要配合objection机制使用,如果在某个phase内部没有objection的raise和drop,运行情况就又不一样。此过程在objection章节讲解。

2.3 调用super.xxx_phase(phase)

       super.xxx_phase(phase)的使用,这句话的含义是,在运行的function或task内部调用父类的该function或者task,那么也就是说,如果一个类继承自某个类,而那个类中还有相同的phase,需要被重载的子类调用父类的phase而执行某些过程,那么就需要写明这句话。

       实际上,super.xxx_phase(phase)在组件继承的uvm_xxxx内部,并没有写过相关的流程和代码,也就是说,大部分情况下,组件如果继承自uvm的component或者component基类,调用super.xxx_phase(phase)不会有什么影响。唯一有区别的就是,在build_phase中,调用super.build_phase(phase),如果有变量通过config_db::set的方式发送给该组件,且该变量在收信组件中注册到了factory机制中,同时注册到了field_automation机制中,可以在收信组件省略get语句。也就是说,super.build_phase(phase)会自动get注册到field_automation机制中的变量。

       另外一种情况,就是用户自定义的组件中存在继承关系,且父类的phase中有一些初始化的动作,必须要执行,那么子类就可以调用super.phase,减少重复的代码,提升代码可重用性。举个例子:

       一般在定义uvm树顶节点的test_case0时,会将用户初始化的一些操作封装成test_base,在test_base的main_phase中做一些初始化的操作,比如配置寄存器等,而用例继承自test_base,需要在用例中调用test_base中的main_phase,先执行初始化动作,再执行具体的用例,那么就需要调用super.main_phase(phase)。

2.4 phase的跳转

       uvm还对phase机制提供了可跳转的功能,想象一个场景,在driver中,main_phase里写明了驱动过程,但是如果突发复位,那么需要在main_phase中执行reset过程,那么其实就会用到phase的跳转,phase跳转的语法为在需要跳转的phase中调用:phase.jump(uvm_xxx_phase::get());

       写段driver的代码看看:

1.	class driver extends uvm_driver#(uvm_sequence_item);
2.	      ......
3.	      extern virtual task drive_pkt();
4.	      extern virtual task reset_phase(uvm_phase phase);
5.	      extern virtual task main_phase(uvm_phase phase);
6.	      ......
7.	endclass
8.	
9.	task driver::reset_phase(uvm_phase phase);
10.	      super.reset_phase(phase);
11.	      phase.raise_objection(this);
12.	      vif.a <= 1'b0;
13.	      vif.b <= 2'h0;
14.	......
15.	      phase.drop_objection(this);
16.	endtask:reset_phase
17.	
18.	task main_phase(uvm_phase phase);
19.	      super.main_phase(phase);
20.	      fork
21.	            while(1) begin
22.	                        seq_item_port.get_next_item(seq);
23.	                        drive_pkt();
24.	                        seq_item_port.item_done();
25.	             end
26.	             begin
27.	                     @(negedge vif.reset_n);
28.	                     phase.jump(uvm_reset_phase::get());
29.	             end
30.	      join
31.	endtask
32.	endclass

可以看到28行,在线程内部发生复位后,可利用phase的跳转,跳到reset_phase,函数的传参使用里uvm_reset_phase的静态方法get(),实际上,除了reset_phase,其他phase都可以调用该方法。

uvm_build_phase::get()

uvm_pre_main_phase::get()

uvm_connect _phase::get()

uvm_main_phase::get()

uvm_end_of_elaboration_phase::get()

uvm_post_main_phase::get()

uvm_start_of_simulation_phase::get()

uvm_pre_shutdown_phase::get()

uvm_pre_reset_phase::get()

uvm_shutdown_phase::get()

uvm_reset_phase::get()

uvm_post_shutdown_phase::get()

uvm_post_reset_phase::get()

uvm_extract_phase::get()

uvm_pre_configure_phase::get()

uvm_check_phase::get()

uvm_configure_phase::get()

uvm_report_phase::get()

uvm_post_configure_phase::get()

uvm_finial_phase::get()

       如果发生跳转,那么其他组件的main_phase就会无法调用drop_objection,此时环境会报warning,那么发生跳转之后,验证环境的执行即从main phase跳转到reset_phase,而重新执行reset_phase->configure_phase->main_phase。

       向前跳转不能够跳到build_phase执行,因为运行task phase已经产生了运行时间,也就是说,main_phase的执行,仿真时间已经从0开始往后走,回调到build_phase要重新执行task phase走仿真运行时间,是不允许的。那么也就是说,main_phase的跳转,不能跳转到build_phase到start_of_simulation_phase之间的任意phase。

       phase的跳转可以向后跳转,也就是说,如果发生复位操作,或者环境想控制发生某个异常而直接结束仿真,那么就可以直接跳转到finial_phase,也就是run time phase之后的function phase,直接结束仿真。

       实际工程中,这种方式其实并不实用,因为通常工程上的验证环境组件都特别多,尤其如果scoreboard多了之后,其他组件的phase跳转,可能会造成其他组件的异常,比如scoreboard在extract phase中进行收到的包流比对,有可能造成多包或者丢包的情况,严重的会造成假pass,因此发生phase跳转,要清空scoreboard的数据包缓存中的数据包。

总结一下:

  • phase跳转发生在某个动态运行的phase中,使用phase.jump(uvm_xxx_phase::get())实现跳转。
  • 跳转发生后,重新执行跳转到的phase和其之后的其他phase,且其他组件中会包没有drop_objection warning。
  • phase跳转可以向前跳转,但是不能在已经走了仿真时间phase跳转到build_phase到start_of_simulation_phase之间的任意需要仿真从0执行的function phase。
  • phase可以向后跳转,且可以直接调转到结束仿真的function phase,如finial phase。
  • phase机制使用的时候要格外小心,一般尽量减少这个功能的使用,因为会增加仿真环境的调试难度(多组件协同方面)。

2.5 phase机制的运行停止机制

       回顾一下,uvm的verbosity机制中,如果突发uvm_fatal,仿真会直接结束,那么如果突发uvm_error,其实仿真是不会直接停止的,会运行到最后,或者运行到uvm_error的出现的最大次数后,仿真停止。实际上,如果在build_phase中突发uvm_error,验证环境也会直接结束,屏幕打印会出现uvm_fatal,这是为什么?uvm_phase机制的build_phase是建立uvm树形结构的主要phase,那么如果在build_phase中发生了uvm_error,uvm会认为无法建立树形结构,或者环境的重要参数无法获取,也就没有继续仿真的必要,因此会直接停掉。

       实际上,不止build_phase,在end_of_elaboration_phase及其之前的function phase中,如果发生uvm_error,uvm都会认为发生了致命错误而停止仿真。

       这个机制在大型设计中十分有帮助,因为大型设计里,编译和初始化往往要花费大量的时间,如果都用uvm_fatal,那么就会形成一个现象,就是修复一个uvm_fatal,运行一次,又会出现另一个uvm_fatal,效率十分低下。如果将end_of_elaboration_phase之前的phase的uvm_fatal全部改为uvm_error,可以极大提升仿真效率。

       另外,UVM还提供了仿真超时停止的设定,可以在某个组件中,一般是base_test中,使用uvm_root.set_timeout(500ns, 0)的形式设置。这句话的含义是,仿真环境运行500ns后停止。uvm_root的set_timeout函数有两个参数,一个是时间,也就是运行多久后仿真停止,作为运行时间的上限,第二个参数是是否可以被其后的其他set_timeout函数所覆盖。如果是1,则可以被后面运行到的set_timeout函数覆盖。如果是0则不可以。

       实际上,uvm提供了一个超时的宏定义:UVM_DEFAULT_TIMEOUT 9200s,也就是说,uvm最大可以运行9200s,这个数字对于eda仿真来讲,是非常大的。在这种机制下,uvm还可以通过在仿真选项上传参,来修改这个值,以达到设置仿真超时的效果,用法如下:

<vcs sim command> +UVM_TIMEOUT=”1000ns, YES”

UVM_TIMEOUT包括两个参数,一个是超时的具体时间,另一个是是否可以被覆盖。

总结一下:

  • uvm提供了两种仿真运行超时时间的设定方式:1是通过uvm_root.set_timeout(时间,0/1),参数两个含义,一个是超时的具体实践上限,另一个是是否可以被后面的set_timeout所覆盖。2是通过仿真命令传参,使用方式为:<vcs command> +UVM_TIMEOUT=”时间,YES/NO”,第一参数为超时时间,第二个参数为是否可以被覆盖。
  • uvm内置了仿真最长时间宏:UVM_DEFAULT_TIMEOUT 9200s,最长可运行9200s,改变这个宏也可以改变超时时间。

2.6 phase机制的调试

       phase机制在运行过程中,如果组件很多,那么debug会显得十分复杂,uvm也提供了phase的调试手段,可以在命令行输入:<vcs command> +UVM_PHASE_TRACE,进行phase的打印调试输出,方便debug。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UVM基础-Phase机制(一) 的相关文章

  • PRBS笔记

    1 概述 PRBS 伪随机二进制序列 也称为伪随机码 通常被用来测试高速信号的信号质量 伪随机 也说明了该码流并不是真正的随机 而是具有特性属性 码流由 多项式 决定 具有重复周期 PRBS具有多种阶数 如PRBS7 PRBS15 PRBS
  • 【Xilinx Vivado时序分析/约束系列6】FPGA开发时序分析/约束-IO时序输入延时

    目录 源同步FPGA输入时序分析的模型 input delay约束 极限input delay 往期系列博客 源同步FPGA输入时序分析的模型 以下为源同步FPGA输入时序分析的模型的示意图 在之前的文章中介绍过 在此介绍一下各个时钟延时的
  • Verilog:【1】时钟分频电路(clk_divider.sv)

    碎碎念 作为Basic Verilog的第一个学习笔记 打算用这种命名方式来对博客进行命名 应该有助于检索 简单阅览了部分工程的代码 发现里面有很多嵌套关系 因此决定先从基础模块开始 也是为了整个博客内容的流畅性 读者朋友有问题的话 也可以
  • Verilog的奇技淫巧[更新中]

    1 Verilog常用的数据选择语句vect a b 或vect a b 转载自 MDY常用的数据选择语句Verilog明德扬论坛 Powered by Discuz vect为变量名字 a为起始位置 加号或者减号代表着升序或者降序 b是进
  • Matlab 高斯信道下QPSK通带通信系统的简单仿真

    1 原理 2 仿真 3 总结反思 4 参考资料 1 原理 QPSK的具体内容请参考百度 QPSK的调制jie框图大致如下 QPSK信号可以采用正交调制的方式产生 如第一张图片的左半部分 I路信号与cos 信号相乘 Q 路信号与sin信号相乘
  • SD卡读写实验(SPI模式)

    对于 SD 卡的 SPI 模式而言 采用的 SPI 的通信模式为模式 3 即 CPOL 1 CPHA 1 在 SD 卡 2 0 版 本协议中 SPI CLK 时钟频率可达 50Mhz SD 卡的 SPI 模式 只用到了 SDIO D3 SP
  • 关于Keil中Memory中观察不到数据变化的问题以及启动文件栈的初始化

    关于Keil中Memory中观察不到数据变化的问题 在KEIL中观察Memory数据变化 一定要记得只能在RAM地址或ROM之内观察 如下图所示 RAM的地址设置在地址为0x20000000开始的地方 大小为0x20000 因此只有在这个范
  • 跨时钟域处理方法(一)——打拍

    一 说明 处理跨时钟域的数据可以分为单bit数据和多bit数据 而打拍的方法主要常见于处理单bit数据的跨时钟域问题 打拍的本质是通过添加寄存器 对输入的数据进行延拍 其主要目标是消除亚稳态的影响 常见的是打2拍 也就是添加2级寄存器 二
  • Verilog实现两路组相联cache

    cache代码 timescale 1ns 1ps cache共32块 分为16组 每组2块 即两路组相联 1块 4字 1字 4字节 主存共1024块 4096个字 主存地址共12位 1 0 为块内偏移 5 2 为组地址 11 6 为Tag
  • 八、RISC-V SoC外设——GPIO接口 代码讲解

    前几篇博文中注释了RISC V的内核CPU部分 从这篇开始来介绍RISC V SoC的外设部分 另外 在最后一个章节中会上传额外添加详细注释的工程代码 完全开源 如有需要可自行下载 目录 0 RISC V SoC注解系列文章目录 1 结构
  • 关于xilinx BRAM IP的延迟以及流程

    关于RAM IP的延迟 1 选择了output registers 可以在RAM输出端口添加register 也可以在core的输出添加 在primitives添加 降低clock to out到primitive的延迟 在core添加re
  • 八段数码管动态显示(输入数据为BCD编码)

    八段数码管动态显示 输入数据为BCD编码 一 数码管概述 图1 八段共阴数码管内部等效原理图 图2 八段共阳数码管内部等效原理图 上面两图分别是对应八段共阴 共阳的数码管内部等效图 共阴是将八个LED数码管的阴极连接在一起接低 阳极segm
  • TestBench编写_激励产生

    TestBench编写 激励产生 TestBench编写 激励产生 基本背景 读取函数介绍 a fopen函数使用 b fread函数使用 c fclose函数使用 实际使用 TestBench编写 激励产生 基本背景 最近遇到项目中需要对
  • FPG—VGA显示器字符显示(附代码)

    目录 1 实操 1 1 字符取模 1 2 顶层模块 1 3 图像数据生成模块 1 3 1 模块框图 1 3 2 波形图绘制 1 3 3 代码编写 1 3 4 仿真验证 2 总结 本例程大部分与VGA显示驱动内容相同 只是显示部分改变了 故此
  • 【FPGA多周期时序约束详解】- 解读FPGA多周期时序约束的全过程

    FPGA多周期时序约束详解 解读FPGA多周期时序约束的全过程 FPGA作为数字电路设计的常见工具 其设计中必然会遇到时序约束的问题 而多周期时序约束更是FPGA设计中不可避免的难点之一 本文将详细介绍FPGA多周期时序约束的全过程 并结合
  • 画时序图软件——TimeGen和Timing Designer下载

    在写实验报告的时候需要画波形图 但是手头没有很好的软件 就上网搜了一些 分享出来 这里分享的是TimeGen和Timing Designer两个软件 资源均来自网上 有侵权请联系 TimeGen使用和安装都比较简单 我发的应该里面有破解方法
  • Matlab图像处理系列——图像复原之噪声模型仿真

    微信公众号上线 搜索公众号 小灰灰的FPGA 关注可获取相关源码 定期更新有关FPGA的项目以及开源项目源码 包括但不限于各类检测芯片驱动 低速接口驱动 高速接口驱动 数据信号处理 图像处理以及AXI总线等 本节目录 一 图像复原的模型 二
  • TRICONEX MA2211-100 芯片上相互连接

    TRICONEX MA2211 100 芯片上相互连接 TRICONEX MA2211 100 所有相同的组件 io的电源 处理器 和内存将需要 但是 你可以看到所有这些带存储器和处理器的OO板 针不能嵌入到一个小的单片机上 现在是 普拉克
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573
  • ESP10B 锁定连接器

    ESP10B 锁定连接器 ESP10B 电机新增内容包括双极型号标准 NEMA 尺寸 17 23 和 34 的步进电机现在包括输出扭矩范围从 61 盎司英寸到 1291 盎司英寸的双极型号 该电机配有带锁定连接器的尾缆 可轻松连接 每转可步

随机推荐

  • windows10 彻底关闭自动更新【绝对管用】

    windows10 彻底关闭自动更新 绝对管用 以下三步必须全做 1 服务里禁用 Windows Update 2 将服务里的 Windows Update的恢复设置为无操作 3 删除自动更新的触发器 这个很重要 否则过一段时间自动更新还是
  • C/C++框架和库

    值得学习的C语言开源项目 Libevent libev是一个开源的事件驱动库 基于epoll kqueue等OS提供的基础设施 其以高效出名 它可以将IO事件 定时器 和信号统一起来 统一放在事件处理这一套框架下处理 基于Reactor模式
  • ESQLC数据类型 - varchar类型

    GBase8s ESQL C字符串数据类型 GBase8s ESQL C支持5种字符串数据类型 如果在数据库的列中使用字符串类型 例如CHAR或者VARCHAR 以下ESQL C字符串类型可以使用 C语言的char类型 GBase8s ES
  • CSS常用水平垂直居中的几种方法

    CSS水平垂直居中 一 利用margin auto 二 利用position absolute 三 弹性盒子 四 利用水平对齐和行高 五 grid 为方便理解 欢迎查看线上效果 在线试一试 一 利用margin auto 元素有宽度和高度时
  • Jquery 找指定div下的radio 加bind事件 select 选中一用 $("#Sex").find("option[data-id='0']").prop("selected"!!!!

    页面加载时处理的事情 document ready function 1 匿名策略数组 给select动态追加option选项 let EncryTypeList id 1 text 前n位后隐藏 id 2 text 后n位后隐藏 Encr
  • Return消息机制

    Return Listener 用于处理一些不可路由的消息 消息生产者通过制定一个Exchane和RoutingKey 把消息送达到某一个队列中去 消费者监听队列进行消费处理 但是在某些情况下 发送消息的时候 当前Exchange不存在或制
  • vs默认编码

    1 工具 选项 环境 文档 不能以代码页的编码格式保持数据时将文档保持为Unicode工具 选择 文本编辑器 自动检测不带签名的UTF 8编码打开cs文件后 点击 文件 高级保存选项 在弹出的对话框中 可以看到目前的编码方式为UTF 8 带
  • python实现 发送图片到打印机 进行打印

    前言 环境 操作系统 win10 python 3 8 16 依赖 pip install openpyxl qrcode pillow pypiwin32 reportlab 功能 python printer py 运行后 会检索本机已
  • 图的基本概念

    图 G Graph V Vertex E Edge 图G由顶点集V和边集E组成 记为G V E 其中V G 表示图G中顶点的有限非空集 E G 表示图G中顶点之间的关系 边 集合 若V V1 V2 Vn 则用 V 表示图G中顶点的个数 也称
  • Android开发之数据储存

    相关文章 Content Provider 内容提供者 Broadcast Receiver 广播接收者 什么是Service 服务 Android提供了五种数据存储方式 分别是 SharePreferences SQLite Conter
  • Android http java.net.SocketException: sendto failed: EPIPE 解决方案

    在项目中Http上传文件时遇到这样一个错误 W System err java net SocketException sendto failed EPIPE Broken pipe Caused by libcore io ErrnoEx
  • 教妹学Java(十):Unicode字符集简介

    大家好 我是沉默王二 一个和黄家驹一样身高 和刘德华一样颜值的程序员 本篇文章通过我和三妹对话的形式来谈一谈 Unicode字符集简介 教妹学 Java 没见过这么有趣的标题吧 语不惊人死不休 没错 本篇文章的标题就是这么酷炫 接受不了的同
  • 深度学习——利用GPU进行训练数据——安装错误的修正

    安装pytorch时 torch cuda is available 返回false 上网查阅资料 输入 conda list 查看从官网下载的pytorch是CPU版本还是GPU版本 显然 我安装的是cup版本 一 卸载pytorch 使
  • tkinter处理附件上传

    python import tkinter as tk from tkinter import filedialog def upload file selectFile tk filedialog askopenfilename entr
  • 包含.cpp .h的文件怎么运行(VisualStudio2013)

    网上下载c 代码 有 cpp h 文件 需要先建立空项目 下面网站中到第4步 再把 cpp文件复制到源文件中 h复制到头文件中 点开 cpp文件 运行ctrl F7 编译 ctrl F5 开始执行 https jingyan baidu c
  • 2.5.1 HMC扫描小型机

    最后更新2021 07 24 HMC扫描小型机是最基本的动作 其前提是HMC与小型机的FSP卡连接正确 由于FSP出厂设置是通过DHCP协议获得自身IP 而HMC自身又设置了DHCP服务功能 所以只要网线接通 HMC就会自动识别到小型机 但
  • 从入门到高手:大数据领域就业和发展指南

    随着秋季校招落下帷幕 网上的各类招聘数据也已分布 大数据行业工程师以平均月薪11 600元领跑全国 成为 超高薪 高大上 的代名词 如果你学的是大数据相关专业 那么恭喜你 你的发展良机来了 如果你想要转行大数据也为时不晚 本文将利用从前程无
  • MySQL之InnoDB主键索引的B+树的高度计算

    文章目录 MySQL之InnoDB主键索引的B 树的高度计算 1 高度为2和3 主键bigint类型 一行记录数据大小1k MySQL之InnoDB主键索引的B 树的高度计算 1 高度为2和3 主键bigint类型 一行记录数据大小1k I
  • 关于static变量的文件作用域

    Scenario A 在一个头文件中都有staic int a 9 然后 此头文件被多个cpp文件包含 不会报错 因为static的变量具有文件作用域 如果去掉static 则报错重复定义错误了 Scenario B 在a cpp中定义两个
  • UVM基础-Phase机制(一)

    一 UVM phase机制基础 1 1 function phase和task phase 在uvm component组件内 注册到factory机制的组件 一般内部都会有运行phase的function或task 保证在验证过程 环境能