MCDF实验——Lab3

2023-11-09

Lab3将在Lab2的基础上使用随机约束和环境结构来改进完善实验代码。Lab3中将对generator和initiator之间的数据生成和数据传输的处理进行改进,还将完善何时结束测试,将其主动权交于generator而不再是test组件。在组件结构方面,在原有的initiator、generator、agent、test组件的基础上,再加上monitor和checker,并且使其构成一个有机的整体,最终可以通过在线比较数据的方式完成对MCDT的测试。

一、随机约束

实验要求:

  1. 继承Lab2的大部分代码,基于Lab2对需要生成的数据包有了新的约束要求。数据类chnl_trans不再只局限于包含一个数据,而是多个数据,同时跟数据之间时间间隔的控制变量也在该类中声明为随机成员变量。
  2. 将原本在chnl_root_test类中用来结束仿真的$finish()变迁到generator中。
  3. 使用“restart”命令多次重启,比对连续两次生成的随机数据。然后再在仿真器命令行处使用“vsim -novopt -solvefaildebug -sv_seed 0 work.tb1”来加载仿真。仿真参数“-solvefaildebug”是为了调试随机变量的,而“-sv_seed NUM”则是为了传递随机的种子。最后再使用“vsim -novopt -solvefaildebug -sv_seed random work.tb1”命令加载仿真,对比前后两次的数据是否相同。

二、更加灵活的测试控制

如果要实现不同的test类,例如chnl_basic_testchnl_burst_testchnl_fifo_full_test,那么对于不同的test需要对chnl_generator的随机变量做出不同的控制,继而进一步控制其内部随机的chnl_trans对象。也就是说,随机化也是可以分层次的,例如在test层可以随机化generator层,而依靠generator被随机化的成员变量,再来利用它们进一步随机化generator中的chnl_trans对象,由此达到顶层到底层的随机化灵活控制。从这个角度出发,需要将generator从agent单元中搬迁出来,并且搁置在test层中来方便test层的随机控制。

实验要求:

  1. 将generator搬迁到test层次中,需要将gen和agent中组件的mailbox连接起来,方便gen与agent中init的数据通信。
  2. 实现在test中使用do_config()对gen进行随机化控制。
  3. 使用仿真时传递的参数来完成测试的选择。在以后的递归测试,即创建脚本命令,由仿真器读入,分别传递不同的随机种子和测试名称即可完成对应的随机测试。在之前的仿真命令添加额外的命令“+TESTNAME=testname”。

三、测试平台的结构

新增monitor和checker两个组件,在顶层环境中,将checker置于test层中,而不是agent中。

实验要求:

  1. chnl_monitor类和mcdt_monitor类各自的mon_trans()方法中需要采集正确的数据,将它们写入mailbox缓存,同时将捕捉的数据打印出来,便于调试。
  2. chnl_agent中,对chnl_monitor对象开始例化、传递虚接口和使其运行。
  3. chnl_checker的任务do_compare()中,需要从checker自己的数据缓存mailbox中分别取得一个输出端的采集数据和一个输入端的采集数据,进而将它们的内容比较。
  4. 在顶层环境chnl_root_test类中,需要对mdct_monitorchnl_checker进行例化、传递虚接口,并且将chnl_monitormcdt_monitor的邮箱句柄分别指向chnl_checker中的信箱实例。

四、代码实现

随机约束

实验要求1:

chnl_trans类实现随机化

  class chnl_trans;
    rand bit[31:0] data[];		//动态数组
    rand int ch_id;				//发送到哪一个channel
    rand int pkt_id;			//第几个数据包,即第几个trans
    rand int data_nidles;		//data之间空闲间隔周期
    rand int pkt_nidles;		//数据包之间空闲间隔周期
    bit rsp;					//响应标志位
    local static int obj_id = 0;
 
    // Specify constraint to match the chnl_basic_test request
    constraint cstr{
      data.size inside {[4:8]};
      foreach(data[i]) data[i] == 'hC000_0000 + (this.ch_id<<24) + (this.pkt_id<<8) + i;
      soft ch_id == 0;
      soft pkt_id == 0;
      data_nidles inside {[0:2]};
      pkt_nidles inside {[1:10]};
    };

    function new();
      this.obj_id++;
    endfunction

    function chnl_trans clone();
      chnl_trans c = new();
      c.data = this.data;
      c.ch_id = this.ch_id;
      c.pkt_id = this.pkt_id;
      c.data_nidles = this.data_nidles;
      c.pkt_nidles = this.pkt_nidles;
      c.rsp = this.rsp;
 
      // Could we put c.obj_id = this.obj_id here? and why?
      return c;
    endfunction

    function string sprint();
      string s;
      s = {s, $sformatf("=======================================\n")};
      s = {s, $sformatf("chnl_trans object content is as below: \n")};
      s = {s, $sformatf("obj_id = %0d: \n", this.obj_id)};
      foreach(data[i]) s = {s, $sformatf("data[%0d] = %8x \n", i, this.data[i])};
      s = {s, $sformatf("ch_id = %0d: \n", this.ch_id)};
      s = {s, $sformatf("pkt_id = %0d: \n", this.pkt_id)};
      s = {s, $sformatf("data_nidles = %0d: \n", this.data_nidles)};
      s = {s, $sformatf("pkt_nidles = %0d: \n", this.pkt_nidles)};
      s = {s, $sformatf("rsp = %0d: \n", this.rsp)};
      s = {s, $sformatf("=======================================\n")};
      return s;
    endfunction
  endclass: chnl_trans

chnl_generator

 class chnl_generator;
    rand int pkt_id = -1;				//
    rand int ch_id = -1;
    rand int data_nidles = -1;
    rand int pkt_nidles = -1;
    rand int data_size = -1;
    rand int ntrans = 10;

    mailbox #(chnl_trans) req_mb;
    mailbox #(chnl_trans) rsp_mb;

    constraint cstr{
      soft ch_id == -1;
      soft pkt_id == -1;
      soft data_size == -1;
      soft data_nidles == -1;
      soft pkt_nidles == -1;
      soft ntrans == 10;
    }

    function new();
      this.req_mb = new();
      this.rsp_mb = new();
    endfunction

    task run();
      repeat(ntrans) send_trans();
    endtask

    // generate transaction and put into local mailbox
    task send_trans();
      chnl_trans req, rsp;
      req = new();
      assert(req.randomize with {local::ch_id >= 0 -> ch_id == local::ch_id; 
                                 local::pkt_id >= 0 -> pkt_id == local::pkt_id;
                                 local::data_nidles >= 0 -> data_nidles == local::data_nidles;
                                 local::pkt_nidles >= 0 -> pkt_nidles == local::pkt_nidles;
                                 local::data_size >0 -> data.size() == local::data_size; 
                               })
        else $fatal("[RNDFAIL] channel packet randomization failure!");
      this.pkt_id++;
      $display(req.sprint());
      this.req_mb.put(req);
      this.rsp_mb.get(rsp);
      $display(rsp.sprint());
      assert(rsp.rsp)
        else $error("[RSPERR] %0t error response received!", $time);
    endtask

    function string sprint();
      string s;
      s = {s, $sformatf("=======================================\n")};
      s = {s, $sformatf("chnl_generator object content is as below: \n")};
      s = {s, $sformatf("ntrans = %0d: \n", this.ntrans)};
      s = {s, $sformatf("ch_id = %0d: \n", this.ch_id)};
      s = {s, $sformatf("pkt_id = %0d: \n", this.pkt_id)};
      s = {s, $sformatf("data_nidles = %0d: \n", this.data_nidles)};
      s = {s, $sformatf("pkt_nidles = %0d: \n", this.pkt_nidles)};
      s = {s, $sformatf("data_size = %0d: \n", this.data_size)};
      s = {s, $sformatf("=======================================\n")};
      return s;
    endfunction

    function void post_randomize();
      string s;
      s = {"AFTER RANDOMIZATION \n", this.sprint()};
      $display(s);
    endfunction
  endclass: chnl_generator

generator的send_trans()任务结构图
FF,t_70)

chnl_initiator类的drive()任务

task drive();
      chnl_trans req, rsp;
      @(posedge intf.rstn);
      forever begin
        this.req_mb.get(req);
        this.chnl_write(req);
        rsp = req.clone();
        rsp.rsp = 1;
        this.rsp_mb.put(rsp);
      end
    endtask

chnl_initiator类的drive()任务的结构图
在这里插入图片描述
chnl_agent类的run()任务负责连接信箱

  task run();
      this.init.req_mb = this.gen.req_mb;
      this.init.rsp_mb = this.gen.rsp_mb;
      fork
        gen.run();
        init.run();
      join_any
  endtask

总结:

将Lab3中的chnl_initiatorchnl_generator与Lab中的作对比,可以看出发送数据的逻辑发生了很大的改变。Lab2中是generator通过get_trans()获得一个句柄,然后立马返回给initiator的chnl_write(),而在Lab3中,generator产生了一个对象,并把句柄写入req_mb这个信箱中,然后initiator会拿到这个句柄,并把它消化掉,消化掉以后会重新克隆一个一模一样的对象,发送之前会把变量rsp置为1,表示已经响应,然后把这个已响应的对象放到rsp_mb信箱中,generator就可以通过变量rsp来判断initiator是否已经消化掉了这个数据。

实验要求2:

generator实现了数据的随机化,并且能够控制仿真的结束,即当调用chnl_root_test类中的run()任务的时候,会进一步调用agent的run()和generator的run(),然后generator会调用send_trans()产生数据,当generator随机化完成以后,agent就会执行$finish,所以说通过generator产生数据以及随机化完成,来实现了仿真的结束,相当于控制权在于generator。

chnl_root_test类中的run()任务

virtual task run();
      $display($sformatf("*****************%s started********************", this.name));
      this.do_config();
      fork
        agent[0].run();
        agent[1].run();
        agent[2].run();
      join_none
      fork
        gen[0].run();
        gen[1].run();
        gen[2].run();
      join
      $display($sformatf("*****************%s finished********************", this.name));
      // USER TODO 1.3
      // Please move the $finish statement from the test run task to generator
      // You woudl put it anywhere you like inside generator to stop test when
      // all transactions have been transfered
      $finish();
    endtask

generator的send_trans()方法

// generate transaction and put into local mailbox
    task send_trans();
      chnl_trans req, rsp;
      req = new();
      assert(req.randomize with {local::ch_id >= 0 -> ch_id == local::ch_id; 
                                 local::pkt_id >= 0 -> pkt_id == local::pkt_id;
                                 local::data_nidles >= 0 -> data_nidles == local::data_nidles;
                                 local::pkt_nidles >= 0 -> pkt_nidles == local::pkt_nidles;
                                 local::data_size >0 -> data.size() == local::data_size; 
                               })
        else $fatal("[RNDFAIL] channel packet randomization failure!");
      this.pkt_id++;
      $display(req.sprint());
      this.req_mb.put(req);
      this.rsp_mb.get(rsp);
      $display(rsp.sprint());
      assert(rsp.rsp)
        else $error("[RSPERR] %0t error response received!", $time);
    endtask
实验要求3:

编译chnl_pkg1.svtb1.sv并运行仿真,然后在restart重启,你会发现多次运行的仿真产生的数据是相同的。而使用“vsim -novopt -solvefaildebug -sv_seed random work.tb1”命令进行仿真是,两次的仿真波形如下图所以,会发现每一次的仿真都产生了不同的随机种子seed,所以产生了不同的随机化的数据。
在这里插入图片描述
在这里插入图片描述

更加灵活的测试控制

实验要求1:

结构图
在这里插入图片描述
在这里插入图片描述
chnl_agent类,将generator拿到了test,这样可以通过do_config()事先对generator进行随机化,generator调用自己的run(),通过调用send_trans()来随机化chnl_trans,进而控制产生多少个数据,产生什么样的数据,然后通过信箱将数据发送给initiator,initiator拿到随机化的数据,通过接口进行激励。

chnl_agent类,里面只剩下了initiator

class chnl_agent;
    chnl_initiator init;
    local virtual chnl_intf vif;
    function new(string name = "chnl_agent");
      this.init = new(name);
    endfunction
    function void set_interface(virtual chnl_intf vif);
      this.vif = vif;
      init.set_interface(vif);
    endfunction
    task run();
      fork
        init.run();
      join
    endtask
endclass: chnl_agent

chnl_root_test

  class chnl_root_test;
    chnl_generator gen[3];
    chnl_agent agents[3];
    ...
    function new(string name = "chnl_root_test");
	  ...
      foreach(agents[i]) begin
        this.agents[i] = new($sformatf("chnl_agent%0d",i));
        this.gen[i] = new();
        
        // Connect the mailboxes handles of gen[i] and agents[i].init
        this.agents[i].init.req_mb = this.gen[i].req_mb;
        this.agents[i].init.rsp_mb = this.gen[i].rsp_mb;
  		...
      end
      ...
    endfunction
    ...
  endclass

实验要求2:

do_config()方法,其他的test都是继承chnl_root_test,根据不同的测试要求改写do_config()方法。

virtual function void do_config();
      super.do_config();
      assert(gen[0].randomize() with {ntrans==100; data_nidles==0; pkt_nidles==1; data_size==8;})
        else $fatal("[RNDFAIL] gen[0] randomization failure!");

     
      // To randomize gen[1] with
      // ntrans==50, data_nidles inside [1:2], pkt_nidles inside [3:5],
      // data_size == 6
      assert(gen[1].randomize() with {ntrans==50; data_nidles inside {[1:2]}; pkt_nidles inside {[3:5]}; data_size==16;})
        else $fatal("[RNDFAIL] gen[1] randomization failure!");

       
      // ntrans==80, data_nidles inside [0:1], pkt_nidles inside [1:2],
      // data_size == 32
      assert(gen[2].randomize() with {ntrans==80; data_nidles inside {[0:1]}; pkt_nidles inside {[1:2]}; data_size==32;})
        else $fatal("[RNDFAIL] gen[2] randomization failure!");
endfunction

实验要求3:

在这里插入图片描述

之前运行不同的测试需要在initial块里面修改,然后再次编译。

  initial begin 
    basic_test = new();
    basic_test.set_interface(chnl0_if, chnl1_if, chnl2_if);
    basic_test.run(); 
  end

现在可以通过仿真的参数来选择想要运行的测试。可以先把三个测试创建好句柄,然后例化,把三个这三个句柄都赋值给父类句柄数组tests。通过命令“+TESTNAME=testname”来运行指定的测试。

  chnl_basic_test basic_test;
  chnl_burst_test burst_test;
  chnl_fifo_full_test fifo_full_test;
  chnl_root_test tests[string];
  string name;

  initial begin 
    basic_test = new();
    burst_test = new();
    fifo_full_test = new();
    tests["chnl_basic_test"] = basic_test;
    tests["chnl_burst_test"] = burst_test;
    tests["chnl_fifo_full_test"] = fifo_full_test;
    if($value$plusargs("TESTNAME=%s", name)) begin
      if(tests.exists(name)) begin
        tests[name].set_interface(chnl0_if, chnl1_if, chnl2_if);
        tests[name].run();
      end
      else begin
        $fatal($sformatf("[ERRTEST], test name %s is invalid, please specify a valid name!", name));
      end
    end
    else begin
      $display("NO runtime optiont TEST=[testname] is configured, and run default test chnl_basic_test");
      tests["chnl_basic_test"].set_interface(chnl0_if, chnl1_if, chnl2_if);
      tests["chnl_basic_test"].run(); 
    end
  end

测试平台的结构

添加monitor和check组件之后,最终的验证结构框图
在这里插入图片描述
首先定义一个监测到的数据类

 typedef struct packed {
    bit[31:0] data;		//监测到的数据
    bit[1:0] id;		//来自哪个channel
  } mon_data_t;

chnl_monitor

  class chnl_monitor;
    local string name;
    local virtual chnl_intf intf;
    mailbox #(mon_data_t) mon_mb;
    function new(string name="chnl_monitor");
      this.name = name;
    endfunction
    function void set_interface(virtual chnl_intf intf);
      if(intf == null)
        $error("interface handle is NULL, please check if target interface has been intantiated");
      else
        this.intf = intf;
    endfunction
    task run();
      this.mon_trans();
    endtask

    task mon_trans();
      mon_data_t m;
      forever begin
        @(posedge intf.clk iff (intf.mon_ck.ch_valid==='b1 && intf.mon_ck.ch_ready==='b1));
    
        // Put the data into the mon_mb and use $display() to print the stored
        // data value with monitor name
        m.data = intf.mon_ck.ch_data;
        mon_mb.put(m);
        $display("%0t %s monitored channle data %8x", $time, this.name, m.data);
      end
    endtask
  endclass

chnl_monitor会在chnl_agent中例化,同时还要设置monitor的接口以及调用monitor的run()

  class chnl_agent;
    local string name;
    chnl_initiator init;
    chnl_monitor mon;
 
    // Refer to how we create, set virtual interface and run the initiator
    // object, use do the similar action to the monitor object
    virtual chnl_intf vif;
    function new(string name = "chnl_agent");
      this.name = name;
      this.init = new({name, ".init"});
      this.mon = new({name, ".mon"});
    endfunction

    function void set_interface(virtual chnl_intf vif);
      this.vif = vif;
      init.set_interface(vif);
      mon.set_interface(vif);
    endfunction
    task run();
      fork
        init.run();
        mon.run();
      join
    endtask
  endclass: chnl_agent

mcdt_monitorchnl_root_test中例化,而且还要例化agent中channel的monitor,然后调用set_interface()设置相应的接口。

  // Create, set interface and run the object mcdt_mon and checker
  // and also connect the mailbox of checker and chnl_mon/mcdt_mon
  class chnl_root_test;
    chnl_generator gen[3];
    chnl_agent agents[3];
    mcdt_monitor mcdt_mon;
    chnl_checker chker;
    protected string name;

    function new(string name = "chnl_root_test");
      this.name = name;
      foreach(agents[i]) begin
        this.agents[i] = new($sformatf("chnl_agent%0d",i));
        this.gen[i] = new();
        // USER TODO 2.1
        // Connect the mailboxes handles of gen[i] and agents[i].init
        this.agents[i].init.req_mb = this.gen[i].req_mb;
        this.agents[i].init.rsp_mb = this.gen[i].rsp_mb;
      end
      $display("%s instantiated and connected objects", this.name);
    endfunction

    virtual task run();
      $display($sformatf("*****************%s started********************", this.name));
      this.do_config();
      fork
        agents[0].run();
        agents[1].run();
        agents[2].run();
      join_none
      fork
        gen[0].run();
        gen[1].run();
        gen[2].run();
      join
      $display($sformatf("*****************%s finished********************", this.name));
       
      // Please move the $finish statement from the test run task to generator
      // You woudl put it anywhere you like inside generator to stop test when
      // all transactions have been transfered
      $finish();
    endtask

    virtual function void set_interface(virtual chnl_intf ch0_vif 
                                        ,virtual chnl_intf ch1_vif 
                                        ,virtual chnl_intf ch2_vif 
                                        ,virtual mcdt_intf mcdt_vif
                                      );
      agents[0].set_interface(ch0_vif);
      agents[1].set_interface(ch1_vif);
      agents[2].set_interface(ch2_vif);
    endfunction

    virtual function void do_config();
    endfunction

  endclass

chnl_checker类,通过run()任务调用do_compare()方法,do_compare()方法会先从out_mb信箱中拿数据,根据数据的id判断数据来自哪个channel,然后根据id从对应的in_mb拿数据,二者进行比较。

  class chnl_checker;
    local string name;
    local int error_count;
    local int cmp_count;
    mailbox #(mon_data_t) in_mbs[3];
    mailbox #(mon_data_t) out_mb;

    function new(string name="chnl_checker");
      this.name = name;
      foreach(this.in_mbs[i]) this.in_mbs[i] = new();
      this.out_mb = new();
      this.error_count = 0;
      this.cmp_count = 0;
    endfunction

    task run();
      this.do_compare();
    endtask


    task do_compare();
      mon_data_t im, om;
      forever begin
        
        // compare data once there is data in in_mb0/in_mb1/in_mb2 and out_mb
        // first, get om from out_mb, and im from one of in_mbs
        out_mb.get(om);
        case(om.id)
          0: in_mbs[0].get(im);
          1: in_mbs[1].get(im);
          2: in_mbs[2].get(im);
          default: $fatal("id %0d is not available", om.id);
        endcase

        if(om.data != im.data) begin
          this.error_count++;
          $error("[CMPFAIL] Compared failed! mcdt out data %8x ch_id %0d is not equal with channel in data %8x", om.data, om.id, im.data);
        end
        else begin
          $display("[CMPSUCD] Compared succeeded! mcdt out data %8x ch_id %0d is equal with channel in data %8x", om.data, om.id, im.data);
        end
        this.cmp_count++;
      end
    endtask
  endclass

整个Lab3结束!运行仿真打印日志如下

使用脚本命令运行在这里插入图片描述

生成的数据
在这里插入图片描述

在这里插入图片描述

monitor和check
在这里插入图片描述

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

MCDF实验——Lab3 的相关文章

  • systemverilog学习 --- DPI和结构体(语法完结)

    DPI systemverilog提供DPI xff08 Direct Programming Interface xff09 xff0c 这是一个直接编程接口 xff0c 可以使得SV和其它的外部语言进行交互 xff0c 外部的语言包括C
  • 数字IC验证学习(一)

    一 数据类型 1 logic logic类型只能有一个驱动 使用wire和reg的地方均可使用logic 但如双向总线等有多个驱动的地方 则不可使用logic 2 二值逻辑 对于二值逻辑变量与DUT中的四值逻辑变量连接时 如果DUT中产生了
  • MCDF实验——Lab3

    Lab3将在Lab2的基础上使用随机约束和环境结构来改进完善实验代码 Lab3中将对generator和initiator之间的数据生成和数据传输的处理进行改进 还将完善何时结束测试 将其主动权交于generator而不再是test组件 在
  • systemverilog中的bind

    最早接触 bind 关键字是在assertion 当中 将assertion 与 dut 进行绑定连接 如下例子 bind cpu fpu props fpu rules 1 a b c cpu 是module 名字 fpu props 是
  • 【验证小白】只有SV+modelsim学验证(4)——想办法合理的结束仿真后,准备好了所有代码

    前言 把checker加入到环境中后 环境组件基本就搭建完成了 试着跑了跑出了发现之前的pkt data有一些问题外 还发现仿真结束机制太不合理了 过于简单粗暴 于是把结束仿真的行为梳理一下 做的更合理一些 参考了VMM的思路 做一个漏洞百
  • Interface中input delay&output delay

    最开始在学习SV的时候 碰到interface的使用并没有过多的在意 只是了解clocking block是为了解决竞争问题 然而在后续使用clocking block的过程中 总会碰到一些时序错位的问题 如下 通过简单的例子来表述下clo
  • 如何在 SystemVerilog 中将变量值传递给宏?

    我认为这个问题很好地概括了我想要的 将变量的值传递给 SystemVerilog 中的宏 例如我想要的 比如说 有 4 个名为 abc X def 的信号 我想将它们全部初始化为 0 所以 没有宏 abc 0 def 4 b0000 abc
  • 打印存储在 reg 类型变量中的有符号整数值

    如何打印存储在 8 位寄存器中的有符号整数值 声明为 reg 7 0 acc Using display acc d acc 它打印无符号值 正确的语法是什么 display功能 如果您声明reg as signed display将显示减
  • 如何使用 Verilog 宏模拟 $display?

    我想创建一个具有多个参数的宏 就像 display 一样 我的代码看起来像这样 但它不起作用 define format macro A write s sformatf A 这就是我调用 format macro 的方式 format m
  • 使用数据流模型的T触发器

    我正在尝试模拟 t flipflop 的工作 timescale 1ns 1ps module t flipflop input t input clk input clear output q output qbar wire sbar
  • SV 或 UVM 中的正则表达式

    我需要调用哪些函数才能在 Systemverilog UVM 中使用正则表达式 注意 我不是问如何使用正则表达式 只是问方法名称 首先 如果您想使用正则表达式 您需要确保您使用的是与其 DPI 代码一起编译的 UVM 库 即UVM NO D
  • x 和 z 值在 Verilog 中到底代表什么?

    Verilog 标准定义了四种类型的位值 0 1 x 和 z 其中 0 表示低 1 表示高 x 表示未知 z 表示未驱动网络 有几个问题 x 是否意味着我们不知道该值是 0 还是 1 0 或 1 或 z 或者该值是未知的并且可以是 0 1
  • System Verilog fork join - 实际上不是并行的?

    我正在学习系统verilog 并认为为每个进程创建单独的线程fork join 但是 我发现如果我有一个while在我的第一个进程中循环 我的第二个进程没有启动 这让我想到fork join实际上并不平行 class A task run
  • 如何在RTL中使用时钟门控?

    我正在对一些时钟进行门控latch以及我设计中的逻辑 我在综合和布局布线方面没有太多经验 在 RTL 中实现时钟门控的正确方法是什么 示例1 always comb begin gated clk clk latch update en e
  • 连接分层模块:SystemVerilog 中的结构与接口

    在 SystemVerilog 中 分层模块可以通过简单数据类型 复杂数据类型 结构 联合等 或接口进行连接 我感兴趣的功能是将两个模块之间的所有信号聚合到一个地方 这简化了代码的维护 例如 在下面的例子中 更改 s point 的定义而不
  • 将枚举转换为逻辑

    考虑以下模块声明 module DFF d q CLK RESET parameter W 2 input W 1 0 d input CLK input RESET output logic W 1 0 q endmodule 当 d 和
  • 如何使用 don't cares 参数化 case 语句?

    我有一条称为输入的电线 我想检测前导的数量 我正在尝试创建一个模块 该模块使用下面的 case 语句根据前导零的数量更改输出数据 然而 输入的大小是可参数化的 如果 X 是固定值 4 我将创建一个 case 语句 case input 4
  • 自动任务和静态任务有什么区别,为什么我们不能通过引用传递静态任务

    静态任务和自动任务有什么区别 program class ref int index value class holding values int ass array task assign value int value int inde
  • Verilog 中的大括号是什么意思?

    我很难理解 Verilog 中的以下语法 input 15 0 a 16 bit input output 31 0 result 32 bit output assign result 16 a 15 a 15 0 我知道assign语句
  • reg 声明中的位顺序

    如果我需要使用 4 个 8 位数字 我会声明以下 reg reg 7 0 numbers 3 0 我对第一个和第二个声明 7 0 和 3 0 之间的区别感到很困惑 他们应该按什么顺序来 第一个是保留数字的大小 而第二个是保留数字的数量 还是

随机推荐

  • 微信小程序-SOA架构(17年1月)

    微信小程序 顾名思义 它有两个方面的含义 重点在小 也就是不用安装就能使用的意思 另一个重点 它是应用程序 它和公众号绑定在一起使用 从用户角度去看 它是各种APP的替代品 有了它以后 不再需要安装APP 作为IT人员 更多的是从工程思维的
  • Snort搭建以及规则编写

    目录 Snort IDS Snort搭建 安装web服务 方便设置sonrt后期访问 Mysql安装 PHP安装 安装 Snort Snort配置 创建snort专用的用户和组 配置目录 配置规则 修改配置文件 规则编写 Snort IDS
  • QGIS二次开发02:交互动作实现

    地图交互动作就是通过鼠标操作与地图间的互动 动作包括按下 press 按键弹起 release 鼠标移动 move 双击等等 QGIS实现地图的交互主要是通过继承QgsMapTool这个类实现 目前集成了QgsMapToolZoom 拉框缩
  • 数据结构---堆的构建和堆排序(向下、向上调整算法)

    一 建堆 1 堆的概念及性质 如果有一个关键码的集合 K k0 k1 k2 kn 1 把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中 并满足 Ki lt K2 i 1 且 Ki lt K2 i 2 Ki gt K2 i 1 且
  • 七大排序知识点

    目录 1 稳定性 2 冒泡排序 3 插入排序 3 1 折半插入排序 4 希尔排序 5 选择排序 6 堆排序 7 快速排序 挖坑法 8 归并排序 9 海量数据的排序问题 1 稳定性 两个相等的数据 如果经过排序后 排序算法能保证其相对位置不发
  • JSON与MODEL互转

    HYBJSONModel h Json2ModelDemo Created by huangyibiao on 14 9 15 Copyright c 2014年 Home All rights reserved import
  • R语言-线性回归实例(包括所有源码)

    题目描述 目录 一 身高体重 1 身高和体重的散点图 先肉眼观察来判断使用什么模型 2 画出拟合后的线性函数与散点图背景对比 3 对该模型的分析 4 置信区间分析和假设检验 5 多图像分析 二 不良贷款 三 污染 1 以二氧化硫排放量 吨
  • (四)现代计算机系统的层次结构

    程序执行结果 不仅取决于算法 程序的编写 而且取决于语言处理系统 操作系统 ISA 微体系结构 不同计算机课程处于不同层次 必须将各层析关联起来解决问题 功能转换 上层是下层的抽象 下层时上层的实现 地位为上层提供支撑环境 计算机系统的不同
  • install chrome

    1 2 wget https dl google com linux direct google chrome stable current i386 deb 没试用过 3 4 wget https dl google com linux
  • ADS学习:Smith Chart Utility使用说明

    打开方式 原理图界面 Tools Smith Chart Utility 功能分区 1 菜单栏 2 工具栏 3 作图区 4 频率响应区
  • 【报告分享】完美日记品牌分析报告.pdf(附68页pdf全文下载链接)

    今天给大家分享的是上海语析信息咨询有限公司于2020年4月份发布的 完美日记品牌分析报告 pdf 该报告由上海交通大学海外教育学院中国商业发展研究所作为学术指导 报告共包含如下五大部分 1 完美日记品牌故事 2 完美日记营销分析 3 完美日
  • 苹果手机屏幕如何投射到win10?

    说起家庭娱乐 大多数人想到的一定是电脑 手机 亦或者是电视 其中每天陪伴的必定有手机 我们很少再使用电视去看影视作品 取而代之的是各大视频网站 比如腾讯 爱奇艺 优酷等 而不需再等候 黄金七点半 很多人一定会把会员在手机端登录 因此想在电脑
  • 川大计算机信息安全基础试题,信息安全概论考试试题..doc

    四川大学2014年春季软件工程研究生班考试试题 课程名称 信息安全概论 任课教师 琚生根 学生人数 印题份数 学号 姓名 考 试 须 知 四川大学学生参加由学校组织或由学校承办的各级各类考试 必须严格执行 四川大学考试工作管理办法 和 四川
  • 泛微E-Mobile 6.0远程命令执行漏洞

    前言 本次测试仅供学习使用 如若非法他用 与本文作者无关 需自行负责 漏洞描述 Weaver E Mobile是中国泛微科技 Weaver 公司的一个协同办公系统 E Mobile6最新版是上海泛微网络科技推出的一款手机办公应用 将企业微信
  • 纯 CSS 实现高度与宽度成比例的效果

    HTML p class image container img src xxx png p CSS p image container width 100 height 0 padding bottom 60 overflow hidde
  • docker 训练深度学习_Docker:把深度学习装进“口袋”

    熟悉深度学习开发框架的朋友都知道 caffe 的安装麻烦 耗时长 而且很容易因为电脑环境没有配置好导致错误 每次有新同事来 我们都要在他电脑上安装一遍 caffe 经常会因为电脑环境而不断报错 目前TensorFlow受到很多深度学习开发者
  • 阿里云oss视频上传及预览图汇总

    阿里云OSS视频上传的几种方式 1 Web端直传实践简介 https help aliyun com document detail 31923 html spm a2c4g 11186623 6 631 apBNnA 2 JavaScri
  • cacheable 过期设置

    1 增加pom依赖
  • 【Java面试题】IO & NIO

    1 什么是IO流 它是一种数据的流从源头流到目的地 比如文件拷贝 输入流和输出流 输入流从文件中读取数据存储到进程 process 中 输出流从进程中读取数据然后写入到目标文件 2 Java中有几种类型的流 按照单位大小 字符流 字节流 按
  • MCDF实验——Lab3

    Lab3将在Lab2的基础上使用随机约束和环境结构来改进完善实验代码 Lab3中将对generator和initiator之间的数据生成和数据传输的处理进行改进 还将完善何时结束测试 将其主动权交于generator而不再是test组件 在