From 7d3a2fcfc5ca2d99b7fd91755938ee1bfdf2a3bf Mon Sep 17 00:00:00 2001 From: Paul Scheffler Date: Thu, 7 Mar 2024 23:13:01 +0100 Subject: [PATCH] treewide: Clean up USB implementation --- Bender.yml | 4 +- hw/cheshire_pkg.sv | 41 +-- hw/cheshire_soc.sv | 416 ++++------------------- hw/future/axi_from_reg.sv | 77 +++++ hw/future/spinal_usb_ohci.sv | 257 ++++++++++++++ hw/regs/cheshire_reg_pkg.sv | 15 +- hw/regs/cheshire_reg_top.sv | 36 +- hw/regs/cheshire_regs.hjson | 9 +- sw/boot/cheshire.dtsi | 6 +- sw/include/params.h | 3 + sw/include/regs/cheshire.h | 9 +- sw/link/common.ldh | 3 + sw/tests/helloworld.c | 129 ------- target/sim/src/fixture_cheshire_soc.sv | 9 +- target/xilinx/constraints/genesys2.xdc | 16 +- target/xilinx/scripts/impl_ip.tcl | 52 +-- target/xilinx/src/cheshire_top_xilinx.sv | 119 ++----- 17 files changed, 541 insertions(+), 660 deletions(-) create mode 100644 hw/future/axi_from_reg.sv create mode 100644 hw/future/spinal_usb_ohci.sv diff --git a/Bender.yml b/Bender.yml index bd01ec85c..eaadfd294 100644 --- a/Bender.yml +++ b/Bender.yml @@ -35,12 +35,14 @@ export_include_dirs: - hw/include sources: + - hw/future/axi_from_reg.sv + - hw/future/UsbOhciAxi4.v + - hw/future/spinal_usb_ohci.sv - hw/bootrom/cheshire_bootrom.sv - hw/regs/cheshire_reg_pkg.sv - hw/regs/cheshire_reg_top.sv - hw/cheshire_pkg.sv - hw/cheshire_soc.sv - - hw/future/UsbOhciAxi4.v - target: any(simulation, test) files: diff --git a/hw/cheshire_pkg.sv b/hw/cheshire_pkg.sv index de6d8d79b..1d2577a74 100644 --- a/hw/cheshire_pkg.sv +++ b/hw/cheshire_pkg.sv @@ -31,6 +31,7 @@ package cheshire_pkg; localparam int unsigned SlinkNumLanes = serial_link_single_channel_reg_pkg::NumBits/2; localparam int unsigned SlinkMaxClkDiv = 1 << serial_link_single_channel_reg_pkg::Log2MaxClkDiv; localparam int unsigned ClintNumCores = clint_reg_pkg::NumCores; + localparam int unsigned UsbNumPorts = spinal_usb_ohci_pkg::NumPhyPorts; // Default JTAG ID code type typedef struct packed { @@ -129,10 +130,10 @@ package cheshire_pkg; bit I2c; bit SpiHost; bit Gpio; - bit Usb; bit Dma; bit SerialLink; bit Vga; + bit Usb; bit AxiRt; bit Clic; bit IrqRouter; @@ -172,15 +173,9 @@ package cheshire_pkg; doub_bt SlinkTxAddrDomain; dw_bt SlinkUserAmoBit; // Parameters for USB - dw_bt UsbConfMaxReadTxns; - dw_bt UsbConfMaxWriteTxns; - aw_bt UsbConfAmoNumCuts; - bit UsbConfAmoPostCut; - bit UsbConfEnableTwoD; - dw_bt UsbNumAxInFlight; - dw_bt UsbMemSysDepth; - aw_bt UsbJobFifoDepth; - bit UsbRAWCouplingAvail; + dw_bt UsbDmaMaxReads; + doub_bt UsbAddrMask; + doub_bt UsbAddrDomain; // Parameters for DMA dw_bt DmaConfMaxReadTxns; dw_bt DmaConfMaxWriteTxns; @@ -281,7 +276,7 @@ package cheshire_pkg; localparam doub_bt AmRegs = 'h0300_0000; localparam doub_bt AmLlc = 'h0300_1000; localparam doub_bt AmSlink = 'h0300_6000; - localparam doub_bt AmBusErr = 'h0300_8000; + localparam doub_bt AmBusErr = 'h0300_9000; localparam doub_bt AmSpm = 'h1000_0000; // Cached region at bottom, uncached on top localparam doub_bt AmClic = 'h0800_0000; @@ -299,9 +294,9 @@ package cheshire_pkg; aw_bt [2**MaxCoresWidth-1:0] cores; aw_bt dbg; aw_bt dma; - aw_bt usb; aw_bt slink; aw_bt vga; + aw_bt usb; aw_bt ext_base; aw_bt num_in; } axi_in_t; @@ -311,10 +306,10 @@ package cheshire_pkg; int unsigned i = 0; for (int j = 0; j < cfg.NumCores; j++) begin ret.cores[i] = i; i++; end ret.dbg = i; - if (cfg.Usb) begin i++; ret.usb = i; end if (cfg.Dma) begin i++; ret.dma = i; end if (cfg.SerialLink) begin i++; ret.slink = i; end if (cfg.Vga) begin i++; ret.vga = i; end + if (cfg.Usb) begin i++; ret.usb = i; end i++; ret.ext_base = i; ret.num_in = i + cfg.AxiExtNumMst; @@ -334,7 +329,6 @@ package cheshire_pkg; aw_bt reg_demux; aw_bt llc; aw_bt spm; - aw_bt usb; aw_bt dma; aw_bt slink; aw_bt ext_base; @@ -361,7 +355,6 @@ package cheshire_pkg; r++; ret.map[r] = '{i, AmSpm, AmSpm + SizeSpm}; r++; ret.map[r] = '{i, AmSpm + 'h0400_0000, AmSpm + 'h0400_0000 + SizeSpm}; end - if (cfg.Usb) begin i++; r++; ret.usb = i; ret.map[r] = '{i, 'h0100_1000, 'h0100_2000}; end if (cfg.Dma) begin i++; r++; ret.dma = i; ret.map[r] = '{i, 'h0100_0000, 'h0100_1000}; end if (cfg.SerialLink) begin i++; r++; ret.slink = i; ret.map[r] = '{i, cfg.SlinkRegionStart, cfg.SlinkRegionEnd}; end @@ -398,6 +391,7 @@ package cheshire_pkg; aw_bt gpio; aw_bt slink; aw_bt vga; + aw_bt usb; aw_bt axirt; aw_bt irq_router; aw_bt [2**MaxCoresWidth-1:0] bus_err; @@ -422,6 +416,7 @@ package cheshire_pkg; if (cfg.Gpio) begin i++; ret.gpio = i; r++; ret.map[r] = '{i, 'h0300_5000, 'h0300_6000}; end if (cfg.SerialLink) begin i++; ret.slink = i; r++; ret.map[r] = '{i, AmSlink, AmSlink +'h1000}; end if (cfg.Vga) begin i++; ret.vga = i; r++; ret.map[r] = '{i, 'h0300_7000, 'h0300_8000}; end + if (cfg.Usb) begin i++; ret.usb = i; r++; ret.map[r] = '{i, 'h0300_8000, 'h0300_9000}; end if (cfg.IrqRouter) begin i++; ret.irq_router = i; r++; ret.map[r] = '{i, 'h0208_0000, 'h020c_0000}; end if (cfg.AxiRt) begin i++; ret.axirt = i; r++; ret.map[r] = '{i, 'h020c_0000, 'h0210_0000}; end if (cfg.Clic) for (int j = 0; j < cfg.NumCores; j++) begin @@ -605,10 +600,10 @@ package cheshire_pkg; I2c : 1, SpiHost : 1, Gpio : 1, - Usb : 1, Dma : 1, SerialLink : 1, Vga : 1, + Usb : 1, AxiRt : 0, Clic : 0, IrqRouter : 0, @@ -647,16 +642,10 @@ package cheshire_pkg; SlinkTxAddrMask : 'hFFFF_FFFF, SlinkTxAddrDomain : 'h0000_0000, SlinkUserAmoBit : 1, // Convention: lower AMO bits for cores, MSB for serial link - // USB config ( for now it's just a copy of the DMA config) - UsbConfMaxReadTxns : 16, - UsbConfMaxWriteTxns : 16, - UsbConfAmoNumCuts : 1, - UsbConfAmoPostCut : 1, - UsbConfEnableTwoD : 1, - UsbNumAxInFlight : 16, - UsbMemSysDepth : 8, - UsbJobFifoDepth : 2, - UsbRAWCouplingAvail : 1, + // USB config + UsbDmaMaxReads : 16, + UsbAddrMask : 'hFFFF_FFFF, + UsbAddrDomain : 'h0000_0000, // DMA config DmaConfMaxReadTxns : 4, DmaConfMaxWriteTxns : 4, diff --git a/hw/cheshire_soc.sv b/hw/cheshire_soc.sv index 31dff513f..4e8dc13ed 100644 --- a/hw/cheshire_soc.sv +++ b/hw/cheshire_soc.sv @@ -98,40 +98,13 @@ module cheshire_soc import cheshire_pkg::*; #( output logic [Cfg.VgaGreenWidth-1:0] vga_green_o, output logic [Cfg.VgaBlueWidth -1:0] vga_blue_o, // USB interface -// (* dont_touch = "yes" *) (* mark_debug = "true" *) output logic usb_dm_o, -// (* dont_touch = "yes" *) (* mark_debug = "true" *) input logic usb_dm_i, -// (* dont_touch = "yes" *) (* mark_debug = "true" *) output logic usb_dm_en_o, -// (* dont_touch = "yes" *) (* mark_debug = "true" *) output logic usb_dp_o, -// (* dont_touch = "yes" *) (* mark_debug = "true" *) input logic usb_dp_i, -// (* dont_touch = "yes" *) (* mark_debug = "true" *) output logic usb_dp_en_o - // Port 0 - output logic usb_0_dm_o, - input logic usb_0_dm_i, - output logic usb_0_dm_en_o, - output logic usb_0_dp_o, - input logic usb_0_dp_i, - output logic usb_0_dp_en_o, - // Port 1 - output logic usb_1_dm_o, - input logic usb_1_dm_i, - output logic usb_1_dm_en_o, - output logic usb_1_dp_o, - input logic usb_1_dp_i, - output logic usb_1_dp_en_o, - // Port 2 - output logic usb_2_dm_o, - input logic usb_2_dm_i, - output logic usb_2_dm_en_o, - output logic usb_2_dp_o, - input logic usb_2_dp_i, - output logic usb_2_dp_en_o, - // Port 3 - output logic usb_3_dm_o, - input logic usb_3_dm_i, - output logic usb_3_dm_en_o, - output logic usb_3_dp_o, - input logic usb_3_dp_i, - output logic usb_3_dp_en_o + input logic usb_clk_i, + input logic [UsbNumPorts-1:0] usb_dm_i, + output logic [UsbNumPorts-1:0] usb_dm_o, + output logic [UsbNumPorts-1:0] usb_dm_oe_o, + input logic [UsbNumPorts-1:0] usb_dp_i, + output logic [UsbNumPorts-1:0] usb_dp_o, + output logic [UsbNumPorts-1:0] usb_dp_oe_o ); `include "axi/typedef.svh" @@ -1027,6 +1000,7 @@ module cheshire_soc import cheshire_pkg::*; #( dma : Cfg.Dma, serial_link : Cfg.SerialLink, vga : Cfg.Vga, + usb : Cfg.Usb, axirt : Cfg.AxiRt, clic : Cfg.Clic, irq_router : Cfg.IrqRouter, @@ -1388,329 +1362,6 @@ module cheshire_soc import cheshire_pkg::*; #( end - /////////// - // USB // - /////////// - - // Define types needed - // For the crtl converter chain - `CHESHIRE_TYPEDEF_AXI_CT(axi_usb_ctrl_ser, addr_t, logic [7:0], axi_data_t, axi_strb_t, axi_user_t) - `CHESHIRE_TYPEDEF_AXI_CT(axi_usb_ctrl_dw, addr_t, logic [7:0], logic [31:0], logic [3:0], axi_user_t) - `CHESHIRE_TYPEDEF_AXI_CT(axi_usb_ctrl, logic [11:0], logic [7:0], logic [31:0], logic [3:0], axi_user_t) - // For the dma converter chain - `CHESHIRE_TYPEDEF_AXI_CT(axi_usb_dma, logic [31:0], logic [Cfg.AxiMstIdWidth-1:0], logic [31:0], logic [3:0], axi_user_t) - `CHESHIRE_TYPEDEF_AXI_CT(axi_usb_dma_dw, logic [31:0], logic [Cfg.AxiMstIdWidth-1:0], axi_data_t, axi_strb_t, axi_user_t) - - if (Cfg.Usb) begin : gen_usb - axi_slv_req_t usb_amo_req, usb_cut_req; // AXI interconnect for atomics and cuts - axi_slv_rsp_t usb_amo_rsp, usb_cut_rsp; - - axi_riscv_atomics_structs #( - .AxiAddrWidth ( Cfg.AddrWidth ), - .AxiDataWidth ( Cfg.AxiDataWidth ), - .AxiIdWidth ( AxiSlvIdWidth ), - .AxiUserWidth ( Cfg.AxiUserWidth ), - .AxiMaxReadTxns ( Cfg.UsbConfMaxReadTxns ), - .AxiMaxWriteTxns ( Cfg.UsbConfMaxWriteTxns ), - .AxiUserAsId ( 1 ), - .AxiUserIdMsb ( Cfg.AxiUserAmoMsb ), - .AxiUserIdLsb ( Cfg.AxiUserAmoLsb ), - .RiscvWordWidth ( 64 ), - .NAxiCuts ( Cfg.UsbConfAmoNumCuts ), - .axi_req_t ( axi_slv_req_t ), - .axi_rsp_t ( axi_slv_rsp_t ) - ) i_usb_ctrl_atomics ( - .clk_i, - .rst_ni, - .axi_slv_req_i ( axi_out_req[AxiOut.usb] ), - .axi_slv_rsp_o ( axi_out_rsp[AxiOut.usb] ), - .axi_mst_req_o ( usb_amo_req ), - .axi_mst_rsp_i ( usb_amo_rsp ) - ); - - axi_cut #( - .Bypass ( ~Cfg.UsbConfAmoPostCut ), - .aw_chan_t ( axi_slv_aw_chan_t ), - .w_chan_t ( axi_slv_w_chan_t ), - .b_chan_t ( axi_slv_b_chan_t ), - .ar_chan_t ( axi_slv_ar_chan_t ), - .r_chan_t ( axi_slv_r_chan_t ), - .axi_req_t ( axi_slv_req_t ), - .axi_resp_t ( axi_slv_rsp_t ) - ) i_usb_ctrl_atomics_cut ( - .clk_i, - .rst_ni, - .slv_req_i ( usb_amo_req ), - .slv_resp_o ( usb_amo_rsp ), - .mst_req_o ( usb_cut_req ), - .mst_resp_i ( usb_cut_rsp ) - ); - - axi_usb_ctrl_ser_req_t usb_ctrl_ser_req; - axi_usb_ctrl_ser_rsp_t usb_ctrl_ser_rsp; - - axi_iw_converter #( - .AxiSlvPortIdWidth ( AxiSlvIdWidth ), - .AxiMstPortIdWidth ( 8 ), - .AxiSlvPortMaxUniqIds ( 1 /* TODO */ ), - .AxiSlvPortMaxTxnsPerId ( 1 /* TODO */ ), - .AxiSlvPortMaxTxns ( 1 /* TODO */ ), - .AxiMstPortMaxUniqIds ( 1 /* TODO */ ), - .AxiMstPortMaxTxnsPerId ( 1 /* TODO */ ), - .AxiAddrWidth ( Cfg.AddrWidth ), - .AxiDataWidth ( Cfg.AxiDataWidth ), - .AxiUserWidth ( Cfg.AxiUserWidth ), - .slv_req_t ( axi_slv_req_t ), - .slv_resp_t ( axi_slv_rsp_t ), - .mst_req_t ( axi_usb_ctrl_ser_req_t ), - .mst_resp_t ( axi_usb_ctrl_ser_rsp_t ) - ) i_usb_ctrl_iw_converter ( - .clk_i, - .rst_ni, - .slv_req_i ( usb_cut_req ), - .slv_resp_o ( usb_cut_rsp ), - .mst_req_o ( usb_ctrl_ser_req ), - .mst_resp_i ( usb_ctrl_ser_rsp ) - ); - - axi_usb_ctrl_dw_req_t usb_ctrl_dw_req; - axi_usb_ctrl_dw_rsp_t usb_ctrl_dw_rsp; - - axi_dw_converter #( - .AxiMaxReads ( 1 /* TODO */ ), - .AxiSlvPortDataWidth ( Cfg.AxiDataWidth ), - .AxiMstPortDataWidth ( 32 ), - .AxiAddrWidth ( Cfg.AddrWidth ), - .AxiIdWidth ( 8 ), - .aw_chan_t ( axi_usb_ctrl_ser_aw_chan_t ), - .ar_chan_t ( axi_usb_ctrl_ser_ar_chan_t ), - .mst_w_chan_t ( axi_usb_ctrl_dw_w_chan_t ), - .slv_w_chan_t ( axi_usb_ctrl_ser_w_chan_t ), - .b_chan_t ( axi_usb_ctrl_ser_b_chan_t ), - .mst_r_chan_t ( axi_usb_ctrl_dw_r_chan_t ), - .slv_r_chan_t ( axi_usb_ctrl_ser_r_chan_t ), - .axi_slv_req_t ( axi_usb_ctrl_ser_req_t ), - .axi_slv_resp_t ( axi_usb_ctrl_ser_rsp_t ), - .axi_mst_req_t ( axi_usb_ctrl_dw_req_t ), - .axi_mst_resp_t ( axi_usb_ctrl_dw_rsp_t ) - ) i_usb_ctrl_dw_converter ( - .clk_i, - .rst_ni, - .slv_req_i ( usb_ctrl_ser_req ), - .slv_resp_o ( usb_ctrl_ser_rsp ), - .mst_req_o ( usb_ctrl_dw_req ), - .mst_resp_i ( usb_ctrl_dw_rsp ) - ); - - axi_usb_ctrl_req_t usb_ctrl_req, usb_ctrl_cut_req; - axi_usb_ctrl_rsp_t usb_ctrl_rsp, usb_ctrl_cut_rsp; - - axi_modify_address #( - .slv_req_t ( axi_usb_ctrl_dw_req_t ), - .mst_req_t ( axi_usb_ctrl_req_t ), - .mst_addr_t ( logic [11:0] ), - .axi_resp_t ( axi_usb_ctrl_rsp_t ) - ) i_usb_ctrl_modify_address ( - .slv_req_i ( usb_ctrl_dw_req ), - .slv_resp_o ( usb_ctrl_dw_rsp ), - .mst_aw_addr_i( usb_ctrl_dw_req.aw.addr[11:0] ), - .mst_ar_addr_i( usb_ctrl_dw_req.ar.addr[11:0] ), - .mst_req_o ( usb_ctrl_req ), - .mst_resp_i ( usb_ctrl_rsp ) - ); - - axi_cut #( - .Bypass ( ~Cfg.UsbConfAmoPostCut ), - .aw_chan_t ( axi_usb_ctrl_aw_chan_t ), - .w_chan_t ( axi_usb_ctrl_w_chan_t ), - .b_chan_t ( axi_usb_ctrl_b_chan_t ), - .ar_chan_t ( axi_usb_ctrl_ar_chan_t ), - .r_chan_t ( axi_usb_ctrl_r_chan_t ), - .axi_req_t ( axi_usb_ctrl_req_t ), - .axi_resp_t ( axi_usb_ctrl_rsp_t ) - ) i_usb_ctrl_cut ( - .clk_i, - .rst_ni, - .slv_req_i ( usb_ctrl_req ), - .slv_resp_o ( usb_ctrl_rsp ), - .mst_req_o ( usb_ctrl_cut_req ), - .mst_resp_i ( usb_ctrl_cut_rsp ) - ); - - - axi_usb_dma_req_t usb_dma_req; - axi_usb_dma_rsp_t usb_dma_rsp; - - axi_usb_dma_dw_req_t usb_dma_dw_req; - axi_usb_dma_dw_rsp_t usb_dma_dw_rsp; - - axi_dw_converter #( - .AxiMaxReads ( 1 /* TODO */ ), - .AxiSlvPortDataWidth ( 32 ), - .AxiMstPortDataWidth ( Cfg.AxiDataWidth ), - .AxiAddrWidth ( Cfg.AddrWidth ), - .AxiIdWidth ( Cfg.AxiMstIdWidth ), - .aw_chan_t ( axi_usb_dma_aw_chan_t ), - .ar_chan_t ( axi_usb_dma_ar_chan_t ), - .mst_w_chan_t ( axi_usb_dma_dw_w_chan_t ), - .slv_w_chan_t ( axi_usb_dma_w_chan_t ), - .b_chan_t ( axi_usb_dma_b_chan_t ), - .mst_r_chan_t ( axi_usb_dma_dw_r_chan_t ), - .slv_r_chan_t ( axi_usb_dma_r_chan_t ), - .axi_slv_req_t ( axi_usb_dma_req_t ), - .axi_slv_resp_t ( axi_usb_dma_rsp_t ), - .axi_mst_req_t ( axi_usb_dma_dw_req_t ), - .axi_mst_resp_t ( axi_usb_dma_dw_rsp_t ) - ) i_usb_dma_dw_converter ( - .clk_i, - .rst_ni, - .slv_req_i ( usb_dma_req ), - .slv_resp_o ( usb_dma_rsp ), - .mst_req_o ( usb_dma_dw_req ), - .mst_resp_i ( usb_dma_dw_rsp ) - ); - - axi_modify_address #( - .slv_req_t ( axi_usb_dma_dw_req_t ), - .mst_req_t ( axi_mst_req_t ), - .mst_addr_t ( addr_t ), - .axi_resp_t ( axi_mst_rsp_t ) - ) i_usb_dma_modify_address ( - .slv_req_i ( usb_dma_dw_req ), - .slv_resp_o ( usb_dma_dw_rsp ), - // TODO: how to write to addresses exceeding 32 bit? Find solution. - .mst_aw_addr_i( addr_t'(usb_dma_dw_req.aw.addr) ), - .mst_ar_addr_i( addr_t'(usb_dma_dw_req.ar.addr) ), - .mst_req_o ( axi_in_req[AxiIn.usb] ), - .mst_resp_i ( axi_in_rsp[AxiIn.usb] ) - ); - - // Tie unconnected AXI IO - always_comb begin - // Ctrl connections - usb_ctrl_cut_rsp.r.user = Cfg.AxiUserDefault; - usb_ctrl_cut_rsp.b.user = Cfg.AxiUserDefault; - // DMA connections - usb_dma_req.aw.id = '0; - usb_dma_req.aw.burst = axi_pkg::BURST_INCR; - usb_dma_req.aw.lock = 0; - usb_dma_req.aw.qos = '0; - usb_dma_req.aw.region = '0; - usb_dma_req.aw.atop = '0; - usb_dma_req.aw.user = Cfg.AxiUserDefault; - usb_dma_req.w.user = Cfg.AxiUserDefault; - usb_dma_req.ar.id = '0; - usb_dma_req.ar.burst = axi_pkg::BURST_INCR; - usb_dma_req.ar.qos = '0; - usb_dma_req.ar.region = '0; - usb_dma_req.ar.user = Cfg.AxiUserDefault; - end - - UsbOhciAxi4 i_usb ( - .io_dma_aw_valid ( usb_dma_req.aw_valid ), - .io_dma_aw_ready ( usb_dma_rsp.aw_ready ), - .io_dma_aw_payload_addr ( usb_dma_req.aw.addr ), - .io_dma_aw_payload_len ( usb_dma_req.aw.len ), - .io_dma_aw_payload_size ( usb_dma_req.aw.size ), - .io_dma_aw_payload_cache ( usb_dma_req.aw.cache ), - .io_dma_aw_payload_prot ( usb_dma_req.aw.prot ), - .io_dma_w_valid ( usb_dma_req.w_valid ), - .io_dma_w_ready ( usb_dma_rsp.w_ready ), - .io_dma_w_payload_data ( usb_dma_req.w.data ), - .io_dma_w_payload_strb ( usb_dma_req.w.strb ), - .io_dma_w_payload_last ( usb_dma_req.w.last ), - .io_dma_b_valid ( usb_dma_rsp.b_valid ), - .io_dma_b_ready ( usb_dma_req.b_ready ), - .io_dma_b_payload_resp ( usb_dma_rsp.b.resp ), - .io_dma_ar_valid ( usb_dma_req.ar_valid ), - .io_dma_ar_ready ( usb_dma_rsp.ar_ready ), - .io_dma_ar_payload_addr ( usb_dma_req.ar.addr ), - .io_dma_ar_payload_len ( usb_dma_req.ar.len ), - .io_dma_ar_payload_size ( usb_dma_req.ar.size ), - .io_dma_ar_payload_cache ( usb_dma_req.ar.cache ), - .io_dma_ar_payload_prot ( usb_dma_req.ar.prot ), - .io_dma_r_valid ( usb_dma_rsp.r_valid ), - .io_dma_r_ready ( usb_dma_req.r_ready ), - .io_dma_r_payload_data ( usb_dma_rsp.r.data ), - .io_dma_r_payload_resp ( usb_dma_rsp.r.resp ), - .io_dma_r_payload_last ( usb_dma_rsp.r.last ), - .io_ctrl_aw_valid ( usb_ctrl_cut_req.aw_valid ), - .io_ctrl_aw_ready ( usb_ctrl_cut_rsp.aw_ready ), - .io_ctrl_aw_payload_addr ( usb_ctrl_cut_req.aw.addr ), - .io_ctrl_aw_payload_id ( usb_ctrl_cut_req.aw.id ), - .io_ctrl_aw_payload_region( usb_ctrl_cut_req.aw.region ), - .io_ctrl_aw_payload_len ( usb_ctrl_cut_req.aw.len ), - .io_ctrl_aw_payload_size ( usb_ctrl_cut_req.aw.size ), - .io_ctrl_aw_payload_burst ( usb_ctrl_cut_req.aw.burst ), - .io_ctrl_aw_payload_lock ( usb_ctrl_cut_req.aw.lock ), - .io_ctrl_aw_payload_cache ( usb_ctrl_cut_req.aw.cache ), - .io_ctrl_aw_payload_qos ( usb_ctrl_cut_req.aw.qos ), - .io_ctrl_aw_payload_prot ( usb_ctrl_cut_req.aw.prot ), - .io_ctrl_w_valid ( usb_ctrl_cut_req.w_valid ), - .io_ctrl_w_ready ( usb_ctrl_cut_rsp.w_ready ), - .io_ctrl_w_payload_data ( usb_ctrl_cut_req.w.data ), - .io_ctrl_w_payload_strb ( usb_ctrl_cut_req.w.strb ), - .io_ctrl_w_payload_last ( usb_ctrl_cut_req.w.last ), - .io_ctrl_b_valid ( usb_ctrl_cut_rsp.b_valid ), - .io_ctrl_b_ready ( usb_ctrl_cut_req.b_ready ), - .io_ctrl_b_payload_id ( usb_ctrl_cut_rsp.b.id ), - .io_ctrl_b_payload_resp ( usb_ctrl_cut_rsp.b.resp ), - .io_ctrl_ar_valid ( usb_ctrl_cut_req.ar_valid ), - .io_ctrl_ar_ready ( usb_ctrl_cut_rsp.ar_ready ), - .io_ctrl_ar_payload_addr ( usb_ctrl_cut_req.ar.addr ), - .io_ctrl_ar_payload_id ( usb_ctrl_cut_req.ar.id ), - .io_ctrl_ar_payload_region( usb_ctrl_cut_req.ar.region ), - .io_ctrl_ar_payload_len ( usb_ctrl_cut_req.ar.len ), - .io_ctrl_ar_payload_size ( usb_ctrl_cut_req.ar.size ), - .io_ctrl_ar_payload_burst ( usb_ctrl_cut_req.ar.burst ), - .io_ctrl_ar_payload_lock ( usb_ctrl_cut_req.ar.lock ), - .io_ctrl_ar_payload_cache ( usb_ctrl_cut_req.ar.cache ), - .io_ctrl_ar_payload_qos ( usb_ctrl_cut_req.ar.qos ), - .io_ctrl_ar_payload_prot ( usb_ctrl_cut_req.ar.prot ), - .io_ctrl_r_valid ( usb_ctrl_cut_rsp.r_valid ), - .io_ctrl_r_ready ( usb_ctrl_cut_req.r_ready ), - .io_ctrl_r_payload_data ( usb_ctrl_cut_rsp.r.data ), - .io_ctrl_r_payload_id ( usb_ctrl_cut_rsp.r.id ), - .io_ctrl_r_payload_resp ( usb_ctrl_cut_rsp.r.resp ), - .io_ctrl_r_payload_last ( usb_ctrl_cut_rsp.r.last ), - .io_interrupt ( intr.intn.usb ), - .io_usb_0_dp_read ( usb_0_dp_i ), - .io_usb_0_dp_write ( usb_0_dp_o ), - .io_usb_0_dp_writeEnable ( usb_0_dp_en_o ), - .io_usb_0_dm_read ( usb_0_dm_i ), - .io_usb_0_dm_write ( usb_0_dm_o ), - .io_usb_0_dm_writeEnable ( usb_0_dm_en_o ), - .io_usb_1_dp_read ( usb_1_dp_i ), - .io_usb_1_dp_write ( usb_1_dp_o ), - .io_usb_1_dp_writeEnable ( usb_1_dp_en_o ), - .io_usb_1_dm_read ( usb_1_dm_i ), - .io_usb_1_dm_write ( usb_1_dm_o ), - .io_usb_1_dm_writeEnable ( usb_1_dm_en_o ), - .io_usb_2_dp_read ( usb_2_dp_i ), - .io_usb_2_dp_write ( usb_2_dp_o ), - .io_usb_2_dp_writeEnable ( usb_2_dp_en_o ), - .io_usb_2_dm_read ( usb_2_dm_i ), - .io_usb_2_dm_write ( usb_2_dm_o ), - .io_usb_2_dm_writeEnable ( usb_2_dm_en_o ), - .io_usb_3_dp_read ( usb_3_dp_i ), - .io_usb_3_dp_write ( usb_3_dp_o ), - .io_usb_3_dp_writeEnable ( usb_3_dp_en_o ), - .io_usb_3_dm_read ( usb_3_dm_i ), - .io_usb_3_dm_write ( usb_3_dm_o ), - .io_usb_3_dm_writeEnable ( usb_3_dm_en_o ), - .phy_clk ( clk_i ), - .phy_reset ( !rst_ni ), - .ctrl_clk ( clk_i ), - .ctrl_reset ( !rst_ni ) - ); - - -// // USB Valid/Ready signals added to ILA -// `define ila(__name, __signal) \ -// (* dont_touch = "yes" *) (* mark_debug = "true" *) logic [$bits(__signal)-1:0] __name; \ -// assign __name = __signal; - end - /////////// // DMA // /////////// @@ -2026,6 +1677,57 @@ module cheshire_soc import cheshire_pkg::*; #( assign intr.intn.bus_err.vga = '0; end + /////////// + // USB // + /////////// + + if (Cfg.Usb) begin : gen_usb + + // TODO: USB has no internal error handling, so it should have a bus error unit (?) + + spinal_usb_ohci #( + .AxiMaxReads ( Cfg.UsbDmaMaxReads ), + .AxiAddrWidth ( Cfg.AddrWidth ), + .AxiDataWidth ( Cfg.AxiDataWidth ), + .AxiIdWidth ( Cfg.AxiMstIdWidth ), + .AxiUserWidth ( Cfg.AxiUserWidth ), + .AxiId ( '0 ), + .AxiUser ( Cfg.AxiUserDefault ), + .AxiAddrDomain ( Cfg.UsbAddrDomain ), + .AxiAddrMask ( Cfg.UsbAddrMask ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ), + .axi_req_t ( axi_mst_req_t ), + .axi_rsp_t ( axi_mst_rsp_t ) + ) i_spinal_usb_ohci ( + .soc_clk_i ( clk_i ), + .soc_rst_ni ( rst_ni ), + .ctrl_req_i ( reg_out_req[RegOut.usb] ), + .ctrl_rsp_o ( reg_out_rsp[RegOut.usb] ), + .dma_req_o ( axi_in_req[AxiIn.usb] ), + .dma_rsp_i ( axi_in_rsp[AxiIn.usb] ), + .intr_o ( intr.intn.usb ), + .phy_clk_i ( usb_clk_i ), + .phy_rst_ni ( rst_ni ), + .phy_dm_i ( usb_dm_i ), + .phy_dm_o ( usb_dm_o ), + .phy_dm_oe_o ( usb_dm_oe_o ), + .phy_dp_i ( usb_dp_i ), + .phy_dp_o ( usb_dp_o ), + .phy_dp_oe_o ( usb_dp_oe_o ) + ); + + end else begin + + assign usb_dm_o = '0; + assign usb_dm_oe_o = '0; + assign usb_dp_o = '0; + assign usb_dp_oe_o = '0; + + assign intr.intn.usb = 0; + + end + ////////////////// // Assertions // ////////////////// diff --git a/hw/future/axi_from_reg.sv b/hw/future/axi_from_reg.sv new file mode 100644 index 000000000..48ac1018e --- /dev/null +++ b/hw/future/axi_from_reg.sv @@ -0,0 +1,77 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Paul Scheffler + +/// A simple Regbus to AXI4 adapter. +/// Address and data width must match in both types! +/// Sends requests with ID 0 and user 0. + +module axi_from_reg #( + parameter int unsigned DataWidth = 0, + parameter axi_pkg::cache_t AxiCache = axi_pkg::CACHE_MODIFIABLE, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + output axi_req_t axi_req_o, + input axi_rsp_t axi_rsp_i +); + `include "common_cells/registers.svh" + + // Set request pending flags on handshakes to block further requests until response. + // Clear request pending flags (with in-cycle precedence over set!) on response. + logic ar_pending_q, aw_pending_q, w_pending_q; + + `FFLARNC(ar_pending_q, axi_rsp_i.ar_ready, axi_req_o.ar_valid, axi_rsp_i.r_valid, 1'b0, clk_i, rst_ni) + `FFLARNC(aw_pending_q, axi_rsp_i.aw_ready, axi_req_o.aw_valid, axi_rsp_i.b_valid, 1'b0, clk_i, rst_ni) + `FFLARNC(w_pending_q, axi_rsp_i.w_ready, axi_req_o.w_valid, axi_rsp_i.b_valid, 1'b0, clk_i, rst_ni) + + // AR: Forward locked-in read requests + assign axi_req_o.ar = '{ + addr: reg_req_i.addr, + size: $clog2(DataWidth/8), + burst: axi_pkg::BURST_INCR, + cache: AxiCache, + default: '0 + }; + + assign axi_req_o.r_ready = reg_req_i.valid & ~reg_req_i.write; + assign axi_req_o.ar_valid = axi_req_o.r_ready & ~ar_pending_q; + + // AW: Forward locked-in write requests + assign axi_req_o.aw = '{ + addr: reg_req_i.addr, + size: $clog2(DataWidth/8), + burst: axi_pkg::BURST_INCR, + cache: AxiCache, + default: '0 + }; + + assign axi_req_o.b_ready = reg_req_i.valid & reg_req_i.write; + assign axi_req_o.aw_valid = axi_req_o.b_ready & ~aw_pending_q; + + // W: lock control flow to AW requests + assign axi_req_o.w = '{ + data: reg_req_i.wdata, + strb: reg_req_i.wstrb, + last: 1'b1, + default: '0 + }; + + assign axi_req_o.w_valid = axi_req_o.b_ready & ~w_pending_q; + + // Regbus response + assign reg_rsp_o = '{ + rdata: axi_rsp_i.r.data, + error: (reg_req_i.write ? axi_rsp_i.b.resp : axi_rsp_i.r.resp) == axi_pkg::RESP_OKAY, + ready: axi_rsp_i.r_valid | axi_rsp_i.b_valid + }; + +endmodule diff --git a/hw/future/spinal_usb_ohci.sv b/hw/future/spinal_usb_ohci.sv new file mode 100644 index 000000000..1591ab8fb --- /dev/null +++ b/hw/future/spinal_usb_ohci.sv @@ -0,0 +1,257 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Luka Guzenko +// Paul Scheffler + +/// Wrapper for the SpinalHDL USB OHCI, configured for AXI4 buses and 4 ports. +/// The config port is adapted to 32b Regbus, the DMA port to parametric AXI4. +/// The IOs are bundled into PULP structs and arrays to simplify connection. + +package spinal_usb_ohci_pkg; + localparam int unsigned NumPhyPorts = 4; +endpackage + +module spinal_usb_ohci import spinal_usb_ohci_pkg::*; #( + /// DMA manager port parameters + parameter int unsigned AxiMaxReads = 0, + parameter int unsigned AxiAddrWidth = 0, + parameter int unsigned AxiDataWidth = 0, + parameter int unsigned AxiIdWidth = 0, + parameter int unsigned AxiUserWidth = 0, + /// The current controller can only address a 32b address space. + /// This parameter can statically add a domain and mask for the lower bits. + parameter logic [AxiAddrWidth-1:0] AxiAddrDomain = '0, + parameter logic [AxiAddrWidth-1:0] AxiAddrMask = 'hFFFF_FFFF, + /// Default User and ID presented on DMA manager AR, AW, W channels. + /// In most systems, these can or should be left at '0. + parameter logic [AxiIdWidth-1:0] AxiId = '0, + parameter logic [AxiUserWidth-1:0] AxiUser = '0, + /// SoC interface types + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic +) ( + /// SoC clock and reset + input logic soc_clk_i, + input logic soc_rst_ni, + /// Control subordinate port + input reg_req_t ctrl_req_i, + output reg_rsp_t ctrl_rsp_o, + /// DMA manager port + output axi_req_t dma_req_o, + input axi_rsp_t dma_rsp_i, + /// Interrupt + output logic intr_o, + /// PHY clock and reset + input logic phy_clk_i, + input logic phy_rst_ni, + /// PHY IO + input logic [NumPhyPorts-1:0] phy_dm_i, + output logic [NumPhyPorts-1:0] phy_dm_o, + output logic [NumPhyPorts-1:0] phy_dm_oe_o, + input logic [NumPhyPorts-1:0] phy_dp_i, + output logic [NumPhyPorts-1:0] phy_dp_o, + output logic [NumPhyPorts-1:0] phy_dp_oe_o +); + + `include "axi/typedef.svh" + + // Convert 32b-DW Regbus subordinate to controller's 32b-DW control AXI port + `AXI_TYPEDEF_ALL(ctrl_int, logic [11:0], logic [7:0], logic [31:0], logic [3:0], logic) + ctrl_int_req_t ctrl_int_req; + ctrl_int_resp_t ctrl_int_rsp; + + // The adapter implicitly truncates our address and emits ID 0 + axi_from_reg #( + .DataWidth ( 32 ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ), + .axi_req_t ( ctrl_int_req_t ), + .axi_rsp_t ( ctrl_int_resp_t ) + ) i_axi_from_reg_ctrl ( + .clk_i ( soc_clk_i ), + .rst_ni ( soc_rst_ni ), + .reg_req_i ( ctrl_req_i ), + .reg_rsp_o ( ctrl_rsp_o ), + .axi_req_o ( ctrl_int_req ), + .axi_rsp_i ( ctrl_int_rsp ) + ); + + // Forward-declare DMA manager port signals + `AXI_TYPEDEF_ALL(dma_int, logic [31:0], logic [AxiIdWidth-1:0], + logic [31:0], logic [3:0], logic [AxiUserWidth-1:0]) + dma_int_req_t dma_int_req; + dma_int_resp_t dma_int_rsp; + + // Tie parts of DMA manager request port not connected to OHCI controller + always_comb begin + // AR + dma_int_req.ar.id = AxiId; + dma_int_req.ar.user = AxiUser; + dma_int_req.ar.burst = axi_pkg::BURST_INCR; + dma_int_req.ar.lock = '0; + dma_int_req.ar.qos = '0; + dma_int_req.ar.region = '0; + // AW + dma_int_req.aw.id = AxiId; + dma_int_req.aw.user = AxiUser; + dma_int_req.aw.burst = axi_pkg::BURST_INCR; + dma_int_req.aw.lock = '0; + dma_int_req.aw.qos = '0; + dma_int_req.aw.region = '0; + dma_int_req.aw.atop = '0; + // W + dma_int_req.w.user = AxiUser; + end + + // Convert 32b DW to our AXI DW + `AXI_TYPEDEF_ALL(dma_int_dw, logic [31:0], logic [AxiIdWidth-1:0], + logic [AxiDataWidth-1:0], logic [AxiDataWidth/8-1:0], logic [AxiUserWidth-1:0]) + dma_int_dw_req_t dma_int_dw_req; + dma_int_dw_resp_t dma_int_dw_rsp; + + axi_dw_converter #( + .AxiMaxReads ( AxiMaxReads ), + .AxiSlvPortDataWidth ( 32 ), + .AxiMstPortDataWidth ( AxiDataWidth ), + .AxiAddrWidth ( 32 ), + .AxiIdWidth ( AxiIdWidth ), + .aw_chan_t ( dma_int_aw_chan_t ), + .ar_chan_t ( dma_int_ar_chan_t ), + .mst_w_chan_t ( dma_int_dw_w_chan_t ), + .slv_w_chan_t ( dma_int_w_chan_t ), + .b_chan_t ( dma_int_b_chan_t ), + .mst_r_chan_t ( dma_int_dw_r_chan_t ), + .slv_r_chan_t ( dma_int_r_chan_t ), + .axi_slv_req_t ( dma_int_req_t ), + .axi_slv_resp_t ( dma_int_resp_t ), + .axi_mst_req_t ( dma_int_dw_req_t ), + .axi_mst_resp_t ( dma_int_dw_resp_t ) + ) i_axi_dw_converter_dma ( + .clk_i ( soc_clk_i ), + .rst_ni ( soc_rst_ni ), + .slv_req_i ( dma_int_req ), + .slv_resp_o ( dma_int_rsp ), + .mst_req_o ( dma_int_dw_req ), + .mst_resp_i ( dma_int_dw_rsp ) + ); + + // Adapt 32b AW to our AXI AW + axi_modify_address #( + .slv_req_t ( dma_int_dw_req_t ), + .mst_req_t ( axi_req_t ), + .mst_addr_t ( logic [AxiAddrWidth-1:0] ), + .axi_resp_t ( axi_rsp_t ) + ) i_axi_modify_address_dma ( + .slv_req_i ( dma_int_dw_req ), + .slv_resp_o ( dma_int_dw_rsp ), + // TODO: how to write to addresses exceeding 32 bit? Find solution. + .mst_aw_addr_i( (AxiAddrDomain & ~AxiAddrMask) | (dma_int_dw_req.aw.addr & AxiAddrMask) ), + .mst_ar_addr_i( (AxiAddrDomain & ~AxiAddrMask) | (dma_int_dw_req.ar.addr & AxiAddrMask) ), + .mst_req_o ( dma_req_o ), + .mst_resp_i ( dma_rsp_i ) + ); + + // Spinal OHCI controller + UsbOhciAxi4 i_UsbOhciAxi4 ( + .io_dma_aw_valid ( dma_int_req.aw_valid ), + .io_dma_aw_ready ( dma_int_rsp.aw_ready ), + .io_dma_aw_payload_addr ( dma_int_req.aw.addr ), + .io_dma_aw_payload_len ( dma_int_req.aw.len ), + .io_dma_aw_payload_size ( dma_int_req.aw.size ), + .io_dma_aw_payload_cache ( dma_int_req.aw.cache ), + .io_dma_aw_payload_prot ( dma_int_req.aw.prot ), + .io_dma_w_valid ( dma_int_req.w_valid ), + .io_dma_w_ready ( dma_int_rsp.w_ready ), + .io_dma_w_payload_data ( dma_int_req.w.data ), + .io_dma_w_payload_strb ( dma_int_req.w.strb ), + .io_dma_w_payload_last ( dma_int_req.w.last ), + .io_dma_b_valid ( dma_int_rsp.b_valid ), + .io_dma_b_ready ( dma_int_req.b_ready ), + .io_dma_b_payload_resp ( dma_int_rsp.b.resp ), + .io_dma_ar_valid ( dma_int_req.ar_valid ), + .io_dma_ar_ready ( dma_int_rsp.ar_ready ), + .io_dma_ar_payload_addr ( dma_int_req.ar.addr ), + .io_dma_ar_payload_len ( dma_int_req.ar.len ), + .io_dma_ar_payload_size ( dma_int_req.ar.size ), + .io_dma_ar_payload_cache ( dma_int_req.ar.cache ), + .io_dma_ar_payload_prot ( dma_int_req.ar.prot ), + .io_dma_r_valid ( dma_int_rsp.r_valid ), + .io_dma_r_ready ( dma_int_req.r_ready ), + .io_dma_r_payload_data ( dma_int_rsp.r.data ), + .io_dma_r_payload_resp ( dma_int_rsp.r.resp ), + .io_dma_r_payload_last ( dma_int_rsp.r.last ), + .io_ctrl_aw_valid ( ctrl_int_req.aw_valid ), + .io_ctrl_aw_ready ( ctrl_int_rsp.aw_ready ), + .io_ctrl_aw_payload_addr ( ctrl_int_req.aw.addr ), + .io_ctrl_aw_payload_id ( ctrl_int_req.aw.id ), + .io_ctrl_aw_payload_region ( ctrl_int_req.aw.region ), + .io_ctrl_aw_payload_len ( ctrl_int_req.aw.len ), + .io_ctrl_aw_payload_size ( ctrl_int_req.aw.size ), + .io_ctrl_aw_payload_burst ( ctrl_int_req.aw.burst ), + .io_ctrl_aw_payload_lock ( ctrl_int_req.aw.lock ), + .io_ctrl_aw_payload_cache ( ctrl_int_req.aw.cache ), + .io_ctrl_aw_payload_qos ( ctrl_int_req.aw.qos ), + .io_ctrl_aw_payload_prot ( ctrl_int_req.aw.prot ), + .io_ctrl_w_valid ( ctrl_int_req.w_valid ), + .io_ctrl_w_ready ( ctrl_int_rsp.w_ready ), + .io_ctrl_w_payload_data ( ctrl_int_req.w.data ), + .io_ctrl_w_payload_strb ( ctrl_int_req.w.strb ), + .io_ctrl_w_payload_last ( ctrl_int_req.w.last ), + .io_ctrl_b_valid ( ctrl_int_rsp.b_valid ), + .io_ctrl_b_ready ( ctrl_int_req.b_ready ), + .io_ctrl_b_payload_id ( ctrl_int_rsp.b.id ), + .io_ctrl_b_payload_resp ( ctrl_int_rsp.b.resp ), + .io_ctrl_ar_valid ( ctrl_int_req.ar_valid ), + .io_ctrl_ar_ready ( ctrl_int_rsp.ar_ready ), + .io_ctrl_ar_payload_addr ( ctrl_int_req.ar.addr ), + .io_ctrl_ar_payload_id ( ctrl_int_req.ar.id ), + .io_ctrl_ar_payload_region ( ctrl_int_req.ar.region ), + .io_ctrl_ar_payload_len ( ctrl_int_req.ar.len ), + .io_ctrl_ar_payload_size ( ctrl_int_req.ar.size ), + .io_ctrl_ar_payload_burst ( ctrl_int_req.ar.burst ), + .io_ctrl_ar_payload_lock ( ctrl_int_req.ar.lock ), + .io_ctrl_ar_payload_cache ( ctrl_int_req.ar.cache ), + .io_ctrl_ar_payload_qos ( ctrl_int_req.ar.qos ), + .io_ctrl_ar_payload_prot ( ctrl_int_req.ar.prot ), + .io_ctrl_r_valid ( ctrl_int_rsp.r_valid ), + .io_ctrl_r_ready ( ctrl_int_req.r_ready ), + .io_ctrl_r_payload_data ( ctrl_int_rsp.r.data ), + .io_ctrl_r_payload_id ( ctrl_int_rsp.r.id ), + .io_ctrl_r_payload_resp ( ctrl_int_rsp.r.resp ), + .io_ctrl_r_payload_last ( ctrl_int_rsp.r.last ), + .io_interrupt ( intr_o ), + .io_usb_0_dp_read ( phy_dp_i [0] ), + .io_usb_0_dp_write ( phy_dp_o [0] ), + .io_usb_0_dp_writeEnable ( phy_dp_oe_o [0] ), + .io_usb_0_dm_read ( phy_dm_i [0] ), + .io_usb_0_dm_write ( phy_dm_o [0] ), + .io_usb_0_dm_writeEnable ( phy_dm_oe_o [0] ), + .io_usb_1_dp_read ( phy_dp_i [1] ), + .io_usb_1_dp_write ( phy_dp_o [1] ), + .io_usb_1_dp_writeEnable ( phy_dp_oe_o [1] ), + .io_usb_1_dm_read ( phy_dm_i [1] ), + .io_usb_1_dm_write ( phy_dm_o [1] ), + .io_usb_1_dm_writeEnable ( phy_dm_oe_o [1] ), + .io_usb_2_dp_read ( phy_dp_i [2] ), + .io_usb_2_dp_write ( phy_dp_o [2] ), + .io_usb_2_dp_writeEnable ( phy_dp_oe_o [2] ), + .io_usb_2_dm_read ( phy_dm_i [2] ), + .io_usb_2_dm_write ( phy_dm_o [2] ), + .io_usb_2_dm_writeEnable ( phy_dm_oe_o [2] ), + .io_usb_3_dp_read ( phy_dp_i [3] ), + .io_usb_3_dp_write ( phy_dp_o [3] ), + .io_usb_3_dp_writeEnable ( phy_dp_oe_o [3] ), + .io_usb_3_dm_read ( phy_dm_i [3] ), + .io_usb_3_dm_write ( phy_dm_o [3] ), + .io_usb_3_dm_writeEnable ( phy_dm_oe_o [3] ), + .phy_clk ( phy_clk_i ), + .phy_reset ( ~phy_rst_ni ), + .ctrl_clk ( soc_clk_i ), + .ctrl_reset ( ~soc_rst_ni ) + ); + +endmodule diff --git a/hw/regs/cheshire_reg_pkg.sv b/hw/regs/cheshire_reg_pkg.sv index e2a44ade2..e2711e3dc 100644 --- a/hw/regs/cheshire_reg_pkg.sv +++ b/hw/regs/cheshire_reg_pkg.sv @@ -57,6 +57,9 @@ package cheshire_reg_pkg; struct packed { logic d; } vga; + struct packed { + logic d; + } usb; struct packed { logic d; } axirt; @@ -89,11 +92,11 @@ package cheshire_reg_pkg; // HW -> register type typedef struct packed { - cheshire_hw2reg_boot_mode_reg_t boot_mode; // [166:165] - cheshire_hw2reg_rtc_freq_reg_t rtc_freq; // [164:133] - cheshire_hw2reg_platform_rom_reg_t platform_rom; // [132:101] - cheshire_hw2reg_num_int_harts_reg_t num_int_harts; // [100:69] - cheshire_hw2reg_hw_features_reg_t hw_features; // [68:56] + cheshire_hw2reg_boot_mode_reg_t boot_mode; // [167:166] + cheshire_hw2reg_rtc_freq_reg_t rtc_freq; // [165:134] + cheshire_hw2reg_platform_rom_reg_t platform_rom; // [133:102] + cheshire_hw2reg_num_int_harts_reg_t num_int_harts; // [101:70] + cheshire_hw2reg_hw_features_reg_t hw_features; // [69:56] cheshire_hw2reg_llc_size_reg_t llc_size; // [55:24] cheshire_hw2reg_vga_params_reg_t vga_params; // [23:0] } cheshire_hw2reg_t; @@ -128,7 +131,7 @@ package cheshire_reg_pkg; parameter logic [31:0] CHESHIRE_RTC_FREQ_RESVAL = 32'h 0; parameter logic [31:0] CHESHIRE_PLATFORM_ROM_RESVAL = 32'h 0; parameter logic [31:0] CHESHIRE_NUM_INT_HARTS_RESVAL = 32'h 0; - parameter logic [12:0] CHESHIRE_HW_FEATURES_RESVAL = 13'h 0; + parameter logic [13:0] CHESHIRE_HW_FEATURES_RESVAL = 14'h 0; parameter logic [31:0] CHESHIRE_LLC_SIZE_RESVAL = 32'h 0; parameter logic [23:0] CHESHIRE_VGA_PARAMS_RESVAL = 24'h 0; diff --git a/hw/regs/cheshire_reg_top.sv b/hw/regs/cheshire_reg_top.sv index bd9f2e272..9e55b807c 100644 --- a/hw/regs/cheshire_reg_top.sv +++ b/hw/regs/cheshire_reg_top.sv @@ -141,6 +141,8 @@ module cheshire_reg_top #( logic hw_features_serial_link_re; logic hw_features_vga_qs; logic hw_features_vga_re; + logic hw_features_usb_qs; + logic hw_features_usb_re; logic hw_features_axirt_qs; logic hw_features_axirt_re; logic hw_features_clic_qs; @@ -794,7 +796,22 @@ module cheshire_reg_top #( ); - // F[axirt]: 9:9 + // F[usb]: 9:9 + prim_subreg_ext #( + .DW (1) + ) u_hw_features_usb ( + .re (hw_features_usb_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.hw_features.usb.d), + .qre (), + .qe (), + .q (), + .qs (hw_features_usb_qs) + ); + + + // F[axirt]: 10:10 prim_subreg_ext #( .DW (1) ) u_hw_features_axirt ( @@ -809,7 +826,7 @@ module cheshire_reg_top #( ); - // F[clic]: 10:10 + // F[clic]: 11:11 prim_subreg_ext #( .DW (1) ) u_hw_features_clic ( @@ -824,7 +841,7 @@ module cheshire_reg_top #( ); - // F[irq_router]: 11:11 + // F[irq_router]: 12:12 prim_subreg_ext #( .DW (1) ) u_hw_features_irq_router ( @@ -839,7 +856,7 @@ module cheshire_reg_top #( ); - // F[bus_err]: 12:12 + // F[bus_err]: 13:13 prim_subreg_ext #( .DW (1) ) u_hw_features_bus_err ( @@ -1051,6 +1068,8 @@ module cheshire_reg_top #( assign hw_features_vga_re = addr_hit[20] & reg_re & !reg_error; + assign hw_features_usb_re = addr_hit[20] & reg_re & !reg_error; + assign hw_features_axirt_re = addr_hit[20] & reg_re & !reg_error; assign hw_features_clic_re = addr_hit[20] & reg_re & !reg_error; @@ -1161,10 +1180,11 @@ module cheshire_reg_top #( reg_rdata_next[6] = hw_features_dma_qs; reg_rdata_next[7] = hw_features_serial_link_qs; reg_rdata_next[8] = hw_features_vga_qs; - reg_rdata_next[9] = hw_features_axirt_qs; - reg_rdata_next[10] = hw_features_clic_qs; - reg_rdata_next[11] = hw_features_irq_router_qs; - reg_rdata_next[12] = hw_features_bus_err_qs; + reg_rdata_next[9] = hw_features_usb_qs; + reg_rdata_next[10] = hw_features_axirt_qs; + reg_rdata_next[11] = hw_features_clic_qs; + reg_rdata_next[12] = hw_features_irq_router_qs; + reg_rdata_next[13] = hw_features_bus_err_qs; end addr_hit[21]: begin diff --git a/hw/regs/cheshire_regs.hjson b/hw/regs/cheshire_regs.hjson index e551a9451..1e8ffbc51 100644 --- a/hw/regs/cheshire_regs.hjson +++ b/hw/regs/cheshire_regs.hjson @@ -98,10 +98,11 @@ { bits: "6", name: "dma", desc: "Whether DMA is available" } { bits: "7", name: "serial_link", desc: "Whether serial link is available" } { bits: "8", name: "vga", desc: "Whether VGA is available" } - { bits: "9", name: "axirt", desc: "Whether AXI RT is available" } - { bits: "10", name: "clic", desc: "Whether CLIC is available" } - { bits: "11", name: "irq_router", desc: "Whether IRQ router is available" } - { bits: "12", name: "bus_err", desc: "Whether UNBENT is available" } + { bits: "9", name: "usb", desc: "Whether USB is available" } + { bits: "10", name: "axirt", desc: "Whether AXI RT is available" } + { bits: "11", name: "clic", desc: "Whether CLIC is available" } + { bits: "12", name: "irq_router", desc: "Whether IRQ router is available" } + { bits: "13", name: "bus_err", desc: "Whether UNBENT is available" } ] } diff --git a/sw/boot/cheshire.dtsi b/sw/boot/cheshire.dtsi index 8d08a0e44..9ae5f6daa 100644 --- a/sw/boot/cheshire.dtsi +++ b/sw/boot/cheshire.dtsi @@ -100,13 +100,11 @@ #address-cells = <1>; #size-cells = <0>; }; - usb@1001000 { + usb@h3009000 { compatible = "generic-ohci"; - reg = <0x0 0x1001000 0x0 0x1000>; + reg = <0x0 0x3009000 0x0 0x1000>; interrupt-parent = <&PLIC0>; interrupts = <19>; - //clock-frequency = <48000000>; - //phy-names = "usb"; }; vga@3007000 { compatible = "eth,axi-vga"; diff --git a/sw/include/params.h b/sw/include/params.h index 5477689e0..40f7db47f 100644 --- a/sw/include/params.h +++ b/sw/include/params.h @@ -27,6 +27,9 @@ extern void *__base_plic; extern void *__base_dma; extern void *__base_axirt; extern void *__base_axirtgrd; +extern void *__base_bus_err; +extern void *__base_clic; +extern void *__base_usb; extern void *__base_spm; extern void *__base_dram; diff --git a/sw/include/regs/cheshire.h b/sw/include/regs/cheshire.h index 542d621ee..d44b0938a 100644 --- a/sw/include/regs/cheshire.h +++ b/sw/include/regs/cheshire.h @@ -100,10 +100,11 @@ extern "C" { #define CHESHIRE_HW_FEATURES_DMA_BIT 6 #define CHESHIRE_HW_FEATURES_SERIAL_LINK_BIT 7 #define CHESHIRE_HW_FEATURES_VGA_BIT 8 -#define CHESHIRE_HW_FEATURES_AXIRT_BIT 9 -#define CHESHIRE_HW_FEATURES_CLIC_BIT 10 -#define CHESHIRE_HW_FEATURES_IRQ_ROUTER_BIT 11 -#define CHESHIRE_HW_FEATURES_BUS_ERR_BIT 12 +#define CHESHIRE_HW_FEATURES_USB_BIT 9 +#define CHESHIRE_HW_FEATURES_AXIRT_BIT 10 +#define CHESHIRE_HW_FEATURES_CLIC_BIT 11 +#define CHESHIRE_HW_FEATURES_IRQ_ROUTER_BIT 12 +#define CHESHIRE_HW_FEATURES_BUS_ERR_BIT 13 // Total size of LLC in bytes #define CHESHIRE_LLC_SIZE_REG_OFFSET 0x54 diff --git a/sw/link/common.ldh b/sw/link/common.ldh index b9bdb43c1..d55a52498 100644 --- a/sw/link/common.ldh +++ b/sw/link/common.ldh @@ -43,7 +43,10 @@ SECTIONS { __base_gpio = 0x03005000; __base_slink = 0x03006000; __base_vga = 0x03007000; + __base_usb = 0x03008000; + __base_bus_err = 0x03009000; __base_plic = 0x04000000; + __base_clic = 0x08000000; __base_spm = ORIGIN(spm); __base_dram = ORIGIN(dram); } diff --git a/sw/tests/helloworld.c b/sw/tests/helloworld.c index 0e282d022..21e944be5 100644 --- a/sw/tests/helloworld.c +++ b/sw/tests/helloworld.c @@ -13,141 +13,12 @@ #include "params.h" #include "util.h" -#define CHESHIRE_VGA_ADDR 0x03007000 -#define CHESHIRE_FB_ADDR 0xA0000000 -#define CHESHIRE_FB_HEIGHT 480 -#define CHESHIRE_FB_WIDTH 640 -#define CHESHIRE_FB_SIZE (CHESHIRE_FB_WIDTH * CHESHIRE_FB_HEIGHT * 2) - -#define VGA(offset) *((volatile unsigned int *) (CHESHIRE_VGA_ADDR + (offset))) - int main(void) { char str[] = "Hello World!\r\n"; uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); uart_init(&__base_uart, reset_freq, __BOOT_BAUDRATE); uart_write_str(&__base_uart, str, sizeof(str)); - - - char rtn[] = "\r\n"; - - // Read USB Host Version (offset 11'h000) - uint32_t* ver_reg = (uint32_t*)0x01001000; - uint32_t ver = *ver_reg; - for (int32_t i = 31; i >= 0; --i) { - uart_write(&__base_uart, (uint8_t)(48 + ((ver >> i) % 2))); - } - uart_write_str(&__base_uart, rtn, sizeof(rtn)); - - // Read USB Host Vendor ID (offset 11'h040) - uint32_t* VID_reg = (uint32_t*)0x01001040; - uint32_t VID = *VID_reg; - for (int32_t i = 31; i >= 0; --i) { - uart_write(&__base_uart, (uint8_t)(48 + ((VID >> i) % 2))); - } - uart_write_str(&__base_uart, rtn, sizeof(rtn)); - - // Read Bus ID (offset 11'h01c) - uint32_t* BID_reg = (uint32_t*)0x0100101c; - uint32_t BID = *BID_reg; - for (int32_t i = 31; i >= 0; --i) { - uart_write(&__base_uart, (uint8_t)(48 + ((BID >> i) % 2))); - } - uart_write_str(&__base_uart, rtn, sizeof(rtn)); - - - // Test HCControl registers (set and clear) OHCI Spec 5.7 - - // Set bits 31, 29, 23, 18, 17 to one - uint32_t set = 0xA0860620; // 10100000 10000110 00000000 00000000 - - uint32_t* HCCset = 0x01001050; // Set register offset 11'h050 - - *HCCset = set; - - // Print HCControl - uint32_t HCC = *HCCset; - for (int32_t i = 31; i >= 0; --i) { - uart_write(&__base_uart, (uint8_t)(48 + ((HCC >> i) % 2))); - } - uart_write_str(&__base_uart, rtn, sizeof(rtn)); - - - // Reset bit 29 to zero - uint32_t clear = 0x80000000; // 10000000 00000000 00000000 00000000 - - uint32_t* HCCclear = 0x01001054; // Clear register offset 11'h054 - - *HCCclear = clear; - - // Print HCControl - HCC = *HCCset; - for (int32_t i = 31; i >= 0; --i) { - uart_write(&__base_uart, (uint8_t)(48 + ((HCC >> i) % 2))); - } - uart_write_str(&__base_uart, rtn, sizeof(rtn)); - - uart_write_flush(&__base_uart); - - - // Initialize VGA controller and populate framebuffer - // Clk div - VGA(0x04) = 0x2; // 8 for Sim, 2 for FPGA - - // Hori: Visible, Front porch, Sync, Back porch - VGA(0x08) = 0x280; - VGA(0x0C) = 0x10; - VGA(0x10) = 0x60; - VGA(0x14) = 0x30; - - // Vert: Visible, Front porch, Sync, Back porch - VGA(0x18) = 0x1e0; - VGA(0x1C) = 0xA; - VGA(0x20) = 0x2; - VGA(0x24) = 0x21; - - // Framebuffer start address - VGA(0x28) = 0xA0000000; // Low 32 bit - VGA(0x2C) = 0x0; // High 32 bit - - // Framebuffer size - VGA(0x30) = 640*480*2; // 640*480 pixel a 2 byte/pixel - - // Burst length - VGA(0x34) = 16; // 256*8 = 2kB Bursts - - // 0: Enable - // 1: Hsync polarity (Active Low = 0) - // 2: Vsync polarity (Active Low = 0) - VGA(0x00) = 0x1; - - uint16_t RGB[8] = { - 0xffff, //White - 0xffe0, //Yellow - 0x07ff, //Cyan - 0x07E0, //Green - 0xf81f, //Magenta - 0xF800, //Red - 0x001F, //Blue - 0x0000, //Black - }; - int col_width = CHESHIRE_FB_WIDTH / 8; - - volatile uint16_t *fb = (volatile uint16_t*)(void*)(uintptr_t) CHESHIRE_FB_ADDR; - - for (int k=0; k < 100; k++) { - for (int i=0; i < CHESHIRE_FB_HEIGHT; i++) { - for (int j=0; j < CHESHIRE_FB_WIDTH; j++) { - fb[CHESHIRE_FB_WIDTH * i + j] = RGB[k & 7]; - } - } - - fence(); - //for (int m=0; m < 10000; m++) { - // asm volatile ("nop"); - //} - } - return 0; } diff --git a/target/sim/src/fixture_cheshire_soc.sv b/target/sim/src/fixture_cheshire_soc.sv index 00f0c4932..68937fd3c 100644 --- a/target/sim/src/fixture_cheshire_soc.sv +++ b/target/sim/src/fixture_cheshire_soc.sv @@ -133,7 +133,14 @@ module fixture_cheshire_soc #( .vga_vsync_o ( ), .vga_red_o ( ), .vga_green_o ( ), - .vga_blue_o ( ) + .vga_blue_o ( ), + .usb_clk_i ( 1'b0 ), + .usb_dm_i ( '0 ), + .usb_dm_o ( ), + .usb_dm_oe_o ( ), + .usb_dp_i ( '0 ), + .usb_dp_o ( ), + .usb_dp_oe_o ( ) ); //////////////////////// diff --git a/target/xilinx/constraints/genesys2.xdc b/target/xilinx/constraints/genesys2.xdc index f812a89d4..ee49e9dc7 100644 --- a/target/xilinx/constraints/genesys2.xdc +++ b/target/xilinx/constraints/genesys2.xdc @@ -165,11 +165,11 @@ set_property -dict { PACKAGE_PIN AE30 IOSTANDARD LVCMOS33 } [get_ports { i2c_sc set_property -dict { PACKAGE_PIN AF30 IOSTANDARD LVCMOS33 } [get_ports { i2c_sda_io }]; #IO_L16N_T2_13 Sch=sys_sda # PMOD Header JA (USB 1.1 Adapter) -set_property -dict { PACKAGE_PIN U27 IOSTANDARD LVCMOS33 } [get_ports { usb_3_dm }]; #IO_L13P_T2_MRCC_14 Sch=ja_p[1] -set_property -dict { PACKAGE_PIN U28 IOSTANDARD LVCMOS33 } [get_ports { usb_3_dp }]; #IO_L13N_T2_MRCC_14 Sch=ja_n[1] -set_property -dict { PACKAGE_PIN T26 IOSTANDARD LVCMOS33 } [get_ports { usb_2_dm }]; #IO_L12P_T1_MRCC_14 Sch=ja_p[2] -set_property -dict { PACKAGE_PIN T27 IOSTANDARD LVCMOS33 } [get_ports { usb_2_dp }]; #IO_L12N_T1_MRCC_14 Sch=ja_n[2] -set_property -dict { PACKAGE_PIN T22 IOSTANDARD LVCMOS33 } [get_ports { usb_1_dm }]; #IO_L5P_T0_D06_14 Sch=ja_p[3] -set_property -dict { PACKAGE_PIN T23 IOSTANDARD LVCMOS33 } [get_ports { usb_1_dp }]; #IO_L5N_T0_D07_14 Sch=ja_n[3] -set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 } [get_ports { usb_0_dm }]; #IO_L4P_T0_D04_14 Sch=ja_p[4] -set_property -dict { PACKAGE_PIN T21 IOSTANDARD LVCMOS33 } [get_ports { usb_0_dp }]; #IO_L4N_T0_D05_14 Sch=ja_n[4] +set_property -dict { PACKAGE_PIN U27 IOSTANDARD LVCMOS33 } [get_ports { usb_dm_io[3] }]; #IO_L13P_T2_MRCC_14 Sch=ja_p[1] +set_property -dict { PACKAGE_PIN U28 IOSTANDARD LVCMOS33 } [get_ports { usb_dp_io[3] }]; #IO_L13N_T2_MRCC_14 Sch=ja_n[1] +set_property -dict { PACKAGE_PIN T26 IOSTANDARD LVCMOS33 } [get_ports { usb_dm_io[2] }]; #IO_L12P_T1_MRCC_14 Sch=ja_p[2] +set_property -dict { PACKAGE_PIN T27 IOSTANDARD LVCMOS33 } [get_ports { usb_dp_io[2] }]; #IO_L12N_T1_MRCC_14 Sch=ja_n[2] +set_property -dict { PACKAGE_PIN T22 IOSTANDARD LVCMOS33 } [get_ports { usb_dm_io[1] }]; #IO_L5P_T0_D06_14 Sch=ja_p[3] +set_property -dict { PACKAGE_PIN T23 IOSTANDARD LVCMOS33 } [get_ports { usb_dp_io[1] }]; #IO_L5N_T0_D07_14 Sch=ja_n[3] +set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 } [get_ports { usb_dm_io[0] }]; #IO_L4P_T0_D04_14 Sch=ja_p[4] +set_property -dict { PACKAGE_PIN T21 IOSTANDARD LVCMOS33 } [get_ports { usb_dp_io[0] }]; #IO_L4N_T0_D05_14 Sch=ja_n[4] diff --git a/target/xilinx/scripts/impl_ip.tcl b/target/xilinx/scripts/impl_ip.tcl index 474787fe7..36abc80bd 100644 --- a/target/xilinx/scripts/impl_ip.tcl +++ b/target/xilinx/scripts/impl_ip.tcl @@ -21,23 +21,25 @@ switch $proj { set_property -dict [list \ CONFIG.PRIM_SOURCE {No_buffer} \ CONFIG.PRIM_IN_FREQ {200.000} \ + CONFIG.CLKOUT1_USED {true} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ CONFIG.CLKOUT4_USED {true} \ - CONFIG.CLK_OUT1_PORT {clk_100} \ - CONFIG.CLK_OUT2_PORT {clk_50} \ + CONFIG.CLK_OUT1_PORT {clk_50} \ + CONFIG.CLK_OUT2_PORT {clk_48} \ CONFIG.CLK_OUT3_PORT {clk_20} \ CONFIG.CLK_OUT4_PORT {clk_10} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {50.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50.000} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {48.000} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20.000} \ CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {10.000} \ CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.MMCM_CLKFBOUT_MULT_F {5.000} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {6.000} \ CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ - CONFIG.MMCM_CLKIN2_PERIOD {10.0} \ - CONFIG.MMCM_CLKOUT1_DIVIDE {20} \ - CONFIG.MMCM_CLKOUT2_DIVIDE {50} \ - CONFIG.MMCM_CLKOUT3_DIVIDE {100} \ + CONFIG.MMCM_CLKOUT1_DIVIDE {24} \ + CONFIG.MMCM_CLKOUT2_DIVIDE {25} \ + CONFIG.MMCM_CLKOUT3_DIVIDE {60} \ + CONFIG.MMCM_CLKOUT4_DIVIDE {120} \ CONFIG.NUM_OUT_CLKS {4} \ CONFIG.CLKOUT1_JITTER {112.316} \ CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ @@ -53,28 +55,36 @@ switch $proj { set_property -dict [list \ CONFIG.CLK_IN1_BOARD_INTERFACE {Custom} \ CONFIG.RESET_BOARD_INTERFACE {Custom} \ + CONFIG.USE_RESET {true} \ + CONFIG.PRIM_SOURCE {No_buffer} \ + CONFIG.PRIM_IN_FREQ {100.000} \ + CONFIG.CLKOUT1_USED {true} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ CONFIG.CLKOUT4_USED {true} \ - CONFIG.CLK_OUT1_PORT {clk_100} \ - CONFIG.CLK_OUT2_PORT {clk_50} \ + CONFIG.CLK_OUT1_PORT {clk_50} \ + CONFIG.CLK_OUT2_PORT {clk_48} \ CONFIG.CLK_OUT3_PORT {clk_20} \ CONFIG.CLK_OUT4_PORT {clk_10} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {50.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50.000} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {48.000} \ CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {20.000} \ CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {10.000} \ - CONFIG.PRIM_SOURCE {No_buffer} \ - CONFIG.USE_RESET {true} \ + CONFIG.MMCM_CLKFBOUT_MULT_F {12.000} \ + CONFIG.MMCM_CLKIN1_PERIOD {5.000} \ CONFIG.MMCM_CLKOUT1_DIVIDE {24} \ - CONFIG.MMCM_CLKOUT2_DIVIDE {60} \ - CONFIG.MMCM_CLKOUT3_DIVIDE {120} \ + CONFIG.MMCM_CLKOUT2_DIVIDE {25} \ + CONFIG.MMCM_CLKOUT3_DIVIDE {60} \ + CONFIG.MMCM_CLKOUT4_DIVIDE {120} \ CONFIG.NUM_OUT_CLKS {4} \ - CONFIG.CLKOUT2_JITTER {132.683} \ - CONFIG.CLKOUT2_PHASE_ERROR {87.180} \ - CONFIG.CLKOUT3_JITTER {162.167} \ - CONFIG.CLKOUT3_PHASE_ERROR {87.180} \ - CONFIG.CLKOUT4_JITTER {188.586} \ - CONFIG.CLKOUT4_PHASE_ERROR {87.180} \ + CONFIG.CLKOUT1_JITTER {112.316} \ + CONFIG.CLKOUT1_PHASE_ERROR {89.971} \ + CONFIG.CLKOUT2_JITTER {129.198} \ + CONFIG.CLKOUT2_PHASE_ERROR {89.971} \ + CONFIG.CLKOUT3_JITTER {155.330} \ + CONFIG.CLKOUT3_PHASE_ERROR {89.971} \ + CONFIG.CLKOUT4_JITTER {178.053} \ + CONFIG.CLKOUT4_PHASE_ERROR {89.971} \ ] [get_ips $proj] } default {nocfgexit $proj $board} diff --git a/target/xilinx/src/cheshire_top_xilinx.sv b/target/xilinx/src/cheshire_top_xilinx.sv index 353263310..4259e89b0 100644 --- a/target/xilinx/src/cheshire_top_xilinx.sv +++ b/target/xilinx/src/cheshire_top_xilinx.sv @@ -13,7 +13,7 @@ // TODO: Expose more IO: unused SPI CS, Serial Link, etc. -module cheshire_top_xilinx ( +module cheshire_top_xilinx import cheshire_pkg::*; ( input logic sys_clk_p, input logic sys_clk_n, @@ -79,23 +79,15 @@ module cheshire_top_xilinx ( output logic uart_tx_o, input logic uart_rx_i, - - inout wire usb_0_dp, - inout wire usb_0_dm, - inout wire usb_1_dp, - inout wire usb_1_dm, - inout wire usb_2_dp, - inout wire usb_2_dm, - inout wire usb_3_dp, - inout wire usb_3_dm + + inout wire [UsbNumPorts-1:0] usb_dm_io, + inout wire [UsbNumPorts-1:0] usb_dp_io ); /////////////////////// // Cheshire Config // /////////////////////// - import cheshire_pkg::*; - // Use default config as far as possible function automatic cheshire_cfg_t gen_cheshire_xilinx_cfg(); cheshire_cfg_t ret = DefaultCfg; @@ -120,6 +112,7 @@ module cheshire_top_xilinx ( wire sys_clk; wire soc_clk; + wire usb_clk; IBUFDS #( .IBUF_LOW_PWR ("FALSE") @@ -133,8 +126,8 @@ module cheshire_top_xilinx ( .clk_in1 ( sys_clk ), .reset ( '0 ), .locked ( ), - .clk_100 ( ), - .clk_50 ( soc_clk ), + .clk_50 ( soc_clk ), + .clk_48 ( usb_clk ), .clk_20 ( ), .clk_10 ( ) ); @@ -336,59 +329,20 @@ module cheshire_top_xilinx ( // USB // /////////// - // Port 0 - logic usb_0_dm_o; - logic usb_0_dm_i; - logic usb_0_dm_en_o; - logic usb_0_dp_o; - logic usb_0_dp_i; - logic usb_0_dp_en_o; - // Port 1 - logic usb_1_dm_o; - logic usb_1_dm_i; - logic usb_1_dm_en_o; - logic usb_1_dp_o; - logic usb_1_dp_i; - logic usb_1_dp_en_o; - // Port 2 - logic usb_2_dm_o; - logic usb_2_dm_i; - logic usb_2_dm_en_o; - logic usb_2_dp_o; - logic usb_2_dp_i; - logic usb_2_dp_en_o; - // Port 3 - logic usb_3_dm_o; - logic usb_3_dm_i; - logic usb_3_dm_en_o; - logic usb_3_dp_o; - logic usb_3_dp_i; - logic usb_3_dp_en_o; - - - // Port 0 - assign usb_0_dp = usb_0_dp_en_o ? usb_0_dp_o : 'z; - assign usb_0_dp_i = usb_0_dp; - assign usb_0_dm = usb_0_dm_en_o ? usb_0_dm_o : 'z; - assign usb_0_dm_i = usb_0_dm; - - // Port 1 - assign usb_1_dp = usb_1_dp_en_o ? usb_1_dp_o : 'z; - assign usb_1_dp_i = usb_1_dp; - assign usb_1_dm = usb_1_dm_en_o ? usb_1_dm_o : 'z; - assign usb_1_dm_i = usb_1_dm; - - // Port 2 - assign usb_2_dp = usb_2_dp_en_o ? usb_2_dp_o : 'z; - assign usb_2_dp_i = usb_2_dp; - assign usb_2_dm = usb_2_dm_en_o ? usb_2_dm_o : 'z; - assign usb_2_dm_i = usb_2_dm; - - // Port 3 - assign usb_3_dp = usb_3_dp_en_o ? usb_3_dp_o : 'z; - assign usb_3_dp_i = usb_3_dp; - assign usb_3_dm = usb_3_dm_en_o ? usb_3_dm_o : 'z; - assign usb_3_dm_i = usb_3_dm; + // SoC IOs + logic [UsbNumPorts-1:0] usb_dm_i; + logic [UsbNumPorts-1:0] usb_dm_o; + logic [UsbNumPorts-1:0] usb_dm_oe_o; + logic [UsbNumPorts-1:0] usb_dp_i; + logic [UsbNumPorts-1:0] usb_dp_o; + logic [UsbNumPorts-1:0] usb_dp_oe_o; + + for (genvar i = 0; i < FPGACfg.Usb*UsbNumPorts; ++i) begin : gen_usb_tristate + assign usb_dp_io [i] = usb_dp_oe_o[i] ? usb_dp_o[i] : 'z; + assign usb_dp_i [i] = usb_dp_io[i]; + assign usb_dm_io [i] = usb_dm_oe_o[i] ? usb_dm_o[i] : 'z; + assign usb_dm_i [i] = usb_dm_io[i]; + end ///////////////////////// // "RTC" Clock Divider // @@ -530,30 +484,13 @@ module cheshire_top_xilinx ( `endif .uart_tx_o, .uart_rx_i, - .usb_0_dm_o, - .usb_0_dm_i, - .usb_0_dm_en_o, - .usb_0_dp_o, - .usb_0_dp_i, - .usb_0_dp_en_o, - .usb_1_dm_o, - .usb_1_dm_i, - .usb_1_dm_en_o, - .usb_1_dp_o, - .usb_1_dp_i, - .usb_1_dp_en_o, - .usb_2_dm_o, - .usb_2_dm_i, - .usb_2_dm_en_o, - .usb_2_dp_o, - .usb_2_dp_i, - .usb_2_dp_en_o, - .usb_3_dm_o, - .usb_3_dm_i, - .usb_3_dm_en_o, - .usb_3_dp_o, - .usb_3_dp_i, - .usb_3_dp_en_o + .usb_clk_i ( usb_clk ), + .usb_dm_i, + .usb_dm_o, + .usb_dm_oe_o, + .usb_dp_i, + .usb_dp_o, + .usb_dp_oe_o ); endmodule