osmo-e1-hardware/gateware/common/rtl/soc_base.v

545 lines
11 KiB
Verilog

/*
* soc_base.v
*
* vim: ts=4 sw=4
*
* Minimal common base for the E1 project SoC
*
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-S-2.0
*/
`default_nettype none
module soc_base #(
parameter integer WB_N = 1,
parameter integer E1_N = 1,
parameter E1_UNIT_HAS_RX = 1'b1,
parameter E1_UNIT_HAS_TX = 1'b1,
parameter integer E1_LIU = 0
)(
// E1 pads
// Raw PHY
input wire [E1_N-1:0] e1_rx_hi_p,
input wire [E1_N-1:0] e1_rx_hi_n,
input wire [E1_N-1:0] e1_rx_lo_p,
input wire [E1_N-1:0] e1_rx_lo_n,
output wire [E1_N-1:0] e1_tx_hi,
output wire [E1_N-1:0] e1_tx_lo,
// LIU
input wire [E1_N-1:0] e1_rx_data,
input wire [E1_N-1:0] e1_rx_clk,
output wire [E1_N-1:0] e1_tx_data,
output wire [E1_N-1:0] e1_tx_clk,
// USB
inout wire usb_dp,
inout wire usb_dn,
output wire usb_pu,
// Flash SPI (raw)
input wire flash_mosi_i,
output wire flash_mosi_o,
output wire flash_mosi_oe,
input wire flash_miso_i,
output wire flash_miso_o,
output wire flash_miso_oe,
input wire flash_clk_i,
output wire flash_clk_o,
output wire flash_clk_oe,
output wire flash_csn_o,
// Debug UART
input wire dbg_rx,
output wire dbg_tx,
// RGB LEDs
output wire [2:0] rgb,
// External Master Wishbone bus (CPU -> Peripheral)
output wire [15:0] wb_m_addr,
input wire [(WB_N*32)-1:0] wb_m_rdata,
output wire [31:0] wb_m_wdata,
output wire [ 3:0] wb_m_wmsk,
output wire wb_m_we,
output wire [ WB_N -1:0] wb_m_cyc,
input wire [ WB_N -1:0] wb_m_ack,
// Ticks
output wire [E1_N-1:0] tick_e1_rx,
output wire [E1_N-1:0] tick_e1_tx,
output wire tick_usb_sof,
// Clock / Reset
input wire clk_sys,
input wire rst_sys,
input wire clk_48m,
input wire rst_48m
);
genvar i;
localparam integer WB_LN = 8;
localparam integer WB_TN = WB_N + WB_LN;
localparam integer WB_DW = 32;
localparam integer WB_MW = WB_DW / 8;
localparam integer WB_AW = 16;
localparam integer WB_AI = 2;
// Signals
// -------
// Picorv32 native bus
wire pb_valid;
wire pb_instr;
wire pb_ready;
wire [31:0] pb_addr;
wire [31:0] pb_rdata;
wire [31:0] pb_wdata;
wire [ 3:0] pb_wstrb;
// SoC RAM
// BRAM
wire [ 7:0] bram_addr;
wire [31:0] bram_rdata;
wire [31:0] bram_wdata;
wire [ 3:0] bram_wmsk;
wire bram_we;
// SPRAM
wire [14:0] spram_addr;
wire [31:0] spram_rdata;
wire [31:0] spram_wdata;
wire [ 3:0] spram_wmsk;
wire spram_we;
// Peripheral wishbone
wire [WB_AW-1:0] wb_addr;
wire [WB_DW-1:0] wb_rdata [0:WB_LN-1];
wire [WB_DW-1:0] wb_wdata;
wire [WB_MW-1:0] wb_wmsk;
wire wb_we;
wire [WB_TN-1:0] wb_cyc;
wire [WB_TN-1:0] wb_ack;
wire [(WB_DW*WB_TN)-1:0] wb_rdata_flat;
// USB
// Wishbone ( @ 48 MHz )
wire [11:0] ub_addr;
wire [15:0] ub_rdata;
wire [15:0] ub_wdata;
wire ub_we;
wire ub_cyc;
wire ub_ack;
// EP interface
wire [ 8:0] ep_tx_addr_0;
wire [31:0] ep_tx_data_0;
wire ep_tx_we_0;
wire [ 8:0] ep_rx_addr_0;
wire [31:0] ep_rx_data_1;
wire ep_rx_re_0;
// SoF
wire usb_sof;
// Wishbone bus E1 to IO buffers
wire [13:0] wb_e1_addr;
wire [31:0] wb_e1_rdata;
wire [31:0] wb_e1_wdata;
wire [ 3:0] wb_e1_wmsk;
wire wb_e1_we;
wire wb_e1_cyc;
wire wb_e1_ack;
// E1 buffer interface
wire [(E1_N*8)-1:0] e1_buf_rx_data;
wire [(E1_N*5)-1:0] e1_buf_rx_ts;
wire [(E1_N*4)-1:0] e1_buf_rx_frame;
wire [(E1_N*7)-1:0] e1_buf_rx_mf;
wire [ E1_N -1:0] e1_buf_rx_we;
wire [ E1_N -1:0] e1_buf_rx_rdy;
wire [(E1_N*8)-1:0] e1_buf_tx_data;
wire [(E1_N*5)-1:0] e1_buf_tx_ts;
wire [(E1_N*4)-1:0] e1_buf_tx_frame;
wire [(E1_N*7)-1:0] e1_buf_tx_mf;
wire [ E1_N -1:0] e1_buf_tx_re;
wire [ E1_N -1:0] e1_buf_tx_rdy;
// SoC core
// --------
// Local CPU reset
reg pb_rst_n;
always @(posedge clk_sys or posedge rst_sys)
if (rst_sys)
pb_rst_n <= 1'b0;
else
pb_rst_n <= 1'b1;
// CPU
picorv32 #(
.PROGADDR_RESET(32'h 0000_0000),
.STACKADDR(32'h 0000_0400),
.BARREL_SHIFTER(0),
`ifdef BOARD_E1_TRACER
.TWO_CYCLE_COMPARE(0),
.TWO_CYCLE_ALU(0),
`else
.TWO_CYCLE_COMPARE(0),
.TWO_CYCLE_ALU(1),
`endif
.COMPRESSED_ISA(0),
.ENABLE_COUNTERS(0),
.ENABLE_MUL(0),
.ENABLE_DIV(0),
.ENABLE_IRQ(0),
.ENABLE_IRQ_QREGS(0),
.CATCH_MISALIGN(0),
.CATCH_ILLINSN(0)
) cpu_I (
.clk (clk_sys),
.resetn (pb_rst_n),
.mem_valid (pb_valid),
.mem_instr (pb_instr),
.mem_ready (pb_ready),
.mem_addr (pb_addr),
.mem_wdata (pb_wdata),
.mem_wstrb (pb_wstrb),
.mem_rdata (pb_rdata)
);
// CPU bridge
soc_picorv32_bridge #(
.WB_N (WB_TN),
.WB_DW (32),
.WB_AW (16),
.WB_AI ( 2),
.WB_REG( 0)
) bridge_I (
.pb_addr (pb_addr),
.pb_rdata (pb_rdata),
.pb_wdata (pb_wdata),
.pb_wstrb (pb_wstrb),
.pb_valid (pb_valid),
.pb_ready (pb_ready),
.bram_addr (bram_addr),
.bram_rdata (bram_rdata),
.bram_wdata (bram_wdata),
.bram_wmsk (bram_wmsk),
.bram_we (bram_we),
.spram_addr (spram_addr),
.spram_rdata(spram_rdata),
.spram_wdata(spram_wdata),
.spram_wmsk (spram_wmsk),
.spram_we (spram_we),
.wb_addr (wb_addr),
.wb_rdata (wb_rdata_flat),
.wb_wdata (wb_wdata),
.wb_wmsk (wb_wmsk),
.wb_we (wb_we),
.wb_cyc (wb_cyc),
.wb_ack (wb_ack),
.clk (clk_sys),
.rst (rst_sys)
);
for (i=0; i<WB_LN; i=i+1)
assign wb_rdata_flat[i*WB_DW+:WB_DW] = wb_rdata[i];
// Boot memory - 1k
soc_bram #(
.AW(8),
.INIT_FILE("boot.hex"),
) bram_I (
.addr (bram_addr),
.rdata(bram_rdata),
.wdata(bram_wdata),
.wmsk (bram_wmsk),
.we (bram_we),
.clk (clk_sys)
);
// Main SoC memory - 64k
soc_spram #(
.AW(14)
) spram_I (
.addr (spram_addr[13:0]),
.rdata(spram_rdata),
.wdata(spram_wdata),
.wmsk (spram_wmsk),
.we (spram_we),
.clk (clk_sys)
);
// Peripheral wishbone export
assign wb_m_addr = wb_addr;
assign wb_m_wdata = wb_wdata;
assign wb_m_wmsk = wb_wmsk;
assign wb_m_we = wb_we;
assign wb_m_cyc = wb_cyc[WB_TN-1:WB_LN];
assign wb_rdata_flat[(WB_TN*WB_DW)-1:(WB_LN*WB_DW)] = wb_m_rdata;
assign wb_ack[WB_TN-1:WB_LN] = wb_m_ack;
// SPI [0]
// ---
ice40_spi_wb #(
.N_CS(1),
.WITH_IOB(0),
.UNIT(0)
) spi_I (
.sio_mosi_i (flash_mosi_i),
.sio_mosi_o (flash_mosi_o),
.sio_mosi_oe(flash_mosi_oe),
.sio_miso_i (flash_miso_i),
.sio_miso_o (flash_miso_o),
.sio_miso_oe(flash_miso_oe),
.sio_clk_i (flash_clk_i),
.sio_clk_o (flash_clk_o),
.sio_clk_oe (flash_clk_oe),
.sio_csn_o (flash_csn_o),
.sio_csn_oe (),
.wb_addr (wb_addr[3:0]),
.wb_rdata (wb_rdata[0]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[0]),
.wb_ack (wb_ack[0]),
.clk (clk_sys),
.rst (rst_sys)
);
// Debug UART [1]
// ----------
uart_wb #(
.DIV_WIDTH(12),
.DW(WB_DW)
) uart_I (
.uart_tx (dbg_tx),
.uart_rx (dbg_rx),
.wb_addr (wb_addr[1:0]),
.wb_rdata (wb_rdata[1]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[1]),
.wb_ack (wb_ack[1]),
.clk (clk_sys),
.rst (rst_sys)
);
// RGB LEDs [2]
// --------
ice40_rgb_wb #(
.CURRENT_MODE("0b1"),
.RGB0_CURRENT("0b000001"),
.RGB1_CURRENT("0b000001"),
.RGB2_CURRENT("0b000001")
) rgb_I (
.pad_rgb (rgb),
.wb_addr (wb_addr[4:0]),
.wb_rdata (wb_rdata[2]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[2]),
.wb_ack (wb_ack[2]),
.clk (clk_sys),
.rst (rst_sys)
);
// USB [3]
// ---
// Core instance ( @ 48 MHz )
usb #(
.EPDW(32)
) usb_I (
.pad_dp (usb_dp),
.pad_dn (usb_dn),
.pad_pu (usb_pu),
.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),
.ep_clk (clk_sys),
.wb_addr (ub_addr),
.wb_rdata (ub_rdata),
.wb_wdata (ub_wdata),
.wb_we (ub_we),
.wb_cyc (ub_cyc),
.wb_ack (ub_ack),
.sof (usb_sof),
.clk (clk_48m),
.rst (rst_48m)
);
// Cross clock bridge
xclk_wb #(
.DW(16),
.AW(12)
) wb_48m_xclk_I (
.s_addr (wb_addr[11:0]),
.s_rdata(wb_rdata[3][15:0]),
.s_wdata(wb_wdata[15:0]),
.s_we (wb_we),
.s_cyc (wb_cyc[3]),
.s_ack (wb_ack[3]),
.s_clk (clk_sys),
.m_addr (ub_addr),
.m_rdata(ub_rdata),
.m_wdata(ub_wdata),
.m_we (ub_we),
.m_cyc (ub_cyc),
.m_ack (ub_ack),
.m_clk (clk_48m),
.rst (rst_sys)
);
assign wb_rdata[3][31:16] = 16'h0000;
// Cross clock SoF
xclk_strobe sof_xclk_I (
.in_stb (usb_sof),
.in_clk (clk_48m),
.out_stb(tick_usb_sof),
.out_clk(clk_sys),
.rst (rst_sys)
);
// IO buffers & DMA
// ----------------
// [4] USB EP buffer
// [5] E1 SPRAM buffer
// [6] DMA
soc_iobuf iobuf_I (
.wb_cpu_addr (wb_addr),
.wb_cpu_rdata(wb_rdata[4]),
.wb_cpu_wdata(wb_wdata),
.wb_cpu_wmsk (wb_wmsk),
.wb_cpu_we (wb_we),
.wb_cpu_cyc (wb_cyc[6:4]),
.wb_cpu_ack (wb_ack[6:4]),
.wb_e1_addr (wb_e1_addr),
.wb_e1_rdata (wb_e1_rdata),
.wb_e1_wdata (wb_e1_wdata),
.wb_e1_wmsk (wb_e1_wmsk),
.wb_e1_we (wb_e1_we),
.wb_e1_cyc (wb_e1_cyc),
.wb_e1_ack (wb_e1_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_sys),
.rst (rst_sys)
);
assign wb_rdata[5] = 32'h00000000;
assign wb_rdata[6] = 32'h00000000;
// E1 [7]
// --
// E1 wishbone module
e1_wb #(
.N(E1_N),
.UNIT_HAS_RX(E1_UNIT_HAS_RX),
.UNIT_HAS_TX(E1_UNIT_HAS_TX),
.LIU(E1_LIU),
.MFW(7)
) e1_I (
.pad_rx_hi_p (e1_rx_hi_p),
.pad_rx_hi_n (e1_rx_hi_n),
.pad_rx_lo_p (e1_rx_lo_p),
.pad_rx_lo_n (e1_rx_lo_n),
.pad_tx_hi (e1_tx_hi),
.pad_tx_lo (e1_tx_lo),
.pad_rx_data (e1_rx_data),
.pad_rx_clk (e1_rx_clk),
.pad_tx_data (e1_tx_data),
.pad_tx_clk (e1_tx_clk),
.buf_rx_data (e1_buf_rx_data),
.buf_rx_ts (e1_buf_rx_ts),
.buf_rx_frame(e1_buf_rx_frame),
.buf_rx_mf (e1_buf_rx_mf),
.buf_rx_we (e1_buf_rx_we),
.buf_rx_rdy (e1_buf_rx_rdy),
.buf_tx_data (e1_buf_tx_data),
.buf_tx_ts (e1_buf_tx_ts),
.buf_tx_frame(e1_buf_tx_frame),
.buf_tx_mf (e1_buf_tx_mf),
.buf_tx_re (e1_buf_tx_re),
.buf_tx_rdy (e1_buf_tx_rdy),
.wb_addr (wb_addr[7:0]),
.wb_rdata (wb_rdata[7][15:0]),
.wb_wdata (wb_wdata[15:0]),
.wb_we (wb_we),
.wb_cyc (wb_cyc[7]),
.wb_ack (wb_ack[7]),
.irq (),
.tick_rx (tick_e1_rx),
.tick_tx (tick_e1_tx),
.clk (clk_sys),
.rst (rst_sys)
);
assign wb_rdata[7][31:16] = 16'h0000;
// E1 buffer interface to Wishbone
e1_buf_if_wb #(
.N(E1_N),
.UNIT_HAS_RX(E1_UNIT_HAS_RX),
.UNIT_HAS_TX(E1_UNIT_HAS_TX),
.MFW(7),
.DW(32)
) e1_buf_I (
.wb_addr (wb_e1_addr),
.wb_rdata (wb_e1_rdata),
.wb_wdata (wb_e1_wdata),
.wb_wmsk (wb_e1_wmsk),
.wb_we (wb_e1_we),
.wb_cyc (wb_e1_cyc),
.wb_ack (wb_e1_ack),
.buf_rx_data (e1_buf_rx_data),
.buf_rx_ts (e1_buf_rx_ts),
.buf_rx_frame(e1_buf_rx_frame),
.buf_rx_mf (e1_buf_rx_mf),
.buf_rx_we (e1_buf_rx_we),
.buf_rx_rdy (e1_buf_rx_rdy),
.buf_tx_data (e1_buf_tx_data),
.buf_tx_ts (e1_buf_tx_ts),
.buf_tx_frame(e1_buf_tx_frame),
.buf_tx_mf (e1_buf_tx_mf),
.buf_tx_re (e1_buf_tx_re),
.buf_tx_rdy (e1_buf_tx_rdy),
.clk (clk_sys),
.rst (rst_sys)
);
endmodule // soc_base