微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 微电子和IC设计 > IC验证交流 > 有人看过uvm_ref_flow_1.1里的uart组件么?

有人看过uvm_ref_flow_1.1里的uart组件么?

时间:10-02 整理:3721RD 点击:

各位:关于uart的采样频率,我有点不大明白。sample_clk是对interface上的时钟进行计数,等于{cfg.baud_rate_div,cfg.baud_rate_gen}的时候开始采样,那我不大清楚,验证的时候该依据什么来配置这两个值。而且,不是说异步的嘛,为什么rx和tx都用同样的配置。
我知道我这样说没有语境,因此,贴上rx_driver、transfer和interface的代码。
dirver:

  1. `ifndef UART_RX_DRIVER
  2. `define UART_RX_DRIVER

  3. class uart_rx_driver extends uvm_driver #(uart_frame) ;

  4. // The virtual interface used to drive and view HDL signals.
  5. virtual interface uart_if vif;

  6. // handle toa cfg class
  7. uart_config cfg;

  8. bit sample_clk;
  9. bit [15:0] ua_brgr;
  10. bit [7:0] ua_bdiv;
  11. int num_of_bits_sent;
  12. int num_frames_sent;

  13. // Provide implementations of virtual methods such as get_type_name and create
  14. `uvm_component_utils_begin(uart_rx_driver)
  15. `uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
  16. `uvm_field_int(ua_brgr, UVM_DEFAULT + UVM_NOPRINT)
  17. `uvm_field_int(ua_bdiv, UVM_DEFAULT + UVM_NOPRINT)
  18. `uvm_component_utils_end

  19. // Constructor - required UVM syntax
  20. function new(string name, uvm_component parent);
  21. super.new(name,parent);
  22. endfunction

  23. // Additional class methods
  24. extern virtual function void build_phase(uvm_phase phase);
  25. extern virtual function void connect_phase(uvm_phase phase);
  26. extern virtual task run_phase(uvm_phase phase);
  27. extern virtual task reset();
  28. extern virtual task get_and_drive();
  29. extern virtual task gen_sample_rate(ref bit [15:0] ua_brgr, ref bit sample_clk);
  30. extern virtual task send_rx_frame(input uart_frame frame);
  31. extern virtual function void report_phase(uvm_phase phase);

  32. endclass : uart_rx_driver

  33. // UVM build_phase
  34. function void uart_rx_driver::build_phase(uvm_phase phase);
  35. super.build_phase(phase);
  36. if(cfg == null)
  37. if (!uvm_config_db#(uart_config)::get(this, "", "cfg", cfg))
  38. `uvm_error("NOCONFIG", "uart_config not set for this component")
  39. endfunction : build_phase

  40. //UVM connect_phase
  41. function void uart_rx_driver::connect_phase(uvm_phase phase);
  42. super.connect_phase(phase);
  43. if (!uvm_config_db#(virtual uart_if)::get(this, "", "vif", vif))
  44. `uvm_error("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
  45. endfunction : connect_phase

  46. //UVM run_phase
  47. task uart_rx_driver::run_phase(uvm_phase phase);
  48. fork
  49. get_and_drive();
  50. gen_sample_rate(ua_brgr, sample_clk);
  51. join
  52. endtask : run_phase

  53. // reset
  54. task uart_rx_driver::reset();
  55. @(negedge vif.reset);
  56. `uvm_info(get_type_name(), "Reset Asserted", UVM_MEDIUM)
  57. vif.rxd = 1;//Receive Data
  58. vif.cts_n = 0;//Clear to Send
  59. vif.dsr_n = 0;//Data Set Ready
  60. vif.ri_n = 0;//Ring Indicator
  61. vif.baud_clk = 0;//Baud Clk - NOT USED
  62. endtask : reset

  63. //get_and drive
  64. task uart_rx_driver::get_and_drive();
  65. while (1) begin
  66. reset();
  67. fork
  68. @(negedge vif.reset)
  69. `uvm_info(get_type_name(), "Reset asserted", UVM_LOW)
  70. begin
  71. forever begin
  72. @(posedge vif.clock iff (vif.reset))
  73. seq_item_port.get_next_item(req);
  74. send_rx_frame(req);
  75. seq_item_port.item_done();
  76. end
  77. end
  78. join_any
  79. disable fork;
  80. //If we are in the middle of a transfer, need to end the rx. Also,
  81. //do any reset cleanup here. The only way we got to this point is via
  82. //a reset.
  83. if(req.is_active()) this.end_tr(req);
  84. end
  85. endtask : get_and_drive

  86. task uart_rx_driver::gen_sample_rate(ref bit [15:0] ua_brgr, ref bit sample_clk);
  87. forever begin
  88. @(posedge vif.clock);
  89. if (!vif.reset) begin
  90. ua_brgr = 0;
  91. sample_clk = 0;
  92. end else begin
  93. if (ua_brgr == ({cfg.baud_rate_div, cfg.baud_rate_gen})) begin
  94. ua_brgr = 0;
  95. sample_clk = 1;
  96. end else begin
  97. sample_clk = 0;
  98. ua_brgr++;
  99. end
  100. end
  101. end
  102. endtask : gen_sample_rate

  103. // -------------------
  104. // send_rx_frame
  105. // -------------------
  106. task uart_rx_driver::send_rx_frame(input uart_frame frame);
  107. bit [7:0] payload_byte;
  108. num_of_bits_sent = 0;

  109. `uvm_info(get_type_name(),
  110. $psprintf("Driver Sending RX Frame...\n%s", frame.sprint()),
  111. UVM_HIGH)

  112. repeat (frame.transmit_delay)
  113. @(posedge vif.clock);
  114. void'(this.begin_tr(frame));

  115. wait((!cfg.rts_en)||(!vif.cts_n));
  116. `uvm_info(get_type_name(), "Driver - Modem RTS or CTS asserted", UVM_HIGH)

  117. while (num_of_bits_sent <= (1 + cfg.char_len_val + cfg.parity_en + cfg.nbstop)) begin
  118. @(posedge vif.clock);
  119. #1;
  120. if (sample_clk) begin
  121. if (num_of_bits_sent == 0) begin
  122. // Start sending rx_frame with "start bit"
  123. vif.rxd = frame.start_bit;
  124. `uvm_info(get_type_name(),
  125. $psprintf("Driver Sending Frame SOP: %b", frame.start_bit),
  126. UVM_HIGH)
  127. end
  128. if ((num_of_bits_sent > 0) && (num_of_bits_sent < (1 + cfg.char_len_val))) begin
  129. // sending "data bits"
  130. payload_byte = frame.payload[num_of_bits_sent-1] ;
  131. vif.rxd = frame.payload[num_of_bits_sent-1];
  132. `uvm_info(get_type_name(),
  133. $psprintf("Driver Sending Frame data bit number:%0d value:'b%b",
  134. (num_of_bits_sent-1), payload_byte), UVM_HIGH)
  135. end
  136. if ((num_of_bits_sent == (1 + cfg.char_len_val)) && (cfg.parity_en)) begin
  137. // sending "parity bit" if parity is enabled
  138. vif.rxd = frame.calc_parity(cfg.char_len_val, cfg.parity_mode);
  139. `uvm_info(get_type_name(),
  140. $psprintf("Driver Sending Frame Parity bit:'b%b",
  141. frame.calc_parity(cfg.char_len_val, cfg.parity_mode)), UVM_HIGH)
  142. end
  143. if (num_of_bits_sent == (1 + cfg.char_len_val + cfg.parity_en)) begin
  144. // sending "stop/error bits"
  145. for (int i = 0; i < cfg.nbstop; i++) begin
  146. `uvm_info(get_type_name(),
  147. $psprintf("Driver Sending Frame Stop bit:'b%b",
  148. frame.stop_bits[i]), UVM_HIGH)
  149. wait (sample_clk);
  150. if (frame.error_bits[i]) begin
  151. vif.rxd = 0;
  152. `uvm_info(get_type_name(),
  153. $psprintf("Driver intensionally corrupting Stop bit since error_bits['b%b] is 'b%b", i, frame.error_bits[i]),
  154. UVM_HIGH)
  155. end else
  156. vif.rxd = frame.stop_bits[i];
  157. num_of_bits_sent++;
  158. wait (!sample_clk);
  159. end
  160. end
  161. num_of_bits_sent++;
  162. wait (!sample_clk);
  163. end
  164. end

  165. num_frames_sent++;
  166. `uvm_info(get_type_name(),
  167. $psprintf("Frame **%0d** Sent...", num_frames_sent), UVM_MEDIUM)
  168. wait (sample_clk);
  169. vif.rxd = 1;

  170. `uvm_info(get_type_name(), "Frame complete...", UVM_MEDIUM)
  171. this.end_tr(frame);

  172. endtask : send_rx_frame

  173. //UVM report_phase
  174. function void uart_rx_driver::report_phase(uvm_phase phase);
  175. `uvm_info(get_type_name(),
  176. $psprintf("UART Frames Sent:%0d", num_frames_sent),
  177. UVM_LOW )
  178. endfunction : report_phase

  179. `endif // UART_RX_DRIVER

复制代码


transfer:

  1. `ifndef UART_FRAME_SVH
  2. `define UART_FRAME_SVH

  3. // Parity Type Control knob
  4. typedef enum bit {GOOD_PARITY, BAD_PARITY} parity_e;

  5. class uart_frame extends uvm_sequence_item;//lab1_note1
  6. // UART Frame
  7. rand bit start_bit;
  8. rand bit [7:0] payload;
  9. bit parity;
  10. rand bit [1:0] stop_bits;
  11. rand bit [3:0] error_bits;

  12. // Control Knobs
  13. rand parity_e parity_type;
  14. rand int transmit_delay;

  15. // Default constraints//lab1_note2
  16. constraint default_txmit_delay {transmit_delay >= 0; transmit_delay < 20;}
  17. constraint default_start_bit { start_bit == 1'b0;}
  18. constraint default_stop_bits { stop_bits == 2'b11;}
  19. constraint default_parity_type { parity_type==GOOD_PARITY;}
  20. constraint default_error_bits { error_bits == 4'b0000;}

  21. // These declarations implement the create() and get_type_name()
  22. // and enable automation of the uart_frame's fields//lab1_note3
  23. `uvm_object_utils_begin(uart_frame)
  24. `uvm_field_int(start_bit, UVM_DEFAULT)
  25. `uvm_field_int(payload, UVM_DEFAULT)
  26. `uvm_field_int(parity, UVM_DEFAULT)
  27. `uvm_field_int(stop_bits, UVM_DEFAULT)
  28. `uvm_field_int(error_bits, UVM_DEFAULT)
  29. `uvm_field_enum(parity_e,parity_type, UVM_DEFAULT + UVM_NOCOMPARE)
  30. `uvm_field_int(transmit_delay, UVM_DEFAULT + UVM_DEC + UVM_NOCOMPARE + UVM_NOCOPY)
  31. `uvm_object_utils_end

  32. // Constructor - required UVM syntax//lab1_note4
  33. function new(string name = "uart_frame");
  34. super.new(name);
  35. endfunction

  36. // This method calculates the parity
  37. function bit calc_parity(int unsigned num_of_data_bits=8,
  38. bit[1:0] ParityMode=0);
  39. bit temp_parity;

  40. if (num_of_data_bits == 6)
  41. temp_parity = ^payload[5:0];
  42. else if (num_of_data_bits == 7)
  43. temp_parity = ^payload[6:0];
  44. else
  45. temp_parity = ^payload;

  46. case(ParityMode[0])
  47. 0: temp_parity = ~temp_parity;
  48. 1: temp_parity = temp_parity;
  49. endcase
  50. case(ParityMode[1])
  51. 0: temp_parity = temp_parity;
  52. 1: temp_parity = ~ParityMode[0];
  53. endcase
  54. if (parity_type == BAD_PARITY)
  55. calc_parity = ~temp_parity;
  56. else
  57. calc_parity = temp_parity;
  58. endfunction

  59. // Parity is calculated in the post_randomize() method//lab1_note5
  60. function void post_randomize();
  61. parity = calc_parity();
  62. endfunction : post_randomize

  63. endclass

  64. `endif

复制代码


interface:

  1. interface uart_if(input clock, reset);

  2. logic txd;// Transmit Data
  3. logic rxd;// Receive Data

  4. logic intrpt;// Interrupt

  5. logic ri_n;// ring indicator
  6. logic cts_n;// clear to send
  7. logic dsr_n;// data set ready
  8. logic rts_n;// request to send
  9. logic dtr_n;// data terminal ready
  10. logic dcd_n;// data carrier detect

  11. logic baud_clk;// Baud Rate Clock

  12. // Control flags
  13. bithas_checks = 1;
  14. bithas_coverage = 1;

  15. /*FIX TO USE CONCURRENT ASSERTIONS
  16. always @(posedge clock)
  17. begin
  18. // rxd must not be X or Z
  19. assertRxdUnknown:assert property (
  20. disable iff(!has_checks || !reset)(!$isunknown(rxd)))
  21. else
  22. $error("ERR_UART001_Rxd_XZ\n Rxd went to X or Z");
  23. end
  24. */

  25. endinterface : uart_if

复制代码

波特率是由你要测试的目的和dut决定的
异步并不是指tx和rx之间,指的是接收端和发送端所使用的时钟是否一样

谢谢!也就是说我要试不同的配置以观察波特率?另外,不光是tx与rx采用一样的sample_clk,我看monitor那边也是这样弄的,driver是发送方,monitor是接收方对吧。

我目前也在看这个例子,有机会交流学习一下。q:466183347

看看

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top