📄 mii_phy.sv
字号:
logic err; bit drop; {nibble1, nibble0} = bytes[i]; en = 1'b1; err = 1'b0; drop = 1'b0; `vmm_callback(mii_phy_layer_callbacks, pre_symbol_tx(this, fr, bytes, i*2, nibble0, en, err, drop)); if (!drop) begin @this.sigs.prx; this.sigs.prx.rxd <= nibble0; this.sigs.prx.rx_dv <= en; this.sigs.prx.rx_err <= err; error |= err; if (this.sigs.col) col = 1; end en = 1'b1; err = 1'b0; drop = 1'b0; `vmm_callback(mii_phy_layer_callbacks, pre_symbol_tx(this, fr, bytes, i*2 + 1, nibble1, en, err, drop)); if (!drop) begin @this.sigs.prx; this.sigs.prx.rxd <= nibble1; this.sigs.prx.rx_dv <= en; this.sigs.prx.rx_err <= err; error |= err; if (this.sigs.col) col = 1; end if (col && !this.cfg.full_duplex) begin error = 1; `vmm_debug(this.log, "Jamming..."); // Jam the transmission for (int j = 0; j < 8; j++) begin nibble0 = $random; en = 1'b1; err = 1'b0; drop = 1'b0; `vmm_callback(mii_phy_layer_callbacks, pre_symbol_tx(this, fr, bytes, i*2 + 2 + j, nibble0, en, err, drop)); if (!drop) begin @this.sigs.prx; this.sigs.prx.rxd <= nibble0; this.sigs.prx.rx_dv <= en; this.sigs.prx.rx_err <= err; end end break; end end this.txing = 0; this.tx_chan.complete(); if (log.start_msg(vmm_log::DEBUG_TYP , vmm_log::TRACE_SEV )) begin log.text("Transmitted frame..."); log.text(fr.psdisplay(" ")); log.end_msg(); end @this.sigs.prx; this.sigs.prx.rxd <= 4'b0; this.sigs.prx.rx_dv <= 1'b0; this.sigs.prx.rx_err <= 1'b0; // Make sure CRS stays asserted for >1 cycle fork begin: hold_crs repeat (2) @this.sigs.prx; if (!this.txing && !this.rxing) begin this.indications.reset(eth_pls_indications::CARRIER); end end join_none `vmm_callback(mii_phy_layer_callbacks, post_frame_tx(this, fr, bytes, error)); this.tx_chan.remove(); endendtask: tx_drivertask mii_phy_layer::rx_monitor(); logic [7:0] bytes[]; integer n_bytes; bit err; bytes = new [1600]; // Has the monitor been started in the middle of a frame being received? if (this.sigs.ptx.tx_en) begin `vmm_warning(this.log, "Transactor started in the middle of a MAC->PHY transfer"); this.indications.indicate(eth_pls_indications::CARRIER); wait (this.sigs.ptx.tx_en === 1'b0); end if (!this.txing) this.indications.reset(eth_pls_indications::CARRIER); forever begin logic [7:0] a_byte; // Wait for the start of the frame wait (this.sigs.ptx.tx_en === 1'b1); this.indications.indicate(eth_pls_indications::CARRIER); `vmm_debug(this.log, "Started to receive symbols..."); this.rxing = 1; // Wait for the SFD while (this.sigs.ptx.txd !== 4'b1101) begin if (this.sigs.ptx.tx_en !== 1'b1) begin // Indicate a false carrier // ToDo... this.indications.reset(eth_pls_indications::CARRIER); break; end @(this.sigs.ptx); end `vmm_debug(this.log, "Started to receive a frame..."); @(this.sigs.ptx); // Skip SFD... // Collect nibbles into bytes (LS first) // until tx_en is deasserted n_bytes = 0; err = 0; while (this.sigs.ptx.tx_en === 1'b1) begin a_byte[3:0] = this.sigs.ptx.txd; if (this.sigs.ptx.tx_err !== 1'b0) err++; `vmm_callback(mii_phy_layer_callbacks, post_symbol_rx(this, n_bytes * 2, this.sigs.ptx.txd, 1'b1, this.sigs.ptx.tx_err)); @this.sigs.ptx; if (this.sigs.ptx.tx_en !== 1'b1) break; a_byte[7:4] = this.sigs.ptx.txd; if (this.sigs.ptx.tx_err !== 1'b0) err++; `vmm_callback(mii_phy_layer_callbacks, post_symbol_rx(this, n_bytes * 2 + 1, this.sigs.ptx.txd, 1'b1, this.sigs.ptx.tx_err)); // Increase byte buffer if necessary if (n_bytes >= bytes.size()) begin bytes = new [bytes.size() * 2] (bytes); end bytes[n_bytes++] = a_byte; @this.sigs.ptx; end this.rxing = 0; // Make sure CRS stays asserted for >1 cycle fork begin repeat (2) @this.sigs.prx; if (!this.txing && !this.rxing) begin this.indications.reset(eth_pls_indications::CARRIER); end end join_none // End of frame. Unpack and forward it if (err == 0) begin // Example 4-62 eth_frame fr = this.utils.bytes_to_frame(this.log, bytes, n_bytes, this.rx_factory); if (fr == null) continue; fr.stream_id = this.stream_id; fr.data_id = this.frame_count++; if (log.start_msg(vmm_log::DEBUG_TYP , vmm_log::TRACE_SEV )) begin log.text("Received frame..."); log.text(fr.psdisplay(" ")); log.end_msg(); end `vmm_callback(mii_phy_layer_callbacks, post_frame_rx(this, fr, bytes, n_bytes)); this.rx_chan.sneak(fr); end else begin if (log.start_msg(vmm_log::DEBUG_TYP , vmm_log::TRACE_SEV )) begin string msg; $sformat(msg, "Dropping received frame because of %0d TxERR...", err); log.text(msg); log.end_msg(); end end endendtask: rx_monitor task mii_phy_layer::crs_driver(); while (1) begin this.indications.wait_for(eth_pls_indications::CARRIER); this.sigs.crs <= 1'b1; this.indications.wait_for_off(eth_pls_indications::CARRIER); this.sigs.crs <= 1'b0; endendtask: crs_driver task mii_phy_layer::col_driver(); fork while (1) begin wait (this.sigs.ptx.tx_en === 1'b1 && this.txing); this.indications.indicate(eth_pls_indications::COLLISION); wait (this.sigs.ptx.tx_en !== 1'b1 || !this.txing); if (this.sigs.ptx.tx_en === 1'b1 && !this.txing) begin // Hold COL pass RX_DV deassert repeat (2) @this.sigs.prx; end this.indications.reset(eth_pls_indications::COLLISION); end join_none while (1) begin this.indications.wait_for(eth_pls_indications::COLLISION); this.sigs.col <= 1'b1; this.indications.wait_for_off(eth_pls_indications::COLLISION); this.sigs.col <= 1'b0; endendtask: col_driver
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -