| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| module top_earlgrey_verilator ( |
| // Clock and Reset |
| input clk_i, |
| input rst_ni |
| ); |
| |
| logic cio_jtag_tck, cio_jtag_tms, cio_jtag_tdi, cio_jtag_tdo; |
| logic cio_jtag_trst_n, cio_jtag_srst_n; |
| |
| logic [31:0] cio_gpio_p2d, cio_gpio_d2p, cio_gpio_en_d2p; |
| logic cio_uart_rx_p2d, cio_uart_tx_d2p, cio_uart_tx_en_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, cio_usbdev_se0_en_d2p; |
| logic cio_usbdev_dp_pullup_d2p, cio_usbdev_dp_pullup_en_d2p; |
| logic cio_usbdev_dn_pullup_d2p, cio_usbdev_dn_pullup_en_d2p; |
| logic cio_usbdev_tx_mode_se_d2p, cio_usbdev_tx_mode_se_en_d2p; |
| logic cio_usbdev_suspend_d2p, cio_usbdev_suspend_en_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; |
| |
| logic IO_JTCK, IO_JTMS, IO_JTRST_N, IO_JTDI, IO_JTDO; |
| |
| // TODO: instantiate padring and route these signals through that module |
| logic [14:0] dio_in; |
| logic [14:0] dio_out; |
| logic [14:0] dio_oe; |
| |
| assign dio_in = {cio_spi_device_sck_p2d, |
| cio_spi_device_csb_p2d, |
| cio_spi_device_sdi_p2d, |
| 1'b0, |
| cio_uart_rx_p2d, |
| 1'b0, |
| cio_usbdev_sense_p2d, |
| 1'b0, |
| 1'b0, |
| 1'b0, |
| 1'b0, |
| 1'b0, |
| cio_usbdev_d_p2d, |
| cio_usbdev_dp_p2d, |
| cio_usbdev_dn_p2d}; |
| |
| assign cio_usbdev_dn_d2p = dio_out[0]; |
| assign cio_usbdev_dp_d2p = dio_out[1]; |
| assign cio_usbdev_d_d2p = dio_out[2]; |
| assign cio_usbdev_suspend_d2p = dio_out[3]; |
| assign cio_usbdev_tx_mode_se_d2p = dio_out[4]; |
| assign cio_usbdev_dn_pullup_d2p = dio_out[5]; |
| assign cio_usbdev_dp_pullup_d2p = dio_out[6]; |
| assign cio_usbdev_se0_d2p = dio_out[7]; |
| assign cio_uart_tx_d2p = dio_out[9]; |
| assign cio_spi_device_sdo_d2p = dio_out[11]; |
| |
| assign cio_usbdev_dn_en_d2p = dio_oe[0]; |
| assign cio_usbdev_dp_en_d2p = dio_oe[1]; |
| assign cio_usbdev_d_en_d2p = dio_oe[2]; |
| assign cio_usbdev_suspend_en_d2p = dio_oe[3]; |
| assign cio_usbdev_tx_mode_se_en_d2p = dio_oe[4]; |
| assign cio_usbdev_dn_pullup_en_d2p = dio_oe[5]; |
| assign cio_usbdev_dp_pullup_en_d2p = dio_oe[6]; |
| assign cio_usbdev_se0_en_d2p = dio_oe[7]; |
| assign cio_uart_tx_en_d2p = dio_oe[9]; |
| assign cio_spi_device_sdo_en_d2p = dio_oe[11]; |
| |
| // dummy ast connections |
| pwrmgr_pkg::pwr_ast_rsp_t ast_base_pwr; |
| ast_wrapper_pkg::ast_rst_t ast_base_rst; |
| ast_wrapper_pkg::ast_alert_req_t ast_base_alerts; |
| ast_wrapper_pkg::ast_status_t ast_base_status; |
| |
| assign ast_base_pwr.slow_clk_val = pwrmgr_pkg::DiffValid; |
| assign ast_base_pwr.core_clk_val = pwrmgr_pkg::DiffValid; |
| assign ast_base_pwr.io_clk_val = pwrmgr_pkg::DiffValid; |
| assign ast_base_pwr.usb_clk_val = pwrmgr_pkg::DiffValid; |
| assign ast_base_pwr.main_pok = 1'b1; |
| |
| assign ast_base_alerts.alerts_p = '0; |
| assign ast_base_alerts.alerts_n = {ast_wrapper_pkg::NumAlerts{1'b1}}; |
| assign ast_base_status.io_pok = {ast_wrapper_pkg::NumIoRails{1'b1}}; |
| |
| // the rst_ni pin only goes to AST |
| // the rest of the logic generates reset based on the 'pok' signal. |
| // for verilator purposes, make these two the same. |
| assign ast_base_rst.aon_pok = rst_ni; |
| // Top-level design |
| top_earlgrey top_earlgrey ( |
| .rst_ni (rst_ni), |
| .clk_main_i (clk_i), |
| .clk_io_i (clk_i), |
| .clk_usb_i (clk_i), |
| .clk_aon_i (clk_i), |
| .rstmgr_ast_i ( ast_base_rst ), |
| .pwrmgr_pwr_ast_req_o ( ), |
| .pwrmgr_pwr_ast_rsp_i ( ast_base_pwr ), |
| .sensor_ctrl_ast_alert_req_i ( ast_base_alerts ), |
| .sensor_ctrl_ast_alert_rsp_o ( ), |
| .sensor_ctrl_ast_status_i ( ast_base_status ), |
| .usbdev_usb_ref_val_o ( ), |
| .usbdev_usb_ref_pulse_o ( ), |
| .ast_tl_req_o ( ), |
| .ast_tl_rsp_i ( '0 ), |
| .otp_ctrl_otp_ast_pwr_seq_o ( ), |
| .otp_ctrl_otp_ast_pwr_seq_h_i ( '0 ), |
| .flash_bist_enable_i ( 1'b0 ), |
| .flash_power_down_h_i ( 1'b0 ), |
| .flash_power_ready_h_i ( 1'b1 ), |
| .flash_test_mode_a_i ('0), |
| .flash_test_voltage_h_i ('0), |
| .clks_ast_o ( ), |
| .rsts_ast_o ( ), |
| |
| .jtag_tck_i (cio_jtag_tck), |
| .jtag_tms_i (cio_jtag_tms), |
| .jtag_trst_ni (cio_jtag_trst_n), |
| .jtag_tdi_i (cio_jtag_tdi), |
| .jtag_tdo_o (cio_jtag_tdo), |
| |
| // Multiplexed I/O |
| .mio_in_i (cio_gpio_p2d), |
| .mio_out_o (cio_gpio_d2p), |
| .mio_oe_o (cio_gpio_en_d2p), |
| |
| // Dedicated I/O |
| .dio_in_i (dio_in), |
| .dio_out_o (dio_out), |
| .dio_oe_o (dio_oe), |
| |
| // Pad attributes |
| .mio_attr_o ( ), |
| .dio_attr_o ( ), |
| |
| // DFT signals |
| .scan_rst_ni (1'b1), |
| .scanmode_i (1'b0) |
| ); |
| |
| // 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) |
| ); |
| |
| // 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) |
| ); |
| |
| `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 |
| // JTAG DPI for OpenOCD |
| 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), |
| .pullupdp_en_d2p (cio_usbdev_dp_pullup_en_d2p), |
| .pullupdn_d2p (cio_usbdev_dn_pullup_d2p), |
| .pullupdn_en_d2p (cio_usbdev_dn_pullup_en_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), |
| .se0_en_d2p (cio_usbdev_se0_en_d2p), |
| .txmode_d2p (cio_usbdev_tx_mode_se_d2p), |
| .txmode_en_d2p (cio_usbdev_tx_mode_se_en_d2p) |
| ); |
| |
| // Tie off unused signals. |
| logic unused_cio_usbdev_suspend_d2p, unused_cio_usbdev_suspend_en_d2p; |
| assign unused_cio_usbdev_suspend_d2p = cio_usbdev_suspend_d2p; |
| assign unused_cio_usbdev_suspend_en_d2p = cio_usbdev_suspend_en_d2p; |
| |
| `define RV_CORE_IBEX top_earlgrey.u_rv_core_ibex |
| `define SIM_SRAM_IF u_sim_sram.u_sim_sram_if |
| |
| // 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 (`RV_CORE_IBEX.tl_d_o_int), |
| .tl_in_o (), |
| .tl_out_o (), |
| .tl_out_i (`RV_CORE_IBEX.tl_d_i) |
| ); |
| |
| // Connect the sim SRAM directly inside rv_core_ibex. |
| assign `RV_CORE_IBEX.tl_d_i_int = u_sim_sram.tl_in_o; |
| assign `RV_CORE_IBEX.tl_d_o = u_sim_sram.tl_out_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), |
| .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]) |
| ); |
| |
| // Set the start address of the simulation SRAM. |
| // Use offset 0 within the sim SRAM 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; |
| end |
| |
| always @(posedge clk_i) begin |
| if (u_sw_test_status_if.sw_test_done) begin |
| $display("Verilator sim termination requested"); |
| $display("Your simulation wrote to 0x%h", u_sw_test_status_if.sw_test_status_addr); |
| dv_test_status_pkg::dv_test_status(u_sw_test_status_if.sw_test_passed); |
| $finish; |
| end |
| end |
| |
| `undef RV_CORE_IBEX |
| `undef SIM_SRAM_IF |
| |
| endmodule |