| // Copyright 2023 Google LLC |
| // Copyright lowRISC contributors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| module chip_sim_tb ( |
| // Clock and Reset |
| input clk_i, |
| input rst_ni |
| ); |
| |
| logic [31:0] cio_gpio_p2d, cio_gpio_d2p, cio_gpio_en_d2p; |
| logic [31:0] cio_gpio_pull_en, cio_gpio_pull_select; |
| logic cio_uart_rx_p2d, cio_uart_tx_d2p, cio_uart_tx_en_d2p; |
| logic cio_smc_uart_rx_p2d, cio_smc_uart_tx_d2p; |
| |
| logic cio_spi_device_sck_p2d, cio_spi_device_csb_p2d; |
| logic cio_spi_device_sdi_p2d; |
| logic cio_spi_device_sdo_d2p, cio_spi_device_sdo_en_d2p; |
| |
| logic cio_usbdev_sense_p2d; |
| logic cio_usbdev_se0_d2p; |
| logic cio_usbdev_dp_pullup_d2p; |
| logic cio_usbdev_dn_pullup_d2p; |
| logic cio_usbdev_rx_enable_d2p; |
| logic cio_usbdev_tx_use_d_se0_d2p; |
| logic cio_usbdev_d_p2d, cio_usbdev_d_d2p, cio_usbdev_d_en_d2p; |
| logic cio_usbdev_dp_p2d, cio_usbdev_dp_d2p, cio_usbdev_dp_en_d2p; |
| logic cio_usbdev_dn_p2d, cio_usbdev_dn_d2p, cio_usbdev_dn_en_d2p; |
| |
| chip_matcha_verilator u_dut ( |
| .clk_i, |
| .rst_ni, |
| |
| // communication with GPIO |
| .cio_gpio_p2d_i(cio_gpio_p2d), |
| .cio_gpio_d2p_o(cio_gpio_d2p), |
| .cio_gpio_en_d2p_o(cio_gpio_en_d2p), |
| .cio_gpio_pull_en_o(cio_gpio_pull_en), |
| .cio_gpio_pull_select_o(cio_gpio_pull_select), |
| |
| // communication with UART |
| .cio_uart_rx_p2d_i(cio_uart_rx_p2d), |
| .cio_uart_tx_d2p_o(cio_uart_tx_d2p), |
| |
| // communication with SMC UART |
| .cio_uart_smc_rx_p2d_i(cio_smc_uart_rx_p2d), |
| .cio_uart_smc_tx_d2p_o(cio_smc_uart_tx_d2p), |
| |
| // communication with SPI |
| .cio_spi_device_sck_p2d_i(cio_spi_device_sck_p2d), |
| .cio_spi_device_csb_p2d_i(cio_spi_device_csb_p2d), |
| .cio_spi_device_sdi_p2d_i(cio_spi_device_sdi_p2d), |
| .cio_spi_device_sdo_d2p_o(cio_spi_device_sdo_d2p), |
| .cio_spi_device_sdo_en_d2p_o(cio_spi_device_sdo_en_d2p), |
| |
| // communication with USB |
| .cio_usbdev_sense_p2d_i(cio_usbdev_sense_p2d), |
| .cio_usbdev_dp_pullup_d2p_o(cio_usbdev_dp_pullup_d2p), |
| .cio_usbdev_dn_pullup_d2p_o(cio_usbdev_dn_pullup_d2p), |
| .cio_usbdev_dp_p2d_i(cio_usbdev_dp_p2d), |
| .cio_usbdev_dp_d2p_o(cio_usbdev_dp_d2p), |
| .cio_usbdev_dp_en_d2p_o(cio_usbdev_dp_en_d2p), |
| .cio_usbdev_dn_p2d_i(cio_usbdev_dn_p2d), |
| .cio_usbdev_dn_d2p_o(cio_usbdev_dn_d2p), |
| .cio_usbdev_dn_en_d2p_o(cio_usbdev_dn_en_d2p), |
| .cio_usbdev_d_p2d_i(cio_usbdev_d_p2d), |
| .cio_usbdev_d_d2p_o(cio_usbdev_d_d2p), |
| .cio_usbdev_d_en_d2p_o(cio_usbdev_d_en_d2p), |
| .cio_usbdev_se0_d2p_o(cio_usbdev_se0_d2p), |
| .cio_usbdev_rx_enable_d2p_o(cio_usbdev_rx_enable_d2p), |
| .cio_usbdev_tx_use_d_se0_d2p_o(cio_usbdev_tx_use_d_se0_d2p), |
| |
| //Communication with I2S |
| .cio_i2s_rx_sd_p2d_i(cio_i2s_rx_sd_p2d), |
| |
| .cio_i2s_rx_sclk_d2p_o(cio_i2s_rx_sclk_d2p), |
| .cio_i2s_rx_ws_d2p_o(cio_i2s_rx_ws_d2p), |
| .cio_i2s_tx_ws_d2p_o(cio_i2s_tx_ws_d2p), |
| .cio_i2s_tx_sd_d2p_o(cio_i2s_tx_sd_d2p_o), |
| .cio_i2s_tx_sclk_d2p_o(cio_i2s_tx_sclk_d2p) |
| ); |
| |
| // GPIO DPI |
| gpiodpi #(.N_GPIO(32)) u_gpiodpi ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| .gpio_p2d (cio_gpio_p2d), |
| .gpio_d2p (cio_gpio_d2p), |
| .gpio_en_d2p(cio_gpio_en_d2p), |
| .gpio_pull_en(cio_gpio_pull_en), |
| .gpio_pull_sel(cio_gpio_pull_select) |
| ); |
| |
| // UART DPI |
| // The baud rate set to match FPGA implementation; the frequency is "artificial". Both baud rate |
| // frequency must match the settings used in the on-chip software at |
| // `sw/device/lib/arch/device_sim_verilator.c`. |
| uartdpi #( |
| .BAUD('d7_200), |
| .FREQ('d500_000) |
| ) u_uart ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| .tx_o (cio_uart_rx_p2d), |
| .rx_i (cio_uart_tx_d2p) |
| ); |
| |
| uartdpi #( |
| .BAUD('d7_200), |
| .FREQ('d500_000), |
| .NAME("smc_uart") |
| ) u_smc_uart ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| .tx_o (cio_smc_uart_rx_p2d), |
| .rx_i (cio_smc_uart_tx_d2p) |
| ); |
| ////////////////////////////////// |
| /// I2S Temporary Test Pattern /// |
| ////////////////////////////////// |
| wire sd; |
| wire sclk_i; |
| reg [DATA_WIDTH-1:0] data_tx; //Oversized 1x bit |
| integer indx_tx; |
| |
| reg ws_rx_lag, ws_rx_reg; |
| wire ws_rx; |
| wire data_incr; |
| |
| //SCLK get from ip |
| assign sclk_i = cio_i2s_rx_sclk_d2p; |
| assign ws_rx = cio_i2s_rx_ws_d2p; |
| assign cio_i2s_rx_sd_p2d = sd; |
| assign data_incr = (ws_rx != ws_rx_reg) && rst_ni; |
| assign sd = (indx_tx >= 0) ? data_tx[indx_tx]: 0; |
| |
| |
| parameter int unsigned DATA_WIDTH = 16; |
| |
| //Transmit data buffer then switch to sending zeros. Real mic will be HI-Z after data. |
| always @(posedge sclk_i or negedge rst_ni) begin |
| if (!rst_ni) begin |
| indx_tx <= DATA_WIDTH-1; |
| ws_rx_reg <= 0; |
| end else begin |
| indx_tx <= (data_incr) ? DATA_WIDTH-1 : indx_tx - 1; |
| ws_rx_reg <= ws_rx; |
| end |
| end |
| |
| always @(posedge sclk_i or negedge rst_ni) begin |
| if (!rst_ni) begin |
| data_tx <= 16'hff_ff; |
| end else begin |
| if (data_incr) begin |
| data_tx <= data_tx - 1; |
| end |
| end |
| end |
| ////////////////////////////////////// |
| /// END I2S Temporary Test Pattern /// |
| ////////////////////////////////////// |
| |
| `ifdef DMIDirectTAP |
| // OpenOCD direct DMI TAP |
| bind rv_dm dmidpi u_dmidpi ( |
| .clk_i, |
| .rst_ni, |
| .dmi_req_valid, |
| .dmi_req_ready, |
| .dmi_req_addr (dmi_req.addr), |
| .dmi_req_op (dmi_req.op), |
| .dmi_req_data (dmi_req.data), |
| .dmi_rsp_valid, |
| .dmi_rsp_ready, |
| .dmi_rsp_data (dmi_rsp.data), |
| .dmi_rsp_resp (dmi_rsp.resp), |
| .dmi_rst_n (dmi_rst_n) |
| ); |
| `else |
| // TODO: this is currently not supported. |
| // connect this to the correct pins once pinout is final and once the |
| // verilator testbench supports DFT/Debug strap sampling. |
| // See also #5221. |
| // |
| // jtagdpi u_jtagdpi ( |
| // .clk_i, |
| // .rst_ni, |
| |
| // .jtag_tck (cio_jtag_tck), |
| // .jtag_tms (cio_jtag_tms), |
| // .jtag_tdi (cio_jtag_tdi), |
| // .jtag_tdo (cio_jtag_tdo), |
| // .jtag_trst_n (cio_jtag_trst_n), |
| // .jtag_srst_n (cio_jtag_srst_n) |
| // ); |
| `endif |
| |
| // SPI DPI |
| spidpi u_spi ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| .spi_device_sck_o (cio_spi_device_sck_p2d), |
| .spi_device_csb_o (cio_spi_device_csb_p2d), |
| .spi_device_sdi_o (cio_spi_device_sdi_p2d), |
| .spi_device_sdo_i (cio_spi_device_sdo_d2p), |
| .spi_device_sdo_en_i (cio_spi_device_sdo_en_d2p) |
| ); |
| |
| // USB DPI |
| usbdpi u_usbdpi ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| .clk_48MHz_i (clk_i), |
| .sense_p2d (cio_usbdev_sense_p2d), |
| .pullupdp_d2p (cio_usbdev_dp_pullup_d2p), |
| .pullupdn_d2p (cio_usbdev_dn_pullup_d2p), |
| .dp_p2d (cio_usbdev_dp_p2d), |
| .dp_d2p (cio_usbdev_dp_d2p), |
| .dp_en_d2p (cio_usbdev_dp_en_d2p), |
| .dn_p2d (cio_usbdev_dn_p2d), |
| .dn_d2p (cio_usbdev_dn_d2p), |
| .dn_en_d2p (cio_usbdev_dn_en_d2p), |
| .d_p2d (cio_usbdev_d_p2d), |
| .d_d2p (cio_usbdev_d_d2p), |
| .d_en_d2p (cio_usbdev_d_en_d2p), |
| .se0_d2p (cio_usbdev_se0_d2p), |
| .rx_enable_d2p (cio_usbdev_rx_enable_d2p), |
| .tx_use_d_se0_d2p(cio_usbdev_tx_use_d_se0_d2p) |
| ); |
| |
| `define RV_CORE_IBEX u_dut.top_matcha.u_rv_core_ibex_sec |
| `define RV_CORE_SMC u_dut.top_matcha.u_rv_core_ibex_smc |
| `define SIM_SRAM_IF u_sim_sram.u_sim_sram_if |
| `define TEST_DONE_SEC u_sw_test_status_if.sw_test_done |
| |
| // Detect SW test termination. |
| sim_sram u_sim_sram ( |
| .clk_i (`RV_CORE_IBEX.clk_i), |
| .rst_ni (`RV_CORE_IBEX.rst_ni), |
| .tl_in_i (tlul_pkg::tl_h2d_t'(`RV_CORE_IBEX.u_tlul_req_buf.out_o)), |
| .tl_in_o (), |
| .tl_out_o (), |
| .tl_out_i () |
| |
| ); |
| |
| // Connect the sim SRAM directly inside rv_core_ibex. |
| assign `RV_CORE_IBEX.tl_win_d2h = u_sim_sram.tl_in_o; |
| |
| // Instantiate the SW test status interface & connect signals from sim_sram_if instance |
| // instantiated inside sim_sram. Bind would have worked nicely here, but Verilator segfaults |
| // when trace is enabled (#3951). |
| sw_test_status_if u_sw_test_status_if ( |
| .clk_i (`SIM_SRAM_IF.clk_i), |
| .rst_ni (`SIM_SRAM_IF.rst_ni), |
| .fetch_en (1'b0), |
| .wr_valid (`SIM_SRAM_IF.wr_valid), |
| .addr (`SIM_SRAM_IF.tl_h2d.a_address), |
| .data (`SIM_SRAM_IF.tl_h2d.a_data[15:0]) |
| ); |
| |
| // Connect the SMC SRAM directly inside rv_core_smc. |
| assign `RV_CORE_SMC.tl_win_d2h = u_dut.top_matcha.u_tl_adapter_ram_smc.tl_o; |
| |
| // Instantiate an interface to the SMC wrapper to monitor SW test termination. |
| sim_sram_if #( |
| .AddrWidth(32) |
| ) u_sim_sram_smc_if ( |
| .clk_i (`RV_CORE_SMC.clk_i), |
| .rst_ni (`RV_CORE_SMC.rst_ni), |
| .tl_h2d (tlul_pkg::tl_h2d_t'(`RV_CORE_SMC.u_tlul_req_buf.out_o)), |
| .tl_d2h (tlul_pkg::tl_d2h_t'(`RV_CORE_SMC.tl_win_d2h)) |
| ); |
| |
| // Instantiate separate sw_test_status_if for the SMC since we don't use address |
| // arbitration here. |
| sw_test_status_if u_sw_test_status_smc_if ( |
| .clk_i (u_sim_sram_smc_if.clk_i), |
| .rst_ni (u_sim_sram_smc_if.rst_ni), |
| .fetch_en (1'b0), |
| .wr_valid (u_sim_sram_smc_if.wr_valid), |
| .addr (u_sim_sram_smc_if.tl_h2d.a_address), |
| .data (u_sim_sram_smc_if.tl_h2d.a_data[15:0]) |
| ); |
| |
| // Set the start address of the simulation SRAM. |
| // Use offset 0 within both sim SRAM interfaces for SW test status indication. |
| initial begin |
| `SIM_SRAM_IF.start_addr = `VERILATOR_TEST_STATUS_ADDR; |
| u_sw_test_status_if.sw_test_status_addr = `SIM_SRAM_IF.start_addr; |
| |
| u_sim_sram_smc_if.start_addr = `SMC_VERILATOR_TEST_STATUS_ADDR; |
| u_sw_test_status_smc_if.sw_test_status_addr = u_sim_sram_smc_if.start_addr; |
| end |
| |
| always @(posedge clk_i) begin |
| if (u_sw_test_status_if.sw_test_done || u_sw_test_status_smc_if.sw_test_done) begin |
| $display("Verilator sim termination requested"); |
| $display("Your simulation wrote to 0x%h", (`TEST_DONE_SEC ? |
| u_sw_test_status_if.sw_test_status_addr : |
| u_sw_test_status_smc_if.sw_test_status_addr)); |
| dv_test_status_pkg::dv_test_status((`TEST_DONE_SEC ? |
| u_sw_test_status_if.sw_test_passed : |
| u_sw_test_status_smc_if.sw_test_passed)); |
| $finish; |
| end |
| end |
| |
| `undef RV_CORE_IBEX |
| `undef RV_CORE_SMC |
| `undef SIM_SRAM_IF |
| `undef TEST_DONE_SEC |
| |
| |
| endmodule // chip_sim_tb |