gateware: Add an option to build with a no2usb core built-in

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2022-05-02 12:18:44 +02:00
parent f0a9338411
commit ca4a2e357b
7 changed files with 238 additions and 7 deletions

3
.gitmodules vendored
View File

@ -10,3 +10,6 @@
[submodule "gateware/cores/no2iso7816"]
path = gateware/cores/no2iso7816
url = https://github.com/no2fpga/no2iso7816.git
[submodule "gateware/cores/no2usb"]
path = gateware/cores/no2usb
url = https://github.com/no2fpga/no2usb.git

View File

@ -11,4 +11,6 @@
#define UART_BASE 0x81000000
#define SPI_BASE 0x82000000
#define LED_BASE 0x83000000
#define ISO7816_BASE 0x84000000
#define USB_CORE_BASE 0x84000000
#define USB_DATA_BASE 0x85000000
#define ISO7816_BASE 0x86000000

1
gateware/cores/no2usb Submodule

@ -0,0 +1 @@
Subproject commit fdf42a6571a4ae49556626e6fffca1582796f7e8

View File

@ -10,6 +10,7 @@ PROJ_RTL_SRCS := $(addprefix rtl/, \
soc_picorv32_base.v \
soc_picorv32_bridge.v \
soc_spram.v \
soc_usb.v \
sysmgr.v \
)
PROJ_PREREQ = \
@ -26,6 +27,12 @@ PACKAGE = sg48
YOSYS_SYNTH_ARGS := -abc9 -device u
NEXTPNR_ARGS := --no-promote-globals --pre-pack data/opt.py
# USB options
ifneq ($(USB),)
PROJ_DEPS += no2usb
YOSYS_READ_ARGS += -DWITH_USB=1
endif
# Include default rules
include ../build/project-rules.mk

View File

@ -1,3 +1,8 @@
# USB
set_io -nowarn usb_dp 31
set_io -nowarn usb_dn 34
set_io -nowarn usb_pu 38
# SPI
set_io -nowarn spi_mosi 14
set_io -nowarn spi_miso 17

View File

@ -0,0 +1,157 @@
/*
* soc_usb.v
*
* vim: ts=4 sw=4
*
* Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-P-2.0
*/
`default_nettype none
module soc_usb #(
parameter integer DW = 32
)(
// USB
inout wire usb_dp,
inout wire usb_dn,
output wire usb_pu,
// Wishbone slave
input wire [ 11:0] wb_addr,
output wire [DW-1:0] wb_rdata,
input wire [DW-1:0] wb_wdata,
input wire wb_we,
input wire [1:0] wb_cyc,
output wire [1:0] wb_ack,
// Misc
output wire usb_sof,
// Clock / Reset
input wire clk_sys,
input wire clk_48m,
input wire rst
);
// Signals
// -------
// Bus OR
wire [DW-1:0] wb_rdata_i[0:1];
// Wishbone in 48 MHz domain
wire [11:0] ub_addr;
wire [15:0] ub_wdata;
wire [15:0] ub_rdata;
wire ub_cyc;
wire ub_we;
wire ub_ack;
// SoF in 48 MHz domain
wire usb_sof_48m;
// EP Buffer
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;
reg ack_ep;
// Cross-clock
// -----------
// Bring control reg wishbone to 48 MHz domain
xclk_wb #(
.DW(16),
.AW(12)
) wb_48m_xclk_I (
.s_addr (wb_addr[11:0]),
.s_wdata (wb_wdata[15:0]),
.s_rdata (wb_rdata_i[0][15:0]),
.s_cyc (wb_cyc[0]),
.s_ack (wb_ack[0]),
.s_we (wb_we),
.s_clk (clk_sys),
.m_addr (ub_addr),
.m_wdata (ub_wdata),
.m_rdata (ub_rdata),
.m_cyc (ub_cyc),
.m_ack (ub_ack),
.m_we (ub_we),
.m_clk (clk_48m),
.rst (rst)
);
if (DW != 16)
assign wb_rdata_i[0][DW-1:16] = 0;
xclk_strobe sof_xclk_I (
.in_stb (usb_sof_48m),
.in_clk (clk_48m),
.out_stb (usb_sof),
.out_clk (clk_sys),
.rst (rst)
);
// Core
// ----
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_48m),
.clk (clk_48m),
.rst (rst)
);
// EP data
// -------
assign ep_tx_addr_0 = wb_addr[8:0];
assign ep_rx_addr_0 = wb_addr[8:0];
assign ep_tx_data_0 = wb_wdata;
assign wb_rdata_i[1] = ack_ep ? ep_rx_data_1 : 32'h00000000;
assign ep_tx_we_0 = wb_cyc[1] & wb_we & ~ack_ep;
assign ep_rx_re_0 = 1'b1;
assign wb_ack[1] = ack_ep;
always @(posedge clk_sys or posedge rst)
if (rst)
ack_ep <= 1'b0;
else
ack_ep <= wb_cyc[1] & ~ack_ep;
// Bus read data
// -------------
assign wb_rdata = wb_rdata_i[0] | wb_rdata_i[1];
endmodule // soc_usb

View File

@ -10,6 +10,13 @@
`default_nettype none
module top (
// USB
`ifdef WITH_USB
inout wire usb_dp,
inout wire usb_dn,
output wire usb_pu,
`endif
// SPI
inout wire spi_mosi,
inout wire spi_miso,
@ -44,7 +51,7 @@ module top (
localparam integer SC_N = 1;
localparam integer SPRAM_AW = 14; /* 14 => 64k, 15 => 128k */
localparam integer WB_N = 4 + SC_N;
localparam integer WB_N = 6 + SC_N;
localparam integer WB_DW = 32;
localparam integer WB_AW = 16;
@ -304,7 +311,56 @@ module top (
);
// ISO7816 UART [4]
// USB [4&5]
// ---
`ifdef WITH_USB
// Signals
wire clk_usb;
// Core
soc_usb usb_I (
.usb_dp (usb_dp),
.usb_dn (usb_dn),
.usb_pu (usb_pu),
.wb_addr (wb_addr[11:0]),
.wb_rdata (wb_rdata[4]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[5:4]),
.wb_ack (wb_ack[5:4]),
.usb_sof (),
.clk_sys (clk_sys),
.clk_48m (clk_usb),
.rst (rst)
);
assign wb_rdata[5] = 32'h00000000;
// Use HF OSC for 48 MHz
SB_HFOSC #(
.TRIM_EN ("0b0"),
.CLKHF_DIV ("0b00") // 48 MHz
) osc_I (
.CLKHFPU (1'b1),
.CLKHFEN (1'b1),
.CLKHF (clk_usb)
);
`else
// Dummy
assign wb_ack[4] = 1'b0;
assign wb_rdata[4] = 32'h00000000;
assign wb_ack[5] = 1'b0;
assign wb_rdata[5] = 32'h00000000;
`endif
// ISO7816 UART [6]
// ------------
// Core
@ -316,12 +372,12 @@ module top (
.io_i (sc_io_i[i]),
.io_o (sc_io_o[i]),
.io_oe (sc_io_oe[i]),
.wb_addr (wb_addr[4:0]),
.wb_rdata (wb_rdata[4+i]),
.wb_addr (wb_addr[6:0]),
.wb_rdata (wb_rdata[6+i]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[4+i]),
.wb_ack (wb_ack[4+i]),
.wb_cyc (wb_cyc[6+i]),
.wb_ack (wb_ack[6+i]),
.clk (clk_sys),
.rst (rst)
);