|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
本帖最后由 oscillator_cn1 于 2013-12-5 09:30 编辑
各位: 关于uart的采样频率,我有点不大明白。sample_clk是对interface上的时钟进行计数,等于{cfg.baud_rate_div,cfg.baud_rate_gen}的时候开始采样,那我不大清楚,验证的时候该依据什么来配置这两个值。而且,不是说异步的嘛,为什么rx和tx都用同样的配置。
我知道我这样说没有语境,因此,贴上rx_driver、transfer和interface的代码。
dirver:
- `ifndef UART_RX_DRIVER
- `define UART_RX_DRIVER
- class uart_rx_driver extends uvm_driver #(uart_frame) ;
- // The virtual interface used to drive and view HDL signals.
- virtual interface uart_if vif;
- // handle to a cfg class
- uart_config cfg;
- bit sample_clk;
- bit [15:0] ua_brgr;
- bit [7:0] ua_bdiv;
- int num_of_bits_sent;
- int num_frames_sent;
- // Provide implementations of virtual methods such as get_type_name and create
- `uvm_component_utils_begin(uart_rx_driver)
- `uvm_field_object(cfg, UVM_DEFAULT | UVM_REFERENCE)
- `uvm_field_int(ua_brgr, UVM_DEFAULT + UVM_NOPRINT)
- `uvm_field_int(ua_bdiv, UVM_DEFAULT + UVM_NOPRINT)
- `uvm_component_utils_end
- // Constructor - required UVM syntax
- function new(string name, uvm_component parent);
- super.new(name,parent);
- endfunction
- // Additional class methods
- extern virtual function void build_phase(uvm_phase phase);
- extern virtual function void connect_phase(uvm_phase phase);
- extern virtual task run_phase(uvm_phase phase);
- extern virtual task reset();
- extern virtual task get_and_drive();
- extern virtual task gen_sample_rate(ref bit [15:0] ua_brgr, ref bit sample_clk);
- extern virtual task send_rx_frame(input uart_frame frame);
- extern virtual function void report_phase(uvm_phase phase);
-
- endclass : uart_rx_driver
- // UVM build_phase
- function void uart_rx_driver::build_phase(uvm_phase phase);
- super.build_phase(phase);
- if(cfg == null)
- if (!uvm_config_db#(uart_config)::get(this, "", "cfg", cfg))
- `uvm_error("NOCONFIG", "uart_config not set for this component")
- endfunction : build_phase
- //UVM connect_phase
- function void uart_rx_driver::connect_phase(uvm_phase phase);
- super.connect_phase(phase);
- if (!uvm_config_db#(virtual uart_if)::get(this, "", "vif", vif))
- `uvm_error("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"})
- endfunction : connect_phase
- //UVM run_phase
- task uart_rx_driver::run_phase(uvm_phase phase);
- fork
- get_and_drive();
- gen_sample_rate(ua_brgr, sample_clk);
- join
- endtask : run_phase
- // reset
- task uart_rx_driver::reset();
- @(negedge vif.reset);
- `uvm_info(get_type_name(), "Reset Asserted", UVM_MEDIUM)
- vif.rxd = 1; //Receive Data
- vif.cts_n = 0; //Clear to Send
- vif.dsr_n = 0; //Data Set Ready
- vif.ri_n = 0; //Ring Indicator
- vif.baud_clk = 0; //Baud Clk - NOT USED
- endtask : reset
- // get_and drive
- task uart_rx_driver::get_and_drive();
- while (1) begin
- reset();
- fork
- @(negedge vif.reset)
- `uvm_info(get_type_name(), "Reset asserted", UVM_LOW)
- begin
- forever begin
- @(posedge vif.clock iff (vif.reset))
- seq_item_port.get_next_item(req);
- send_rx_frame(req);
- seq_item_port.item_done();
- end
- end
- join_any
- disable fork;
- //If we are in the middle of a transfer, need to end the rx. Also,
- //do any reset cleanup here. The only way we got to this point is via
- //a reset.
- if(req.is_active()) this.end_tr(req);
- end
- endtask : get_and_drive
- task uart_rx_driver::gen_sample_rate(ref bit [15:0] ua_brgr, ref bit sample_clk);
- forever begin
- @(posedge vif.clock);
- if (!vif.reset) begin
- ua_brgr = 0;
- sample_clk = 0;
- end else begin
- if (ua_brgr == ({cfg.baud_rate_div, cfg.baud_rate_gen})) begin
- ua_brgr = 0;
- sample_clk = 1;
- end else begin
- sample_clk = 0;
- ua_brgr++;
- end
- end
- end
- endtask : gen_sample_rate
- // -------------------
- // send_rx_frame
- // -------------------
- task uart_rx_driver::send_rx_frame(input uart_frame frame);
- bit [7:0] payload_byte;
- num_of_bits_sent = 0;
- `uvm_info(get_type_name(),
- $psprintf("Driver Sending RX Frame...\n%s", frame.sprint()),
- UVM_HIGH)
-
- repeat (frame.transmit_delay)
- @(posedge vif.clock);
- void'(this.begin_tr(frame));
-
- wait((!cfg.rts_en)||(!vif.cts_n));
- `uvm_info(get_type_name(), "Driver - Modem RTS or CTS asserted", UVM_HIGH)
- while (num_of_bits_sent <= (1 + cfg.char_len_val + cfg.parity_en + cfg.nbstop)) begin
- @(posedge vif.clock);
- #1;
- if (sample_clk) begin
- if (num_of_bits_sent == 0) begin
- // Start sending rx_frame with "start bit"
- vif.rxd = frame.start_bit;
- `uvm_info(get_type_name(),
- $psprintf("Driver Sending Frame SOP: %b", frame.start_bit),
- UVM_HIGH)
- end
- if ((num_of_bits_sent > 0) && (num_of_bits_sent < (1 + cfg.char_len_val))) begin
- // sending "data bits"
- payload_byte = frame.payload[num_of_bits_sent-1] ;
- vif.rxd = frame.payload[num_of_bits_sent-1];
- `uvm_info(get_type_name(),
- $psprintf("Driver Sending Frame data bit number:%0d value:'b%b",
- (num_of_bits_sent-1), payload_byte), UVM_HIGH)
- end
- if ((num_of_bits_sent == (1 + cfg.char_len_val)) && (cfg.parity_en)) begin
- // sending "parity bit" if parity is enabled
- vif.rxd = frame.calc_parity(cfg.char_len_val, cfg.parity_mode);
- `uvm_info(get_type_name(),
- $psprintf("Driver Sending Frame Parity bit:'b%b",
- frame.calc_parity(cfg.char_len_val, cfg.parity_mode)), UVM_HIGH)
- end
- if (num_of_bits_sent == (1 + cfg.char_len_val + cfg.parity_en)) begin
- // sending "stop/error bits"
- for (int i = 0; i < cfg.nbstop; i++) begin
- `uvm_info(get_type_name(),
- $psprintf("Driver Sending Frame Stop bit:'b%b",
- frame.stop_bits[i]), UVM_HIGH)
- wait (sample_clk);
- if (frame.error_bits[i]) begin
- vif.rxd = 0;
- `uvm_info(get_type_name(),
- $psprintf("Driver intensionally corrupting Stop bit since error_bits['b%b] is 'b%b", i, frame.error_bits[i]),
- UVM_HIGH)
- end else
- vif.rxd = frame.stop_bits[i];
- num_of_bits_sent++;
- wait (!sample_clk);
- end
- end
- num_of_bits_sent++;
- wait (!sample_clk);
- end
- end
-
- num_frames_sent++;
- `uvm_info(get_type_name(),
- $psprintf("Frame **%0d** Sent...", num_frames_sent), UVM_MEDIUM)
- wait (sample_clk);
- vif.rxd = 1;
- `uvm_info(get_type_name(), "Frame complete...", UVM_MEDIUM)
- this.end_tr(frame);
-
- endtask : send_rx_frame
- //UVM report_phase
- function void uart_rx_driver::report_phase(uvm_phase phase);
- `uvm_info(get_type_name(),
- $psprintf("UART Frames Sent:%0d", num_frames_sent),
- UVM_LOW )
- endfunction : report_phase
- `endif // UART_RX_DRIVER
复制代码
transfer:
- `ifndef UART_FRAME_SVH
- `define UART_FRAME_SVH
- // Parity Type Control knob
- typedef enum bit {GOOD_PARITY, BAD_PARITY} parity_e;
- class uart_frame extends uvm_sequence_item; //lab1_note1
- // UART Frame
- rand bit start_bit;
- rand bit [7:0] payload;
- bit parity;
- rand bit [1:0] stop_bits;
- rand bit [3:0] error_bits;
-
- // Control Knobs
- rand parity_e parity_type;
- rand int transmit_delay;
- // Default constraints //lab1_note2
- constraint default_txmit_delay {transmit_delay >= 0; transmit_delay < 20;}
- constraint default_start_bit { start_bit == 1'b0;}
- constraint default_stop_bits { stop_bits == 2'b11;}
- constraint default_parity_type { parity_type==GOOD_PARITY;}
- constraint default_error_bits { error_bits == 4'b0000;}
- // These declarations implement the create() and get_type_name()
- // and enable automation of the uart_frame's fields //lab1_note3
- `uvm_object_utils_begin(uart_frame)
- `uvm_field_int(start_bit, UVM_DEFAULT)
- `uvm_field_int(payload, UVM_DEFAULT)
- `uvm_field_int(parity, UVM_DEFAULT)
- `uvm_field_int(stop_bits, UVM_DEFAULT)
- `uvm_field_int(error_bits, UVM_DEFAULT)
- `uvm_field_enum(parity_e,parity_type, UVM_DEFAULT + UVM_NOCOMPARE)
- `uvm_field_int(transmit_delay, UVM_DEFAULT + UVM_DEC + UVM_NOCOMPARE + UVM_NOCOPY)
- `uvm_object_utils_end
- // Constructor - required UVM syntax //lab1_note4
- function new(string name = "uart_frame");
- super.new(name);
- endfunction
-
- // This method calculates the parity
- function bit calc_parity(int unsigned num_of_data_bits=8,
- bit[1:0] ParityMode=0);
- bit temp_parity;
- if (num_of_data_bits == 6)
- temp_parity = ^payload[5:0];
- else if (num_of_data_bits == 7)
- temp_parity = ^payload[6:0];
- else
- temp_parity = ^payload;
- case(ParityMode[0])
- 0: temp_parity = ~temp_parity;
- 1: temp_parity = temp_parity;
- endcase
- case(ParityMode[1])
- 0: temp_parity = temp_parity;
- 1: temp_parity = ~ParityMode[0];
- endcase
- if (parity_type == BAD_PARITY)
- calc_parity = ~temp_parity;
- else
- calc_parity = temp_parity;
- endfunction
- // Parity is calculated in the post_randomize() method //lab1_note5
- function void post_randomize();
- parity = calc_parity();
- endfunction : post_randomize
- endclass
- `endif
复制代码
interface:
- interface uart_if(input clock, reset);
- logic txd; // Transmit Data
- logic rxd; // Receive Data
-
- logic intrpt; // Interrupt
- logic ri_n; // ring indicator
- logic cts_n; // clear to send
- logic dsr_n; // data set ready
- logic rts_n; // request to send
- logic dtr_n; // data terminal ready
- logic dcd_n; // data carrier detect
- logic baud_clk; // Baud Rate Clock
-
- // Control flags
- bit has_checks = 1;
- bit has_coverage = 1;
- /* FIX TO USE CONCURRENT ASSERTIONS
- always @(posedge clock)
- begin
- // rxd must not be X or Z
- assertRxdUnknown:assert property (
- disable iff(!has_checks || !reset)(!$isunknown(rxd)))
- else
- $error("ERR_UART001_Rxd_XZ\n Rxd went to X or Z");
- end
- */
- endinterface : uart_if
复制代码 |
|