| // 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_mosi_p2d; |
| logic cio_spi_device_miso_d2p, cio_spi_device_miso_en_d2p; |
| |
| logic cio_usbdev_sense_p2d; |
| logic cio_usbdev_se0_d2p, cio_usbdev_se0_en_d2p; |
| logic cio_usbdev_pullup_d2p, cio_usbdev_pullup_en_d2p; |
| logic cio_usbdev_tx_mode_se_d2p, cio_usbdev_tx_mode_se_en_d2p; |
| logic cio_usbdev_supsend_d2p, cio_usbdev_supsend_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; |
| |
| // Top-level design |
| top_earlgrey top_earlgrey ( |
| .clk_i (clk_i), |
| .rst_ni (rst_ni), |
| |
| .clk_usb_48mhz_i (clk_i), |
| |
| .jtag_tck_i (cio_jtag_tck), |
| .jtag_tms_i (cio_jtag_tms), |
| .jtag_trst_ni (cio_jtag_trst_n), |
| .jtag_td_i (cio_jtag_tdi), |
| .jtag_td_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_uart_rx_i (cio_uart_rx_p2d), |
| .dio_uart_tx_o (cio_uart_tx_d2p), |
| .dio_uart_tx_en_o (cio_uart_tx_en_d2p), |
| |
| .dio_spi_device_sck_i (cio_spi_device_sck_p2d), |
| .dio_spi_device_csb_i (cio_spi_device_csb_p2d), |
| .dio_spi_device_mosi_i (cio_spi_device_mosi_p2d), |
| .dio_spi_device_miso_o (cio_spi_device_miso_d2p), |
| .dio_spi_device_miso_en_o (cio_spi_device_miso_en_d2p), |
| |
| .dio_usbdev_sense_i (cio_usbdev_sense_p2d), |
| .dio_usbdev_se0_o (cio_usbdev_se0_d2p), |
| .dio_usbdev_se0_en_o (cio_usbdev_se0_en_d2p), |
| .dio_usbdev_pullup_o (cio_usbdev_pullup_d2p), |
| .dio_usbdev_pullup_en_o (cio_usbdev_pullup_en_d2p), |
| .dio_usbdev_tx_mode_se_o (cio_usbdev_tx_mode_se_d2p), |
| .dio_usbdev_tx_mode_se_en_o (cio_usbdev_tx_mode_se_en_d2p), |
| .dio_usbdev_suspend_o (cio_usbdev_suspend_d2p), |
| .dio_usbdev_suspend_en_o (cio_usbdev_suspend_en_d2p), |
| .dio_usbdev_d_i (cio_usbdev_d_p2d), |
| .dio_usbdev_d_o (cio_usbdev_d_d2p), |
| .dio_usbdev_d_en_o (cio_usbdev_d_en_d2p), |
| .dio_usbdev_dp_i (cio_usbdev_dp_p2d), |
| .dio_usbdev_dp_o (cio_usbdev_dp_d2p), |
| .dio_usbdev_dp_en_o (cio_usbdev_dp_en_d2p), |
| .dio_usbdev_dn_i (cio_usbdev_dn_p2d), |
| .dio_usbdev_dn_o (cio_usbdev_dn_d2p), |
| .dio_usbdev_dn_en_o (cio_usbdev_dn_en_d2p), |
| |
| .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 and frequency must match the settings used in the on-chip |
| // software. |
| uartdpi #( |
| .BAUD('d9_600), |
| .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_mosi_o (cio_spi_device_mosi_p2d), |
| .spi_device_miso_i (cio_spi_device_miso_d2p), |
| .spi_device_miso_en_i (cio_spi_device_miso_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), |
| .pullup_d2p (cio_usbdev_pullup_d2p), |
| .pullup_en_d2p (cio_usbdev_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) |
| ); |
| |
| // Tie off unused signals. |
| logic unused_cio_usbdev_se0_d2p, unused_cio_usbdev_se0_en_d2p; |
| logic unused_cio_usbdev_tx_mode_se_d2p, unused_cio_usbdev_tx_mode_se_en_d2p; |
| logic unused_cio_usbdev_supsend_d2p, unused_cio_usbdev_supsend_en_d2p; |
| logic unused_cio_usbdev_d_d2p, unused_cio_usbdev_d_en_d2p; |
| assign unused_cio_usbdev_se0_d2p = cio_usbdev_se0_d2p; |
| assign unused_cio_usbdev_se0_en_d2p = cio_usbdev_se0_en_d2p; |
| assign unused_cio_usbdev_tx_mode_se_d2p = cio_usbdev_tx_mode_se_d2p; |
| assign unused_cio_usbdev_tx_mode_se_en_d2p = cio_usbdev_tx_mode_se_en_d2p; |
| assign unused_cio_usbdev_suspend_d2p = cio_usbdev_suspend_d2p; |
| assign unused_cio_usbdev_suspend_en_d2p = cio_usbdev_suspend_en_d2p; |
| assign cio_usbdev_d_p2d = 1'b0; |
| assign unused_cio_usbdev_d_d2p = cio_usbdev_d_d2p; |
| assign unused_cio_usbdev_d_en_d2p = cio_usbdev_d_en_d2p; |
| |
| // monitor for termination |
| `ifndef END_MON_PATH |
| `define END_MON_PATH top_earlgrey.u_ram1p_ram_main |
| `endif |
| |
| logic valid; |
| logic [31:0] addr; |
| logic end_valid; |
| |
| // mem address in design is offset from base, re-create the full address here |
| assign addr = `VERILATOR_MEM_BASE + {`END_MON_PATH.addr_i, 2'h0}; |
| assign valid = `END_MON_PATH.req_i & `END_MON_PATH.write_i & `END_MON_PATH.rst_ni; |
| assign end_valid = valid & (addr == `VERILATOR_END_SIM_ADDR); |
| |
| always_ff @(posedge clk_i) begin |
| if (end_valid) begin |
| $display("Verilator sim termination requested"); |
| $display("Your simulation wrote to 0x%h", `VERILATOR_END_SIM_ADDR); |
| $finish; |
| end |
| end |
| |
| endmodule |