-
Notifications
You must be signed in to change notification settings - Fork 18
[chip, I2C, DV] Top level I2C host test #473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
KinzaQamar
wants to merge
4
commits into
lowRISC:main
Choose a base branch
from
KinzaQamar:i2c_dv
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e783ecf
[chip, I2C, DV] Top level wiring of I2C ports with the interface
KinzaQamar 8c06101
[chip, I2C, DV] Wired up I2C agent in the chip environment
KinzaQamar 52e5ed4
chip, I2C, SW] Added I2C host TX_RX test
KinzaQamar 0265992
[chip, I2C, DV] Added Host TX-RX vseq
KinzaQamar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
hw/top_chip/dv/env/seq_lib/top_chip_dv_i2c_host_tx_rx_vseq.sv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Copyright lowRISC contributors (COSMIC project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // Virtual sequence for testing the DUT as an I2C host/controller. | ||
| // | ||
| // The agent is configured in Device mode, acting as a reactive target that responds to transactions | ||
| // initiated by the DUT. The i2c_monitor watches the bus and forwards observed items to the | ||
| // i2c_sequencer via an analysis port. The i2c_device_response_seq then creates ACK/NACK/Rdata | ||
| // responses and i2c_driver drives them back to the DUT in response. | ||
| class top_chip_dv_i2c_host_tx_rx_vseq extends top_chip_dv_i2c_tx_rx_vseq; | ||
| `uvm_object_utils(top_chip_dv_i2c_host_tx_rx_vseq) | ||
|
|
||
| extern function new(string name=""); | ||
| extern task body(); | ||
| extern virtual task dut_init(string reset_kind = "HARD"); | ||
| endclass : top_chip_dv_i2c_host_tx_rx_vseq | ||
|
|
||
| function top_chip_dv_i2c_host_tx_rx_vseq::new(string name = ""); | ||
| super.new(name); | ||
| endfunction | ||
|
|
||
| task top_chip_dv_i2c_host_tx_rx_vseq::dut_init(string reset_kind = "HARD"); | ||
| super.dut_init(reset_kind); | ||
|
|
||
| // Read the timing parameters through SW backdoor load | ||
| sw_symbol_backdoor_read("sys_clk_period_ns", sw_sys_clk_period_ns); | ||
| sw_symbol_backdoor_read("scl_low_time_ns", sw_scl_low_time_ns); | ||
| sw_symbol_backdoor_read("hold_data_time_ns", sw_data_hold_time_ns); | ||
|
|
||
| scl_low_cycles = round_up_divide({sw_scl_low_time_ns[1], sw_scl_low_time_ns[0]}, | ||
| sw_sys_clk_period_ns[0]); | ||
| sda_hold_cycles = round_up_divide({sw_data_hold_time_ns[1], sw_data_hold_time_ns[0]}, | ||
| sw_sys_clk_period_ns[0]); | ||
|
|
||
| endtask | ||
|
KinzaQamar marked this conversation as resolved.
|
||
|
|
||
| task top_chip_dv_i2c_host_tx_rx_vseq::body(); | ||
|
KinzaQamar marked this conversation as resolved.
|
||
| i2c_device_response_seq seq = i2c_device_response_seq::type_id::create("seq"); | ||
|
|
||
| // Configure the agent to be reactive | ||
| cfg.m_i2c_agent_cfg.if_mode = Device; | ||
| super.body(); | ||
|
|
||
| `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest); | ||
| `uvm_info(`gfn, "Starting I2C Host TX-RX test", UVM_LOW) | ||
|
|
||
| configure_agent_timing(); | ||
| print_i2c_timing_cfg(); | ||
| fork | ||
| seq.start(p_sequencer.i2c_sqr); | ||
| join_none | ||
| endtask | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| // Copyright lowRISC contributors (COSMIC project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| class top_chip_dv_i2c_tx_rx_vseq extends top_chip_dv_base_vseq; | ||
| `uvm_object_utils(top_chip_dv_i2c_tx_rx_vseq) | ||
|
|
||
| // Below variables will get assigned through SW backdoor load. They are defined as byte size | ||
| // arrays because "sw_symbol_backdoor_read/overwrite" takes an array as an argument to write or | ||
| // read the SW symbol. | ||
| protected bit [7:0] sw_sys_clk_period_ns[1]; | ||
| protected bit [7:0] sw_scl_low_time_ns[2]; | ||
| protected bit [7:0] sw_data_hold_time_ns[2]; | ||
|
|
||
| // The timing parameters in cycles used by the agent to add relevant delays before driving the | ||
| // responses. | ||
| protected bit [15:0] scl_low_cycles; | ||
| protected bit [15:0] sda_hold_cycles; | ||
|
|
||
| extern function new(string name=""); | ||
|
|
||
| // Returns the ceiling of (a / b), converting a timing parameter "a" in nanoseconds to an integer | ||
| // number of cycles by rounding up. | ||
| extern protected function int unsigned round_up_divide(int unsigned a, int unsigned b); | ||
|
|
||
| // Compute timing parameters utilized by the agent to add delays to the responses | ||
| extern protected function void configure_agent_timing(); | ||
| extern protected function void print_i2c_timing_cfg(); | ||
| endclass : top_chip_dv_i2c_tx_rx_vseq | ||
|
|
||
| function top_chip_dv_i2c_tx_rx_vseq::new(string name = ""); | ||
| super.new(name); | ||
| endfunction | ||
|
|
||
| function int unsigned top_chip_dv_i2c_tx_rx_vseq::round_up_divide(int unsigned a, int unsigned b); | ||
| return (((a - 1) / b) + 1); | ||
| endfunction | ||
|
|
||
| function void top_chip_dv_i2c_tx_rx_vseq::configure_agent_timing(); | ||
| // tSetupBit are the cycles before SCL goes high to drive SDA. Agent should drive at least two | ||
| // cycles before SCL goes high. | ||
| int unsigned tSetupBit = 2; | ||
| cfg.m_i2c_agent_cfg.timing_cfg.tSetupBit = tSetupBit; | ||
|
|
||
| // tHoldBit are the cycles to hold SDA after SCL goes low. | ||
| cfg.m_i2c_agent_cfg.timing_cfg.tHoldBit = sda_hold_cycles; | ||
|
|
||
| // Used by i2c_if to stretch SCL by tClockpulse cycles before driving SDA. If tClockPulse cycles | ||
| // are greater than the cycles taken by an SCL pulse, then i2c_monitor acknowledges the "ack" | ||
| // late and then drives Rdata when SCL is high. | ||
| cfg.m_i2c_agent_cfg.timing_cfg.tClockPulse = scl_low_cycles; | ||
|
|
||
| // tClockLow are the SCL low cycles that the i2c_driver use before driving SDA after stretching | ||
| // SCL by tClockPulse cycles. Drive SDA at least tSetupBit cycles earlier to avoid the chances of | ||
| // SDA interference. | ||
| cfg.m_i2c_agent_cfg.timing_cfg.tClockLow = scl_low_cycles - tSetupBit; | ||
| endfunction | ||
|
|
||
| function void top_chip_dv_i2c_tx_rx_vseq::print_i2c_timing_cfg(); | ||
| timing_cfg_t timing_cfg = cfg.m_i2c_agent_cfg.timing_cfg; | ||
| string str = ""; | ||
|
|
||
| // Print the timing parameters in a tabular form | ||
| str = {str, "\n+----------------------+---------+"}; | ||
| str = {str, $sformatf("\n| %-20s | %-7s |", "Timing Parameter", "Value")}; | ||
| str = {str, "\n+----------------------+---------+"}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSetupStart", timing_cfg.tSetupStart)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tHoldStart", timing_cfg.tHoldStart)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tClockStart", timing_cfg.tClockStart)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tClockLow", timing_cfg.tClockLow)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSetupBit", timing_cfg.tSetupBit)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tClockPulse", timing_cfg.tClockPulse)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tHoldBit", timing_cfg.tHoldBit)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tClockStop", timing_cfg.tClockStop)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSetupStop", timing_cfg.tSetupStop)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tHoldStop", timing_cfg.tHoldStop)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tTimeOut", timing_cfg.tTimeOut)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "enbTimeOut", timing_cfg.enbTimeOut)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tStretchHostClock",timing_cfg.tStretchHostClock)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSdaUnstable", timing_cfg.tSdaUnstable)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSdaInterference", timing_cfg.tSdaInterference)}; | ||
| str = {str, $sformatf("\n| %-20s | %7d |", "tSclInterference", timing_cfg.tSclInterference)}; | ||
| `uvm_info(`gfn, $sformatf("%s", str), UVM_MEDIUM); | ||
| endfunction | ||
|
KinzaQamar marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -38,10 +38,23 @@ module tb; | |||||
| logic rng_valid; | ||||||
| logic [top_pkg::EntropySrcRngBusWidth-1:0] rng_bits; | ||||||
|
|
||||||
| // I2C connections | ||||||
| wire scl; | ||||||
| wire sda; | ||||||
| logic scl_en_o; | ||||||
| logic sda_en_o; | ||||||
| logic scl_o; | ||||||
| logic sda_o; | ||||||
|
|
||||||
| // ------ Interfaces ------ | ||||||
| clk_rst_if sys_clk_if(.clk(clk), .rst_n(rst_n)); | ||||||
| uart_if uart_if(); | ||||||
| pins_if #(NUM_GPIOS) gpio_pins_if (.pins(gpio_pads)); | ||||||
| i2c_if i2c_if (.clk_i(clk ), | ||||||
| .rst_ni(rst_n ), | ||||||
| .scl_io(scl ), | ||||||
| .sda_io(sda ) | ||||||
| ); | ||||||
|
|
||||||
| // ------ Mock DRAM ------ | ||||||
| top_pkg::axi_dram_req_t dram_req; | ||||||
|
|
@@ -82,6 +95,13 @@ module tb; | |||||
| // UART receive and transmit. | ||||||
| .uart_rx_i (uart_if.uart_rx ), | ||||||
| .uart_tx_o (uart_if.uart_tx ), | ||||||
| // I2C controller/target bidirectional interface. | ||||||
| .i2c_scl_i (scl ), | ||||||
| .i2c_scl_o (scl_o ), | ||||||
| .i2c_scl_en_o (scl_en_o ), | ||||||
| .i2c_sda_i (sda ), | ||||||
| .i2c_sda_o (sda_o ), | ||||||
| .i2c_sda_en_o (sda_en_o ), | ||||||
| // External Mailbox port | ||||||
| .axi_mailbox_req_i ('0 ), | ||||||
| .axi_mailbox_resp_o ( ), | ||||||
|
|
@@ -126,6 +146,10 @@ module tb; | |||||
| assign gpio_pads[i] = dut_gpio_en_o[i] ? dut_gpio_o[i] : 1'bz; | ||||||
| end | ||||||
|
|
||||||
| // Modelling the open-drain circuit | ||||||
| assign (strong0, weak1) scl = (scl_en_o) ? scl_o : 1'b1; | ||||||
| assign (strong0, weak1) sda = (sda_en_o) ? sda_o : 1'b1; | ||||||
|
|
||||||
| // Signals to connect the sink | ||||||
| logic sim_sram_clk; | ||||||
| logic sim_sram_rst; | ||||||
|
|
@@ -260,6 +284,7 @@ module tb; | |||||
| uvm_config_db#(virtual clk_rst_if)::set(null, "*", "sys_clk_if", sys_clk_if); | ||||||
| uvm_config_db#(virtual uart_if)::set(null, "*.env.m_uart_agent*", "vif", uart_if); | ||||||
| uvm_config_db#(virtual pins_if #(NUM_GPIOS))::set(null, "*.env", "gpio_vif", gpio_pins_if); | ||||||
| uvm_config_db#(virtual i2c_if)::set(null, "*.env.m_i2c_agent", "vif", i2c_if); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably best to add a wildcard as if a sub-component of i2c agent tries to get this handle it will fail. But it doesn't hurt us to give this possibility in case:
Suggested change
|
||||||
|
|
||||||
| // SW logger and test status interfaces. | ||||||
| uvm_config_db#(virtual sw_test_status_if)::set( | ||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
elliotb-lowrisc marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| // Copyright lowRISC contributors (COSMIC project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| #include "hal/i2c.h" | ||
| #include "hal/mmio.h" | ||
| #include "hal/mocha.h" | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| // The const variables below are treated as symbols read by top_chip_dv_i2c_host_tx_rx_vseq in order | ||
| // to calculate agent timing parameters. | ||
| const uint8_t sys_clk_period_ns = SYSCLK_NS; | ||
|
|
||
| // The constants are the spec minimums for standard mode speed except hold_data_time_ns which should | ||
| // be at least one according to OpenTitan's programming guide. | ||
| const uint16_t scl_low_time_ns = 4700; | ||
| const uint16_t hold_data_time_ns = 1; | ||
|
|
||
| enum : uint8_t { | ||
| device_addr = 0x3A, | ||
| num_bytes = 0x8, | ||
| }; | ||
|
|
||
| static bool write_transfer(i2c_t i2c, uint8_t addr, const uint8_t *data, uint8_t num_bytes) | ||
| { | ||
| // Start a write transfer | ||
| i2c_write_bytes(i2c, addr, data, num_bytes); | ||
| return i2c_wait_transfer_finish(i2c); | ||
| } | ||
|
|
||
| static bool read_transfer(i2c_t i2c, uint8_t addr, uint8_t num_bytes) | ||
| { | ||
| // Start a read transfer | ||
| i2c_read_bytes(i2c, addr, num_bytes); | ||
| return i2c_wait_transfer_finish(i2c); | ||
| } | ||
|
|
||
| static bool drive_transfer(i2c_t i2c, uint8_t addr, const uint8_t *data, uint8_t num_bytes) | ||
| { | ||
| bool write_transfer_status = write_transfer(i2c, addr, data, num_bytes); | ||
| bool read_transfer_status = read_transfer(i2c, addr, num_bytes); | ||
|
|
||
| return (write_transfer_status && read_transfer_status); | ||
| } | ||
|
|
||
| static bool host_tx_rx_test(i2c_t i2c) | ||
| { | ||
| // Data bytes to send to the target's receiver. | ||
| uint8_t data_bytes[num_bytes]; | ||
|
|
||
| // Write walking 1's pattern | ||
| for (uint8_t i = 0; i < num_bytes; i++) { | ||
| data_bytes[i] = 1u << (i % 8); | ||
| } | ||
|
|
||
| if (!drive_transfer(i2c, device_addr, data_bytes, num_bytes)) { | ||
| return false; | ||
| } | ||
|
|
||
| for (uint8_t i = 0; i < num_bytes; i++) { | ||
| if (data_bytes[i] != i2c_rdata_byte(i2c)) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool test_main() | ||
| { | ||
| i2c_t i2c = mocha_system_i2c(); | ||
| i2c_init(i2c, i2c_speed_mode_standard); | ||
| i2c_enable_controller_mode(i2c); | ||
| return host_tx_rx_test(i2c); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.