/* * soc_iobuf.v * * vim: ts=4 sw=4 * * Copyright (C) 2019-2020 Sylvain Munaut * SPDX-License-Identifier: CERN-OHL-S-2.0 */ `default_nettype none module soc_iobuf ( // Wishbone slave (from CPU) input wire [15:0] wb_cpu_addr, output wire [31:0] wb_cpu_rdata, input wire [31:0] wb_cpu_wdata, input wire [ 3:0] wb_cpu_wmsk, input wire wb_cpu_we, input wire [ 2:0] wb_cpu_cyc, // 0=EP buf, 1=SPRAM, 2=DMA output wire [ 2:0] wb_cpu_ack, // Wishbone slave (from E1) input wire [13:0] wb_e1_addr, output wire [31:0] wb_e1_rdata, input wire [31:0] wb_e1_wdata, input wire [ 3:0] wb_e1_wmsk, input wire wb_e1_we, input wire wb_e1_cyc, output wire wb_e1_ack, // USB EP-Buf master output wire [ 8:0] ep_tx_addr_0, output wire [31:0] ep_tx_data_0, output wire ep_tx_we_0, output wire [ 8:0] ep_rx_addr_0, input wire [31:0] ep_rx_data_1, output wire ep_rx_re_0, /* Clock / Reset */ input wire clk, input wire rst ); // Signals // ------- // SPRAM wire [13:0] spr_addr; wire [31:0] spr_rdata; wire [31:0] spr_wdata; wire [ 3:0] spr_wmsk; wire spr_we; wire spr_cyc; wire spr_ack; wire [13:0] spr0_addr; wire [31:0] spr0_rdata; wire [31:0] spr0_wdata; wire [ 3:0] spr0_wmsk; wire spr0_we; wire spr0_cyc; wire spr0_ack; wire [13:0] spr1_addr; wire [31:0] spr1_rdata; wire [31:0] spr1_wdata; wire [ 3:0] spr1_wmsk; wire spr1_we; wire spr1_cyc; wire spr1_ack; wire [13:0] spr2_addr; wire [31:0] spr2_rdata; wire [31:0] spr2_wdata; wire [ 3:0] spr2_wmsk; wire spr2_we; wire spr2_cyc; wire spr2_ack; // EP Buffer wire [ 8:0] epb_addr; wire [31:0] epb_rdata; wire [31:0] epb_wdata; wire epb_we; wire epb_cyc; wire epb_ack; wire [ 8:0] epb0_addr; wire [31:0] epb0_rdata; wire [31:0] epb0_wdata; wire epb0_we; wire epb0_cyc; wire epb0_ack; wire [ 8:0] epb1_addr; wire [31:0] epb1_rdata; wire [31:0] epb1_wdata; wire epb1_we; wire epb1_cyc; wire epb1_ack; // DMA wire [31:0] wb_rdata_dma; // SPRAM // ----- // Instance ice40_spram_wb #( .DW(32), .AW(14), .ZERO_RDATA(0) ) spram_I ( .wb_addr (spr_addr), .wb_rdata(spr_rdata), .wb_wdata(spr_wdata), .wb_wmsk (spr_wmsk), .wb_we (spr_we), .wb_cyc (spr_cyc), .wb_ack (spr_ack), .clk (clk), .rst (rst) ); // Arbiter wb_arbiter #( .N(3), .DW(32), .AW(14) ) spram_arb_I ( .s_addr ({spr2_addr, spr1_addr, spr0_addr}), .s_rdata({spr2_rdata, spr1_rdata, spr0_rdata}), .s_wdata({spr2_wdata, spr1_wdata, spr0_wdata}), .s_wmsk ({spr2_wmsk, spr1_wmsk, spr0_wmsk}), .s_we ({spr2_we, spr1_we, spr0_we}), .s_cyc ({spr2_cyc, spr1_cyc, spr0_cyc}), .s_ack ({spr2_ack, spr1_ack, spr0_ack}), .m_addr (spr_addr), .m_rdata(spr_rdata), .m_wdata(spr_wdata), .m_wmsk (spr_wmsk), .m_we (spr_we), .m_cyc (spr_cyc), .m_ack (spr_ack), .clk (clk), .rst (rst) ); // EP buffer // --------- // Instance wb_epbuf #( .AW(9), .DW(32) ) epbuf_I ( .wb_addr (epb_addr), .wb_rdata (epb_rdata), .wb_wdata (epb_wdata), .wb_we (epb_we), .wb_cyc (epb_cyc), .wb_ack (epb_ack), .ep_tx_addr_0(ep_tx_addr_0), .ep_tx_data_0(ep_tx_data_0), .ep_tx_we_0 (ep_tx_we_0), .ep_rx_addr_0(ep_rx_addr_0), .ep_rx_data_1(ep_rx_data_1), .ep_rx_re_0 (ep_rx_re_0), .clk (clk), .rst (rst) ); // Arbiter wb_arbiter #( .N(2), .DW(32), .AW(9) ) epbam_arb_I ( .s_addr ({epb1_addr, epb0_addr}), .s_rdata({epb1_rdata, epb0_rdata}), .s_wdata({epb1_wdata, epb0_wdata}), .s_wmsk (8'hff), .s_we ({epb1_we, epb0_we}), .s_cyc ({epb1_cyc, epb0_cyc}), .s_ack ({epb1_ack, epb0_ack}), .m_addr (epb_addr), .m_rdata(epb_rdata), .m_wdata(epb_wdata), .m_we (epb_we), .m_cyc (epb_cyc), .m_ack (epb_ack), .clk (clk), .rst (rst) ); // DMA // --- wb_dma #( .A0W(14), .A1W(9), .DW(32) ) dma_I ( .m0_addr (spr2_addr), .m0_rdata (spr2_rdata), .m0_wdata (spr2_wdata), .m0_we (spr2_we), .m0_cyc (spr2_cyc), .m0_ack (spr2_ack), .m1_addr (epb1_addr), .m1_rdata (epb1_rdata), .m1_wdata (epb1_wdata), .m1_we (epb1_we), .m1_cyc (epb1_cyc), .m1_ack (epb1_ack), .ctl_addr (wb_cpu_addr[1:0]), .ctl_rdata(wb_rdata_dma), .ctl_wdata(wb_cpu_wdata), .ctl_we (wb_cpu_we), .ctl_cyc (wb_cpu_cyc[2]), .ctl_ack (wb_cpu_ack[2]), .clk (clk), .rst (rst) ); assign spr2_wmsk = 4'h0; // External accesses // ----------------- // CPU assign spr1_addr = wb_cpu_addr[13:0]; assign spr1_wdata = wb_cpu_wdata; assign spr1_wmsk = wb_cpu_wmsk; assign spr1_we = wb_cpu_we; assign spr1_cyc = wb_cpu_cyc[1]; assign wb_cpu_ack[1] = spr1_ack; assign epb0_addr = wb_cpu_addr[8:0]; assign epb0_wdata = wb_cpu_wdata; assign epb0_we = wb_cpu_we; assign epb0_cyc = wb_cpu_cyc[0]; assign wb_cpu_ack[0] = epb0_ack; assign wb_cpu_rdata = spr1_rdata | epb0_rdata | wb_rdata_dma; // E1 assign spr0_addr = wb_e1_addr; assign spr0_wdata = wb_e1_wdata; assign spr0_wmsk = wb_e1_wmsk; assign spr0_we = wb_e1_we; assign spr0_cyc = wb_e1_cyc; assign wb_e1_rdata = spr0_rdata; assign wb_e1_ack = spr0_ack; endmodule // soc_iobuf