MCDF实验4:魔龙的狂舞(从verilog到SV的入门lab4)_mcdf sv lab4

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

读写寄存器

  • bit(0):通道使能信号。1为打开,0位关闭。复位值为1。 bit(2:1):优先级。0为最高,3为最低。复位值为3。
  • bit(5:3):数据包长度,解码对应表为,
    0对应长度4,1对应长度8,2对应长度16,3对应长度32,其它数值(4-7)均暂时对应长度32。复位值为0。
  • bit(31:6):保留位,无法写入。复位值为0。

只读寄存器

bit(7:0):上行数据从端FIFO的可写余量,同FIFO的数据余量保持同步变化。复位值为FIFO的深度数。
bit(31:8):保留位,复位值为0。

1.12 clone、sprint、
    function reg_trans clone();
      reg_trans c = new();
      c.addr = this.addr;
      c.cmd = this.cmd;
      c.data = this.data;
      c.rsp = this.rsp;
      return c;
    endfunction

   function string sprint();
      string s;
      s = {s, $sformatf("=======================================\n")};
      s = {s, $sformatf("reg\_trans object content is as below: \n")};
      s = {s, $sformatf("addr = %2x: \n", this.addr)};
      s = {s, $sformatf("cmd = %2b: \n", this.cmd)};
      s = {s, $sformatf("data = %8x: \n", this.data)};
      s = {s, $sformatf("rsp = %0d: \n", this.rsp)};
      s = {s, $sformatf("=======================================\n")};
      return s;
    endfunction
  endclass

1.2 reg_driver

  class reg_driver;
    local string name;
    local virtual reg_intf intf;
    mailbox #(reg_trans) req_mb;
    mailbox #(reg_trans) rsp_mb;

    function new(string name = "reg\_driver");
      this.name = name;
    endfunction
  
    function void set\_interface(virtual reg_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();
      fork
        this.do\_drive();
        this.do\_reset();
      join
    endtask

    task do\_reset(); //复位
      forever begin
        @(negedge intf.rstn);
        intf.cmd_addr <= 0;
        intf.cmd <= `IDLE;
        intf.cmd_data_m2s <= 0;
      end
    endtask

    task do\_drive();
      reg_trans req, rsp;
      @(posedge intf.rstn);
      forever begin
        this.req_mb.get(req);
        this.reg\_write(req);
        rsp = req.clone();
        rsp.rsp = 1;
        this.rsp_mb.put(rsp);
      end
    endtask
  
    task reg\_write(reg_trans t);//给寄存器
      @(posedge intf.clk iff intf.rstn);
      case(t.cmd)
        `WRITE: begin //如果是写操作
                  intf.drv_ck.cmd_addr <= t.addr; //地址
                  intf.drv_ck.cmd <= t.cmd; 
                  intf.drv_ck.cmd_data_m2s <= t.data; //数据
                end
        `READ:  begin 
                  intf.drv_ck.cmd_addr <= t.addr; //总线
                  intf.drv_ck.cmd <= t.cmd; 
                  repeat(2) @(negedge intf.clk);//等两个时钟的下降沿,第一个下降沿还在
                  t.data = intf.cmd_data_s2m; //采样了intf的数据
                end
        `IDLE:  begin 
                  this.reg\_idle(); //等一拍
                end
        default: $error("command %b is illegal", t.cmd);
      endcase
      $display("%0t reg driver [%s] sent addr %2x, cmd %2b, data %8x", $time, name, t.addr, t.cmd, t.data);
    endtask

当case为 READ时,等待了两个时钟的下降沿。
第一个下降沿还在当前周期,第二个下降沿就在下一个周期了。此时数据已经驱动到接口cmd_data_s2m处了,这时去采样接口处的数据就一定是要读的数据。
在这里插入图片描述

  • 在控制寄存器接口上,需要在每一个时钟解析cmd。当cmd为写(WR)指令时,需要把数据cmd_data_in写入到cmd_addr对应的寄存器中;当cmd为读指令(RD)时,即需要从cmd_addr对应的寄存器中读取数据,并在下一个周期,将数据驱动至cmd_data_out接口。
    task reg\_idle();
      @(posedge intf.clk);
      intf.drv_ck.cmd_addr <= 0;
      intf.drv_ck.cmd <= `IDLE;
      intf.drv_ck.cmd_data_m2s <= 0;
    endtask
  endclass

1.3 reg_generator

  class reg_generator;
    rand bit[7:0] addr = -1;
    rand bit[1:0] cmd = -1;
    rand bit[31:0] data = -1;

    mailbox #(reg_trans) req_mb;
    mailbox #(reg_trans) rsp_mb;

    reg_trans reg_req[$];

    constraint cstr{
      soft addr == -1;
      soft cmd == -1;
      soft data == -1;
    }

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

    task start();
      send\_trans();
    endtask
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值