电力电子转战数字IC20220616day26——回顾SV+实验2

Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.https://sleet-nutria-a7f.notion.site/System-Verilog-6e734bba759e43438c73f3f610ec7527

目录

实验2

1.0 接口的使用

 1.1 用接口中的时钟块来实现数据的采样和驱动

 1.2 用idle_cycles表示相邻两个有效数据之间的周期

$urandom_range系统函数

2.0 basic test

2.1 数据间隔为0,发送500个数据

3.1 例化initiator和generator

3.2 连接initiator和接口

 ​编辑

 3.3 test的项目不变


实验2

 首先是要用接口来封装信号

1.0 接口的使用

`timescale 1ns/1ps
//定义一个接口chnl_intf,其输入是clk和rstn
interface chnl_intf(input clk, input rstn);
//定义四个变量,这些在实验1时是作为initiator的输入和输出来处理的,接口的作用就是来封装这些信号
  logic [31:0] ch_data;
  logic        ch_valid;
  logic        ch_ready;
  logic [ 5:0] ch_margin;
//定义时钟块进行采样和输出,防止竞争
  clocking drv_ck @(posedge clk);
    default input #1ns output #1ns;
//采样的是ready和margin,要准备好且有剩余空间才可以驱动data
//驱动data和valid
    output ch_data, ch_valid;
    input ch_ready, ch_margin;
  endclocking
endinterface

//定义initiator,输入是上面定义的interface。intf表示什么?????
module chnl_initiator(chnl_intf intf);
  string name;
  int idle_cycles = 1;//表示相邻有效数据之间的间隔
  
  //输入n,将idle_cycles设置为n,初始值是1
  function automatic void set_idle_cycles(int n);
    idle_cycles = n;
  endfunction
 //输入字符串s,将name设置为s
  function automatic void set_name(string s);
    name = s;
  endfunction

 1.1 用接口中的时钟块来实现数据的采样和驱动

时钟块的定义如上面的代码,以下是应用

  task automatic chnl_write(input logic[31:0] data);
    @(posedge intf.clk);
 //用interface中的时钟块drv_ck取代之前的clk
 //上升沿到了就把data送到接口对应的logic中
    intf.drv_ck.ch_valid <= 1;
    intf.drv_ck.ch_data <= data;
    @(negedge intf.clk);
    wait(intf.ch_ready === 'b1);
    $display("%t channel initiator [%s] sent data %x", $time, name, data);
    repeat(idle_cycles) chnl_idle();//两个有效数据之间有多少间隔就执行多少次下面的任务chnl_idle()
  endtask

  task automatic chnl_idle();
    @(posedge intf.clk);
    intf.drv_ck.ch_valid <= 0;
    intf.drv_ck.ch_data <= 0;
  endtask
endmodule

 1.2 用idle_cycles表示相邻两个有效数据之间的周期

上面是接口,接下来是generator

//generator的代码
module chnl_generator;
  int chnl_arr[$];//定义一个队列,队列元素的标号从0到$,一开始空间为0
  int num;
  int id;
//初始化的函数,输入id且num清0
  function automatic void initialize(int n);
    id = n;
    num = 0;
  endfunction

//这里发现了实验1中偷懒没搞明白的地方,为什么data是这样算,为什么有c?
//回去看了对应的部分,这里是给出数据流
  function automatic int get_data();
    int data;
    data = 'h00C0_0000 + (id<<16) + num;
    num++;
    chnl_arr.push_back(data);//从队列尾部写入一个data
    return data;
  endfunction
endmodule

 然后是tb的主体部分了,这里还是先用module。

三个通道一共12个信号都被封装到接口中。

//先给出的是实验1中没有接口时的变量和例化
module tb4_ref;
logic         clk;
logic         rstn;
logic [31:0]  ch0_data;
logic         ch0_valid;
logic         ch0_ready;
logic [ 5:0]  ch0_margin;
logic [31:0]  ch1_data;
logic         ch1_valid;
logic         ch1_ready;
logic [ 5:0]  ch1_margin;
logic [31:0]  ch2_data;
logic         ch2_valid;
logic         ch2_ready;
logic [ 5:0]  ch2_margin;
logic [31:0]  mcdt_data;
logic         mcdt_val;
logic [ 1:0]  mcdt_id;

//接口连接到mcdt上
mcdt dut(
   .clk_i(clk)
  ,.rstn_i(rstn)
  ,.ch0_data_i(ch0_data)
  ,.ch0_valid_i(ch0_valid)
  ,.ch0_ready_o(ch0_ready)
  ,.ch0_margin_o(ch0_margin)
  ,.ch1_data_i(ch1_data)
  ,.ch1_valid_i(ch1_valid)
  ,.ch1_ready_o(ch1_ready)
  ,.ch1_margin_o(ch1_margin)
  ,.ch2_data_i(ch2_data)
  ,.ch2_valid_i(ch2_valid)
  ,.ch2_ready_o(ch2_ready)
  ,.ch2_margin_o(ch2_margin)
  ,.mcdt_data_o(mcdt_data)
  ,.mcdt_val_o(mcdt_val)
  ,.mcdt_id_o(mcdt_id)
);

//————————————————————————————————————————————————————————————
//然后是实验2用接口封装了这些信号后的tb例化
module tb1_ref;
  logic         clk;
  logic         rstn;
  logic [31:0]  mcdt_data;
  logic         mcdt_val;
  logic [ 1:0]  mcdt_id;
  
  mcdt dut(
     .clk_i       (clk                )
    ,.rstn_i      (rstn               )
    ,.ch0_data_i  (chnl0_if.ch_data   )
    ,.ch0_valid_i (chnl0_if.ch_valid  )
    ,.ch0_ready_o (chnl0_if.ch_ready  )
    ,.ch0_margin_o(chnl0_if.ch_margin )
    ,.ch1_data_i  (chnl1_if.ch_data   )
    ,.ch1_valid_i (chnl1_if.ch_valid  )
    ,.ch1_ready_o (chnl1_if.ch_ready  )
    ,.ch1_margin_o(chnl1_if.ch_margin )
    ,.ch2_data_i  (chnl2_if.ch_data   )
    ,.ch2_valid_i (chnl2_if.ch_valid  )
    ,.ch2_ready_o (chnl2_if.ch_ready  )
    ,.ch2_margin_o(chnl2_if.ch_margin )
    ,.mcdt_data_o (mcdt_data          )
    ,.mcdt_val_o  (mcdt_val           )
    ,.mcdt_id_o   (mcdt_id            )
  );

时钟和复位信号是相同的

  // clock generation
  initial begin 
    clk <= 0;
    forever begin
      #5 clk <= !clk;
    end
  end
  
  // reset trigger
  initial begin 
    #10 rstn <= 0;
    repeat(10) @(posedge clk);
    rstn <= 1;
  end

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值