• 电力电子转战数字IC20220825day69——MCDF更新APB总线


     MCDF更新APB总线

    原来的寄存器做总线换成了APB总线,通道数量加了1。所有的接口几乎都发生了改变。

     channel更新为slave node

     data和valid接口保留,新增了parity和wait和error,wait接口就是原来的ready接口,表示fifo空满、是否准备好接收新的data。数据校验位parity是data的异或!(return^data;)

    时序图:

     作为item的chnl_trans类不变,没有变化。传送的信号还是原来的那些。

    时序图发生变化,所以驱动item的chnl_driver发生了变化:重置任务中多了ch_data_p这个信号(parity);chnl_write任务也需要多这个信号,并定义一个获取校验位的函数get_parity,就是data异或。

    1. task chnl_write(input chnl_trans t);
    2. foreach(t.data[i]) begin
    3. @(posedge intf.clk);
    4. intf.drv_ck.ch_valid <= 1;
    5. intf.drv_ck.ch_data <= t.data[i];
    6. intf.drv_ck.ch_data_p <= get_parity(t.data[i]);
    7. @(negedge intf.clk);
    8. wait(intf.ch_wait === 'b0);
    9. `uvm_info(get_type_name(), $sformatf("sent data 'h%8x", t.data[i]), UVM_HIGH)
    10. repeat(t.data_nidles) chnl_idle();
    11. end
    12. repeat(t.pkt_nidles) chnl_idle();
    13. endtask
    14. task chnl_idle();
    15. @(posedge intf.clk);
    16. intf.drv_ck.ch_valid <= 0;
    17. intf.drv_ck.ch_data <= 0;
    18. intf.drv_ck.ch_data_p <= 0;
    19. endtask
    20. function get_parity(bit[31:0] data);
    21. return ^data;
    22. endfunction

    sequencer只有注册和new函数,无需更新。

    sequence,成员变量多了动态数组data[],暂时还不知道为什么?

    并对所有成员变量增加了约束。

    1. class chnl_data_sequence extends uvm_sequence #(chnl_trans);
    2. rand int pkt_id = 0;
    3. rand int ch_id = -1;
    4. rand int data_nidles = -1;
    5. rand int pkt_nidles = -1;
    6. rand int data_size = -1;
    7. rand int ntrans = 10;
    8. rand int data[];
    9. constraint cstr{
    10. soft pkt_id == 0;
    11. soft ch_id == -1;
    12. soft data_nidles == -1;
    13. soft pkt_nidles == -1;
    14. soft data_size == -1;
    15. soft ntrans == 10;
    16. soft data.size() == data_size;
    17. foreach(data[i]) soft data[i] == -1;
    18. };
    19. `uvm_object_utils_begin(chnl_data_sequence)
    20. `uvm_field_int(pkt_id, UVM_ALL_ON)
    21. `uvm_field_int(ch_id, UVM_ALL_ON)
    22. `uvm_field_int(data_nidles, UVM_ALL_ON)
    23. `uvm_field_int(pkt_nidles, UVM_ALL_ON)
    24. `uvm_field_int(data_size, UVM_ALL_ON)
    25. `uvm_field_int(ntrans, UVM_ALL_ON)
    26. `uvm_object_utils_end
    27. `uvm_declare_p_sequencer(chnl_sequencer)
    28. function new (string name = "chnl_data_sequence");
    29. super.new(name);
    30. endfunction

    monitor的PORT从uvm_blocking_put_port变成了uvm_analysis_port,为什么?对应调用的方法也从put变成了write,ready信号更新为wait

    agent的变化也稍微大了点,build_phase中调用uvm_config_db配置了接口,connect_phase调用了set_interface连接了接口。之前的接口是从顶层拿到接口指针后调用这里的set_interface

    对比的文件是还没更新MCDF前的uvm入门实验5的文件。

    tb中接口的更新:多了parity,ready改成wait,多了parity error,对应的时钟块信号发生变化,error作为input,parity作为output

    1. interface chnl_intf(input clk, input rstn);
    2. logic [31:0] ch_data;
    3. logic ch_data_p;
    4. logic ch_valid;
    5. logic ch_wait;
    6. logic ch_parity_err;
    7. clocking drv_ck @(posedge clk);
    8. default input #1ps output #1ps;
    9. output ch_data, ch_valid, ch_data_p;
    10. input ch_wait, ch_parity_err;
    11. endclocking
    12. clocking mon_ck @(posedge clk);
    13. default input #1ps output #1ps;
    14. input ch_data, ch_valid, ch_data_p, ch_wait, ch_parity_err;
    15. endclocking
    16. endinterface

    module中的接口分别连接四个node,并且更新到dut的连接

    1. chnl_intf chnl0_if(.*);
    2. chnl_intf chnl1_if(.*);
    3. chnl_intf chnl2_if(.*);
    4. chnl_intf chnl3_if(.*);
    1. .slv0_data_i (chnl0_if.ch_data ) , //
    2. .slv0_data_p_i (chnl0_if.ch_data_p ) , // one bit parity of data_i
    3. .slv0_valid_i (chnl0_if.ch_valid ) , //
    4. .slv0_wait_o (chnl0_if.ch_wait ) , //
    5. .slv0_parity_err_o (chnl0_if.ch_parity_err ) , //
    6. .slv1_data_i (chnl1_if.ch_data ) , //
    7. .slv1_data_p_i (chnl1_if.ch_data_p ) , // one bit parity of data_i
    8. .slv1_valid_i (chnl1_if.ch_valid ) , //
    9. .slv1_wait_o (chnl1_if.ch_wait ) , //
    10. .slv1_parity_err_o (chnl1_if.ch_parity_err ) , //
    11. .slv2_data_i (chnl2_if.ch_data ) , //
    12. .slv2_data_p_i (chnl2_if.ch_data_p ) , // one bit parity of data_i
    13. .slv2_valid_i (chnl2_if.ch_valid ) , //
    14. .slv2_wait_o (chnl2_if.ch_wait ) , //
    15. .slv2_parity_err_o (chnl2_if.ch_parity_err ) , //
    16. .slv3_data_i (chnl3_if.ch_data ) , //
    17. .slv3_data_p_i (chnl3_if.ch_data_p ) , // one bit parity of data_i
    18. .slv3_valid_i (chnl3_if.ch_valid ) , //
    19. .slv3_wait_o (chnl3_if.ch_wait ) , //
    20. .slv3_parity_err_o (chnl3_if.ch_parity_err ) , //

    initial块中自上而下配置接口到各个层次:top-env-agent;top-env

    1. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.chnl_agts[0]", "vif", chnl0_if);
    2. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.chnl_agts[1]", "vif", chnl1_if);
    3. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.chnl_agts[2]", "vif", chnl2_if);
    4. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.chnl_agts[3]", "vif", chnl3_if);
    5. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.*", "chnl_vifs[0]", chnl0_if);
    6. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.*", "chnl_vifs[1]", chnl1_if);
    7. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.*", "chnl_vifs[2]", chnl2_if);
    8. uvm_config_db#(virtual chnl_intf)::set(uvm_root::get(), "uvm_test_top.env.*", "chnl_vifs[3]", chnl3_if);

    formatter的更新

     len从0-255表示1-256个payload

     时序图如下:

    fmt_trans多了校验parity。

    先看接口的更新,接口变为5个,ready其实就是原来的grant

    1. interface fmt_intf(input clk, input rstn);
    2. logic fmt_ready;
    3. logic fmt_valid;
    4. logic [31:0] fmt_data;
    5. logic fmt_first;
    6. logic fmt_last;
    7. clocking drv_ck @(posedge clk);
    8. default input #1ps output #1ps;
    9. input fmt_valid, fmt_data, fmt_first, fmt_last;
    10. output fmt_ready;
    11. endclocking
    12. clocking mon_ck @(posedge clk);
    13. default input #1ps output #1ps;
    14. input fmt_ready, fmt_valid, fmt_data, fmt_first, fmt_last;
    15. endclocking
    16. endinterface

    连接到dut的接口对应更新

    1. .rev_rdy_i (fmt_if.fmt_ready ) , // receiver rdy
    2. .pkg_vld_o (fmt_if.fmt_valid ) , // data is valid
    3. .pkg_dat_o (fmt_if.fmt_data ) , // data/payload
    4. .pkg_fst_o (fmt_if.fmt_first ) , // header indicator
    5. .pkg_lst_o (fmt_if.fmt_last ) // parirty data

    driver更新了do_receive,一开始的思路是,看剩余的空间是否比item的长度还长,也就是余量是否充足,如果余量不足就停止了。

    更新后的逻辑是,不管里面是不是装满了,放不下的时候ready拉低即可

    1. task do_receive();
    2. forever begin
    3. @(posedge intf.fmt_req);
    4. forever begin
    5. @(posedge intf.clk);
    6. if((this.fifo_bound-this.fifo.num()) >= intf.fmt_length)
    7. break;
    8. end
    9. intf.drv_ck.fmt_grant <= 1;
    10. @(posedge intf.fmt_start);
    11. fork
    12. begin
    13. @(posedge intf.clk);
    14. intf.drv_ck.fmt_grant <= 0;
    15. end
    16. join_none
    17. repeat(intf.fmt_length) begin
    18. @(negedge intf.clk);
    19. this.fifo.put(intf.fmt_data);
    20. end
    21. end
    22. endtask
    23. task do_receive();
    24. forever begin
    25. @(intf.drv_ck); #10ps;
    26. if(intf.fmt_valid === 1'b1) begin
    27. forever begin
    28. if((this.fifo_bound-this.fifo.num()) >= 1)
    29. break;
    30. @(intf.drv_ck); #10ps;//不行就再等多一拍
    31. end
    32. this.fifo.put(intf.fmt_data);
    33. #1ps; intf.fmt_ready <= 1;
    34. end
    35. else begin
    36. #1ps; intf.fmt_ready <= 0;
    37. end
    38. end
    39. endtask

    monitor端口同样变为ap。原来的只看start是否拉高,现在是一个一个data进行记录,条件变多,信息集成度更高,将id、长度等集成在fmt_data的后16位

    1. task mon_trans();
    2. fmt_trans m;
    3. string s;
    4. forever begin
    5. @(intf.mon_ck iff intf.mon_ck.fmt_first && intf.mon_ck.fmt_valid && intf.mon_ck.fmt_ready);
    6. m = new();
    7. //例化后将拿到的数据包写进这个一模一样的trans对象中
    8. m.length = intf.mon_ck.fmt_data[23:16];//包头的len
    9. m.ch_id = intf.mon_ck.fmt_data[31:24];//最前面的ID
    10. m.data = new[m.length + 3];//为什么加3?这里的new是创建动态数组(trans里面已经有声明随机变量的32位动态数组data),length+3表示动态数组的长度
    11. //len+1=(payload的数量),包头first和包尾last分别占1个payload
    12. foreach(m.data[i]) begin
    13. m.data[i] = intf.mon_ck.fmt_data;
    14. if(i == m.data.size()-1) m.parity = m.data[i];
    15. if(i < m.data.size()-1) @(intf.mon_ck iff intf.mon_ck.fmt_valid && intf.mon_ck.fmt_ready);
    16. end
    17. mon_ana_port.write(m);

    agent也做了接口的配置和连接

    顶层环境有哪些?

    chnl、reg、fmt的agent,mcdf的checker、coverage、rgm,mcdf_virtual_sequencer

    mcdf中rgm的更新

    run_phase中无需do_reg_update(模拟硬件寄存器数组更新),现在更新后用的是rgm

     

    由于通道数加了1,do_packet多了一个;packet的方式变化了,现在是调用rgm的函数来获得id和长度等信息

    1. class mcdf_refmod extends uvm_component;
    2. mcdf_rgm rgm;
    3. uvm_blocking_get_port #(apb_transfer) reg_bg_port;
    4. uvm_blocking_get_peek_port #(mon_data_t) in_bgpk_ports[4];
    5. uvm_tlm_analysis_fifo #(fmt_trans) out_tlm_fifos[4];
    6. `uvm_component_utils(mcdf_refmod)
    7. function new (string name = "mcdf_refmod", uvm_component parent);
    8. super.new(name, parent);
    9. reg_bg_port = new("reg_bg_port", this);
    10. foreach(in_bgpk_ports[i]) in_bgpk_ports[i] = new($sformatf("in_bgpk_ports[%0d]", i), this);
    11. foreach(out_tlm_fifos[i]) out_tlm_fifos[i] = new($sformatf("out_tlm_fifos[%0d]", i), this);
    12. endfunction
    13. function void build_phase(uvm_phase phase);
    14. super.build_phase(phase);
    15. if(!uvm_config_db#(mcdf_rgm)::get(this,"","rgm", rgm)) begin
    16. `uvm_fatal("GETRGM","cannot get RGM handle from config DB")
    17. end
    18. endfunction
    19. task run_phase(uvm_phase phase);
    20. fork
    21. do_packet(0);
    22. do_packet(1);
    23. do_packet(2);
    24. do_packet(3);
    25. join
    26. endtask
    27. task do_packet(int ch);
    28. fmt_trans ot;
    29. mon_data_t it;
    30. forever begin
    31. this.in_bgpk_ports[ch].peek(it);
    32. ot = new();
    33. ot.length = rgm.get_reg_field_length(ch);
    34. ot.ch_id = rgm.get_reg_field_id(ch);
    35. ot.data = new[ot.length+3];
    36. foreach(ot.data[m]) begin
    37. if(m == 0) begin//包头
    38. ot.data[m] = (ot.ch_id<<24) + (ot.length<<16);
    39. ot.parity = ot.data[m];
    40. end
    41. else if(m == ot.data.size()-1) begin//包尾
    42. ot.data[m] = ot.parity;
    43. end
    44. else begin //中间数据payload
    45. this.in_bgpk_ports[ch].get(it);
    46. ot.data[m] = it.data;
    47. ot.parity ^= it.data;
    48. end
    49. end
    50. this.out_tlm_fifos[ch].put(ot);
    51. end
    52. endtask
    53. endclass: mcdf_refmod

    checker的更新

    大量的PORT和mailbox被TLM analysis fifo替代,

  • 相关阅读:
    光伏仪器-87110A/B太阳辐照度计
    机器学习 | 简单但是能提升模型效果的特征标准化方法(RobustScaler、MinMaxScaler、StandardScaler 比较和解析)
    什么是3D摄影机,与普通摄影机有什么不同?
    vue全局字典值获取方法一例
    dll文件找不到,微软官方地址
    SpringCloud——网关Gateway
    【2 线性表】奇偶数划分先后,奇在前偶在后。
    云堡垒机和软件堡垒机哪个好?区别是什么?
    Clickhouse冷热配置
    大疆面试笔试一部分总结
  • 原文地址:https://blog.csdn.net/weixin_39668316/article/details/126526704