blob: fd79548bfc2e724be388059ef7a09d5be8401fb4 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
module top_earlgrey_usb #(
parameter N_USB = 1,
parameter MAX_USB = 2,
parameter USB_UART = 1,
parameter USB_DEVICE = 0
) (
// Clock and Reset
input clk_i,
input rst_ni,
// JTAG interface
input jtag_tck_i,
input jtag_tms_i,
input jtag_trst_ni,
input jtag_td_i,
output jtag_td_o,
// UART interface
input cio_uart_rx_p2d_i,
output cio_uart_tx_d2p_o,
output cio_uart_tx_en_d2p_o,
// USB interface
input clk_48mhz_i,
input cio_usb_dp_i[MAX_USB],
output logic cio_usb_dp_o[MAX_USB],
output logic cio_usb_dp_en_o[MAX_USB],
input cio_usb_dn_i[MAX_USB],
output logic cio_usb_dn_o[MAX_USB],
output logic cio_usb_dn_en_o[MAX_USB],
input cio_usb_sense_i[MAX_USB],
output logic cio_usb_pullup_o[MAX_USB],
output logic cio_usb_pullup_en_o[MAX_USB],
// GPIO x 16 interface
input [31:0] cio_gpio_p2d_i,
output [31:0] cio_gpio_d2p_o,
output [31:0] cio_gpio_en_d2p_o,
// SPI Interface (Device)
input cio_spi_device_sck_i,
input cio_spi_device_csb_i,
input cio_spi_device_mosi_i,
output cio_spi_device_miso_o,
output cio_spi_device_miso_en_o,
input scanmode_i // 1 for Scan
);
import tlul_pkg::*;
import top_pkg::*;
import tl_main_pkg::*;
tl_h2d_t tl_h_h2d [N_HOST];
tl_d2h_t tl_h_d2h [N_HOST];
tl_h2d_t tl_d_h2d [N_DEVICE];
tl_d2h_t tl_d_d2h [N_DEVICE];
logic [63:0] intr_vector;
logic irq_req;
logic [4:0] irq_rid;
logic irq_ack;
logic [4:0] irq_aid;
// Non-debug module reset == reset for everything except for the debug module
// and the logic required to access it.
logic ndmreset_n;
logic ndmreset_from_dm;
assign ndmreset_n = (scanmode_i) ? rst_ni : ~ndmreset_from_dm & rst_ni;
logic debug_req;
// processor core
rv_core_ibex #(
.MHPMCounterNum (8),
.MHPMCounterWidth (40),
.RV32E (0),
.RV32M (1),
.DmHaltAddr (ADDR_SPACE_DEBUG_MEM + dm::HaltAddress),
.DmExceptionAddr (ADDR_SPACE_DEBUG_MEM + dm::ExceptionAddress)
) core (
// clock and reset
.clk_i (clk_i),
.rst_ni (ndmreset_n),
.test_en_i (1'b0),
// static pinning
.hart_id_i (32'b0),
.boot_addr_i (ADDR_SPACE_RAM_MAIN + 'h1000), // no ROM for now, straight out of SRAM
// TL-UL buses
.tl_i_o (tl_h_h2d[TlCorei]),
.tl_i_i (tl_h_d2h[TlCorei]),
.tl_d_o (tl_h_h2d[TlCored]),
.tl_d_i (tl_h_d2h[TlCored]),
// interrupts
.irq_i (irq_req),//in // level sensitive IR lines
.irq_id_i (irq_rid),//in [4:0]
.irq_ack_o (irq_ack),//out // irq ack
.irq_id_o (irq_aid),//out [4:0]
// debug interface
.debug_req_i (debug_req),
// CPU control signals
.fetch_enable_i (1'b1)
);
// Debug Module (RISC-V Debug Spec 0.13)
//
dm::dmi_req_t dmi_req;
dm::dmi_resp_t dmi_rsp;
logic dmi_req_valid, dmi_req_ready;
logic dmi_rsp_valid, dmi_rsp_ready;
logic dmi_rst_n;
rv_dm #(
.NrHarts ( 1)
) u_dm_top (
.clk_i (clk_i),
.rst_ni (rst_ni),
.testmode_i (1'b0),
.ndmreset_o (ndmreset_from_dm),
.dmactive_o (),
.debug_req_o (debug_req),
.unavailable_i (1'b0),
// bus device with debug memory (for execution-based debug)
.tl_d_i (tl_d_h2d[TlDebugMem]),
.tl_d_o (tl_d_d2h[TlDebugMem]),
// bus host (for system bus accesses, SBA)
.tl_h_o (tl_h_h2d[TlDmSba]),
.tl_h_i (tl_h_d2h[TlDmSba]),
// Connection to DTM - compatible to RocketChip Debug Module
.dmi_rst_ni (dmi_rst_n),
.dmi_req_valid_i (dmi_req_valid),
.dmi_req_ready_o (dmi_req_ready),
.dmi_req_i (dmi_req ),
.dmi_resp_valid_o (dmi_rsp_valid),
.dmi_resp_ready_i (dmi_rsp_ready),
.dmi_resp_o (dmi_rsp )
);
dmi_jtag #(
.IdcodeValue (32'h00000001) // Temporary value
// xxxx version
// xxxxxxxxxxxxxxxx part number
// xxxxxxxxxxx manufacturer id
// 1 required by standard
) dap (
.clk_i (clk_i),
.rst_ni (rst_ni),
.testmode_i (1'b0),
.dmi_rst_no (dmi_rst_n),
.dmi_req_o (dmi_req),
.dmi_req_valid_o (dmi_req_valid),
.dmi_req_ready_i (dmi_req_ready),
.dmi_resp_i (dmi_rsp ),
.dmi_resp_ready_o (dmi_rsp_ready),
.dmi_resp_valid_i (dmi_rsp_valid),
//JTAG
.tck_i (jtag_tck_i),
.tms_i (jtag_tms_i),
.trst_ni (jtag_trst_ni),
.td_i (jtag_td_i),
.td_o (jtag_td_o),
.tdo_oe_o ( )
);
// sram device
logic req;
logic we;
logic [13:0] addr;
logic [31:0] wdata;
logic [31:0] wmask;
logic [31:0] rdata;
logic rvalid;
tlul_adapter_sram #(
.SramAw(14),
.SramDw(32),
.Outstanding(1)
) tl_adapter (
.clk_i,
.rst_ni (ndmreset_n),
.tl_i (tl_d_h2d[TlRamMain]),
.tl_o (tl_d_d2h[TlRamMain]),
.req_o (req),
.gnt_i (1'b1), // Always grant as only one requester exists
.we_o (we),
.addr_o (addr),
.wdata_o (wdata),
.wmask_o (wmask),
.rdata_i (rdata),
.rvalid_i (rvalid),
.rerror_i (2'b00)
);
prim_ram_1p #(
.Width(32),
.Depth(64 * 1024 / 4) // 64 kB
) u_ram (
.clk_i,
.rst_ni (ndmreset_n),
.req_i (req),
.write_i (we),
.addr_i (addr),
.wdata_i (wdata),
.wmask_i (wmask),
.rvalid_o (rvalid),
.rdata_o (rdata));
// UART
logic intr_uart_tx_watermark, intr_uart_rx_watermark;
logic intr_uart_tx_overflow, intr_uart_rx_overflow;
logic intr_uart_rx_frame_err, intr_uart_rx_break_err;
logic intr_uart_rx_timeout, intr_uart_rx_parity_err;
if (USB_UART == 0) begin : gen_uart
uart uart (
.clk_i (clk_i),
.rst_ni (ndmreset_n),
.tl_i (tl_d_h2d[TlUart]),
.tl_o (tl_d_d2h[TlUart]),
.cio_rx_i (cio_uart_rx_p2d_i),
.cio_tx_o (cio_uart_tx_d2p_o),
.cio_tx_en_o (cio_uart_tx_en_d2p_o),
.intr_tx_watermark_o (intr_uart_tx_watermark),
.intr_rx_watermark_o (intr_uart_rx_watermark),
.intr_tx_overflow_o (intr_uart_tx_overflow),
.intr_rx_overflow_o (intr_uart_rx_overflow),
.intr_rx_frame_err_o (intr_uart_rx_frame_err),
.intr_rx_break_err_o (intr_uart_rx_break_err),
.intr_rx_timeout_o (intr_uart_rx_timeout),
.intr_rx_parity_err_o (intr_uart_rx_parity_err)
);
end else begin : gen_uuart
logic unused_rx = cio_uart_rx_p2d_i;
assign cio_uart_tx_d2p_o = 0;
assign cio_uart_tx_en_d2p_o = 0;
usbuart uart (
.clk_i (clk_i),
.clk_48mhz_i (clk_48mhz_i),
.rst_ni (ndmreset_n),
.tl_i (tl_d_h2d[TlUart]),
.tl_o (tl_d_d2h[TlUart]),
.cio_usb_dp_i (cio_usb_dp_i[USB_UART - 1]),
.cio_usb_dp_o (cio_usb_dp_o[USB_UART - 1]),
.cio_usb_dp_en_o (cio_usb_dp_en_o[USB_UART - 1]),
.cio_usb_dn_i (cio_usb_dn_i[USB_UART - 1]),
.cio_usb_dn_o (cio_usb_dn_o[USB_UART - 1]),
.cio_usb_dn_en_o (cio_usb_dn_en_o[USB_UART - 1]),
.cio_usb_sense_i (cio_usb_sense_i[USB_UART - 1]),
.cio_pullup_o (cio_usb_pullup_o[USB_UART - 1]),
.cio_pullup_en_o (cio_usb_pullup_en_o[USB_UART - 1]),
.intr_tx_watermark_o (intr_uart_tx_watermark),
.intr_rx_watermark_o (intr_uart_rx_watermark),
.intr_tx_overflow_o (intr_uart_tx_overflow),
.intr_rx_overflow_o (intr_uart_rx_overflow),
.intr_rx_frame_err_o (intr_uart_rx_frame_err),
.intr_rx_break_err_o (intr_uart_rx_break_err),
.intr_rx_timeout_o (intr_uart_rx_timeout),
.intr_rx_parity_err_o (intr_uart_rx_parity_err)
);
end // block: gen_uuart
// GPIO
logic [31:0] intr_gpio;
gpio gpio (
.clk_i (clk_i),
.rst_ni (ndmreset_n),
.tl_i (tl_d_h2d[TlGpio]),
.tl_o (tl_d_d2h[TlGpio]),
.cio_gpio_i (cio_gpio_p2d_i),
.cio_gpio_o (cio_gpio_d2p_o),
.cio_gpio_en_o (cio_gpio_en_d2p_o),
.intr_gpio_o (intr_gpio)
);
// SPI Device instance
logic intr_spi_device_rxne, intr_spi_device_rxlvl, intr_spi_device_rxerr;
logic intr_spi_device_txe, intr_spi_device_txf;
if (USB_DEVICE == 0) begin : gen_spi
spi_device spi_device (
.clk_i,
.rst_ni (ndmreset_n),
.tl_i (tl_d_h2d[TlSpiDevice]),
.tl_o (tl_d_d2h[TlSpiDevice]),
.cio_sck_i (cio_spi_device_sck_i),
.cio_csb_i (cio_spi_device_csb_i),
.cio_mosi_i (cio_spi_device_mosi_i),
.cio_miso_o (cio_spi_device_miso_o),
.cio_miso_en_o (cio_spi_device_miso_en_o),
.intr_rxne_o (intr_spi_device_rxne),
.intr_rxlvl_o (intr_spi_device_rxlvl),
.intr_txe_o (intr_spi_device_txe),
.intr_txf_o (intr_spi_device_txf),
.intr_rxerr_o (intr_spi_device_rxerr),
.intr_txlvl_o ()
);
end else begin : gen_usbdev // block: gen_spi
logic unused_sck = cio_spi_device_sck_i;
logic unused_csb = cio_spi_device_csb_i;
logic unused_mosi = cio_spi_device_mosi_i;
assign intr_spi_device_rxlvl = 0;
assign intr_spi_device_txf = 0;
assign cio_spi_device_miso_o = 0;
assign cio_spi_device_miso_en_o = 0;
usbdev udev (
.clk_i (clk_i),
.clk_usb_48mhz_i (clk_48mhz_i),
.rst_ni (ndmreset_n),
.tl_d_i (tl_d_h2d[TlSpiDevice]),
.tl_d_o (tl_d_d2h[TlSpiDevice]),
.cio_usb_dp_i (cio_usb_dp_i[USB_DEVICE - 1]),
.cio_usb_dp_o (cio_usb_dp_o[USB_DEVICE - 1]),
.cio_usb_dp_en_o (cio_usb_dp_en_o[USB_DEVICE - 1]),
.cio_usb_dn_i (cio_usb_dn_i[USB_DEVICE - 1]),
.cio_usb_dn_o (cio_usb_dn_o[USB_DEVICE - 1]),
.cio_usb_dn_en_o (cio_usb_dn_en_o[USB_DEVICE - 1]),
.cio_usb_sense_i (cio_usb_sense_i[USB_DEVICE - 1]),
.cio_usb_pullup_o (cio_usb_pullup_o[USB_DEVICE - 1]),
.cio_usb_pullup_en_o (cio_usb_pullup_en_o[USB_DEVICE - 1]),
.intr_pkt_received_o (intr_spi_device_rxne),
.intr_pkt_sent_o (intr_spi_device_txe),
.intr_disconnected_o (),
.intr_host_lost_o (),
.intr_link_reset_o (),
.intr_link_suspend_o (),
.intr_link_resume_o (),
.intr_av_empty_o (intr_spi_device_rxlvl),
.intr_rx_full_o (intr_spi_device_rxerr),
.intr_av_overflow_o (intr_spi_device_txf)
);
end // block: gen_usbdev
// interrupt assignments
assign intr_vector = {
35'h0,
intr_spi_device_rxne,
intr_spi_device_rxlvl,
intr_spi_device_txe,
intr_spi_device_txf,
intr_spi_device_rxerr,
intr_uart_tx_watermark,
intr_uart_rx_watermark,
intr_uart_tx_overflow,
intr_uart_rx_overflow,
intr_uart_rx_frame_err,
intr_uart_rx_break_err,
intr_uart_rx_timeout,
intr_uart_rx_parity_err,
intr_gpio[15:0]
};
// TODO: Connect Interrupt controller
assign irq_req = intr_gpio[15];
assign irq_rid = 'd15;
// TL-UL Crossbar
tlul_xbar_usb u_xbar (
.clk_i (clk_i),
.rst_ni (ndmreset_n),
.tl_h_i (tl_h_h2d),
.tl_h_o (tl_h_d2h),
.tl_d_o (tl_d_h2d),
.tl_d_i (tl_d_d2h)
);
// Tie off unused USB
if (N_USB < MAX_USB) begin: gen_utie
for (genvar j = N_USB; j < MAX_USB; j = j + 1) begin
logic unused_usb;
assign unused_usb = cio_usb_dp_i[j] | cio_usb_dn_i[j] | cio_usb_sense_i[j];
assign cio_usb_dp_o[j] = 1'b0;
assign cio_usb_dp_en_o[j] = 1'b0;
assign cio_usb_dn_o[j] = 1'b0;
assign cio_usb_dn_en_o[j] = 1'b0;
assign cio_usb_pullup_o[j] = 1'b0;
assign cio_usb_pullup_en_o[j] = 1'b0;
end
end // block: gen_utie
endmodule