gateware: Initial import of all common parts
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>changes/37/20537/1
parent
1599a58344
commit
21b03baf47
|
@ -0,0 +1,15 @@
|
|||
[submodule "gateware/build"]
|
||||
path = gateware/build
|
||||
url = https://github.com/no2fpga/no2build.git
|
||||
[submodule "gateware/cores/no2e1"]
|
||||
path = gateware/cores/no2e1
|
||||
url = https://github.com/no2fpga/no2e1.git
|
||||
[submodule "gateware/cores/no2ice40"]
|
||||
path = gateware/cores/no2ice40
|
||||
url = https://github.com/no2fpga/no2ice40.git
|
||||
[submodule "gateware/cores/no2misc"]
|
||||
path = gateware/cores/no2misc
|
||||
url = https://github.com/no2fpga/no2misc.git
|
||||
[submodule "gateware/cores/no2usb"]
|
||||
path = gateware/cores/no2usb
|
||||
url = https://github.com/no2fpga/no2usb.git
|
|
@ -0,0 +1,19 @@
|
|||
E1 related gateware
|
||||
===================
|
||||
|
||||
This directory contains the iCE40 gateware for various boards hosted
|
||||
in this repository.
|
||||
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
Most of the cores/HDL in here is licensed under one of the CERL OHL 2.0
|
||||
license. See the `doc/` subdirectory for the full license texts and refer
|
||||
to each file header to know the license applicable to each file.
|
||||
|
||||
Some files have been imported from other projects with compatible licenses.
|
||||
Refer to each file header for the proper copyright and license information.
|
||||
|
||||
The repository also includes submodules which have their own licensing
|
||||
and copyright terms.
|
|
@ -0,0 +1 @@
|
|||
Subproject commit e9d0d86baff55e1341ccd0ab510eb7e17f9c0fb7
|
|
@ -0,0 +1,3 @@
|
|||
*.elf
|
||||
*.bin
|
||||
*.hex
|
|
@ -0,0 +1,22 @@
|
|||
CROSS = riscv-none-embed-
|
||||
|
||||
CC := $(CROSS)gcc
|
||||
OBJCOPY := $(CROSS)objcopy
|
||||
|
||||
CFLAGS=-Wall -Os -march=rv32i -mabi=ilp32 -ffreestanding -flto -nostartfiles -fomit-frame-pointer -Wl,--gc-section
|
||||
|
||||
all: boot.hex
|
||||
|
||||
boot.elf: lnk-boot.lds boot.S
|
||||
$(CC) $(CFLAGS) -Wl,-Bstatic,-T,lnk-boot.lds,--strip-debug -DAPP_FLASH_ADDR=0x000a0000 -o $@ boot.S
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
%.hex: %.bin
|
||||
./bin2hex.py $< $@
|
||||
|
||||
clean:
|
||||
rm -f *.bin *.hex *.elf *.o
|
||||
|
||||
.PHONY: clean
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Converts binary into something that can be used by `readmemh`
|
||||
#
|
||||
# Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
def main(argv0, in_name, out_name):
|
||||
with open(in_name, 'rb') as in_fh, open(out_name, 'w') as out_fh:
|
||||
while True:
|
||||
b = in_fh.read(4)
|
||||
if len(b) < 4:
|
||||
break
|
||||
out_fh.write('%08x\n' % struct.unpack('<I', b))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(*sys.argv)
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* boot.S
|
||||
*
|
||||
* SPI boot code
|
||||
*
|
||||
* Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef APP_FLASH_ADDR
|
||||
#define APP_FLASH_ADDR 0x00100000
|
||||
#endif
|
||||
|
||||
#ifndef APP_SRAM_ADDR
|
||||
#define APP_SRAM_ADDR 0x00020000
|
||||
#endif
|
||||
|
||||
#ifndef APP_SIZE
|
||||
#define APP_SIZE 0x00010000
|
||||
#endif
|
||||
|
||||
.section .text.start
|
||||
.global _start
|
||||
_start:
|
||||
// SPI init
|
||||
jal spi_init
|
||||
|
||||
// Read from flash to SRAM
|
||||
li a0, APP_SRAM_ADDR
|
||||
li a1, APP_SIZE
|
||||
li a2, APP_FLASH_ADDR
|
||||
jal spi_flash_read
|
||||
|
||||
// Setup reboot code
|
||||
li t0, 0x0002006f
|
||||
sw t0, 0(zero)
|
||||
|
||||
// Jump to main code
|
||||
j APP_SRAM_ADDR
|
||||
|
||||
|
||||
.equ SPI_BASE, 0x80000000
|
||||
.equ SPICR0, 4 * 0x08
|
||||
.equ SPICR1, 4 * 0x09
|
||||
.equ SPICR2, 4 * 0x0a
|
||||
.equ SPIBR, 4 * 0x0b
|
||||
.equ SPISR, 4 * 0x0c
|
||||
.equ SPITXDR, 4 * 0x0d
|
||||
.equ SPIRXDR, 4 * 0x0e
|
||||
.equ SPICSR, 4 * 0x0f
|
||||
|
||||
|
||||
spi_init:
|
||||
li a0, SPI_BASE
|
||||
|
||||
li a1, 0xff
|
||||
sw a1, SPICR0(a0)
|
||||
|
||||
li a1, 0x80
|
||||
sw a1, SPICR1(a0)
|
||||
|
||||
li a1, 0xc0
|
||||
sw a1, SPICR2(a0)
|
||||
|
||||
li a1, 0x03
|
||||
sw a1, SPIBR(a0)
|
||||
|
||||
li a1, 0x0f
|
||||
sw a1, SPICSR(a0)
|
||||
|
||||
ret
|
||||
|
||||
|
||||
// Params:
|
||||
// a0 - destination pointer
|
||||
// a1 - length (bytes)
|
||||
// a2 - flash offset
|
||||
//
|
||||
|
||||
spi_flash_read:
|
||||
// Save params
|
||||
mv s0, a0
|
||||
mv s1, a1
|
||||
mv s2, ra
|
||||
|
||||
// Setup CS
|
||||
li t0, SPI_BASE
|
||||
li t1, 0x0e
|
||||
sw t1, SPICSR(t0)
|
||||
|
||||
// Send command
|
||||
li a0, 0x03
|
||||
jal _spi_do_one
|
||||
|
||||
srli a0, a2, 16
|
||||
and a0, a0, 0xff
|
||||
jal _spi_do_one
|
||||
|
||||
srli a0, a2, 8
|
||||
and a0, a0, 0xff
|
||||
jal _spi_do_one
|
||||
|
||||
and a0, a2, 0xff
|
||||
jal _spi_do_one
|
||||
|
||||
// Read loop
|
||||
_spi_loop:
|
||||
li a0, 0x00
|
||||
jal _spi_do_one
|
||||
sb a0, 0(s0)
|
||||
addi s0, s0, 1
|
||||
addi s1, s1, -1
|
||||
bne s1, zero, _spi_loop
|
||||
|
||||
// Release CS
|
||||
li t0, SPI_BASE
|
||||
li t1, 0x0f
|
||||
sw t1, SPICSR(t0)
|
||||
|
||||
// Done
|
||||
jr s2
|
||||
|
||||
|
||||
// Params: a0 - Data to TX
|
||||
// Returns: a0 - RX data
|
||||
// Clobbers t0, t1
|
||||
_spi_do_one:
|
||||
li t0, SPI_BASE
|
||||
li t1, 0x08
|
||||
|
||||
// Write TX data
|
||||
sw a0, SPITXDR(t0)
|
||||
|
||||
// Wait for RXRDY
|
||||
1:
|
||||
lw a0, SPISR(t0)
|
||||
and a0, a0, t1
|
||||
bne a0, t1, 1b
|
||||
|
||||
// Read RX data
|
||||
lw a0, SPIRXDR(t0)
|
||||
|
||||
// Done
|
||||
ret
|
|
@ -0,0 +1,14 @@
|
|||
MEMORY
|
||||
{
|
||||
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x0400
|
||||
}
|
||||
ENTRY(_start)
|
||||
SECTIONS {
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text.start)
|
||||
*(.text)
|
||||
*(.text*)
|
||||
} >ROM
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* dfu_helper.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 dfu_helper #(
|
||||
parameter integer TIMER_WIDTH = 24,
|
||||
parameter integer BTN_MODE = 3, // [2] Use btn_tick, [1] Include IO buffer, [0] Invert (active-low)
|
||||
parameter integer DFU_MODE = 0 // 0 = For user app, 1 = For bootloader
|
||||
)(
|
||||
// External control
|
||||
input wire [1:0] boot_sel,
|
||||
input wire boot_now,
|
||||
|
||||
// Button
|
||||
input wire btn_pad,
|
||||
input wire btn_tick,
|
||||
|
||||
// Outputs
|
||||
output wire btn_val,
|
||||
output reg rst_req,
|
||||
|
||||
// Clock
|
||||
input wire clk,
|
||||
input wire rst
|
||||
);
|
||||
|
||||
// Signals
|
||||
// -------
|
||||
|
||||
// Button
|
||||
wire btn_iob;
|
||||
wire btn_v;
|
||||
wire btn_r;
|
||||
wire btn_f;
|
||||
|
||||
// Timer and arming logic
|
||||
reg armed;
|
||||
reg [TIMER_WIDTH-1:0] timer;
|
||||
(* keep="true" *) wire timer_act;
|
||||
|
||||
// Boot logic
|
||||
reg [1:0] wb_sel;
|
||||
reg wb_req;
|
||||
reg wb_now;
|
||||
|
||||
|
||||
// Button logic
|
||||
// ------------
|
||||
|
||||
// IOB
|
||||
generate
|
||||
if (BTN_MODE[1])
|
||||
SB_IO #(
|
||||
.PIN_TYPE(6'b000000), // Reg input, no output
|
||||
.PULLUP(1'b1),
|
||||
.IO_STANDARD("SB_LVCMOS")
|
||||
) btn_iob_I (
|
||||
.PACKAGE_PIN(btn_pad),
|
||||
.INPUT_CLK (clk),
|
||||
.D_IN_0 (btn_iob)
|
||||
);
|
||||
else
|
||||
assign btn_iob = btn_pad;
|
||||
endgenerate
|
||||
|
||||
// Deglitch
|
||||
glitch_filter #(
|
||||
.L(BTN_MODE[2] ? 2 : 4),
|
||||
.RST_VAL(BTN_MODE[0]),
|
||||
.WITH_SYNCHRONIZER(1),
|
||||
.WITH_SAMP_COND(BTN_MODE[2])
|
||||
) btn_flt_I (
|
||||
.in (btn_iob ^ BTN_MODE[0]),
|
||||
.samp_cond(btn_tick),
|
||||
.val (btn_v),
|
||||
.rise (btn_r),
|
||||
.fall (btn_f),
|
||||
.clk (clk),
|
||||
`ifdef SIM
|
||||
.rst (rst)
|
||||
`else
|
||||
// Don't reset so we let the filter settle before
|
||||
// the rest of the logic engages
|
||||
.rst (1'b0)
|
||||
`endif
|
||||
);
|
||||
|
||||
assign btn_val = btn_v;
|
||||
|
||||
|
||||
// Arming & Timer
|
||||
// --------------
|
||||
|
||||
assign timer_act = btn_v ^ armed;
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
if (rst)
|
||||
armed <= 1'b0;
|
||||
else
|
||||
armed <= armed | timer[TIMER_WIDTH-2];
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
if (rst)
|
||||
timer <= 0;
|
||||
else
|
||||
timer <= timer_act ? { TIMER_WIDTH{1'b0} } : (timer + { { (TIMER_WIDTH-1){1'b0} }, ~timer[TIMER_WIDTH-1] });
|
||||
|
||||
|
||||
// Boot Logic
|
||||
// ----------
|
||||
|
||||
// Decision
|
||||
always @(posedge clk or posedge rst)
|
||||
if (rst) begin
|
||||
wb_sel <= 2'b00;
|
||||
wb_req <= 1'b0;
|
||||
rst_req <= 1'b0;
|
||||
end else if (~wb_req) begin
|
||||
if (boot_now) begin
|
||||
// External boot request
|
||||
wb_sel <= boot_sel;
|
||||
wb_req <= 1'b1;
|
||||
rst_req <= 1'b0;
|
||||
end else begin
|
||||
if (DFU_MODE == 1) begin
|
||||
// We're in a DFU bootloader, any button press results in
|
||||
// boot to application
|
||||
wb_sel <= 2'b10;
|
||||
wb_req <= wb_now | (armed & btn_f);
|
||||
rst_req <= 1'b0;
|
||||
end else begin
|
||||
// We're in user application, short press resets the
|
||||
// logic, long press triggers DFU reboot
|
||||
wb_sel <= 2'b01;
|
||||
wb_req <= wb_now | (armed & btn_f & timer[TIMER_WIDTH-1]);
|
||||
rst_req <= rst_req | (armed & btn_f & ~timer[TIMER_WIDTH-1]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Ensure select bits are set before the boot pulse
|
||||
always @(posedge clk or posedge rst)
|
||||
if (rst)
|
||||
wb_now <= 1'b0;
|
||||
else
|
||||
wb_now <= wb_req;
|
||||
|
||||
// IP core
|
||||
SB_WARMBOOT warmboot (
|
||||
.BOOT(wb_now),
|
||||
.S0(wb_sel[0]),
|
||||
.S1(wb_sel[1])
|
||||
);
|
||||
|
||||
endmodule // dfu_helper
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,544 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* soc_bram.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_bram #(
|
||||
parameter integer AW = 8,
|
||||
parameter INIT_FILE = ""
|
||||
)(
|
||||
input wire [AW-1:0] addr,
|
||||
output reg [31:0] rdata,
|
||||
input wire [31:0] wdata,
|
||||
input wire [ 3:0] wmsk,
|
||||
input wire we,
|
||||
input wire clk
|
||||
);
|
||||
|
||||
reg [31:0] mem [0:(1<<AW)-1];
|
||||
|
||||
initial
|
||||
if (INIT_FILE != "")
|
||||
$readmemh(INIT_FILE, mem);
|
||||
|
||||
always @(posedge clk) begin
|
||||
rdata <= mem[addr];
|
||||
if (we & ~wmsk[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
|
||||
if (we & ~wmsk[1]) mem[addr][15: 8] <= wdata[15: 8];
|
||||
if (we & ~wmsk[2]) mem[addr][23:16] <= wdata[23:16];
|
||||
if (we & ~wmsk[3]) mem[addr][31:24] <= wdata[31:24];
|
||||
end
|
||||
|
||||
endmodule // soc_bram
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* soc_iobuf.v
|
||||
*
|
||||
* vim: ts=4 sw=4
|
||||
*
|
||||
* Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
|
||||
* 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
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* soc_picorv32_bridge.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_picorv32_bridge #(
|
||||
parameter integer WB_N = 8,
|
||||
parameter integer WB_DW = 32,
|
||||
parameter integer WB_AW = 16,
|
||||
parameter integer WB_AI = 2,
|
||||
parameter integer WB_REG = 0 // [0] = cyc / [1] = addr/wdata/wstrb / [2] = ack/rdata
|
||||
)(
|
||||
/* PicoRV32 bus */
|
||||
input wire [31:0] pb_addr,
|
||||
output wire [31:0] pb_rdata,
|
||||
input wire [31:0] pb_wdata,
|
||||
input wire [ 3:0] pb_wstrb,
|
||||
input wire pb_valid,
|
||||
output wire pb_ready,
|
||||
|
||||
/* BRAM */
|
||||
output wire [ 7:0] bram_addr,
|
||||
input wire [31:0] bram_rdata,
|
||||
output wire [31:0] bram_wdata,
|
||||
output wire [ 3:0] bram_wmsk,
|
||||
output wire bram_we,
|
||||
|
||||
/* SPRAM */
|
||||
output wire [14:0] spram_addr,
|
||||
input wire [31:0] spram_rdata,
|
||||
output wire [31:0] spram_wdata,
|
||||
output wire [ 3:0] spram_wmsk,
|
||||
output wire spram_we,
|
||||
|
||||
/* Wishbone buses */
|
||||
output wire [WB_AW-1:0] wb_addr,
|
||||
input wire [(WB_DW*WB_N)-1:0] wb_rdata,
|
||||
output wire [WB_DW-1:0] wb_wdata,
|
||||
output wire [(WB_DW/8)-1:0] wb_wmsk,
|
||||
output wire wb_we,
|
||||
output wire [WB_N-1:0] wb_cyc,
|
||||
input wire [WB_N-1:0] wb_ack,
|
||||
|
||||
/* Clock / Reset */
|
||||
input wire clk,
|
||||
input wire rst
|
||||
);
|
||||
|
||||
// Signals
|
||||
// -------
|
||||
|
||||
wire ram_sel;
|
||||
reg ram_rdy;
|
||||
wire [31:0] ram_rdata;
|
||||
|
||||
(* keep *) wire [WB_N-1:0] wb_match;
|
||||
(* keep *) wire wb_cyc_rst;
|
||||
|
||||
reg [31:0] wb_rdata_or;
|
||||
wire [31:0] wb_rdata_out;
|
||||
wire wb_rdy;
|
||||
|
||||
|
||||
// RAM access
|
||||
// ----------
|
||||
// BRAM : 0x00000000 -> 0x000003ff
|
||||
// SPRAM : 0x00020000 -> 0x0003ffff
|
||||
|
||||
assign bram_addr = pb_addr[ 9:2];
|
||||
assign spram_addr = pb_addr[16:2];
|
||||
|
||||
assign bram_wdata = pb_wdata;
|
||||
assign spram_wdata = pb_wdata;
|
||||
|
||||
assign bram_wmsk = ~pb_wstrb;
|
||||
assign spram_wmsk = ~pb_wstrb;
|
||||
|
||||
assign bram_we = pb_valid & ~pb_addr[31] & |pb_wstrb & ~pb_addr[17];
|
||||
assign spram_we = pb_valid & ~pb_addr[31] & |pb_wstrb & pb_addr[17];
|
||||
|
||||
assign ram_rdata = ~pb_addr[31] ? (pb_addr[17] ? spram_rdata : bram_rdata) : 32'h00000000;
|
||||
|
||||
assign ram_sel = pb_valid & ~pb_addr[31];
|
||||
|
||||
always @(posedge clk)
|
||||
ram_rdy <= ram_sel && ~ram_rdy;
|
||||
|
||||
|
||||
// Wishbone
|
||||
// --------
|
||||
// wb[x] = 0x8x000000 - 0x8xffffff
|
||||
|
||||
// Access Cycle
|
||||
genvar i;
|
||||
for (i=0; i<WB_N; i=i+1)
|
||||
assign wb_match[i] = (pb_addr[27:24] == i);
|
||||
|
||||
if (WB_REG & 1) begin
|
||||
// Register
|
||||
reg [WB_N-1:0] wb_cyc_reg;
|
||||
always @(posedge clk)
|
||||
if (wb_cyc_rst)
|
||||
wb_cyc_reg <= 0;
|
||||
else
|
||||
wb_cyc_reg <= wb_match & ~wb_ack;
|
||||
assign wb_cyc = wb_cyc_reg;
|
||||
end else begin
|
||||
// Direct connection
|
||||
assign wb_cyc = wb_cyc_rst ? { WB_N{1'b0} } : wb_match;
|
||||
end
|
||||
|
||||
// Addr / Write-Data / Write-Mask / Write-Enable
|
||||
if (WB_REG & 2) begin
|
||||
// Register
|
||||
reg [WB_AW-1:0] wb_addr_reg;
|
||||
reg [WB_DW-1:0] wb_wdata_reg;
|
||||
reg [(WB_DW/8)-1:0] wb_wmsk_reg;
|
||||
reg wb_we_reg;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
wb_addr_reg <= pb_addr[WB_AW+WB_AI-1:WB_AI];
|
||||
wb_wdata_reg <= pb_wdata[WB_DW-1:0];
|
||||
wb_wmsk_reg <= ~pb_wstrb[(WB_DW/8)-1:0];
|
||||
wb_we_reg <= |pb_wstrb;
|
||||
end
|
||||
|
||||
assign wb_addr = wb_addr_reg;
|
||||
assign wb_wdata = wb_wdata_reg;
|
||||
assign wb_wmsk = wb_wmsk_reg;
|
||||
assign wb_we = wb_we_reg;
|
||||
end else begin
|
||||
// Direct connection
|
||||
assign wb_addr = pb_addr[WB_AW+WB_AI-1:WB_AI];
|
||||
assign wb_wdata = pb_wdata[WB_DW-1:0];
|
||||
assign wb_wmsk = pb_wstrb[(WB_DW/8)-1:0];
|
||||
assign wb_we = |pb_wstrb;
|
||||
end
|
||||
|
||||
// Ack / Read-Data
|
||||
always @(*)
|
||||
begin : wb_or
|
||||
integer i;
|
||||
wb_rdata_or = 0;
|
||||
for (i=0; i<WB_N; i=i+1)
|
||||
wb_rdata_or[WB_DW-1:0] = wb_rdata_or[WB_DW-1:0] | wb_rdata[WB_DW*i+:WB_DW];
|
||||
end
|
||||
|
||||
if (WB_REG & 4) begin
|
||||
// Register
|
||||
reg wb_rdy_reg;
|
||||
reg [31:0] wb_rdata_reg;
|
||||
|
||||
always @(posedge clk)
|
||||
wb_rdy_reg <= |wb_ack;
|
||||
|
||||
always @(posedge clk)
|
||||
if (wb_cyc_rst)
|
||||
wb_rdata_reg <= 32'h00000000;
|
||||
else
|
||||
wb_rdata_reg <= wb_rdata_or;
|
||||
|
||||
assign wb_cyc_rst = ~pb_valid | ~pb_addr[31] | wb_rdy_reg;
|
||||
assign wb_rdy = wb_rdy_reg;
|
||||
assign wb_rdata_out = wb_rdata_reg;
|
||||
end else begin
|
||||
// Direct connection
|
||||
assign wb_cyc_rst = ~pb_valid | ~pb_addr[31];
|
||||
assign wb_rdy = |wb_ack;
|
||||
assign wb_rdata_out = wb_rdata_or;
|
||||
end
|
||||
|
||||
|
||||
// Final data combining
|
||||
// --------------------
|
||||
|
||||
assign pb_rdata = ram_rdata | wb_rdata_out;
|
||||
assign pb_ready = ram_rdy | wb_rdy;
|
||||
|
||||
endmodule // soc_picorv32_bridge
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* soc_spram.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_spram #(
|
||||
parameter integer AW = 14
|
||||
)(
|
||||
input wire [AW-1:0] addr,
|
||||
output wire [31:0] rdata,
|
||||
input wire [31:0] wdata,
|
||||
input wire [ 3:0] wmsk,
|
||||
input wire we,
|
||||
input wire clk
|
||||
);
|
||||
|
||||
wire [7:0] msk_nibble = {
|
||||
wmsk[3], wmsk[3],
|
||||
wmsk[2], wmsk[2],
|
||||
wmsk[1], wmsk[1],
|
||||
wmsk[0], wmsk[0]
|
||||
};
|
||||
|
||||
ice40_spram_gen #(
|
||||
.ADDR_WIDTH(AW),
|
||||
.DATA_WIDTH(32)
|
||||
) spram_I (
|
||||
.addr(addr),
|
||||
.rd_data(rdata),
|
||||
.rd_ena(1'b1),
|
||||
.wr_data(wdata),
|
||||
.wr_mask(msk_nibble),
|
||||
.wr_ena(we),
|
||||
.clk(clk)
|
||||
);
|
||||
|
||||
endmodule // soc_spram
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* wb_arbiter.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 wb_arbiter #(
|
||||
parameter integer N = 3,
|
||||
parameter integer DW = 32,
|
||||
parameter integer AW = 16,
|
||||