Merge branch 'main' of github.com:rdolbeau/SBusFPGA into main
This commit is contained in:
@@ -298,32 +298,7 @@ sbusfpga_curve25519engine_attach(device_t parent, device_t self, void *aux)
|
||||
}
|
||||
|
||||
#define CONFIG_CSR_DATA_WIDTH 32
|
||||
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
|
||||
#define CSR_LEDS_BASE
|
||||
//#define CSR_CURVE25519ENGINE_BASE
|
||||
#define CSR_DDRPHY_BASE
|
||||
#define CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#define CSR_SBUS_BUS_STAT_BASE
|
||||
#define CSR_SDRAM_BASE
|
||||
#define CSR_SDBLOCK2MEM_BASE
|
||||
#define CSR_SDCORE_BASE
|
||||
#define CSR_SDIRQ_BASE
|
||||
#define CSR_SDMEM2BLOCK_BASE
|
||||
#define CSR_SDPHY_BASE
|
||||
#define CSR_TRNG_BASE
|
||||
#include "dev/sbus/litex_csr.h"
|
||||
#undef CSR_LEDS_BASE
|
||||
//#undef CSR_CURVE25519ENGINE_BASE
|
||||
#undef CSR_DDRPHY_BASE
|
||||
#undef CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#undef CSR_SBUS_BUS_STAT_BASE
|
||||
#undef CSR_SDRAM_BASE
|
||||
#undef CSR_SDBLOCK2MEM_BASE
|
||||
#undef CSR_SDCORE_BASE
|
||||
#undef CSR_SDIRQ_BASE
|
||||
#undef CSR_SDMEM2BLOCK_BASE
|
||||
#undef CSR_SDPHY_BASE
|
||||
#undef CSR_TRNG_BASE
|
||||
#include "dev/sbus/sbusfpga_csr_curve25519engine.h"
|
||||
|
||||
#define REG_BASE(reg) (base + (reg * 32))
|
||||
#define SUBREG_ADDR(reg, off) (REG_BASE(reg) + (off)*4)
|
||||
|
||||
@@ -198,6 +198,22 @@ dma_init(struct sbusfpga_sdram_softc *sc);
|
||||
int
|
||||
dma_memtest(struct sbusfpga_sdram_softc *sc);
|
||||
|
||||
int
|
||||
init_last_blocks(struct sbusfpga_sdram_softc *sc);
|
||||
int
|
||||
init_last_blocks(struct sbusfpga_sdram_softc *sc) {
|
||||
u_int32_t data[512];
|
||||
u_int32_t i;
|
||||
int res = 0;
|
||||
for (i = 0 ; i < 512 ; i++) {
|
||||
data[i] = 0x00FF00FF;
|
||||
}
|
||||
for (i = 254*1024*2 ; i < 256*1024*2 && !res; i+=4) {
|
||||
res = sbusfpga_sdram_write_block(sc, i, 4, data);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find
|
||||
*/
|
||||
@@ -306,12 +322,15 @@ sbusfpga_sdram_attach(device_t parent, device_t self, void *aux)
|
||||
sc->sc_bustag,
|
||||
sc->sc_burst,
|
||||
sbsc->sc_burst);
|
||||
|
||||
|
||||
// the controller is now initialized in the PROM from values computed by sdram_init()
|
||||
// if the board isn't a ZTex 2.13a, new bitslip/delays value might be needed
|
||||
/*
|
||||
if (!sdram_init(sc)) {
|
||||
aprint_error_dev(self, "couldn't initialize SDRAM\n");
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
if (!dma_init(sc)) {
|
||||
aprint_error_dev(self, "couldn't initialize DMA for SDRAM\n");
|
||||
return;
|
||||
@@ -363,6 +382,11 @@ sbusfpga_sdram_attach(device_t parent, device_t self, void *aux)
|
||||
lp->d_checksum = dkcksum(lp);
|
||||
}
|
||||
|
||||
/*
|
||||
// initialize some blocks were the FB lives to test the output
|
||||
init_last_blocks(sc);
|
||||
*/
|
||||
|
||||
/*
|
||||
aprint_normal_dev(self, "sc->dk.sc_dkdev.dk_blkshift = %d\n", sc->dk.sc_dkdev.dk_blkshift);
|
||||
aprint_normal_dev(self, "sc->dk.sc_dkdev.dk_byteshift = %d\n", sc->dk.sc_dkdev.dk_byteshift);
|
||||
@@ -540,37 +564,12 @@ sbusfpga_sdram_diskstart(device_t self, struct buf *bp)
|
||||
|
||||
|
||||
#define CONFIG_CSR_DATA_WIDTH 32
|
||||
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
|
||||
#define CSR_LEDS_BASE
|
||||
#define CSR_CURVE25519ENGINE_BASE
|
||||
//#define CSR_DDRPHY_BASE
|
||||
//#define CSR_SDRAM_BASE
|
||||
//#define CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#define CSR_SBUS_BUS_STAT_BASE
|
||||
#define CSR_SDBLOCK2MEM_BASE
|
||||
#define CSR_SDCORE_BASE
|
||||
#define CSR_SDIRQ_BASE
|
||||
#define CSR_SDMEM2BLOCK_BASE
|
||||
#define CSR_SDPHY_BASE
|
||||
#define CSR_TRNG_BASE
|
||||
|
||||
/* grrr */
|
||||
#define sbusfpga_exchange_with_mem_softc sbusfpga_sdram_softc
|
||||
#define sbusfpga_ddrphy_softc sbusfpga_sdram_softc
|
||||
|
||||
#include "dev/sbus/litex_csr.h"
|
||||
#undef CSR_LEDS_BASE
|
||||
#undef CSR_CURVE25519ENGINE_BASE
|
||||
//#undef CSR_DDRPHY_BASE
|
||||
//#undef CSR_SDRAM_BASE
|
||||
//#undef CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#undef CSR_SBUS_BUS_STAT_BASE
|
||||
#undef CSR_SDBLOCK2MEM_BASE
|
||||
#undef CSR_SDCORE_BASE
|
||||
#undef CSR_SDIRQ_BASE
|
||||
#undef CSR_SDMEM2BLOCK_BASE
|
||||
#undef CSR_SDPHY_BASE
|
||||
#undef CSR_TRNG_BASE
|
||||
#include "dev/sbus/sbusfpga_csr_exchange_with_mem.h"
|
||||
#include "dev/sbus/sbusfpga_csr_ddrphy.h"
|
||||
#include "dev/sbus/sbusfpga_csr_sdram.h"
|
||||
|
||||
/* not yet generated */
|
||||
static inline void exchange_with_mem_checksum_read(struct sbusfpga_sdram_softc *sc, uint32_t* data) {
|
||||
|
||||
@@ -106,33 +106,7 @@ sbusfpga_stat_match(device_t parent, cfdata_t cf, void *aux)
|
||||
}
|
||||
|
||||
#define CONFIG_CSR_DATA_WIDTH 32
|
||||
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
|
||||
#define CSR_LEDS_BASE
|
||||
#define CSR_CURVE25519ENGINE_BASE
|
||||
#define CSR_DDRPHY_BASE
|
||||
#define CSR_EXCHANGE_WITH_MEM_BASE
|
||||
// #define CSR_SBUS_BUS_STAT_BASE
|
||||
#define CSR_SDRAM_BASE
|
||||
#define CSR_SDBLOCK2MEM_BASE
|
||||
#define CSR_SDCORE_BASE
|
||||
#define CSR_SDIRQ_BASE
|
||||
#define CSR_SDMEM2BLOCK_BASE
|
||||
#define CSR_SDPHY_BASE
|
||||
#define CSR_TRNG_BASE
|
||||
#include "dev/sbus/litex_csr.h"
|
||||
#undef CSR_LEDS_BASE
|
||||
#undef CSR_CURVE25519ENGINE_BASE
|
||||
#undef CSR_DDRPHY_BASE
|
||||
#undef CSR_EXCHANGE_WITH_MEM_BASE
|
||||
// #undef CSR_SBUS_BUS_STAT_BASE
|
||||
#undef CSR_SDRAM_BASE
|
||||
#undef CSR_SDBLOCK2MEM_BASE
|
||||
#undef CSR_SDCORE_BASE
|
||||
#undef CSR_SDIRQ_BASE
|
||||
#undef CSR_SDMEM2BLOCK_BASE
|
||||
#undef CSR_SDPHY_BASE
|
||||
//#undef CSR_TRNG_BASE
|
||||
|
||||
#include "dev/sbus/sbusfpga_csr_sbus_bus_stat.h"
|
||||
|
||||
static void sbusfpga_stat_display(void *);
|
||||
|
||||
|
||||
@@ -107,32 +107,7 @@ sbusfpga_trng_match(device_t parent, cfdata_t cf, void *aux)
|
||||
}
|
||||
|
||||
#define CONFIG_CSR_DATA_WIDTH 32
|
||||
// define CSR_LEDS_BASE & others to avoid defining the CSRs of HW we don't handle
|
||||
#define CSR_LEDS_BASE
|
||||
#define CSR_CURVE25519ENGINE_BASE
|
||||
#define CSR_DDRPHY_BASE
|
||||
#define CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#define CSR_SBUS_BUS_STAT_BASE
|
||||
#define CSR_SDRAM_BASE
|
||||
#define CSR_SDBLOCK2MEM_BASE
|
||||
#define CSR_SDCORE_BASE
|
||||
#define CSR_SDIRQ_BASE
|
||||
#define CSR_SDMEM2BLOCK_BASE
|
||||
#define CSR_SDPHY_BASE
|
||||
//#define CSR_TRNG_BASE
|
||||
#include "dev/sbus/litex_csr.h"
|
||||
#undef CSR_LEDS_BASE
|
||||
#undef CSR_CURVE25519ENGINE_BASE
|
||||
#undef CSR_DDRPHY_BASE
|
||||
#undef CSR_EXCHANGE_WITH_MEM_BASE
|
||||
#undef CSR_SBUS_BUS_STAT_BASE
|
||||
#undef CSR_SDRAM_BASE
|
||||
#undef CSR_SDBLOCK2MEM_BASE
|
||||
#undef CSR_SDCORE_BASE
|
||||
#undef CSR_SDIRQ_BASE
|
||||
#undef CSR_SDMEM2BLOCK_BASE
|
||||
#undef CSR_SDPHY_BASE
|
||||
//#undef CSR_TRNG_BASE
|
||||
#include "dev/sbus/sbusfpga_csr_trng.h"
|
||||
|
||||
static void
|
||||
sbusfpga_trng_getentropy(size_t nbytes, void *cookie) {
|
||||
|
||||
131
sbus-to-ztex-gateware-migen/cg3.fth
Normal file
131
sbus-to-ztex-gateware-migen/cg3.fth
Normal file
@@ -0,0 +1,131 @@
|
||||
\ simplified version of the OpenBIOS cgthree code
|
||||
|
||||
: openbios-video-width
|
||||
h# SBUSFPGA_CG3_WIDTH
|
||||
;
|
||||
|
||||
: openbios-video-height
|
||||
h# SBUSFPGA_CG3_HEIGHT
|
||||
;
|
||||
|
||||
: depth-bits
|
||||
h# 8
|
||||
;
|
||||
|
||||
: line-bytes
|
||||
h# SBUSFPGA_CG3_WIDTH
|
||||
;
|
||||
|
||||
h# 400000 constant cg3-off-dac
|
||||
h# 20 constant /cg3-off-dac
|
||||
|
||||
h# 800000 constant cg3-off-fb
|
||||
h# SBUSFPGA_CG3_BUFSIZE constant /cg3-off-fb
|
||||
|
||||
: >cg3-reg-spec ( offset size -- encoded-reg )
|
||||
>r 0 my-address d+ my-space encode-phys r> encode-int encode+
|
||||
;
|
||||
|
||||
: cg3-reg
|
||||
\ A real cg3 rom appears to just map the entire region with a
|
||||
\ single entry
|
||||
h# 0 h# 1000000 >cg3-reg-spec
|
||||
" reg" property
|
||||
;
|
||||
|
||||
: do-map-in ( offset size -- virt )
|
||||
>r my-space r> " map-in" $call-parent
|
||||
;
|
||||
|
||||
: do-map-out ( virt size )
|
||||
" map-out" $call-parent
|
||||
;
|
||||
|
||||
\
|
||||
\ DAC
|
||||
\
|
||||
|
||||
-1 value cg3-dac
|
||||
-1 value fb-addr
|
||||
|
||||
: dac! ( data reg# -- )
|
||||
cg3-dac + c!
|
||||
;
|
||||
|
||||
external
|
||||
|
||||
: color! ( r g b c# -- )
|
||||
0 dac! ( r g b )
|
||||
swap rot ( b g r )
|
||||
4 dac! ( b g )
|
||||
4 dac! ( b )
|
||||
4 dac! ( )
|
||||
;
|
||||
|
||||
headerless
|
||||
|
||||
\
|
||||
\ Mapping
|
||||
\
|
||||
|
||||
: dac-map
|
||||
cg3-off-dac /cg3-off-dac do-map-in to cg3-dac
|
||||
;
|
||||
|
||||
: fb-map
|
||||
cg3-off-fb /cg3-off-fb do-map-in to fb-addr
|
||||
;
|
||||
|
||||
: map-regs
|
||||
dac-map fb-map
|
||||
;
|
||||
|
||||
\
|
||||
\ Installation
|
||||
\
|
||||
|
||||
" cgthree" device-name
|
||||
" display" device-type
|
||||
" SUNW,501-1415" model
|
||||
|
||||
: qemu-cg3-driver-install ( -- )
|
||||
cg3-dac -1 = if
|
||||
map-regs
|
||||
|
||||
\ Initial pallette taken from Sun's "Writing FCode Programs"
|
||||
h# ff h# ff h# ff h# 0 color! \ Background white
|
||||
h# 0 h# 0 h# 0 h# ff color! \ Foreground black
|
||||
h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo
|
||||
|
||||
fb-addr to frame-buffer-adr
|
||||
default-font set-font
|
||||
|
||||
frame-buffer-adr encode-int " address" property
|
||||
|
||||
openbios-video-width openbios-video-height over char-width / over char-height /
|
||||
fb8-install
|
||||
then
|
||||
;
|
||||
|
||||
: qemu-cg3-driver-init
|
||||
|
||||
cg3-reg
|
||||
|
||||
openbios-video-height encode-int " height" property
|
||||
openbios-video-width encode-int " width" property
|
||||
line-bytes encode-int " linebytes" property
|
||||
|
||||
h# 39 encode-int 0 encode-int encode+ " intr" property
|
||||
|
||||
\ Monitor sense. Some searching suggests that this is
|
||||
\ 5 for 1024x768 and 7 for 1152x900
|
||||
h# 5 encode-int " monitor-sense" property
|
||||
|
||||
" RDOL" encode-string " manufacturer" property
|
||||
" ISO8859-1" encode-string " character-set" property
|
||||
h# c encode-int " cursorshift" property
|
||||
|
||||
['] qemu-cg3-driver-install is-install
|
||||
;
|
||||
|
||||
qemu-cg3-driver-init
|
||||
320
sbus-to-ztex-gateware-migen/cg3_fb.py
Normal file
320
sbus-to-ztex-gateware-migen/cg3_fb.py
Normal file
@@ -0,0 +1,320 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
|
||||
from litex.soc.interconnect.csr import *
|
||||
from litex.soc.interconnect import stream
|
||||
from litex.soc.interconnect import wishbone
|
||||
from litex.soc.cores.code_tmds import TMDSEncoder
|
||||
|
||||
from litex.build.io import SDROutput, DDROutput
|
||||
|
||||
from litex.soc.cores.video import *
|
||||
|
||||
from math import ceil;
|
||||
|
||||
# " 108000000,71808,76,32,128,192,1152,2,8,33,900,COLOR,0OFFSET"
|
||||
cg3_timings = {
|
||||
"1152x900@76Hz": {
|
||||
"pix_clk" : 108e6,
|
||||
"h_active" : 1152,
|
||||
"h_blanking" : 352,
|
||||
"h_sync_offset" : 32,
|
||||
"h_sync_width" : 128,
|
||||
"v_active" : 900,
|
||||
"v_blanking" : 43,
|
||||
"v_sync_offset" : 2,
|
||||
"v_sync_width" : 8,
|
||||
},
|
||||
}
|
||||
|
||||
def cg3_rounded_size(hres, vres):
|
||||
return int(1048576 * ceil(((hres * vres) + 262144) / 1048576))
|
||||
|
||||
class VideoFrameBuffer256c(Module, AutoCSR):
|
||||
"""Video FrameBuffer256c"""
|
||||
def __init__(self, dram_port, upd_clut_fifo = None, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False):
|
||||
clut = Array(Array(Signal(8, reset = (255-i)) for i in range(0, 256)) for j in range(0, 3))
|
||||
|
||||
print(f"FRAMEBUFFER: dram_port.data_width = {dram_port.data_width}, {hres}x{vres}, 0x{base:x}, in {clock_domain}, clock_faster_than_sys={clock_faster_than_sys}")
|
||||
|
||||
vga_sync = getattr(self.sync, clock_domain)
|
||||
vga_sync += [
|
||||
If(upd_clut_fifo.readable,
|
||||
upd_clut_fifo.re.eq(1),
|
||||
clut[upd_clut_fifo.dout[0:2]][upd_clut_fifo.dout[2:10]].eq(upd_clut_fifo.dout[10:18]),
|
||||
).Else(
|
||||
upd_clut_fifo.re.eq(0),
|
||||
)
|
||||
]
|
||||
|
||||
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
||||
self.source = source = stream.Endpoint(video_data_layout)
|
||||
self.underflow = Signal()
|
||||
|
||||
# # #
|
||||
|
||||
# Video DMA.
|
||||
from litedram.frontend.dma import LiteDRAMDMAReader
|
||||
self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
|
||||
self.dma.add_csr(
|
||||
default_base = base,
|
||||
default_length = hres*vres*8//8, # 8-bit PseudoColor
|
||||
default_enable = 0,
|
||||
default_loop = 1
|
||||
)
|
||||
|
||||
# If DRAM Data Width > 8-bit and Video clock is faster than sys_clk:
|
||||
if (dram_port.data_width > 8) and clock_faster_than_sys:
|
||||
# Do Clock Domain Crossing first...
|
||||
self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
|
||||
self.comb += self.dma.source.connect(self.cdc.sink)
|
||||
# ... and then Data-Width Conversion.
|
||||
self.submodules.conv = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 8))
|
||||
self.comb += self.cdc.source.connect(self.conv.sink)
|
||||
video_pipe_source = self.conv.source
|
||||
# Elsif DRAM Data Widt < 8-bit or Video clock is slower than sys_clk:
|
||||
else:
|
||||
# Do Data-Width Conversion first...
|
||||
self.submodules.conv = stream.Converter(dram_port.data_width, 8)
|
||||
self.comb += self.dma.source.connect(self.conv.sink)
|
||||
# ... and then Clock Domain Crossing.
|
||||
self.submodules.cdc = stream.ClockDomainCrossing([("data", 8)], cd_from="sys", cd_to=clock_domain)
|
||||
self.comb += self.conv.source.connect(self.cdc.sink)
|
||||
video_pipe_source = self.cdc.source
|
||||
|
||||
#counter = Signal(11)
|
||||
#vga_sync += If(vtg_sink.de,
|
||||
# If(counter == (hres-1),
|
||||
# counter.eq(0)
|
||||
# ).Else(
|
||||
# counter.eq(counter + 1))).Else(
|
||||
# counter.eq(0))
|
||||
|
||||
# Video Generation.
|
||||
self.comb += [
|
||||
#vtg_sink.ready.eq(1),
|
||||
#vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
|
||||
#If(vtg_sink.de,
|
||||
# source.r.eq(Cat(Signal(6, reset = 0), counter[2:4])),
|
||||
# source.g.eq(Cat(Signal(6, reset = 0), counter[4:6])),
|
||||
# source.b.eq(Cat(Signal(6, reset = 0), counter[6:8])),
|
||||
#).Else(source.r.eq(0),
|
||||
# source.g.eq(0),
|
||||
# source.b.eq(0),)
|
||||
vtg_sink.ready.eq(1),
|
||||
If(vtg_sink.valid & vtg_sink.de,
|
||||
video_pipe_source.connect(source, keep={"valid", "ready"}),
|
||||
vtg_sink.ready.eq(source.valid & source.ready),
|
||||
),
|
||||
vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
|
||||
If(vtg_sink.de,
|
||||
source.r.eq(clut[0][video_pipe_source.data]),
|
||||
source.g.eq(clut[1][video_pipe_source.data]),
|
||||
source.b.eq(clut[2][video_pipe_source.data])
|
||||
#source.r.eq(video_pipe_source.data),
|
||||
#source.g.eq(video_pipe_source.data),
|
||||
#source.b.eq(video_pipe_source.data),
|
||||
).Else(
|
||||
source.r.eq(0),
|
||||
source.g.eq(0),
|
||||
source.b.eq(0)
|
||||
)
|
||||
]
|
||||
|
||||
# Underflow.
|
||||
self.comb += self.underflow.eq(~source.valid)
|
||||
|
||||
|
||||
class cg3(Module, AutoCSR):
|
||||
def __init__(self, soc, phy=None, timings = None, clock_domain="sys"):
|
||||
|
||||
# 2 bits for color (0/r, 1/g, 2/b), 8 for @ and 8 for value
|
||||
self.submodules.upd_cmap_fifo = upd_cmap_fifo = ClockDomainsRenamer({"read": "vga", "write": "sys"})(AsyncFIFOBuffered(width=2+8+8, depth=8))
|
||||
|
||||
name = "video_framebuffer"
|
||||
# near duplicate of plaform.add_video_framebuffer
|
||||
# Video Timing Generator.
|
||||
vtg = VideoTimingGenerator(default_video_timings=timings if isinstance(timings, str) else timings[1])
|
||||
vtg = ClockDomainsRenamer(clock_domain)(vtg)
|
||||
setattr(self.submodules, f"{name}_vtg", vtg)
|
||||
|
||||
# Video FrameBuffer.
|
||||
timings = timings if isinstance(timings, str) else timings[0]
|
||||
base = soc.mem_map.get(name)
|
||||
print(f"CG3: visible memory at {base:x}")
|
||||
hres = int(timings.split("@")[0].split("x")[0])
|
||||
vres = int(timings.split("@")[0].split("x")[1])
|
||||
freq = vtg.video_timings["pix_clk"]
|
||||
print(f"CG3: using {hres} x {vres}, {freq/1e6} MHz pixclk")
|
||||
vfb = VideoFrameBuffer256c(dram_port = soc.sdram.crossbar.get_port(),
|
||||
upd_clut_fifo = upd_cmap_fifo,
|
||||
hres = hres,
|
||||
vres = vres,
|
||||
base = base,
|
||||
clock_domain = clock_domain,
|
||||
clock_faster_than_sys = (vtg.video_timings["pix_clk"] > soc.sys_clk_freq))
|
||||
setattr(self.submodules, name, vfb)
|
||||
|
||||
# Connect Video Timing Generator to Video FrameBuffer.
|
||||
self.comb += vtg.source.connect(vfb.vtg_sink)
|
||||
|
||||
# Connect Video FrameBuffer to Video PHY.
|
||||
self.comb += vfb.source.connect(phy if isinstance(phy, stream.Endpoint) else phy.sink)
|
||||
|
||||
# Constants.
|
||||
soc.add_constant("VIDEO_FRAMEBUFFER_BASE", base)
|
||||
soc.add_constant("VIDEO_FRAMEBUFFER_HRES", hres)
|
||||
soc.add_constant("VIDEO_FRAMEBUFFER_VRES", vres)
|
||||
|
||||
# cg3 registers
|
||||
# struct bt_regs {
|
||||
# u_int bt_addr; /* map address register */
|
||||
# u_int bt_cmap; /* colormap data register */
|
||||
# u_int bt_ctrl; /* control register */
|
||||
# u_int bt_omap; /* overlay (cursor) map register */
|
||||
# };
|
||||
# /*
|
||||
# * Sbus framebuffer control look like this (usually at offset 0x400000).
|
||||
# */
|
||||
# struct fbcontrol {
|
||||
# struct bt_regs fbc_dac;
|
||||
# u_char fbc_ctrl;
|
||||
# u_char fbc_status;
|
||||
# u_char fbc_cursor_start;
|
||||
# u_char fbc_cursor_end;
|
||||
# u_char fbc_vcontrol[12]; /* 12 bytes of video timing goo */
|
||||
# };
|
||||
|
||||
self.bus = bus = wishbone.Interface()
|
||||
|
||||
bt_cmap_idx = Signal(8)
|
||||
bt_cmap_state = Signal(2)
|
||||
bt_cmap_buf = Signal(24)
|
||||
|
||||
fbc_ctrl = Signal(8) # 0x10 ?
|
||||
fbc_status = Signal(8, reset = 0x61) # 1152x900 color # 0x11 ?
|
||||
fbc_cursor_start = Signal(8) # 0x12 ?
|
||||
fbc_cursor_end = Signal(8) # 0x13 ?
|
||||
fbc_vcontrol = Array(Signal(8) for a in range(0, 3))
|
||||
|
||||
# current cmap logic for the CG3.
|
||||
# the CG6 takes 32 bits write but only use the top 8 bits, for bt_addr & bt_cmap
|
||||
# alto it uses the BT HW cursor (though probably not in the console?)
|
||||
|
||||
self.submodules.wishbone_fsm = wishbone_fsm = FSM(reset_state = "Reset")
|
||||
wishbone_fsm.act("Reset",
|
||||
NextState("Idle"))
|
||||
wishbone_fsm.act("Idle",
|
||||
If(bus.cyc & bus.stb & bus.we & upd_cmap_fifo.writable, #write
|
||||
# FIXME: should check for prefix?
|
||||
Case(bus.adr[0:3], {
|
||||
# bt_addr
|
||||
0: [ NextValue(bt_cmap_idx, bus.dat_w[0:8]),
|
||||
NextValue(bt_cmap_state, 0),
|
||||
],
|
||||
# bt_cmap
|
||||
1: [ Case(bus.sel, {
|
||||
"default": [ NextValue(bt_cmap_buf, bus.dat_w[0:24]),
|
||||
upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bus.dat_w[24:32])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
NextState("cmap_a"),
|
||||
],
|
||||
# will sel be 1 or 8 ?
|
||||
1: [ upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bus.dat_w[24:32])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
})
|
||||
],
|
||||
8: [ upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bus.dat_w[24:32])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
})
|
||||
],
|
||||
})],
|
||||
# bt_ctrl: unused ??
|
||||
2: [],
|
||||
# bt_omap: unused ??
|
||||
3: [],
|
||||
# fbc_ctrl & friends: 4 in one go
|
||||
# should be byte-accessed
|
||||
# CHECKME: byte ordering
|
||||
4: [ Case(bus.sel, {
|
||||
8: [ NextValue(fbc_ctrl, bus.dat_w[24:32]),],
|
||||
4: [ NextValue(fbc_status, fbc_status & 0x7F),], #FIXME: if high bit set, cancel interrupt
|
||||
2: [ NextValue(fbc_cursor_start, bus.dat_w[24:32]),],
|
||||
1: [ NextValue(fbc_cursor_end, bus.dat_w[24:32]),],
|
||||
}),
|
||||
],
|
||||
5: [NextValue(fbc_vcontrol[0], (bus.dat_w & Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8))) | (fbc_vcontrol[0] & ~Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8)))) ],
|
||||
6: [NextValue(fbc_vcontrol[1], (bus.dat_w & Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8))) | (fbc_vcontrol[1] & ~Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8)))) ],
|
||||
7: [NextValue(fbc_vcontrol[2], (bus.dat_w & Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8))) | (fbc_vcontrol[2] & ~Cat(Replicate(bus.sel[3], 8), Replicate(bus.sel[2], 8), Replicate(bus.sel[1], 8), Replicate(bus.sel[0], 8)))) ],
|
||||
}),
|
||||
bus.ack.eq(1),
|
||||
).Elif(bus.cyc & bus.stb & ~bus.we, #read
|
||||
Case(bus.adr[0:3], {
|
||||
# bt_addr
|
||||
0: [ bus.dat_r.eq(0), ],
|
||||
# bt_cmap
|
||||
1: [ bus.dat_r.eq(0),],
|
||||
# bt_ctrl: unused ??
|
||||
2: [ bus.dat_r.eq(0),],
|
||||
# bt_omap: unused ??
|
||||
3: [ bus.dat_r.eq(0),],
|
||||
# fbc_ctrl & friends: 4 in one go
|
||||
# should be byte-accessed
|
||||
# CHECKME: byte ordering
|
||||
4: [ bus.dat_r.eq(Cat(fbc_cursor_end, fbc_cursor_start, fbc_status, fbc_ctrl))],
|
||||
5: [ bus.dat_r.eq(fbc_vcontrol[0]),],
|
||||
6: [ bus.dat_r.eq(fbc_vcontrol[1]),],
|
||||
7: [ bus.dat_r.eq(fbc_vcontrol[2]),],
|
||||
}),
|
||||
bus.ack.eq(1),
|
||||
))
|
||||
|
||||
wishbone_fsm.act("cmap_a",
|
||||
If(upd_cmap_fifo.writable,
|
||||
upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bt_cmap_buf[16:24])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
NextState("cmap_b")))
|
||||
wishbone_fsm.act("cmap_b",
|
||||
If(upd_cmap_fifo.writable,
|
||||
upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bt_cmap_buf[8:16])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
NextState("cmap_c")))
|
||||
wishbone_fsm.act("cmap_c",
|
||||
If(upd_cmap_fifo.writable,
|
||||
upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_cmap_idx, bt_cmap_buf[0:8])),
|
||||
Case(bt_cmap_state, {
|
||||
0: [ NextValue(bt_cmap_state, 1), ],
|
||||
1: [ NextValue(bt_cmap_state, 2), ],
|
||||
2: [ NextValue(bt_cmap_state, 0), NextValue(bt_cmap_idx, (bt_cmap_idx+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
NextState("Idle")))
|
||||
24
sbus-to-ztex-gateware-migen/cg3_init.fth
Normal file
24
sbus-to-ztex-gateware-migen/cg3_init.fth
Normal file
@@ -0,0 +1,24 @@
|
||||
: cg3_vid_fb_vtg_enable_rd ( -- csr_value)
|
||||
cg3-virt h# 0000 + l@
|
||||
;
|
||||
|
||||
: cg3_vid_fb_dma_enable_rd ( -- csr_value)
|
||||
cg3-virt h# 002c + l@
|
||||
;
|
||||
|
||||
: cg3_vid_fb_vtg_enable_wr ( value -- )
|
||||
cg3-virt h# 0000 + l!
|
||||
;
|
||||
|
||||
: cg3_vid_fb_dma_enable_wr ( value -- )
|
||||
cg3-virt h# 002c + l!
|
||||
;
|
||||
|
||||
: cg3_init!
|
||||
map-in-cg3extraregs
|
||||
0 cg3_vid_fb_vtg_enable_wr
|
||||
0 cg3_vid_fb_dma_enable_wr
|
||||
1 cg3_vid_fb_vtg_enable_wr
|
||||
1 cg3_vid_fb_dma_enable_wr
|
||||
map-out-cg3extraregs
|
||||
;
|
||||
@@ -797,8 +797,8 @@ Potential corner case
|
||||
There is a potential corner case where if the carry-propagated result going into
|
||||
"normalize" is between
|
||||
|
||||
0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFDA and
|
||||
0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFEC
|
||||
0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFDA and
|
||||
0x7FFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFEC
|
||||
|
||||
In this case, the top bit would be wrapped around, multiplied by 19, and added to
|
||||
the LSB, but the result would not be a member of $2^{{255}}-19$ (it would be one
|
||||
@@ -1434,7 +1434,7 @@ carries that have already been propagated. If we fail to do this, then we re-pro
|
||||
self.dsp_match3 &
|
||||
self.dsp_match2 &
|
||||
self.dsp_match1 &
|
||||
(self.dsp_p0 >= 0x1_ffed)
|
||||
(self.dsp_p0[:17] >= 0x1_ffed)
|
||||
)
|
||||
]
|
||||
|
||||
@@ -1606,151 +1606,78 @@ class ExecAES(ExecUnit, AutoDoc):
|
||||
seq.act("IDLE",
|
||||
If(start_pipe,
|
||||
# put the first byte in the lookup tables (LANE1)
|
||||
# [ NextValue(aes_in[i], self.a[32*i:32*i+8]) for i in range(0, 4) ],
|
||||
NextValue(aes_in[0], self.a[ 0: 8]),
|
||||
NextValue(aes_in[1], self.a[ 32: 40]),
|
||||
NextValue(aes_in[2], self.a[ 64: 72]),
|
||||
NextValue(aes_in[3], self.a[ 96:104]),
|
||||
[ NextValue(aes_in[i], self.a[(i*32):(i*32)+8]) for i in range(0, 4) ],
|
||||
NextState("LANE2_1")))
|
||||
seq.act("LANE2_1",
|
||||
# put the first byte in the lookup tables (LANE2)
|
||||
NextValue(aes_in[0], self.a[128:136]),
|
||||
NextValue(aes_in[1], self.a[160:168]),
|
||||
NextValue(aes_in[2], self.a[192:200]),
|
||||
NextValue(aes_in[3], self.a[224:232]),
|
||||
[ NextValue(aes_in[i], self.a[(i*32)+128:(i*32)+8+128]) for i in range(0, 4) ],
|
||||
NextState("LANE1_2"))
|
||||
seq.act("LANE1_2",
|
||||
# store the xor'ed result for LANE1, byte 1 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[ 0: 32], self.b[ 0: 32] ^ Cat(aes_out[0][ 0:16], aes_out[0][ 8:24])),
|
||||
NextValue(aes_buf[ 32: 64], self.b[ 32: 64] ^ Cat(aes_out[1][ 0:16], aes_out[1][ 8:24])),
|
||||
NextValue(aes_buf[ 64: 96], self.b[ 64: 96] ^ Cat(aes_out[2][ 0:16], aes_out[2][ 8:24])),
|
||||
NextValue(aes_buf[ 96:128], self.b[ 96:128] ^ Cat(aes_out[3][ 0:16], aes_out[3][ 8:24]))],
|
||||
1:[ NextValue(aes_buf[ 0: 32], self.b[ 0: 32] ^ Cat(aes_out[0][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[ 32: 64], self.b[ 32: 64] ^ Cat(aes_out[1][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[ 64: 96], self.b[ 64: 96] ^ Cat(aes_out[2][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[ 96:128], self.b[ 96:128] ^ Cat(aes_out[3][ 8:16], Signal(24, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32):(i*32)+32], self.b[(i*32):(i*32)+32] ^ Cat(aes_out[i][ 0:16], aes_out[i][ 8:24])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32):(i*32)+32], self.b[(i*32):(i*32)+32] ^ Cat(aes_out[i][ 8:16], Signal(24, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the second byte in the lookup tables (LANE1)
|
||||
NextValue(aes_in[3], self.a[ 8: 16]),
|
||||
NextValue(aes_in[0], self.a[ 40: 48]),
|
||||
NextValue(aes_in[1], self.a[ 72: 80]),
|
||||
NextValue(aes_in[2], self.a[104:112]),
|
||||
[ NextValue(aes_in[(i+3)%4], self.a[(i*32)+8:(i*32)+16]) for i in range(0, 4) ],
|
||||
NextState("LANE2_2"))
|
||||
seq.act("LANE2_2",
|
||||
# store the xor'ed result for LANE2, byte 1 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[128:160], self.b[128:160] ^ Cat(aes_out[0][ 0:16], aes_out[0][ 8:24])),
|
||||
NextValue(aes_buf[160:192], self.b[160:192] ^ Cat(aes_out[1][ 0:16], aes_out[1][ 8:24])),
|
||||
NextValue(aes_buf[192:224], self.b[192:224] ^ Cat(aes_out[2][ 0:16], aes_out[2][ 8:24])),
|
||||
NextValue(aes_buf[224:256], self.b[224:256] ^ Cat(aes_out[3][ 0:16], aes_out[3][ 8:24]))],
|
||||
1:[ NextValue(aes_buf[128:160], self.b[128:160] ^ Cat(aes_out[0][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[160:192], self.b[160:192] ^ Cat(aes_out[1][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[192:224], self.b[192:224] ^ Cat(aes_out[2][ 8:16], Signal(24, reset = 0))),
|
||||
NextValue(aes_buf[224:256], self.b[224:256] ^ Cat(aes_out[3][ 8:16], Signal(24, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], self.b[(i*32)+128:(i*32)+32+128] ^ Cat(aes_out[i][ 0:16], aes_out[i][ 8:24])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], self.b[(i*32)+128:(i*32)+32+128] ^ Cat(aes_out[i][ 8:16], Signal(24, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the second byte in the lookup tables (LANE2)
|
||||
NextValue(aes_in[3], self.a[136:144]),
|
||||
NextValue(aes_in[0], self.a[168:176]),
|
||||
NextValue(aes_in[1], self.a[200:208]),
|
||||
NextValue(aes_in[2], self.a[232:240]),
|
||||
[ NextValue(aes_in[(i+3)%4], self.a[(i*32)+8+128:(i*32)+16+128]) for i in range(0, 4) ],
|
||||
NextState("LANE1_3"))
|
||||
seq.act("LANE1_3",
|
||||
# store the xor'ed result for LANE1, byte 2 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(aes_out[0][16:24], aes_out[0][ 0:16], aes_out[0][ 8:16])),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(aes_out[1][16:24], aes_out[1][ 0:16], aes_out[1][ 8:16])),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(aes_out[2][16:24], aes_out[2][ 0:16], aes_out[2][ 8:16])),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(aes_out[3][16:24], aes_out[3][ 0:16], aes_out[3][ 8:16]))],
|
||||
1:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(Signal(8, reset = 0), aes_out[0][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(Signal(8, reset = 0), aes_out[1][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(Signal(8, reset = 0), aes_out[2][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(Signal(8, reset = 0), aes_out[3][ 8:16], Signal(16, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(aes_out[i][16:24], aes_out[i][ 0:16], aes_out[i][ 8:16])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(Signal(8, reset = 0), aes_out[i][ 8:16], Signal(16, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the third byte in the lookup tables (LANE1)
|
||||
NextValue(aes_in[2], self.a[ 16: 24]),
|
||||
NextValue(aes_in[3], self.a[ 48: 56]),
|
||||
NextValue(aes_in[0], self.a[ 80: 88]),
|
||||
NextValue(aes_in[1], self.a[112:120]),
|
||||
[ NextValue(aes_in[(i+2)%4], self.a[(i*32)+16:(i*32)+24]) for i in range(0, 4) ],
|
||||
NextState("LANE2_3"))
|
||||
seq.act("LANE2_3",
|
||||
# store the xor'ed result for LANE2, byte 2 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(aes_out[0][16:24], aes_out[0][ 0:16], aes_out[0][ 8:16])),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(aes_out[1][16:24], aes_out[1][ 0:16], aes_out[1][ 8:16])),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(aes_out[2][16:24], aes_out[2][ 0:16], aes_out[2][ 8:16])),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(aes_out[3][16:24], aes_out[3][ 0:16], aes_out[3][ 8:16]))],
|
||||
1:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(Signal(8, reset = 0), aes_out[0][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(Signal(8, reset = 0), aes_out[1][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(Signal(8, reset = 0), aes_out[2][ 8:16], Signal(16, reset = 0))),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(Signal(8, reset = 0), aes_out[3][ 8:16], Signal(16, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(aes_out[i][16:24], aes_out[i][ 0:16], aes_out[i][ 8:16])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(Signal(8, reset = 0), aes_out[i][ 8:16], Signal(16, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the third byte in the lookup tables (LANE2)
|
||||
NextValue(aes_in[2], self.a[144:152]),
|
||||
NextValue(aes_in[3], self.a[176:184]),
|
||||
NextValue(aes_in[0], self.a[208:216]),
|
||||
NextValue(aes_in[1], self.a[240:248]),
|
||||
[ NextValue(aes_in[(i+2)%4], self.a[(i*32)+16+128:(i*32)+24+128]) for i in range(0, 4) ],
|
||||
NextState("LANE1_4"))
|
||||
seq.act("LANE1_4",
|
||||
# store the xor'ed result for LANE1, byte 3 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(aes_out[0][ 8:24], aes_out[0][ 0:16])),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(aes_out[1][ 8:24], aes_out[1][ 0:16])),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(aes_out[2][ 8:24], aes_out[2][ 0:16])),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(aes_out[3][ 8:24], aes_out[3][ 0:16]))],
|
||||
1:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(Signal(16, reset = 0), aes_out[0][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(Signal(16, reset = 0), aes_out[1][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(Signal(16, reset = 0), aes_out[2][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(Signal(16, reset = 0), aes_out[3][ 8:16], Signal(8, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(aes_out[i][ 8:24], aes_out[i][ 0:16])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(Signal(16, reset = 0), aes_out[i][ 8:16], Signal(8, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the fourth byte in the lookup tables (LANE1)
|
||||
NextValue(aes_in[1], self.a[ 24: 32]),
|
||||
NextValue(aes_in[2], self.a[ 56: 64]),
|
||||
NextValue(aes_in[3], self.a[ 88: 96]),
|
||||
NextValue(aes_in[0], self.a[120:128]),
|
||||
[ NextValue(aes_in[(i+1)%4], self.a[(i*32)+24:(i*32)+32]) for i in range(0, 4) ],
|
||||
NextState("LANE2_4"))
|
||||
seq.act("LANE2_4",
|
||||
# store the xor'ed result for LANE2, byte 3 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(aes_out[0][ 8:24], aes_out[0][ 0:16])),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(aes_out[1][ 8:24], aes_out[1][ 0:16])),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(aes_out[2][ 8:24], aes_out[2][ 0:16])),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(aes_out[3][ 8:24], aes_out[3][ 0:16]))],
|
||||
1:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(Signal(16, reset = 0), aes_out[0][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(Signal(16, reset = 0), aes_out[1][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(Signal(16, reset = 0), aes_out[2][ 8:16], Signal(8, reset = 0))),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(Signal(16, reset = 0), aes_out[3][ 8:16], Signal(8, reset = 0)))],
|
||||
0:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(aes_out[i][ 8:24], aes_out[i][ 0:16])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(Signal(16, reset = 0), aes_out[i][ 8:16], Signal(8, reset = 0))) for i in range(0, 4) ],
|
||||
}),
|
||||
# put the fourth byte in the lookup tables (LANE2)
|
||||
NextValue(aes_in[1], self.a[152:160]),
|
||||
NextValue(aes_in[2], self.a[184:192]),
|
||||
NextValue(aes_in[3], self.a[216:224]),
|
||||
NextValue(aes_in[0], self.a[248:256]),
|
||||
[ NextValue(aes_in[(i+1)%4], self.a[(i*32)+24+128:(i*32)+32+128]) for i in range(0, 4) ],
|
||||
NextState("LANE1_F"))
|
||||
seq.act("LANE1_F",
|
||||
# store the xor'ed result for LANE1, byte 4 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(aes_out[0][ 8:16], aes_out[0][ 8:24], aes_out[0][ 0: 8])),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(aes_out[1][ 8:16], aes_out[1][ 8:24], aes_out[1][ 0: 8])),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(aes_out[2][ 8:16], aes_out[2][ 8:24], aes_out[2][ 0: 8])),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(aes_out[3][ 8:16], aes_out[3][ 8:24], aes_out[3][ 0: 8]))],
|
||||
1:[ NextValue(aes_buf[ 0: 32], aes_buf[ 0: 32] ^ Cat(Signal(24, reset = 0), aes_out[0][ 8:16])),
|
||||
NextValue(aes_buf[ 32: 64], aes_buf[ 32: 64] ^ Cat(Signal(24, reset = 0), aes_out[1][ 8:16])),
|
||||
NextValue(aes_buf[ 64: 96], aes_buf[ 64: 96] ^ Cat(Signal(24, reset = 0), aes_out[2][ 8:16])),
|
||||
NextValue(aes_buf[ 96:128], aes_buf[ 96:128] ^ Cat(Signal(24, reset = 0), aes_out[3][ 8:16]))],
|
||||
0:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(aes_out[i][ 8:16], aes_out[i][ 8:24], aes_out[i][ 0: 8])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32):(i*32)+32], aes_buf[(i*32):(i*32)+32] ^ Cat(Signal(24, reset = 0), aes_out[i][ 8:16])) for i in range(0, 4) ],
|
||||
}),
|
||||
NextState("LANE2_F"))
|
||||
seq.act("LANE2_F",
|
||||
# store the xor'ed result for LANE2, byte 4 in aes_buf
|
||||
Case(self.instruction.immediate[0:1], {
|
||||
0:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(aes_out[0][ 8:16], aes_out[0][ 8:24], aes_out[0][ 0: 8])),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(aes_out[1][ 8:16], aes_out[1][ 8:24], aes_out[1][ 0: 8])),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(aes_out[2][ 8:16], aes_out[2][ 8:24], aes_out[2][ 0: 8])),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(aes_out[3][ 8:16], aes_out[3][ 8:24], aes_out[3][ 0: 8]))],
|
||||
1:[ NextValue(aes_buf[128:160], aes_buf[128:160] ^ Cat(Signal(24, reset = 0), aes_out[0][ 8:16])),
|
||||
NextValue(aes_buf[160:192], aes_buf[160:192] ^ Cat(Signal(24, reset = 0), aes_out[1][ 8:16])),
|
||||
NextValue(aes_buf[192:224], aes_buf[192:224] ^ Cat(Signal(24, reset = 0), aes_out[2][ 8:16])),
|
||||
NextValue(aes_buf[224:256], aes_buf[224:256] ^ Cat(Signal(24, reset = 0), aes_out[3][ 8:16]))],
|
||||
0:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(aes_out[i][ 8:16], aes_out[i][ 8:24], aes_out[i][ 0: 8])) for i in range(0, 4) ],
|
||||
1:[ NextValue(aes_buf[(i*32)+128:(i*32)+32+128], aes_buf[(i*32)+128:(i*32)+32+128] ^ Cat(Signal(24, reset = 0), aes_out[i][ 8:16])) for i in range(0, 4) ],
|
||||
}),
|
||||
NextState("AES_EVEN1"))
|
||||
seq.act("AES_EVEN1",
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
PFX=prom_migen
|
||||
for V in "V1_0" "V1_2"; do
|
||||
|
||||
rm -f ${PFX}.fc
|
||||
PFX=prom_${V}
|
||||
|
||||
# (export BP=~/SPARC/SBusFPGA/sbus-to-ztex/openfirmware ; toke ${PFX}.forth )
|
||||
if test -f ${PFX}.fth; then
|
||||
echo "GENERATING PROM for $V"
|
||||
|
||||
( export BP=`pwd`/openfirmware ; openfirmware/cpu/x86/Linux/forth openfirmware/cpu/x86/build/builder.dic prom_migen.bth ) 2>&1 | tee forth.log
|
||||
rm -f ${PFX}.fc
|
||||
|
||||
# (export BP=~/SPARC/SBusFPGA/sbus-to-ztex/openfirmware ; toke ${PFX}.forth )
|
||||
|
||||
( export BP=`pwd`/openfirmware ; openfirmware/cpu/x86/Linux/forth openfirmware/cpu/x86/build/builder.dic ${PFX}.bth ) 2>&1 | tee forth.log
|
||||
|
||||
rm -f /tmp/${PFX}.hexa
|
||||
|
||||
od --endian=big -w4 -x ${PFX}.fc | awk '{ print $2,$3"," }' >| /tmp/${PFX}.hexa
|
||||
|
||||
rm -f /tmp/${PFX}.txt_hexa
|
||||
|
||||
cat /tmp/${PFX}.hexa | sed -e 's/^\([a-f0-9][a-f0-9][a-f0-9][a-f0-9]\) \([a-f0-9][a-f0-9][a-f0-9][a-f0-9]\),/0x\1\2,/g' -e 's/^\([a-f0-9][a-f0-9]*\) ,/0x\10000,/' -e 's/^ ,/0x00000000,/' -e 's/\(0x[0-9a-fA-F]*\),/if (idx == 0):\n\treturn \1;/' > /tmp/${PFX}.txt_hexa
|
||||
|
||||
#echo "rom = ["
|
||||
#cat /tmp/${PFX}.txt_hexa
|
||||
#echo "]"
|
||||
fi
|
||||
|
||||
rm -f /tmp/${PFX}.hexa
|
||||
|
||||
od --endian=big -w4 -x ${PFX}.fc | awk '{ print $2,$3"," }' >| /tmp/${PFX}.hexa
|
||||
|
||||
rm -f /tmp/${PFX}.txt_hexa
|
||||
|
||||
cat /tmp/${PFX}.hexa | sed -e 's/^\([a-f0-9][a-f0-9][a-f0-9][a-f0-9]\) \([a-f0-9][a-f0-9][a-f0-9][a-f0-9]\),/0x\1\2,/g' -e 's/^\([a-f0-9][a-f0-9]*\) ,/0x\10000,/' -e 's/^ ,/0x00000000,/' -e 's/\(0x[0-9a-fA-F]*\),/if (idx == 0):\n\treturn \1;/' > /tmp/${PFX}.txt_hexa
|
||||
|
||||
#echo "rom = ["
|
||||
#cat /tmp/${PFX}.txt_hexa
|
||||
#echo "]"
|
||||
done
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
13
sbus-to-ztex-gateware-migen/prom_V1_0.bth
Normal file
13
sbus-to-ztex-gateware-migen/prom_V1_0.bth
Normal file
@@ -0,0 +1,13 @@
|
||||
purpose: Load file for SBusFPGA
|
||||
|
||||
command: &builder &this
|
||||
|
||||
build-now
|
||||
|
||||
\ silent on
|
||||
|
||||
begin-tokenizing prom_V1_0.fc
|
||||
|
||||
fload prom_V1_0.fth
|
||||
|
||||
end-tokenizing
|
||||
13
sbus-to-ztex-gateware-migen/prom_V1_2.bth
Normal file
13
sbus-to-ztex-gateware-migen/prom_V1_2.bth
Normal file
@@ -0,0 +1,13 @@
|
||||
purpose: Load file for SBusFPGA
|
||||
|
||||
command: &builder &this
|
||||
|
||||
build-now
|
||||
|
||||
\ silent on
|
||||
|
||||
begin-tokenizing prom_V1_2.fc
|
||||
|
||||
fload prom_V1_2.fth
|
||||
|
||||
end-tokenizing
|
||||
@@ -1,14 +0,0 @@
|
||||
\ auto-generated base regions for CSRs in the PROM
|
||||
h# 40000 constant sbusfpga_csraddr_leds
|
||||
h# 41000 constant sbusfpga_csraddr_curve25519engine
|
||||
h# 42000 constant sbusfpga_csraddr_ddrphy
|
||||
h# 43000 constant sbusfpga_csraddr_exchange_with_mem
|
||||
h# 44000 constant sbusfpga_csraddr_sbus_bus_stat
|
||||
h# 45000 constant sbusfpga_csraddr_sdram
|
||||
h# 46000 constant sbusfpga_csraddr_trng
|
||||
h# 80000 constant sbusfpga_regionaddr_usb_host_ctrl
|
||||
h# 0 constant sbusfpga_regionaddr_prom
|
||||
h# 80000000 constant sbusfpga_regionaddr_main_ram
|
||||
h# fc000000 constant sbusfpga_regionaddr_usb_fake_dma
|
||||
h# a0000 constant sbusfpga_regionaddr_curve25519engine
|
||||
h# 40000 constant sbusfpga_regionaddr_csr
|
||||
@@ -49,7 +49,8 @@ my-address sbusfpga_regionaddr_usb_host_ctrl + my-space h# 1000 reg
|
||||
h# 7c xdrint " slave-burst-sizes" attribute
|
||||
h# 7c xdrint " burst-sizes" attribute
|
||||
|
||||
1 xdrint " interrupts" attribute
|
||||
\ USB has an interrupt
|
||||
sbusfpga_irq_usb_host xdrint " interrupts" attribute
|
||||
|
||||
headers
|
||||
-1 instance value regs-virt
|
||||
|
||||
@@ -9,8 +9,9 @@ from litex.soc.interconnect import wishbone
|
||||
# width of fromsbus_req_fifo is 'blk_addr_width' + 'vaddr' (blk_addr + vaddr)
|
||||
# width of fromsbus_fifo is 'blk_addr_width' + 'burst_size * 32' (blk_addr + data)
|
||||
# the blk_addr does the round-trip to accompany the data
|
||||
# mem_size in MiB, might be weird if some space is reserved for other use (e.g. FrameBuffer)
|
||||
class ExchangeWithMem(Module, AutoCSR):
|
||||
def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, burst_size = 8, do_checksum = False):
|
||||
def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, mem_size=256, burst_size = 8, do_checksum = False):
|
||||
#self.wishbone_r_slave = wishbone.Interface(data_width=soc.bus.data_width)
|
||||
#self.wishbone_w_slave = wishbone.Interface(data_width=soc.bus.data_width)
|
||||
self.tosbus_fifo = tosbus_fifo
|
||||
@@ -19,6 +20,8 @@ class ExchangeWithMem(Module, AutoCSR):
|
||||
self.dram_dma_writer = dram_dma_writer
|
||||
self.dram_dma_reader = dram_dma_reader
|
||||
|
||||
print(f"Configuring the SDRAM for {mem_size} MiB\n")
|
||||
|
||||
data_width = burst_size * 4
|
||||
data_width_bits = burst_size * 32
|
||||
blk_addr_width = 32 - log2_int(data_width) # 27 for burst_size == 8
|
||||
@@ -55,7 +58,7 @@ class ExchangeWithMem(Module, AutoCSR):
|
||||
self.mem_size = CSRStatus(32) # report how much memory we have
|
||||
self.comb += self.blk_size.status.eq(data_width)
|
||||
self.comb += self.blk_base.status.eq(soc.wb_mem_map["main_ram"] >> log2_int(data_width))
|
||||
self.comb += self.mem_size.status.eq((256 * 1024 * 1024) >> log2_int(data_width)) # is it already available from mem_regions ?
|
||||
self.comb += self.mem_size.status.eq((mem_size * 1024 * 1024) >> log2_int(data_width))
|
||||
|
||||
self.blk_addr = CSRStorage(32, description = "SDRAM Block address to read/write from Wishbone memory (block of size {})".format(data_width))
|
||||
self.dma_addr = CSRStorage(32, description = "Host Base address where to write/read data (i.e. SPARC Virtual addr)")
|
||||
|
||||
@@ -124,10 +124,68 @@ def get_csr_header(regions, constants, csr_base=None, with_access_functions=True
|
||||
return r
|
||||
|
||||
|
||||
def get_csr_forth_header(csr_regions, mem_regions, constants, csr_base=None):
|
||||
def get_csr_forth_header(csr_regions, mem_regions, device_irq_map, constants, csr_base=None):
|
||||
r = "\\ auto-generated base regions for CSRs in the PROM\n"
|
||||
for name, region in csr_regions.items():
|
||||
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_csraddr_{}".format(name) + "\n"
|
||||
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_csraddr_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
|
||||
for name, region in mem_regions.items():
|
||||
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_regionaddr_{}".format(name) + "\n"
|
||||
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_regionaddr_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
|
||||
for device, irq in device_irq_map.items():
|
||||
if ((irq < 7) and (irq > 0)):
|
||||
r += "h# " + hex(irq).replace("0x", "") + " constant " + "sbusfpga_irq_{}".format(device) + "\n"
|
||||
return r
|
||||
|
||||
|
||||
def get_csr_header_split(regions, constants, csr_base=None, with_access_functions=True):
|
||||
alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32)
|
||||
ar = dict()
|
||||
for name, region in regions.items():
|
||||
r = generated_banner("//")
|
||||
|
||||
r += "#ifndef __GENERATED_{}_CSR_H\n#define __GENERATED_{}_CSR_H\n".format(name.upper(), name.upper())
|
||||
csr_base = csr_base if csr_base is not None else regions[next(iter(regions))].origin
|
||||
|
||||
origin = region.origin - csr_base
|
||||
r += "\n/* "+name+" */\n"
|
||||
r += "#ifndef CSR_BASE\n"
|
||||
r += "#define CSR_BASE {}L\n".format(hex(csr_base))
|
||||
r += "#endif\n"
|
||||
r += "#ifndef CSR_"+name.upper()+"_BASE\n"
|
||||
r += "#define CSR_"+name.upper()+"_BASE (CSR_BASE + "+hex(origin)+"L)\n"
|
||||
if not isinstance(region.obj, Memory):
|
||||
for csr in region.obj:
|
||||
nr = (csr.size + region.busword - 1)//region.busword
|
||||
r += _get_rw_functions_c(name, csr.name, origin, region.origin - csr_base, nr, region.busword, alignment,
|
||||
getattr(csr, "read_only", False), with_access_functions)
|
||||
origin += alignment//8*nr
|
||||
if hasattr(csr, "fields"):
|
||||
for field in csr.fields.fields:
|
||||
offset = str(field.offset)
|
||||
size = str(field.size)
|
||||
r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_OFFSET "+offset+"\n"
|
||||
r += "#define CSR_"+name.upper()+"_"+csr.name.upper()+"_"+field.name.upper()+"_SIZE "+size+"\n"
|
||||
if with_access_functions and csr.size <= 32: # FIXME: Implement extract/read functions for csr.size > 32-bit.
|
||||
reg_name = name + "_" + csr.name.lower()
|
||||
field_name = reg_name + "_" + field.name.lower()
|
||||
r += "static inline uint32_t " + field_name + "_extract(struct sbusfpga_" + name + "_softc *sc, uint32_t oldword) {\n"
|
||||
r += "\tuint32_t mask = ((1 << " + size + ")-1);\n"
|
||||
r += "\treturn ( (oldword >> " + offset + ") & mask );\n}\n"
|
||||
r += "static inline uint32_t " + field_name + "_read(struct sbusfpga_" + name + "_softc *sc) {\n"
|
||||
r += "\tuint32_t word = " + reg_name + "_read(sc);\n"
|
||||
r += "\treturn " + field_name + "_extract(sc, word);\n"
|
||||
r += "}\n"
|
||||
if not getattr(csr, "read_only", False):
|
||||
r += "static inline uint32_t " + field_name + "_replace(struct sbusfpga_" + name + "_softc *sc, uint32_t oldword, uint32_t plain_value) {\n"
|
||||
r += "\tuint32_t mask = ((1 << " + size + ")-1);\n"
|
||||
r += "\treturn (oldword & (~(mask << " + offset + "))) | (mask & plain_value)<< " + offset + " ;\n}\n"
|
||||
r += "static inline void " + field_name + "_write(struct sbusfpga_" + name + "_softc *sc, uint32_t plain_value) {\n"
|
||||
r += "\tuint32_t oldword = " + reg_name + "_read(sc);\n"
|
||||
r += "\tuint32_t newword = " + field_name + "_replace(sc, oldword, plain_value);\n"
|
||||
r += "\t" + reg_name + "_write(sc, newword);\n"
|
||||
r += "}\n"
|
||||
|
||||
r += "#endif // CSR_"+name.upper()+"_BASE\n"
|
||||
r += "\n#endif\n"
|
||||
ar[name] = r
|
||||
|
||||
return ar
|
||||
|
||||
@@ -25,13 +25,21 @@ ADDR_PHYS_LOW = 0
|
||||
ADDR_PFX_HIGH = ADDR_PHYS_HIGH
|
||||
ADDR_PFX_LOW = 16 ## 64 KiB per prefix
|
||||
ADDR_PFX_LENGTH = 12 #(1 + ADDR_PFX_HIGH - ADDR_PFX_LOW)
|
||||
ROM_ADDR_PFX = Signal(12, reset = 0x000)
|
||||
WISHBONE_CSR_ADDR_PFX = Signal(12, reset = 0x004)
|
||||
USBOHCI_ADDR_PFX = Signal(12, reset = 0x008)
|
||||
SRAM_ADDR_PFX = Signal(12, reset = 0x009)
|
||||
ENGINE_ADDR_PFXA = Signal(12, reset = 0x00a)
|
||||
ENGINE_ADDR_PFXB = Signal(12, reset = 0x00b)
|
||||
#SDRAM_ADDR_PFX = Signal(12, reset = 2048)
|
||||
ROM_ADDR_PFX = Signal(12, reset = 0x000) # read only
|
||||
WISHBONE_CSR_ADDR_PFX = Signal(12, reset = 0x004)
|
||||
USBOHCI_ADDR_PFX = Signal(12, reset = 0x008)
|
||||
SRAM_ADDR_PFX = Signal(12, reset = 0x009) # unmapped ; LE
|
||||
ENGINE_ADDR_PFXA = Signal(12, reset = 0x00a)
|
||||
ENGINE_ADDR_PFXB = Signal(12, reset = 0x00b)
|
||||
CG3_REGISTERS_ADDR_PFX = Signal(12, reset = 0x040)
|
||||
|
||||
ADDR_BIGPFX_HIGH = ADDR_PHYS_HIGH
|
||||
ADDR_BIGPFX_LOW = 20 ## 1 MiB per bigprefix
|
||||
ADDR_BIGPFX_LENGTH = 8 #(1 + ADDR_BIGPFX_HIGH - ADDR_BIGPFX_LOW)
|
||||
CG3_PIXELS_ADDR_BIGPFX = Signal(8, reset = 0x08) # cg3_pixels, remapped, first MiB, LE
|
||||
CG3_PIXELS_ADDR_BIGVAL = 0x08
|
||||
CG3_PIXELS_ADDR2_BIGPFX = Signal(8, reset = 0x09) # cg3_pixels, remapped, second MiB, LE
|
||||
CG3_PIXELS_ADDR2_BIGVAL = 0x09
|
||||
|
||||
wishbone_default_timeout = 120 ##
|
||||
sbus_default_timeout = 50 ## must be below 255
|
||||
@@ -175,7 +183,7 @@ LED_M_READ = 0x20
|
||||
LED_M_CACHE = 0x40
|
||||
|
||||
class SBusFPGABus(Module):
|
||||
def __init__(self, platform, hold_reset, wishbone_slave, wishbone_master, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, burst_size = 8):
|
||||
def __init__(self, platform, hold_reset, wishbone_slave, wishbone_master, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, version, burst_size = 8, cg3_fb_size = 0, cg3_base=0x8ff00000 ):
|
||||
self.platform = platform
|
||||
self.hold_reset = hold_reset
|
||||
|
||||
@@ -185,6 +193,19 @@ class SBusFPGABus(Module):
|
||||
self.tosbus_fifo = tosbus_fifo
|
||||
self.fromsbus_fifo = fromsbus_fifo
|
||||
self.fromsbus_req_fifo = fromsbus_req_fifo
|
||||
|
||||
if (cg3_fb_size <= 1048576): #round up to 1 MiB
|
||||
CG3_UPPER_BITS=12
|
||||
CG3_KEPT_UPPER_BIT=20
|
||||
elif (cg3_fb_size == (2*1048576)):
|
||||
CG3_UPPER_BITS=11
|
||||
CG3_KEPT_UPPER_BIT=21
|
||||
else:
|
||||
print(f"CG3 configuration ({cg3_fb_size//1048576} MiB) not yet supported\n")
|
||||
assert(False)
|
||||
CG3_REMAPPED_BASE=cg3_base >> CG3_KEPT_UPPER_BIT
|
||||
|
||||
print(f"CG3 remapping: {cg3_fb_size//1048576} Mib starting at prefix {CG3_REMAPPED_BASE:x} ({(CG3_REMAPPED_BASE<<CG3_KEPT_UPPER_BIT):x})")
|
||||
|
||||
data_width = burst_size * 4
|
||||
data_width_bits = burst_size * 32
|
||||
@@ -193,9 +214,10 @@ class SBusFPGABus(Module):
|
||||
fifo_blk_addr = Signal(blk_addr_width)
|
||||
fifo_buffer = Signal(data_width_bits)
|
||||
|
||||
pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
|
||||
SBUS_DATA_OE_LED_o = Signal()
|
||||
self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o)
|
||||
#pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
|
||||
#SBUS_DATA_OE_LED_o = Signal()
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o)
|
||||
|
||||
##pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2")
|
||||
##SBUS_DATA_OE_LED_2_o = Signal()
|
||||
##self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o)
|
||||
@@ -217,8 +239,7 @@ class SBusFPGABus(Module):
|
||||
pad_SBUS_3V3_ERRs = platform.request("SBUS_3V3_ERRs")
|
||||
#pad_SBUS_3V3_RSTs = platform.request("SBUS_3V3_RSTs")
|
||||
pad_SBUS_3V3_SELs = platform.request("SBUS_3V3_SELs")
|
||||
#pad_SBUS_3V3_INT1s = platform.request("SBUS_3V3_INT1s")
|
||||
pad_SBUS_3V3_INT7s = platform.request("SBUS_3V3_INT7s")
|
||||
|
||||
pad_SBUS_3V3_PPRD = platform.request("SBUS_3V3_PPRD")
|
||||
pad_SBUS_OE = platform.request("SBUS_OE")
|
||||
pad_SBUS_3V3_ACKs = platform.request("SBUS_3V3_ACKs")
|
||||
@@ -231,11 +252,9 @@ class SBusFPGABus(Module):
|
||||
sbus_oe_data = Signal(reset=0)
|
||||
sbus_oe_slave_in = Signal(reset=0)
|
||||
sbus_oe_master_in = Signal(reset=0)
|
||||
#sbus_oe_int1 = Signal(reset=0)
|
||||
sbus_oe_int7 = Signal(reset=0)
|
||||
#sbus_oe_master_br = Signal(reset=0)
|
||||
|
||||
sbus_last_pa = Signal(28)
|
||||
sbus_last_pa = Signal(32)
|
||||
burst_index = Signal(4)
|
||||
burst_counter = Signal(4)
|
||||
burst_limit_m1 = Signal(4)
|
||||
@@ -254,10 +273,7 @@ class SBusFPGABus(Module):
|
||||
#SBUS_3V3_RSTs = Signal()
|
||||
SBUS_3V3_SELs_i = Signal(reset=1)
|
||||
self.comb += SBUS_3V3_SELs_i.eq(pad_SBUS_3V3_SELs)
|
||||
#SBUS_3V3_INT1s_o = Signal(reset=1)
|
||||
#self.specials += Tristate(pad_SBUS_3V3_INT1s, SBUS_3V3_INT1s_o, sbus_oe_int1, None)
|
||||
SBUS_3V3_INT7s_o = Signal(reset=1)
|
||||
self.specials += Tristate(pad_SBUS_3V3_INT7s, SBUS_3V3_INT7s_o, sbus_oe_int7, None)
|
||||
|
||||
SBUS_3V3_PPRD_i = Signal()
|
||||
SBUS_3V3_PPRD_o = Signal()
|
||||
self.specials += Tristate(pad_SBUS_3V3_PPRD, SBUS_3V3_PPRD_o, sbus_oe_slave_in, SBUS_3V3_PPRD_i)
|
||||
@@ -333,7 +349,7 @@ class SBusFPGABus(Module):
|
||||
#self.sync += platform.request("user_led", 5).eq(self.wishbone_slave.cyc)
|
||||
#self.sync += platform.request("user_led", 6).eq(~SBUS_3V3_BRs_o)
|
||||
#self.sync += platform.request("user_led", 7).eq(~SBUS_3V3_BGs_i)
|
||||
self.sync += SBUS_DATA_OE_LED_o.eq(~SBUS_3V3_BGs_i),
|
||||
#self.sync += SBUS_DATA_OE_LED_o.eq(~SBUS_3V3_BGs_i),
|
||||
|
||||
#cycle_counter = Signal(8, reset = 0)
|
||||
#self.sync += cycle_counter.eq(cycle_counter + 1)
|
||||
@@ -427,12 +443,12 @@ class SBusFPGABus(Module):
|
||||
If((self.hold_reset == 0), NextState("Idle"))
|
||||
)
|
||||
slave_fsm.act("Idle",
|
||||
# ***** Slave (Multi-)Word Read *****
|
||||
If(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(siz_is_word(SBUS_3V3_SIZ_i)) &
|
||||
(SBUS_3V3_PPRD_i == 1)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
NextValue(burst_counter, 0),
|
||||
Case(SBUS_3V3_SIZ_i, {
|
||||
SIZ_WORD: NextValue(burst_limit_m1, 0),
|
||||
@@ -451,22 +467,52 @@ class SBusFPGABus(Module):
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == USBOHCI_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXA) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB)),
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
If(self.wishbone_master.cyc == 0,
|
||||
NextValue(self.wishbone_master.cyc, 1),
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data")
|
||||
).Else(
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Wishbone")
|
||||
)
|
||||
@@ -478,29 +524,59 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
)
|
||||
# ***** Slave Byte Read *****
|
||||
).Elif(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(SIZ_BYTE == SBUS_3V3_SIZ_i) &
|
||||
(SBUS_3V3_PPRD_i == 1)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
If(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ROM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
If(self.wishbone_master.cyc == 0,
|
||||
NextValue(self.wishbone_master.cyc, 1),
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Data")
|
||||
).Else(
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Wishbone")
|
||||
)
|
||||
@@ -512,12 +588,12 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
)
|
||||
# ***** Slave HalfWord Read *****
|
||||
).Elif(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(SIZ_HWORD == SBUS_3V3_SIZ_i) &
|
||||
(SBUS_3V3_PPRD_i == 1)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
If(SBUS_3V3_PA_i[0:1] != 0,
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_ERR),
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
@@ -525,22 +601,52 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ROM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
If(self.wishbone_master.cyc == 0,
|
||||
NextValue(self.wishbone_master.cyc, 1),
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Data")
|
||||
).Else(
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
NextValue(sbus_slave_timeout, sbus_default_timeout),
|
||||
NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Wishbone")
|
||||
)
|
||||
@@ -552,12 +658,12 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
)
|
||||
# ***** Slave (Multi-)Word Write *****
|
||||
).Elif(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(siz_is_word(SBUS_3V3_SIZ_i)) &
|
||||
(SBUS_3V3_PPRD_i == 0)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
NextValue(burst_counter, 0),
|
||||
Case(SBUS_3V3_SIZ_i, {
|
||||
SIZ_WORD: NextValue(burst_limit_m1, 0),
|
||||
@@ -576,9 +682,26 @@ class SBusFPGABus(Module):
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == USBOHCI_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXA) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB)),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
If(~self.wishbone_master.cyc,
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
@@ -599,15 +722,32 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
)
|
||||
# ***** Slave Byte Write *****
|
||||
).Elif(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(SIZ_BYTE == SBUS_3V3_SIZ_i) &
|
||||
(SBUS_3V3_PPRD_i == 0)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
If(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
If(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
If(~self.wishbone_master.cyc,
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_BYTE),
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
@@ -628,21 +768,38 @@ class SBusFPGABus(Module):
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
)
|
||||
# ***** Slave HalfWord Write *****
|
||||
).Elif(((SBUS_3V3_SELs_i == 0) &
|
||||
(SBUS_3V3_ASs_i == 0) &
|
||||
(SIZ_HWORD == SBUS_3V3_SIZ_i) &
|
||||
(SBUS_3V3_PPRD_i == 0)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
NextValue(sbus_last_pa, SBUS_3V3_PA_i),
|
||||
If(SBUS_3V3_PA_i[0:1] != 0,
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_ERR),
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
#NextValue(led0123, led0123 | LED_PARITY),
|
||||
NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)),
|
||||
).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(sbus_wishbone_le,
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR2_BIGPFX)),
|
||||
NextValue(stat_slave_start_counter, stat_slave_start_counter + 1),
|
||||
Case(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH], {
|
||||
"default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
],
|
||||
# next remap X MiB to last MiB of SDRAM
|
||||
CG3_PIXELS_ADDR_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
CG3_PIXELS_ADDR2_BIGVAL: [
|
||||
NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))),
|
||||
],
|
||||
}),
|
||||
If(~self.wishbone_master.cyc,
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_HWORD),
|
||||
NextValue(SBUS_3V3_ERRs_o, 1),
|
||||
@@ -915,8 +1072,8 @@ class SBusFPGABus(Module):
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
NextValue(self.wishbone_master.adr, Cat(index_with_wrap(burst_counter+1, burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]), # 4 bits, adr FIXME
|
||||
sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr
|
||||
sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr
|
||||
Signal(4, reset = 0))),
|
||||
sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr
|
||||
)),
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE),
|
||||
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data")
|
||||
)
|
||||
@@ -954,7 +1111,7 @@ class SBusFPGABus(Module):
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))),
|
||||
NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data")
|
||||
@@ -1015,7 +1172,7 @@ class SBusFPGABus(Module):
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))),
|
||||
NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Data")
|
||||
@@ -1074,7 +1231,7 @@ class SBusFPGABus(Module):
|
||||
NextValue(self.wishbone_master.stb, 1),
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.we, 0),
|
||||
NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))),
|
||||
NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]),
|
||||
NextValue(wishbone_master_timeout, wishbone_default_timeout),
|
||||
#NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))),
|
||||
NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Data")
|
||||
@@ -1094,8 +1251,8 @@ class SBusFPGABus(Module):
|
||||
NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1),
|
||||
NextValue(self.wishbone_master.adr, Cat(index_with_wrap(burst_counter, burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]), # 4 bits, adr FIXME
|
||||
sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr
|
||||
sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr
|
||||
Signal(4, reset = 0))),
|
||||
sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr
|
||||
)),
|
||||
Case(sbus_wishbone_le, {
|
||||
0: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i)),
|
||||
1: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[24:32],
|
||||
@@ -1132,7 +1289,7 @@ class SBusFPGABus(Module):
|
||||
NextState("Slave_Ack_Reg_Write_Burst")
|
||||
).Elif(sbus_slave_timeout == 0, ### this is taking too long
|
||||
NextValue(SBUS_3V3_ACKs_o, ACK_RERUN),
|
||||
#NextValue(self.led_display.value, Cat(Signal(8, reset = LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD), sbus_last_pa, Signal(4, reset = 0))),
|
||||
#NextValue(self.led_display.value, Cat(Signal(8, reset = LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD), sbus_last_pa)),
|
||||
#NextValue(led0123, LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD),
|
||||
NextValue(stat_slave_rerun_counter, stat_slave_rerun_counter + 1),
|
||||
NextState("Slave_Error")
|
||||
@@ -1154,8 +1311,8 @@ class SBusFPGABus(Module):
|
||||
}),
|
||||
NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6], # 4 bits, adr FIXME
|
||||
sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr
|
||||
sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr
|
||||
Signal(4, reset = 0))),
|
||||
sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr
|
||||
)),
|
||||
Case(sbus_wishbone_le, {
|
||||
0: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[16:32],
|
||||
SBUS_3V3_D_i[16:32])),
|
||||
@@ -1201,8 +1358,8 @@ class SBusFPGABus(Module):
|
||||
}),
|
||||
NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6], # 4 bits, adr FIXME
|
||||
sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr
|
||||
sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr
|
||||
Signal(4, reset = 0))),
|
||||
sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr
|
||||
)),
|
||||
NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[24:32], # LE/BE identical
|
||||
SBUS_3V3_D_i[24:32],
|
||||
SBUS_3V3_D_i[24:32],
|
||||
|
||||
164
sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py
Normal file
164
sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py
Normal file
@@ -0,0 +1,164 @@
|
||||
import os
|
||||
import json
|
||||
import inspect
|
||||
from shutil import which
|
||||
from sysconfig import get_platform
|
||||
|
||||
from migen import *
|
||||
|
||||
import cg3_fb
|
||||
|
||||
|
||||
def get_header_map_stuff(gname, name, size, type="csr", reg=True):
|
||||
r = ""
|
||||
if (reg):
|
||||
r += f"my-address sbusfpga_{type}addr_{name} + my-space h# {size:x} reg\n"
|
||||
r += "h# 7f xdrint \" slave-burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "h# 7f xdrint \" burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "headers\n"
|
||||
r += f"-1 instance value {name}-virt\nmy-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
|
||||
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
|
||||
r += f": map-in-{gname} ( -- ) my-sbus-address sbusfpga_{type}addr_{name} + my-sbus-space h# {size:x} map-in is {name}-virt ;\n"
|
||||
r += f": map-out-{gname} ( -- ) {name}-virt h# {size:x} map-out ;\n"
|
||||
return r
|
||||
|
||||
def get_header_map2_stuff(gname, name1, name2, size1, size2, type1="csr", type2="csr"):
|
||||
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space xdrphys h# {size1:x} xdrint xdr+\n"
|
||||
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space xdrphys xdr+ h# {size2:x} xdrint xdr+\n"
|
||||
r += "\" reg\" attribute\n"
|
||||
r += "h# 7f xdrint \" slave-burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "h# 7f xdrint \" burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "headers\n"
|
||||
r += f"-1 instance value {name1}-virt\n"
|
||||
r += f"-1 instance value {name2}-virt\n"
|
||||
r += "my-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
|
||||
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
|
||||
r += f": map-in-{gname} ( -- )\n"
|
||||
r += f"my-sbus-address sbusfpga_{type1}addr_{name1} + my-sbus-space h# {size1:x} map-in is {name1}-virt\n"
|
||||
r += f"my-sbus-address sbusfpga_{type2}addr_{name2} + my-sbus-space h# {size2:x} map-in is {name2}-virt\n"
|
||||
r += ";\n"
|
||||
r += f": map-out-{gname} ( -- )\n"
|
||||
r += f"{name1}-virt h# {size1:x} map-out\n"
|
||||
r += f"{name2}-virt h# {size2:x} map-out\n"
|
||||
r += ";\n"
|
||||
return r
|
||||
|
||||
def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1="csr", type2="csr", type3="csr"):
|
||||
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space xdrphys h# {size1:x} xdrint xdr+\n"
|
||||
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space xdrphys xdr+ h# {size2:x} xdrint xdr+\n"
|
||||
r += f"my-address sbusfpga_{type3}addr_{name3} + my-space xdrphys xdr+ h# {size3:x} xdrint xdr+\n"
|
||||
r += "\" reg\" attribute\n"
|
||||
r += "h# 7f xdrint \" slave-burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "h# 7f xdrint \" burst-sizes\" attribute\n" # fixme: burst-sizes
|
||||
r += "headers\n"
|
||||
r += f"-1 instance value {name1}-virt\n"
|
||||
r += f"-1 instance value {name2}-virt\n"
|
||||
r += f"-1 instance value {name3}-virt\n"
|
||||
r += "my-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
|
||||
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
|
||||
r += f": map-in-{gname} ( -- )\n"
|
||||
r += f"my-sbus-address sbusfpga_{type1}addr_{name1} + my-sbus-space h# {size1:x} map-in is {name1}-virt\n"
|
||||
r += f"my-sbus-address sbusfpga_{type2}addr_{name2} + my-sbus-space h# {size2:x} map-in is {name2}-virt\n"
|
||||
r += f"my-sbus-address sbusfpga_{type3}addr_{name3} + my-sbus-space h# {size3:x} map-in is {name3}-virt\n"
|
||||
r += ";\n"
|
||||
r += f": map-out-{gname} ( -- )\n"
|
||||
r += f"{name1}-virt h# {size1:x} map-out\n"
|
||||
r += f"{name2}-virt h# {size2:x} map-out\n"
|
||||
r += f"{name3}-virt h# {size3:x} map-out\n"
|
||||
r += ";\n"
|
||||
return r
|
||||
|
||||
def get_prom(soc,
|
||||
version="V1.0",
|
||||
usb=False,
|
||||
sdram=True,
|
||||
engine=False,
|
||||
i2c=False,
|
||||
cg3=False,
|
||||
cg3_res=None):
|
||||
|
||||
r = "fcode-version2\nfload prom_csr_{}.fth\n".format(version.replace(".", "_"))
|
||||
|
||||
if (version == "V1.0"):
|
||||
r += "\" RDOL,led\" device-name\n"
|
||||
r += get_header_map_stuff("leds", "leds", 4)
|
||||
r += ": setled! ( pattern -- )\nmap-in-leds\nleds-virt l! ( pattern virt -- )\nmap-out-leds\n;\n"
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
r += "\" RDOL,sbusstat\" device-name\n"
|
||||
r += get_header_map_stuff("sbus_bus_stat", "sbus_bus_stat", 256)
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
r += "\" RDOL,neorv32trng\" device-name\n"
|
||||
r += get_header_map_stuff("trng", "trng", 8)
|
||||
r += ": disabletrng! ( -- )\n"
|
||||
r += " map-in-trng\n"
|
||||
r += " 1 trng-virt l! ( pattern virt -- )\n"
|
||||
r += " map-out-trng\n"
|
||||
r += ";\n"
|
||||
r += "disabletrng!\n"
|
||||
if (usb or sdram or engine or i2c or cg3):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (usb):
|
||||
r += "\" generic-ohci\" device-name\n"
|
||||
r += "sbusfpga_irq_usb_host xdrint \" interrupts\" attribute\n"
|
||||
r += get_header_map_stuff("usb_host_ctrl", "usb_host_ctrl", 4096, type="region")
|
||||
r += ": my-reset! ( -- )\n"
|
||||
r += " map-in-usb_host_ctrl\n"
|
||||
r += " 00000001 usb_host_ctrl-virt h# 4 + l! ( -- ) ( reset the HC )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 18 + l! ( -- ) ( reset HCCA & friends )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 1c + l! ( -- )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 20 + l! ( -- )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 24 + l! ( -- )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 28 + l! ( -- )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 2c + l! ( -- )\n"
|
||||
r += " 00000000 usb_host_ctrl-virt h# 30 + l! ( -- )\n"
|
||||
r += " map-out-usb_host_ctrl\n"
|
||||
r += ";\n"
|
||||
r += "my-reset!\n"
|
||||
if (sdram or engine or i2c or cg3):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (sdram):
|
||||
r += "\" RDOL,sdram\" device-name\n"
|
||||
r += get_header_map3_stuff("mregs", "ddrphy", "sdram", "exchange_with_mem", 4096, 4096, 4096)
|
||||
r += "fload sdram_init.fth\ninit!\n"
|
||||
if (engine or i2c or cg3):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (engine):
|
||||
r += "\" betrustedc25519e\" device-name\n"
|
||||
r += ": sbusfpga_regionaddr_curve25519engine-microcode sbusfpga_regionaddr_curve25519engine ;\n"
|
||||
r += ": sbusfpga_regionaddr_curve25519engine-regfile sbusfpga_regionaddr_curve25519engine h# 10000 + ;\n"
|
||||
r += get_header_map3_stuff("curve25519engine", "curve25519engine-regs", "curve25519engine-microcode", "curve25519engine-regfile", 4096, 4096, 65536, type2="region", type3="region")
|
||||
if (i2c or cg3):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (i2c):
|
||||
r += "\" RDOL,i2c\" device-name\n"
|
||||
r += get_header_map_stuff("i2c", "i2c", 64)
|
||||
if (cg3):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (cg3):
|
||||
hres = int(cg3_res.split("@")[0].split("x")[0])
|
||||
vres = int(cg3_res.split("@")[0].split("x")[1])
|
||||
hres_h=(f"{hres:x}").replace("0x", "")
|
||||
vres_h=(f"{vres:x}").replace("0x", "")
|
||||
cg3_file = open("cg3.fth")
|
||||
cg3_lines = cg3_file.readlines()
|
||||
buf_size=cg3_fb.cg3_rounded_size(hres, vres)
|
||||
for line in cg3_lines:
|
||||
r += line.replace("SBUSFPGA_CG3_WIDTH", hres_h).replace("SBUSFPGA_CG3_HEIGHT", vres_h).replace("SBUSFPGA_CG3_BUFSIZE", f"{buf_size:x}")
|
||||
#r += "\" LITEX,fb\" device-name\n"
|
||||
#r += get_header_map2_stuff("cg3extraregs", "vid_fb", "vid_fb_vtg", 4096, 4096)
|
||||
#r += "fload fb_init.fth\nfb_init!\n"
|
||||
|
||||
r += "\n"
|
||||
r += get_header_map_stuff("cg3extraregs", "cg3", 4096, reg=False)
|
||||
r += "fload cg3_init.fth\ncg3_init!\n"
|
||||
|
||||
r += "end0\n"
|
||||
|
||||
return r
|
||||
@@ -1,6 +1,9 @@
|
||||
import os
|
||||
import argparse
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
from migen.fhdl.specials import Tristate
|
||||
|
||||
import litex
|
||||
from litex.build.generic_platform import *
|
||||
from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict
|
||||
@@ -11,7 +14,6 @@ from litex.soc.interconnect import wishbone
|
||||
from litex.soc.cores.clock import *
|
||||
from litex.soc.cores.led import LedChaser
|
||||
import ztex213_sbus
|
||||
from migen.genlib.fifo import *
|
||||
|
||||
from litedram.modules import MT41J128M16
|
||||
from litedram.phy import s7ddrphy
|
||||
@@ -27,26 +29,45 @@ from engine import Engine;
|
||||
from migen.genlib.cdc import BusSynchronizer
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer;
|
||||
|
||||
# betrusted-io/gateware
|
||||
from gateware import i2c;
|
||||
|
||||
import sbus_to_fpga_export;
|
||||
import sbus_to_fpga_prom;
|
||||
|
||||
from litex.soc.cores.video import VideoVGAPHY
|
||||
import cg3_fb;
|
||||
#import cgtrois;
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
|
||||
class _CRG(Module):
|
||||
def __init__(self, platform, sys_clk_freq, usb=True):
|
||||
def __init__(self, platform, sys_clk_freq,
|
||||
usb=False,
|
||||
usb_clk_freq=48e6,
|
||||
sdram=True,
|
||||
engine=False,
|
||||
i2c=False,
|
||||
cg3=False,
|
||||
pix_clk=0):
|
||||
self.clock_domains.cd_sys = ClockDomain() # 100 MHz PLL, reset'ed by SBus (via pll), SoC/Wishbone main clock
|
||||
self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
|
||||
self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
|
||||
self.clock_domains.cd_idelay = ClockDomain()
|
||||
if (sdram):
|
||||
self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
|
||||
self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
|
||||
self.clock_domains.cd_idelay = ClockDomain()
|
||||
## self.clock_domains.cd_sys = ClockDomain() # 16.67-25 MHz SBus, reset'ed by SBus, native SBus & SYS clock domain
|
||||
self.clock_domains.cd_native = ClockDomain(reset_less=True) # 48MHz native, non-reset'ed (for power-on long delay, never reset, we don't want the delay after a warm reset)
|
||||
self.clock_domains.cd_sbus = ClockDomain() # 16.67-25 MHz SBus, reset'ed by SBus, native SBus clock domain
|
||||
# self.clock_domains.cd_por = ClockDomain() # 48 MHz native, reset'ed by SBus, power-on-reset timer
|
||||
if (usb):
|
||||
self.clock_domains.cd_usb = ClockDomain() # 48 MHZ PLL, reset'ed by SBus (via pll), for USB controller
|
||||
self.clock_domains.cd_clk50 = ClockDomain() # 50 MHz (gated) for curve25519engine -> eng_clk
|
||||
#self.clock_domains.cd_clk100 = ClockDomain() # 100 MHz for curve25519engine -> sys_clk
|
||||
self.clock_domains.cd_clk100_gated = ClockDomain() # 100 MHz (gated) for curve25519engine -> mul_clk
|
||||
self.clock_domains.cd_clk200 = ClockDomain() # 200 MHz (gated) for curve25519engine -> rf_clk
|
||||
if (engine): # also used for cgtrois
|
||||
self.clock_domains.cd_clk50 = ClockDomain() # 50 MHz (gated) for curve25519engine -> eng_clk
|
||||
#self.clock_domains.cd_clk100 = ClockDomain() # 100 MHz for curve25519engine -> sys_clk
|
||||
self.clock_domains.cd_clk200 = ClockDomain() # 200 MHz (gated) for curve25519engine -> rf_clk
|
||||
self.clock_domains.cd_clk100_gated = ClockDomain() # 100 MHz (gated) for curve25519engine -> mul_clk # aways created, along sysclk
|
||||
if (cg3):
|
||||
self.clock_domains.cd_vga = ClockDomain(reset_less=True)
|
||||
|
||||
# # #
|
||||
clk48 = platform.request("clk48")
|
||||
@@ -63,34 +84,50 @@ class _CRG(Module):
|
||||
#self.cd_native.clk = clk48
|
||||
|
||||
clk_sbus = platform.request("SBUS_3V3_CLK")
|
||||
if (clk_sbus is None):
|
||||
print(" ***** ERROR ***** Can't find the SBus Clock !!!!\n");
|
||||
assert(false)
|
||||
self.cd_sbus.clk = clk_sbus
|
||||
rst_sbus = platform.request("SBUS_3V3_RSTs")
|
||||
self.comb += self.cd_sbus.rst.eq(~rst_sbus)
|
||||
platform.add_platform_command("create_clock -name SBUS_3V3_CLK -period 40.0 [get_nets SBUS_3V3_CLK]")
|
||||
##self.cd_sys.clk = clk_sbus
|
||||
##self.comb += self.cd_sys.rst.eq(~rst_sbus)
|
||||
|
||||
self.curve25519_on = Signal()
|
||||
|
||||
num_adv = 0
|
||||
num_clk = 0
|
||||
|
||||
self.submodules.pll = pll = S7MMCM(speedgrade=-1)
|
||||
#pll.register_clkin(clk48, 48e6)
|
||||
pll.register_clkin(self.clk48_bufg, 48e6)
|
||||
pll.create_clkout(self.cd_sys, sys_clk_freq, gated_replicas={self.cd_clk100_gated : pll.locked & self.curve25519_on})
|
||||
platform.add_platform_command("create_generated_clock -name sysclk [get_pins {{MMCME2_ADV/CLKOUT0}}]")
|
||||
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq)
|
||||
platform.add_platform_command("create_generated_clock -name sys4xclk [get_pins {{MMCME2_ADV/CLKOUT1}}]")
|
||||
pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90)
|
||||
platform.add_platform_command("create_generated_clock -name sys4x90clk [get_pins {{MMCME2_ADV/CLKOUT2}}]")
|
||||
platform.add_platform_command("create_generated_clock -name sysclk [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
|
||||
num_clk = num_clk + 1
|
||||
if (sdram):
|
||||
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq)
|
||||
platform.add_platform_command("create_generated_clock -name sys4xclk [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
|
||||
num_clk = num_clk + 1
|
||||
pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90)
|
||||
platform.add_platform_command("create_generated_clock -name sys4x90clk [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
|
||||
num_clk = num_clk + 1
|
||||
self.comb += pll.reset.eq(~rst_sbus) # | ~por_done
|
||||
platform.add_false_path_constraints(self.cd_native.clk, self.cd_sbus.clk)
|
||||
platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_native.clk)
|
||||
platform.add_false_path_constraints(self.cd_native.clk, self.cd_sbus.clk) # FIXME?
|
||||
platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_native.clk) # FIXME?
|
||||
#platform.add_false_path_constraints(self.cd_sys.clk, self.cd_sbus.clk)
|
||||
#platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_sys.clk)
|
||||
##platform.add_false_path_constraints(self.cd_native.clk, self.cd_sys.clk)
|
||||
|
||||
pll.create_clkout(self.cd_clk50, sys_clk_freq/2, ce=pll.locked & self.curve25519_on)
|
||||
platform.add_platform_command("create_generated_clock -name clk50 [get_pins {{MMCME2_ADV/CLKOUT3}}]")
|
||||
pll.create_clkout(self.cd_clk200, sys_clk_freq*2, ce=pll.locked & self.curve25519_on)
|
||||
platform.add_platform_command("create_generated_clock -name clk200 [get_pins {{MMCME2_ADV/CLKOUT4}}]")
|
||||
if (engine): # also used for cgtrois
|
||||
pll.create_clkout(self.cd_clk50, sys_clk_freq/2, ce=pll.locked & self.curve25519_on)
|
||||
platform.add_platform_command("create_generated_clock -name clk50 [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
|
||||
num_clk = num_clk + 1
|
||||
pll.create_clkout(self.cd_clk200, sys_clk_freq*2, ce=pll.locked & self.curve25519_on)
|
||||
platform.add_platform_command("create_generated_clock -name clk200 [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
|
||||
num_clk = num_clk + 1
|
||||
|
||||
num_adv = num_adv + 1
|
||||
num_clk = 0
|
||||
|
||||
#self.submodules.curve25519_pll = curve25519_pll = S7MMCM(speedgrade=-1)
|
||||
#curve25519_clk_freq = 90e6
|
||||
@@ -126,22 +163,53 @@ class _CRG(Module):
|
||||
self.submodules.usb_pll = usb_pll = S7MMCM(speedgrade=-1)
|
||||
#usb_pll.register_clkin(clk48, 48e6)
|
||||
usb_pll.register_clkin(self.clk48_bufg, 48e6)
|
||||
usb_pll.create_clkout(self.cd_usb, 48e6, margin = 0)
|
||||
platform.add_platform_command("create_generated_clock -name usbclk [get_pins {{MMCME2_ADV_2/CLKOUT0}}]")
|
||||
usb_pll.create_clkout(self.cd_usb, usb_clk_freq, margin = 0)
|
||||
platform.add_platform_command("create_generated_clock -name usbclk [get_pins {{{{MMCME2_ADV_{}/CLKOUT{}}}}}]".format(num_adv, num_clk))
|
||||
num_clk = num_clk + 1
|
||||
self.comb += usb_pll.reset.eq(~rst_sbus) # | ~por_done
|
||||
platform.add_false_path_constraints(self.cd_sys.clk, self.cd_usb.clk)
|
||||
|
||||
self.submodules.pll_idelay = pll_idelay = S7MMCM(speedgrade=-1)
|
||||
#pll_idelay.register_clkin(clk48, 48e6)
|
||||
pll_idelay.register_clkin(self.clk48_bufg, 48e6)
|
||||
pll_idelay.create_clkout(self.cd_idelay, 200e6, margin = 0)
|
||||
platform.add_platform_command("create_generated_clock -name idelayclk [get_pins {{MMCME2_ADV_3/CLKOUT0}}]")
|
||||
self.comb += pll_idelay.reset.eq(~rst_sbus) # | ~por_done
|
||||
platform.add_false_path_constraints(self.cd_sys.clk, self.cd_usb.clk) # FIXME?
|
||||
num_adv = num_adv + 1
|
||||
num_clk = 0
|
||||
|
||||
self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay)
|
||||
if (sdram):
|
||||
self.submodules.pll_idelay = pll_idelay = S7MMCM(speedgrade=-1)
|
||||
#pll_idelay.register_clkin(clk48, 48e6)
|
||||
pll_idelay.register_clkin(self.clk48_bufg, 48e6)
|
||||
pll_idelay.create_clkout(self.cd_idelay, 200e6, margin = 0)
|
||||
platform.add_platform_command("create_generated_clock -name idelayclk [get_pins {{{{MMCME2_ADV_{}/CLKOUT{}}}}}]".format(num_adv, num_clk))
|
||||
num_clk = num_clk + 1
|
||||
self.comb += pll_idelay.reset.eq(~rst_sbus) # | ~por_done
|
||||
self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay)
|
||||
num_adv = num_adv + 1
|
||||
num_clk = 0
|
||||
|
||||
if (cg3):
|
||||
self.submodules.video_pll = video_pll = S7MMCM(speedgrade=-1)
|
||||
video_pll.register_clkin(self.clk48_bufg, 48e6)
|
||||
video_pll.create_clkout(self.cd_vga, pix_clk, margin = 0.0005)
|
||||
platform.add_platform_command("create_generated_clock -name vga_clk [get_pins {{{{MMCME2_ADV_{}/CLKOUT{}}}}}]".format(num_adv, num_clk))
|
||||
num_clk = num_clk + 1
|
||||
self.comb += video_pll.reset.eq(~rst_sbus)
|
||||
#platform.add_false_path_constraints(self.cd_sys.clk, self.cd_vga.clk)
|
||||
platform.add_false_path_constraints(self.cd_sys.clk, video_pll.clkin)
|
||||
num_adv = num_adv + 1
|
||||
num_clk = 0
|
||||
|
||||
|
||||
|
||||
class SBusFPGA(SoCCore):
|
||||
def __init__(self, version, usb, **kwargs):
|
||||
# Add USB Host
|
||||
def add_usb_host_custom(self, name="usb_host", pads=None, usb_clk_freq=48e6):
|
||||
from litex.soc.cores.usb_ohci import USBOHCI
|
||||
self.submodules.usb_host = USBOHCI(platform=self.platform, pads=pads, usb_clk_freq=usb_clk_freq, dma_data_width=32)
|
||||
usb_host_region_size = 0x10000
|
||||
usb_host_region = SoCRegion(origin=self.mem_map.get(name, None), size=usb_host_region_size, cached=False)
|
||||
self.bus.add_slave("usb_host_ctrl", self.usb_host.wb_ctrl, region=usb_host_region)
|
||||
self.bus.add_master("usb_host_dma", master=self.usb_host.wb_dma)
|
||||
#if self.irq.enabled:
|
||||
#self.irq.add(name, use_loc_if_exists=True)
|
||||
|
||||
def __init__(self, version, sys_clk_freq, usb, sdram, engine, i2c, cg3, cg3_res, **kwargs):
|
||||
print(f"Building SBusFPGA for board version {version}")
|
||||
|
||||
kwargs["cpu_type"] = "None"
|
||||
@@ -149,12 +217,23 @@ class SBusFPGA(SoCCore):
|
||||
kwargs["with_uart"] = False
|
||||
kwargs["with_timer"] = False
|
||||
|
||||
self.sys_clk_freq = sys_clk_freq = 100e6 ## 25e6
|
||||
self.sys_clk_freq = sys_clk_freq
|
||||
|
||||
self.platform = platform = ztex213_sbus.Platform(variant="ztex2.13a", version = version)
|
||||
|
||||
if (version == "V1.0"):
|
||||
self.platform.add_extension(ztex213_sbus._usb_io_v1_0)
|
||||
if (cg3 and (version == "V1.2")):
|
||||
platform.add_extension(ztex213_sbus._vga_pmod_io_v1_2)
|
||||
|
||||
if (cg3):
|
||||
hres = int(cg3_res.split("@")[0].split("x")[0])
|
||||
vres = int(cg3_res.split("@")[0].split("x")[1])
|
||||
cg3_fb_size = cg3_fb.cg3_rounded_size(hres, vres)
|
||||
print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the CG3")
|
||||
else:
|
||||
hres = 0
|
||||
vres = 0
|
||||
cg3_fb_size = 0
|
||||
litex.soc.cores.video.video_timings.update(cg3_fb.cg3_timings)
|
||||
|
||||
SoCCore.__init__(self,
|
||||
platform=platform,
|
||||
@@ -163,7 +242,7 @@ class SBusFPGA(SoCCore):
|
||||
csr_paging=0x1000, # default is 0x800
|
||||
**kwargs)
|
||||
|
||||
# This mem-map is also exposed in the FSM (matched prefixes)
|
||||
# *** This mem-map is also exposed in the FSM (matched prefixes) ***
|
||||
# and in the PROM (to tell NetBSD where everything is)
|
||||
# Currently it is a straight mapping between the two:
|
||||
# the physical address here are used as offset in the SBus
|
||||
@@ -173,30 +252,52 @@ class SBusFPGA(SoCCore):
|
||||
# the virtual address space used by NetBSD DMA allocators
|
||||
# (themselves constrained by the SBus MMU capabilities)
|
||||
self.wb_mem_map = wb_mem_map = {
|
||||
"prom": 0x00000000,
|
||||
"prom": 0x00000000, # 256 Kib ought to be enough for anybody (we're using < 2.5 Kib now...)
|
||||
"csr" : 0x00040000,
|
||||
"usb_host": 0x00080000,
|
||||
"usb_shared_mem": 0x00090000, # unused
|
||||
"curve25519engine": 0x000a0000,
|
||||
"main_ram": 0x80000000,
|
||||
"usb_fake_dma": 0xfc000000,
|
||||
"usb_host": 0x00080000, # OHCI registers are here, not in CSR
|
||||
#"usb_shared_mem": 0x00090000, # unused ATM
|
||||
"curve25519engine": 0x000a0000, # includes microcode (4 KiB@0) and registers (16 KiB @ 64 KiB)
|
||||
"cg3_registers": 0x00400000, # required for compatibility
|
||||
"fb_accel_rom": 0x00410000,
|
||||
"fb_accel_ram": 0x00420000,
|
||||
#"cg6_fbc": 0x00700000, # required for compatibility
|
||||
"cg3_pixels": 0x00800000, # required for compatibility, 1-2 MiB for now (2nd MiB is 0x00900000)
|
||||
"main_ram": 0x80000000, # not directly reachable from SBus mapping (only 0x0 - 0x10000000 is accessible),
|
||||
"video_framebuffer":0x80000000 + 0x10000000 - cg3_fb_size, # FIXME
|
||||
"usb_fake_dma": 0xfc000000, # required to match DVMA virtual addresses
|
||||
}
|
||||
self.mem_map.update(wb_mem_map)
|
||||
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb)
|
||||
self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6) # SBus max
|
||||
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, usb_clk_freq=48e6, sdram=sdram, engine=engine, cg3=cg3, pix_clk=litex.soc.cores.video.video_timings[cg3_res]["pix_clk"])
|
||||
#self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6) # SBus max
|
||||
|
||||
## add our custom timings after the clocks have been defined
|
||||
xdc_timings_filename = None;
|
||||
if (version == "V1.0"):
|
||||
xdc_timings_filename = "/home/dolbeau/SBusFPGA/sbus-to-ztex-gateware/sbus-to-ztex-timings.xdc"
|
||||
self.platform.add_extension(ztex213_sbus._usb_io_v1_0)
|
||||
elif (version == "V1.2"):
|
||||
xdc_timings_filename = "/home/dolbeau/SBusFPGA/sbus-to-ztex-gateware/sbus-to-ztex-timings-V1_2.xdc"
|
||||
|
||||
if (xdc_timings_filename != None):
|
||||
xdc_timings_file = open(xdc_timings_filename)
|
||||
xdc_timings_lines = xdc_timings_file.readlines()
|
||||
for line in xdc_timings_lines:
|
||||
if (line[0:3] == "set"):
|
||||
fix_line = line.strip().replace("{", "{{").replace("}", "}}")
|
||||
#print(fix_line)
|
||||
platform.add_platform_command(fix_line)
|
||||
|
||||
if (version == "V1.0"):
|
||||
self.submodules.leds = LedChaser(
|
||||
pads = platform.request("SBUS_DATA_OE_LED_2"), #platform.request("user_led", 7),
|
||||
pads = platform.request("SBUS_DATA_OE_LED_2"),
|
||||
sys_clk_freq = sys_clk_freq)
|
||||
self.add_csr("leds")
|
||||
|
||||
if (usb):
|
||||
self.add_usb_host(pads=platform.request("usb"), usb_clk_freq=48e6)
|
||||
if (version == "V1.0"):
|
||||
pad_usb_interrupt = platform.request("SBUS_3V3_INT1s") ## only one usable
|
||||
elif (version == "V1.2"):
|
||||
pad_usb_interrupt = platform.request("SBUS_3V3_INT3s") ## can be 1-6, beware others
|
||||
self.add_usb_host_custom(pads=platform.request("usb"), usb_clk_freq=48e6)
|
||||
pad_usb_interrupt = platform.get_irq(irq_req=4, device="usb_host", next_down=True, next_up=False)
|
||||
if (pad_usb_interrupt is None):
|
||||
print(" ***** ERROR ***** USB requires an interrupt")
|
||||
sig_usb_interrupt = Signal(reset=1)
|
||||
# the 74LVC2G07 takes care of the Z state: 1 -> Z on the bus, 0 -> 0 on the bus (asserted interrupt)
|
||||
self.comb += pad_usb_interrupt.eq(sig_usb_interrupt)
|
||||
@@ -211,7 +312,7 @@ class SBusFPGA(SoCCore):
|
||||
#self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o)
|
||||
#self.comb += SBUS_DATA_OE_LED_o.eq(~SBUS_3V3_INT1s_o)
|
||||
|
||||
prom_file = "prom_migen.fc"
|
||||
prom_file = "prom_{}.fc".format(version.replace(".", "_"))
|
||||
prom_data = soc_core.get_mem_data(prom_file, "big")
|
||||
# prom = Array(prom_data)
|
||||
#print("\n****************************************\n")
|
||||
@@ -222,19 +323,31 @@ class SBusFPGA(SoCCore):
|
||||
#getattr(self,"prom").mem.init = prom_data
|
||||
#getattr(self,"prom").mem.depth = 2**14
|
||||
|
||||
self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"),
|
||||
memtype = "DDR3",
|
||||
nphases = 4,
|
||||
sys_clk_freq = sys_clk_freq)
|
||||
self.add_sdram("sdram",
|
||||
phy = self.ddrphy,
|
||||
module = MT41J128M16(sys_clk_freq, "1:4"),
|
||||
l2_cache_size = 0,
|
||||
)
|
||||
if (sdram):
|
||||
self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"),
|
||||
memtype = "DDR3",
|
||||
nphases = 4,
|
||||
sys_clk_freq = sys_clk_freq)
|
||||
self.add_sdram("sdram",
|
||||
phy = self.ddrphy,
|
||||
module = MT41J128M16(sys_clk_freq, "1:4"),
|
||||
l2_cache_size = 0,
|
||||
)
|
||||
avail_sdram = self.bus.regions["main_ram"].size
|
||||
else:
|
||||
avail_sdram = 0
|
||||
|
||||
if (cg3):
|
||||
if (avail_sdram >= cg3_fb_size):
|
||||
avail_sdram = avail_sdram - cg3_fb_size
|
||||
else:
|
||||
print("***** ERROR ***** Can't have a FrameBuffer without main ram\n")
|
||||
assert(False)
|
||||
|
||||
# don't enable anything on the SBus side for 20 seconds after power up
|
||||
# this avoids FPGA initialization messing with the cold boot process
|
||||
# requires us to reset the SPARCstation afterward so the FPGA board
|
||||
# is properly identified
|
||||
# is properly identified - or to 'probe-slot'
|
||||
# This is in the 'native' ClockDomain that is never reset
|
||||
hold_reset_ctr = Signal(30, reset=960000000)
|
||||
self.sync.native += If(hold_reset_ctr>0, hold_reset_ctr.eq(hold_reset_ctr - 1))
|
||||
@@ -252,26 +365,31 @@ class SBusFPGA(SoCCore):
|
||||
# burst_size=16 should work on Ultra systems, but then they probably should go for 64-bits ET as well...
|
||||
# Older systems are probably limited to burst_size=4, (it should always be available)
|
||||
burst_size=8
|
||||
self.submodules.tosbus_fifo = ClockDomainsRenamer({"read": "sbus", "write": "sys"})(AsyncFIFOBuffered(width=(32+burst_size*32), depth=burst_size))
|
||||
self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+burst_size*32), depth=burst_size))
|
||||
self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "sbus", "write": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+32), depth=burst_size))
|
||||
if (sdram):
|
||||
self.submodules.tosbus_fifo = ClockDomainsRenamer({"read": "sbus", "write": "sys"})(AsyncFIFOBuffered(width=(32+burst_size*32), depth=burst_size))
|
||||
self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+burst_size*32), depth=burst_size))
|
||||
self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "sbus", "write": "sys"})(AsyncFIFOBuffered(width=((30-log2_int(burst_size))+32), depth=burst_size))
|
||||
self.submodules.dram_dma_writer = LiteDRAMDMAWriter(port=self.sdram.crossbar.get_port(mode="write", data_width=burst_size*32),
|
||||
fifo_depth=4,
|
||||
fifo_buffered=True)
|
||||
|
||||
self.submodules.dram_dma_reader = LiteDRAMDMAReader(port=self.sdram.crossbar.get_port(mode="read", data_width=burst_size*32),
|
||||
fifo_depth=4,
|
||||
fifo_buffered=True)
|
||||
|
||||
self.submodules.dram_dma_writer = LiteDRAMDMAWriter(port=self.sdram.crossbar.get_port(mode="write", data_width=burst_size*32),
|
||||
fifo_depth=4,
|
||||
fifo_buffered=True)
|
||||
|
||||
self.submodules.dram_dma_reader = LiteDRAMDMAReader(port=self.sdram.crossbar.get_port(mode="read", data_width=burst_size*32),
|
||||
fifo_depth=4,
|
||||
fifo_buffered=True)
|
||||
|
||||
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
||||
tosbus_fifo=self.tosbus_fifo,
|
||||
fromsbus_fifo=self.fromsbus_fifo,
|
||||
fromsbus_req_fifo=self.fromsbus_req_fifo,
|
||||
dram_dma_writer=self.dram_dma_writer,
|
||||
dram_dma_reader=self.dram_dma_reader,
|
||||
burst_size=burst_size,
|
||||
do_checksum = True)
|
||||
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
||||
tosbus_fifo=self.tosbus_fifo,
|
||||
fromsbus_fifo=self.fromsbus_fifo,
|
||||
fromsbus_req_fifo=self.fromsbus_req_fifo,
|
||||
dram_dma_writer=self.dram_dma_writer,
|
||||
dram_dma_reader=self.dram_dma_reader,
|
||||
mem_size=avail_sdram//1048576,
|
||||
burst_size=burst_size,
|
||||
do_checksum = True)
|
||||
else:
|
||||
self.submodules.tosbus_fifo = None
|
||||
self.submodules.fromsbus_fifo = None
|
||||
self.submodules.fromsbus_req_fifo = None
|
||||
|
||||
_sbus_bus = SBusFPGABus(platform=self.platform,
|
||||
hold_reset=hold_reset,
|
||||
@@ -280,7 +398,10 @@ class SBusFPGA(SoCCore):
|
||||
tosbus_fifo=self.tosbus_fifo,
|
||||
fromsbus_fifo=self.fromsbus_fifo,
|
||||
fromsbus_req_fifo=self.fromsbus_req_fifo,
|
||||
burst_size=burst_size)
|
||||
version=version,
|
||||
burst_size=burst_size,
|
||||
cg3_fb_size=cg3_fb_size,
|
||||
cg3_base=(self.wb_mem_map["main_ram"] + avail_sdram))
|
||||
#self.submodules.sbus_bus = _sbus_bus
|
||||
self.submodules.sbus_bus = ClockDomainsRenamer("sbus")(_sbus_bus)
|
||||
self.submodules.sbus_bus_stat = SBusFPGABusStat(sbus_bus = self.sbus_bus)
|
||||
@@ -300,41 +421,109 @@ class SBusFPGA(SoCCore):
|
||||
# the local engine.py was slightly modified to have configurable names, so we can have 'clk50', 'clk100', 'clk200'
|
||||
# Beware that Engine implicitely runs in 'sys' by default, need to rename that one as well
|
||||
# Actually renaming 'sys' doesn't work - unless we can CDC the CSRs as well
|
||||
self.submodules.curve25519engine = ClockDomainsRenamer({"eng_clk":"clk50", "rf_clk":"clk200", "mul_clk":"clk100_gated"})(Engine(platform=platform,prefix=self.mem_map.get("curve25519engine", None))) # , "sys":"clk100"
|
||||
#self.submodules.curve25519engine_wishbone_cdc = wishbone.WishboneDomainCrossingMaster(platform=self.platform, slave=self.curve25519engine.bus, cd_master="sys", cd_slave="clk100")
|
||||
#self.bus.add_slave("curve25519engine", self.curve25519engine_wishbone_cdc, SoCRegion(origin=self.mem_map.get("curve25519engine", None), size=0x20000, cached=False))
|
||||
self.bus.add_slave("curve25519engine", self.curve25519engine.bus, SoCRegion(origin=self.mem_map.get("curve25519engine", None), size=0x20000, cached=False))
|
||||
self.bus.add_master(name="curve25519engineLS", master=self.curve25519engine.busls)
|
||||
#self.submodules.curve25519_on_sync = BusSynchronizer(width = 1, idomain = "clk100", odomain = "sys")
|
||||
#self.comb += self.curve25519_on_sync.i.eq(self.curve25519engine.power.fields.on)
|
||||
#self.comb += self.crg.curve25519_on.eq(self.curve25519_on_sync.o)
|
||||
self.comb += self.crg.curve25519_on.eq(self.curve25519engine.power.fields.on)
|
||||
if (engine):
|
||||
self.submodules.curve25519engine = ClockDomainsRenamer({"eng_clk":"clk50", "rf_clk":"clk200", "mul_clk":"clk100_gated"})(Engine(platform=platform,prefix=self.mem_map.get("curve25519engine", None))) # , "sys":"clk100"
|
||||
#self.submodules.curve25519engine_wishbone_cdc = wishbone.WishboneDomainCrossingMaster(platform=self.platform, slave=self.curve25519engine.bus, cd_master="sys", cd_slave="clk100")
|
||||
#self.bus.add_slave("curve25519engine", self.curve25519engine_wishbone_cdc, SoCRegion(origin=self.mem_map.get("curve25519engine", None), size=0x20000, cached=False))
|
||||
self.bus.add_slave("curve25519engine", self.curve25519engine.bus, SoCRegion(origin=self.mem_map.get("curve25519engine", None), size=0x20000, cached=False))
|
||||
self.bus.add_master(name="curve25519engineLS", master=self.curve25519engine.busls)
|
||||
#self.submodules.curve25519_on_sync = BusSynchronizer(width = 1, idomain = "clk100", odomain = "sys")
|
||||
#self.comb += self.curve25519_on_sync.i.eq(self.curve25519engine.power.fields.on)
|
||||
#self.comb += self.crg.curve25519_on.eq(self.curve25519_on_sync.o)
|
||||
self.comb += self.crg.curve25519_on.eq(self.curve25519engine.power.fields.on)
|
||||
|
||||
if (i2c):
|
||||
self.submodules.i2c = i2c.RTLI2C(platform, pads=platform.request("i2c"))
|
||||
|
||||
if (cg3):
|
||||
self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga")
|
||||
self.submodules.cg3 = cg3_fb.cg3(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga") # clock_domain for the VGA side, cg3 is running in cd_sys
|
||||
self.bus.add_slave("cg3_registers", self.cg3.bus, SoCRegion(origin=self.mem_map.get("cg3_registers", None), size=0x1000, cached=False))
|
||||
##self.submodules.cgtrois = ClockDomainsRenamer({"eng_clk":"clk50", "rf_clk":"clk200", "mul_clk":"clk100_gated"})(cgtrois.CGTrois(platform=platform,prefix=self.mem_map.get("curve25519engine", None), hres=hres, vres=vres, base=(self.wb_mem_map["main_ram"] + avail_sdram)))
|
||||
##self.add_video_framebuffer(phy=self.videophy, timings=cg3_res, clock_domain="vga")
|
||||
pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(~self.cg3.video_framebuffer.dma.source.valid)
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(~self.cg3.video_framebuffer.conv.source.valid)
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(~self.cg3.video_framebuffer.cdc.source.valid)
|
||||
self.comb += pad_SBUS_DATA_OE_LED.eq(~self.cg3.video_framebuffer_vtg.source.valid)
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(self.cg3.video_framebuffer.underflow)
|
||||
##self.comb += pad_SBUS_DATA_OE_LED.eq(self.video_framebuffer.underflow)
|
||||
|
||||
print("IRQ to Device map:\n")
|
||||
print(platform.irq_device_map)
|
||||
print("Device to IRQ map:\n")
|
||||
print(platform.device_irq_map)
|
||||
|
||||
#disable remaining IRQs
|
||||
if (version == "V1.0"):
|
||||
platform.avail_irqs.add(7)
|
||||
|
||||
for irq in platform.avail_irqs:
|
||||
pad_int = platform.request(f"SBUS_3V3_INT{irq}s")
|
||||
oe_int = Signal(reset = 0)
|
||||
val_int = Signal(reset = 1)
|
||||
self.specials += Tristate(pad_int, val_int, oe_int, None)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="SbusFPGA")
|
||||
parser.add_argument("--build", action="store_true", help="Build bitstream")
|
||||
parser.add_argument("--version", default="V1.0", help="SBusFPGA board version (default V1.0)")
|
||||
parser.add_argument("--usb", action="store_true", help="add a USB OHCI controller")
|
||||
parser.add_argument("--sys-clk-freq", default=100e6, help="SBusFPGA system clock (default 100e6 = 100 MHz)")
|
||||
parser.add_argument("--sdram", action="store_true", help="add a SDRAM controller (mandatory) [all]")
|
||||
parser.add_argument("--usb", action="store_true", help="add a USB OHCI controller [V1.2]")
|
||||
parser.add_argument("--engine", action="store_true", help="add a Engine crypto core [all]")
|
||||
parser.add_argument("--i2c", action="store_true", help="add an I2C bus [none, placeholder]")
|
||||
parser.add_argument("--cg3", action="store_true", help="add a CG3 framebuffer [V1.2+VGA_RGB222 pmod]")
|
||||
parser.add_argument("--cg3-res", default="1152x900@76Hz", help="Specify the CG3 resolution")
|
||||
builder_args(parser)
|
||||
vivado_build_args(parser)
|
||||
args = parser.parse_args()
|
||||
|
||||
if (args.sdram == False):
|
||||
print(" ***** ERROR ***** : disabling the SDRAM doesn't actually work (too integrated in the SBus FSM...)\n")
|
||||
assert(False)
|
||||
if (args.usb and (args.version == "V1.0")):
|
||||
print(" ***** WARNING ***** : USB on V1.0 is an ugly hack \n");
|
||||
if (args.i2c):
|
||||
print(" ***** WARNING ***** : I2C on V1.x is for testing the core \n");
|
||||
if (args.cg3 and (args.version == "V1.0")):
|
||||
print(" ***** ERROR ***** : VGA not supported on V.10\n")
|
||||
assert(False)
|
||||
|
||||
soc = SBusFPGA(**soc_core_argdict(args),
|
||||
version=args.version,
|
||||
usb=args.usb)
|
||||
sys_clk_freq=int(float(args.sys_clk_freq)),
|
||||
sdram=args.sdram,
|
||||
usb=args.usb,
|
||||
engine=args.engine,
|
||||
i2c=args.i2c,
|
||||
cg3=args.cg3,
|
||||
cg3_res=args.cg3_res)
|
||||
#soc.add_uart(name="uart", baudrate=115200, fifo_depth=16)
|
||||
|
||||
version_for_filename = args.version.replace(".", "_")
|
||||
|
||||
soc.platform.name += "_" + version_for_filename
|
||||
|
||||
builder = Builder(soc, **builder_argdict(args))
|
||||
builder.build(**vivado_build_argdict(args), run=args.build)
|
||||
|
||||
# Generate modified CSR registers definitions/access functions to netbsd_csr.h.
|
||||
# should be split per-device (and without base) to still work if we have identical devices in different configurations on multiple boards
|
||||
csr_contents = sbus_to_fpga_export.get_csr_header(
|
||||
# now it is split
|
||||
#csr_contents = sbus_to_fpga_export.get_csr_header(
|
||||
# regions = soc.csr_regions,
|
||||
# constants = soc.constants,
|
||||
# csr_base = soc.mem_regions['csr'].origin)
|
||||
#write_to_file(os.path.join("netbsd_csr.h"), csr_contents)
|
||||
|
||||
csr_contents_dict = sbus_to_fpga_export.get_csr_header_split(
|
||||
regions = soc.csr_regions,
|
||||
constants = soc.constants,
|
||||
csr_base = soc.mem_regions['csr'].origin)
|
||||
write_to_file(os.path.join("netbsd_csr.h"), csr_contents)
|
||||
|
||||
for name in csr_contents_dict.keys():
|
||||
write_to_file(os.path.join("sbusfpga_csr_{}.h".format(name)), csr_contents_dict[name])
|
||||
|
||||
# tells the prom where to find what
|
||||
# just one, as that is board-specific
|
||||
# BEWARE! then need to run 'forth_to_migen_rom.sh' *and* regenerate the bitstream with the proper PROM built-in!
|
||||
@@ -342,9 +531,20 @@ def main():
|
||||
csr_forth_contents = sbus_to_fpga_export.get_csr_forth_header(
|
||||
csr_regions = soc.csr_regions,
|
||||
mem_regions = soc.mem_regions,
|
||||
device_irq_map = soc.platform.device_irq_map,
|
||||
constants = soc.constants,
|
||||
csr_base = soc.mem_regions['csr'].origin)
|
||||
write_to_file(os.path.join("prom_csr.fth"), csr_forth_contents)
|
||||
write_to_file(os.path.join(f"prom_csr_{version_for_filename}.fth"), csr_forth_contents)
|
||||
|
||||
prom_content = sbus_to_fpga_prom.get_prom(soc=soc, version=args.version,
|
||||
usb=args.usb,
|
||||
sdram=args.sdram,
|
||||
engine=args.engine,
|
||||
i2c=args.i2c,
|
||||
cg3=args.cg3,
|
||||
cg3_res=args.cg3_res)
|
||||
write_to_file(os.path.join(f"prom_{version_for_filename}.fth"), prom_content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,228 +1,228 @@
|
||||
: dphy_rst_rd ( -- csr_value )
|
||||
mregs-virt h# 1000 + l@
|
||||
ddrphy-virt h# 0000 + l@
|
||||
;
|
||||
: dphy_half_sys8x_taps_rd ( -- csr_value )
|
||||
mregs-virt h# 1004 + l@
|
||||
ddrphy-virt h# 0004 + l@
|
||||
;
|
||||
: dphy_wlevel_en_rd ( -- csr_value )
|
||||
mregs-virt h# 1008 + l@
|
||||
ddrphy-virt h# 0008 + l@
|
||||
;
|
||||
: dphy_wlevel_strobe_rd ( -- csr_value )
|
||||
mregs-virt h# 100c + l@
|
||||
ddrphy-virt h# 000c + l@
|
||||
;
|
||||
: dphy_dly_sel_rd ( -- csr_value )
|
||||
mregs-virt h# 1010 + l@
|
||||
ddrphy-virt h# 0010 + l@
|
||||
;
|
||||
: dphy_rdly_dq_rst_rd ( -- csr_value )
|
||||
mregs-virt h# 1014 + l@
|
||||
ddrphy-virt h# 0014 + l@
|
||||
;
|
||||
: dphy_rdly_dq_inc_rd ( -- csr_value )
|
||||
mregs-virt h# 1018 + l@
|
||||
ddrphy-virt h# 0018 + l@
|
||||
;
|
||||
: dphy_rdly_dq_bitslip_rst_rd ( -- csr_value )
|
||||
mregs-virt h# 101c + l@
|
||||
ddrphy-virt h# 001c + l@
|
||||
;
|
||||
: dphy_rdly_dq_bitslip_rd ( -- csr_value )
|
||||
mregs-virt h# 1020 + l@
|
||||
ddrphy-virt h# 0020 + l@
|
||||
;
|
||||
: dphy_wdly_dq_bitslip_rst_rd ( -- csr_value )
|
||||
mregs-virt h# 1024 + l@
|
||||
ddrphy-virt h# 0024 + l@
|
||||
;
|
||||
: dphy_wdly_dq_bitslip_rd ( -- csr_value )
|
||||
mregs-virt h# 1028 + l@
|
||||
ddrphy-virt h# 0028 + l@
|
||||
;
|
||||
: dphy_rdphase_rd ( -- csr_value )
|
||||
mregs-virt h# 102c + l@
|
||||
ddrphy-virt h# 002c + l@
|
||||
;
|
||||
: dphy_wrphase_rd ( -- csr_value )
|
||||
mregs-virt h# 1030 + l@
|
||||
ddrphy-virt h# 0030 + l@
|
||||
;
|
||||
: sdr_dfii_control_rd ( -- csr_value )
|
||||
mregs-virt h# 2000 + l@
|
||||
sdram-virt h# 0000 + l@
|
||||
;
|
||||
: sdr_dfii_pi0_command_rd ( -- csr_value )
|
||||
mregs-virt h# 2004 + l@
|
||||
sdram-virt h# 0004 + l@
|
||||
;
|
||||
: sdr_dfii_pi0_command_issue_rd ( -- csr_value )
|
||||
mregs-virt h# 2008 + l@
|
||||
sdram-virt h# 0008 + l@
|
||||
;
|
||||
: sdr_dfii_pi0_address_rd ( -- csr_value )
|
||||
mregs-virt h# 200c + l@
|
||||
sdram-virt h# 000c + l@
|
||||
;
|
||||
: sdr_dfii_pi0_baddress_rd ( -- csr_value )
|
||||
mregs-virt h# 2010 + l@
|
||||
sdram-virt h# 0010 + l@
|
||||
;
|
||||
: sdr_dfii_pi0_wrdata_rd ( -- csr_value )
|
||||
mregs-virt h# 2014 + l@
|
||||
sdram-virt h# 0014 + l@
|
||||
;
|
||||
: sdr_dfii_pi0_rddata_rd ( -- csr_value )
|
||||
mregs-virt h# 2018 + l@
|
||||
sdram-virt h# 0018 + l@
|
||||
;
|
||||
: sdr_dfii_pi1_command_rd ( -- csr_value )
|
||||
mregs-virt h# 201c + l@
|
||||
sdram-virt h# 001c + l@
|
||||
;
|
||||
: sdr_dfii_pi1_command_issue_rd ( -- csr_value )
|
||||
mregs-virt h# 2020 + l@
|
||||
sdram-virt h# 0020 + l@
|
||||
;
|
||||
: sdr_dfii_pi1_address_rd ( -- csr_value )
|
||||
mregs-virt h# 2024 + l@
|
||||
sdram-virt h# 0024 + l@
|
||||
;
|
||||
: sdr_dfii_pi1_baddress_rd ( -- csr_value )
|
||||
mregs-virt h# 2028 + l@
|
||||
sdram-virt h# 0028 + l@
|
||||
;
|
||||
: sdr_dfii_pi1_wrdata_rd ( -- csr_value )
|
||||
mregs-virt h# 202c + l@
|
||||
sdram-virt h# 002c + l@
|
||||
;
|
||||
: sdr_dfii_pi1_rddata_rd ( -- csr_value )
|
||||
mregs-virt h# 2030 + l@
|
||||
sdram-virt h# 0030 + l@
|
||||
;
|
||||
: sdr_dfii_pi2_command_rd ( -- csr_value )
|
||||
mregs-virt h# 2034 + l@
|
||||
sdram-virt h# 0034 + l@
|
||||
;
|
||||
: sdr_dfii_pi2_command_issue_rd ( -- csr_value )
|
||||
mregs-virt h# 2038 + l@
|
||||
sdram-virt h# 0038 + l@
|
||||
;
|
||||
: sdr_dfii_pi2_address_rd ( -- csr_value )
|
||||
mregs-virt h# 203c + l@
|
||||
sdram-virt h# 003c + l@
|
||||
;
|
||||
: sdr_dfii_pi2_baddress_rd ( -- csr_value )
|
||||
mregs-virt h# 2040 + l@
|
||||
sdram-virt h# 0040 + l@
|
||||
;
|
||||
: sdr_dfii_pi2_wrdata_rd ( -- csr_value )
|
||||
mregs-virt h# 2044 + l@
|
||||
sdram-virt h# 0044 + l@
|
||||
;
|
||||
: sdr_dfii_pi2_rddata_rd ( -- csr_value )
|
||||
mregs-virt h# 2048 + l@
|
||||
sdram-virt h# 0048 + l@
|
||||
;
|
||||
: sdr_dfii_pi3_command_rd ( -- csr_value )
|
||||
mregs-virt h# 204c + l@
|
||||
sdram-virt h# 004c + l@
|
||||
;
|
||||
: sdr_dfii_pi3_command_issue_rd ( -- csr_value )
|
||||
mregs-virt h# 2050 + l@
|
||||
sdram-virt h# 0050 + l@
|
||||
;
|
||||
: sdr_dfii_pi3_address_rd ( -- csr_value )
|
||||
mregs-virt h# 2054 + l@
|
||||
sdram-virt h# 0054 + l@
|
||||
;
|
||||
: sdr_dfii_pi3_baddress_rd ( -- csr_value )
|
||||
mregs-virt h# 2058 + l@
|
||||
sdram-virt h# 0058 + l@
|
||||
;
|
||||
: sdr_dfii_pi3_wrdata_rd ( -- csr_value )
|
||||
mregs-virt h# 205c + l@
|
||||
sdram-virt h# 005c + l@
|
||||
;
|
||||
: sdr_dfii_pi3_rddata_rd ( -- csr_value )
|
||||
mregs-virt h# 2060 + l@
|
||||
sdram-virt h# 0060 + l@
|
||||
;
|
||||
: dphy_rst_wr ( value -- )
|
||||
mregs-virt h# 1000 + l!
|
||||
ddrphy-virt h# 0000 + l!
|
||||
;
|
||||
: dphy_half_sys8x_taps_wr ( value -- )
|
||||
mregs-virt h# 1004 + l!
|
||||
ddrphy-virt h# 0004 + l!
|
||||
;
|
||||
: dphy_wlevel_en_wr ( value -- )
|
||||
mregs-virt h# 1008 + l!
|
||||
ddrphy-virt h# 0008 + l!
|
||||
;
|
||||
: dphy_wlevel_strobe_wr ( value -- )
|
||||
mregs-virt h# 100c + l!
|
||||
ddrphy-virt h# 000c + l!
|
||||
;
|
||||
: dphy_dly_sel_wr ( value -- )
|
||||
mregs-virt h# 1010 + l!
|
||||
ddrphy-virt h# 0010 + l!
|
||||
;
|
||||
: dphy_rdly_dq_rst_wr ( value -- )
|
||||
mregs-virt h# 1014 + l!
|
||||
ddrphy-virt h# 0014 + l!
|
||||
;
|
||||
: dphy_rdly_dq_inc_wr ( value -- )
|
||||
mregs-virt h# 1018 + l!
|
||||
ddrphy-virt h# 0018 + l!
|
||||
;
|
||||
: dphy_rdly_dq_bitslip_rst_wr ( value -- )
|
||||
mregs-virt h# 101c + l!
|
||||
ddrphy-virt h# 001c + l!
|
||||
;
|
||||
: dphy_rdly_dq_bitslip_wr ( value -- )
|
||||
mregs-virt h# 1020 + l!
|
||||
ddrphy-virt h# 0020 + l!
|
||||
;
|
||||
: dphy_wdly_dq_bitslip_rst_wr ( value -- )
|
||||
mregs-virt h# 1024 + l!
|
||||
ddrphy-virt h# 0024 + l!
|
||||
;
|
||||
: dphy_wdly_dq_bitslip_wr ( value -- )
|
||||
mregs-virt h# 1028 + l!
|
||||
ddrphy-virt h# 0028 + l!
|
||||
;
|
||||
: dphy_rdphase_wr ( value -- )
|
||||
mregs-virt h# 102c + l!
|
||||
ddrphy-virt h# 002c + l!
|
||||
;
|
||||
: dphy_wrphase_wr ( value -- )
|
||||
mregs-virt h# 1030 + l!
|
||||
ddrphy-virt h# 0030 + l!
|
||||
;
|
||||
: sdr_dfii_control_wr ( value -- )
|
||||
mregs-virt h# 2000 + l!
|
||||
sdram-virt h# 0000 + l!
|
||||
;
|
||||
: sdr_dfii_pi0_command_wr ( value -- )
|
||||
mregs-virt h# 2004 + l!
|
||||
sdram-virt h# 0004 + l!
|
||||
;
|
||||
: sdr_dfii_pi0_command_issue_wr ( value -- )
|
||||
mregs-virt h# 2008 + l!
|
||||
sdram-virt h# 0008 + l!
|
||||
;
|
||||
: sdr_dfii_pi0_address_wr ( value -- )
|
||||
mregs-virt h# 200c + l!
|
||||
sdram-virt h# 000c + l!
|
||||
;
|
||||
: sdr_dfii_pi0_baddress_wr ( value -- )
|
||||
mregs-virt h# 2010 + l!
|
||||
sdram-virt h# 0010 + l!
|
||||
;
|
||||
: sdr_dfii_pi0_wrdata_wr ( value -- )
|
||||
mregs-virt h# 2014 + l!
|
||||
sdram-virt h# 0014 + l!
|
||||
;
|
||||
: sdr_dfii_pi0_rddata_wr ( value -- )
|
||||
mregs-virt h# 2018 + l!
|
||||
sdram-virt h# 0018 + l!
|
||||
;
|
||||
: sdr_dfii_pi1_command_wr ( value -- )
|
||||
mregs-virt h# 201c + l!
|
||||
sdram-virt h# 001c + l!
|
||||
;
|
||||
: sdr_dfii_pi1_command_issue_wr ( value -- )
|
||||
mregs-virt h# 2020 + l!
|
||||
sdram-virt h# 0020 + l!
|
||||
;
|
||||
: sdr_dfii_pi1_address_wr ( value -- )
|
||||
mregs-virt h# 2024 + l!
|
||||
sdram-virt h# 0024 + l!
|
||||
;
|
||||
: sdr_dfii_pi1_baddress_wr ( value -- )
|
||||
mregs-virt h# 2028 + l!
|
||||
sdram-virt h# 0028 + l!
|
||||
;
|
||||
: sdr_dfii_pi1_wrdata_wr ( value -- )
|
||||
mregs-virt h# 202c + l!
|
||||
sdram-virt h# 002c + l!
|
||||
;
|
||||
: sdr_dfii_pi1_rddata_wr ( value -- )
|
||||
mregs-virt h# 2030 + l!
|
||||
sdram-virt h# 0030 + l!
|
||||
;
|
||||
: sdr_dfii_pi2_command_wr ( value -- )
|
||||
mregs-virt h# 2034 + l!
|
||||
sdram-virt h# 0034 + l!
|
||||
;
|
||||
: sdr_dfii_pi2_command_issue_wr ( value -- )
|
||||
mregs-virt h# 2038 + l!
|
||||
sdram-virt h# 0038 + l!
|
||||
;
|
||||
: sdr_dfii_pi2_address_wr ( value -- )
|
||||
mregs-virt h# 203c + l!
|
||||
sdram-virt h# 003c + l!
|
||||
;
|
||||
: sdr_dfii_pi2_baddress_wr ( value -- )
|
||||
mregs-virt h# 2040 + l!
|
||||
sdram-virt h# 0040 + l!
|
||||
;
|
||||
: sdr_dfii_pi2_wrdata_wr ( value -- )
|
||||
mregs-virt h# 2044 + l!
|
||||
sdram-virt h# 0044 + l!
|
||||
;
|
||||
: sdr_dfii_pi2_rddata_wr ( value -- )
|
||||
mregs-virt h# 2048 + l!
|
||||
sdram-virt h# 0048 + l!
|
||||
;
|
||||
: sdr_dfii_pi3_command_wr ( value -- )
|
||||
mregs-virt h# 204c + l!
|
||||
sdram-virt h# 004c + l!
|
||||
;
|
||||
: sdr_dfii_pi3_command_issue_wr ( value -- )
|
||||
mregs-virt h# 2050 + l!
|
||||
sdram-virt h# 0050 + l!
|
||||
;
|
||||
: sdr_dfii_pi3_address_wr ( value -- )
|
||||
mregs-virt h# 2054 + l!
|
||||
sdram-virt h# 0054 + l!
|
||||
;
|
||||
: sdr_dfii_pi3_baddress_wr ( value -- )
|
||||
mregs-virt h# 2058 + l!
|
||||
sdram-virt h# 0058 + l!
|
||||
;
|
||||
: sdr_dfii_pi3_wrdata_wr ( value -- )
|
||||
mregs-virt h# 205c + l!
|
||||
sdram-virt h# 005c + l!
|
||||
;
|
||||
: sdr_dfii_pi3_rddata_wr ( value -- )
|
||||
mregs-virt h# 2060 + l!
|
||||
sdram-virt h# 0060 + l!
|
||||
;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
headers
|
||||
|
||||
fload sdram_csr.fth
|
||||
|
||||
external
|
||||
\ useful stuff
|
||||
|
||||
: popcnt ( n -- u)
|
||||
0 swap
|
||||
BEGIN dup WHILE tuck 1 AND + swap 1 rshift REPEAT
|
||||
DROP
|
||||
;
|
||||
\ : popcnt ( n -- u)
|
||||
\ 0 swap
|
||||
\ BEGIN dup WHILE tuck 1 AND + swap 1 rshift REPEAT
|
||||
\ DROP
|
||||
\ ;
|
||||
|
||||
: cdelay ( count -- )
|
||||
\ Forth loop always have a least one iteration
|
||||
@@ -17,7 +15,7 @@ external
|
||||
else drop then
|
||||
;
|
||||
|
||||
headers
|
||||
\ helpers
|
||||
|
||||
: sdram_software_control_on ( -- )
|
||||
sdr_dfii_control_rd
|
||||
@@ -29,6 +27,8 @@ headers
|
||||
h# 1 <> if h# 1 sdr_dfii_control_wr then
|
||||
;
|
||||
|
||||
\ only p0 is really used
|
||||
|
||||
: command_p0 ( cmd -- )
|
||||
sdr_dfii_pi0_command_wr
|
||||
1 sdr_dfii_pi0_command_issue_wr
|
||||
@@ -46,470 +46,52 @@ headers
|
||||
1 sdr_dfii_pi3_command_issue_wr
|
||||
;
|
||||
|
||||
\ init for 2.13a (might need change for others?)
|
||||
|
||||
: init_sequence ( -- )
|
||||
.( init_sequence ) cr
|
||||
\ .( init_sequence ) cr
|
||||
\ Release reset
|
||||
h# 0 sdr_dfii_pi0_address_wr
|
||||
h# 0 sdr_dfii_pi0_baddress_wr
|
||||
h# c sdr_dfii_control_wr
|
||||
50 ms
|
||||
5 ms
|
||||
|
||||
\ Bring CKE high
|
||||
h# 0 sdr_dfii_pi0_address_wr
|
||||
h# 0 sdr_dfii_pi0_baddress_wr
|
||||
h# e sdr_dfii_control_wr
|
||||
10 ms
|
||||
1 ms
|
||||
|
||||
\ Load Mode register 2, CWL=5
|
||||
h# 200 sdr_dfii_pi0_address_wr
|
||||
h# 2 sdr_dfii_pi0_baddress_wr
|
||||
h# f command_p0
|
||||
|
||||
\ Load Mode register 3
|
||||
h# 0 sdr_dfii_pi0_address_wr
|
||||
h# 3 sdr_dfii_pi0_baddress_wr
|
||||
h# f command_p0
|
||||
|
||||
\ Load Mode Register 1
|
||||
h# 6 sdr_dfii_pi0_address_wr
|
||||
h# 1 sdr_dfii_pi0_baddress_wr
|
||||
h# f command_p0
|
||||
|
||||
\ Load Mode Register 0, CL=6, BL=8
|
||||
h# 920 sdr_dfii_pi0_address_wr
|
||||
h# 0 sdr_dfii_pi0_baddress_wr
|
||||
h# f command_p0
|
||||
200 cdelay
|
||||
|
||||
\ ZQ Calibration
|
||||
h# 400 sdr_dfii_pi0_address_wr
|
||||
0 sdr_dfii_pi0_baddress_wr
|
||||
h# 3 command_p0
|
||||
200 cdelay
|
||||
;
|
||||
|
||||
: sdram_read_leveling_rst_delay ( modulenum -- )
|
||||
h# 1 swap << dphy_dly_sel_wr
|
||||
h# 1 dphy_rdly_dq_rst_wr
|
||||
h# 0 dphy_dly_sel_wr
|
||||
;
|
||||
|
||||
: sdram_read_leveling_inc_delay ( modulenum -- )
|
||||
h# 1 swap << dphy_dly_sel_wr
|
||||
h# 1 dphy_rdly_dq_inc_wr
|
||||
h# 0 dphy_dly_sel_wr
|
||||
;
|
||||
|
||||
: sdram_read_leveling_rst_bitslip ( modulenum -- )
|
||||
h# 1 swap << dphy_dly_sel_wr
|
||||
h# 1 dphy_rdly_dq_bitslip_rst_wr
|
||||
h# 0 dphy_dly_sel_wr
|
||||
;
|
||||
|
||||
: sdram_read_leveling_inc_bitslip ( modulenum -- )
|
||||
h# 1 swap << dphy_dly_sel_wr
|
||||
h# 1 dphy_rdly_dq_bitslip_wr
|
||||
h# 0 dphy_dly_sel_wr
|
||||
;
|
||||
|
||||
: lfsr ( bits prev -- res )
|
||||
dup 1 and not ( bits prev -- bits prev ~{prev&1} )
|
||||
swap 1 >> ( bits prev ~{prev&1} -- bits ~{prev&1} {prev>>1} )
|
||||
swap ( bits prev ~{prev&1} -- bits {prev>>1} ~{prev&1} )
|
||||
rot ( bits {prev>>1} ~{prev&1} -- {prev>>1} ~{prev&1} bits )
|
||||
\ assume bits is 32, 'cause it is
|
||||
drop h# 80200003 ( {prev>>1} ~{prev&1} bits -- {prev>>1} ~{prev&1} lfsr_taps[bits] )
|
||||
and
|
||||
xor
|
||||
;
|
||||
|
||||
: sdram_activate_test_row ( -- )
|
||||
h# 0 sdr_dfii_pi0_address_wr
|
||||
h# 0 sdr_dfii_pi0_baddress_wr
|
||||
h# 9 command_p0
|
||||
15 cdelay
|
||||
;
|
||||
|
||||
: sdram_precharge_test_row ( -- )
|
||||
h# 0 sdr_dfii_pi0_address_wr
|
||||
h# 0 sdr_dfii_pi0_baddress_wr
|
||||
h# b command_p0
|
||||
15 cdelay
|
||||
;
|
||||
|
||||
: command_px ( phase value -- )
|
||||
over 3 = if dup command_p3 then
|
||||
over 2 = if dup command_p2 then
|
||||
over 1 = if dup command_p1 then
|
||||
over 0 = if dup command_p0 then
|
||||
2drop
|
||||
;
|
||||
|
||||
: command_prd ( value -- )
|
||||
dphy_rdphase_rd
|
||||
swap command_px
|
||||
;
|
||||
|
||||
: command_pwr ( value -- )
|
||||
dphy_wrphase_rd
|
||||
swap command_px
|
||||
;
|
||||
|
||||
: sdr_dfii_pix_address_wr ( phase value -- )
|
||||
over 3 = if dup sdr_dfii_pi3_address_wr then
|
||||
over 2 = if dup sdr_dfii_pi2_address_wr then
|
||||
over 1 = if dup sdr_dfii_pi1_address_wr then
|
||||
over 0 = if dup sdr_dfii_pi0_address_wr then
|
||||
2drop
|
||||
;
|
||||
|
||||
: sdr_dfii_pird_address_wr ( value -- )
|
||||
dphy_rdphase_rd
|
||||
swap sdr_dfii_pix_address_wr
|
||||
;
|
||||
|
||||
: sdr_dfii_piwr_address_wr ( value -- )
|
||||
dphy_wrphase_rd
|
||||
swap sdr_dfii_pix_address_wr
|
||||
;
|
||||
|
||||
: sdr_dfii_pix_baddress_wr ( phase value -- )
|
||||
over 3 = if dup sdr_dfii_pi3_baddress_wr then
|
||||
over 2 = if dup sdr_dfii_pi2_baddress_wr then
|
||||
over 1 = if dup sdr_dfii_pi1_baddress_wr then
|
||||
over 0 = if dup sdr_dfii_pi0_baddress_wr then
|
||||
2drop
|
||||
;
|
||||
|
||||
: sdr_dfii_pird_baddress_wr ( value -- )
|
||||
dphy_rdphase_rd
|
||||
swap sdr_dfii_pix_baddress_wr
|
||||
;
|
||||
|
||||
: sdr_dfii_piwr_baddress_wr ( value -- )
|
||||
dphy_wrphase_rd
|
||||
swap sdr_dfii_pix_baddress_wr
|
||||
;
|
||||
|
||||
: sdr_wr_rd_chk_tst_pat_get ( seed -- A B C D )
|
||||
\ .( sdr_wr_rd_chk_tst_pat_get ) cr
|
||||
dup 42 = if h# 00000080 swap then
|
||||
dup 42 = if h# 00000000 swap then
|
||||
dup 42 = if h# 00000000 swap then
|
||||
dup 42 = if h# 15090700 swap then
|
||||
dup 84 = if h# 00000000 swap then
|
||||
dup 84 = if h# 00000000 swap then
|
||||
dup 84 = if h# 00000000 swap then
|
||||
dup 84 = if h# 2a150907 swap then
|
||||
drop
|
||||
;
|
||||
|
||||
: sdr_wr_rd_check_test_pattern ( modulenum seed -- errors )
|
||||
\ .( sdr_wr_rd_check_test_pattern ) cr
|
||||
sdram_activate_test_row
|
||||
dup sdr_wr_rd_chk_tst_pat_get
|
||||
\ should have the 4 patterns on top of the stack: modulenum seed p0 p1 p2 p3
|
||||
sdr_dfii_pi0_wrdata_wr
|
||||
sdr_dfii_pi1_wrdata_wr
|
||||
sdr_dfii_pi2_wrdata_wr
|
||||
sdr_dfii_pi3_wrdata_wr
|
||||
\ should be back at modulenum seed
|
||||
h# 0 sdr_dfii_piwr_address_wr
|
||||
h# 0 sdr_dfii_piwr_baddress_wr
|
||||
h# 17 command_pwr
|
||||
15 cdelay
|
||||
|
||||
h# 0 sdr_dfii_pird_address_wr
|
||||
h# 0 sdr_dfii_pird_baddress_wr
|
||||
h# 25 command_prd
|
||||
15 cdelay
|
||||
|
||||
sdram_precharge_test_row
|
||||
|
||||
sdr_wr_rd_chk_tst_pat_get
|
||||
\ should have the 4 patterns on top of the stack: modulenum p0 p1 p2 p3
|
||||
sdr_dfii_pi0_rddata_rd xor popcnt
|
||||
\ should be at modulenum p0 p1 p2 errors
|
||||
swap sdr_dfii_pi0_rddata_rd xor popcnt +
|
||||
\ should be at modulenum p0 p1 errors
|
||||
swap sdr_dfii_pi0_rddata_rd xor popcnt +
|
||||
\ should be at modulenum p0 errors
|
||||
swap sdr_dfii_pi0_rddata_rd xor popcnt +
|
||||
\ should be at modulenum errors
|
||||
\ drop modulenum
|
||||
nip
|
||||
;
|
||||
|
||||
: sdram_read_leveling_scan_module ( modulenum bitslip -- score )
|
||||
\ .( sdram_read_leveling_scan_module ) cr
|
||||
over sdram_read_leveling_rst_delay
|
||||
\ push score
|
||||
0
|
||||
\ we should be at 'modulenum bitslip score'
|
||||
32 0 do
|
||||
\ .( starting rd_lvl_scan loop with stack: ) .s cr
|
||||
2 pick 42 sdr_wr_rd_check_test_pattern
|
||||
\ now we have an error count at the top
|
||||
3 pick 84 sdr_wr_rd_check_test_pattern
|
||||
\ merge both error count
|
||||
+
|
||||
\ we should be at 'modulenum bitslip score errorcount'
|
||||
dup 0=
|
||||
\ we should be at 'modulenum bitslip score errorcount working?'
|
||||
if 16384 else 0 then
|
||||
\ we should be at 'modulenum bitslip score errorcount (0|16384)'
|
||||
swap 512 swap -
|
||||
\ we should be at 'modulenum bitslip score (0|16384) (512-errorcount)'
|
||||
+
|
||||
+
|
||||
\ we should be at 'modulenum bitslip score'
|
||||
2 pick sdram_read_leveling_inc_delay
|
||||
loop
|
||||
nip
|
||||
nip
|
||||
;
|
||||
|
||||
: sdr_wr_lat_cal_bitslip_loop ( modulenum bestbitslip bestscore bitslip -- modulenum bestbitslip bestscore )
|
||||
\ .( sdr_wr_lat_cal_bitslip_loop for module: ) 3 pick . .( bitslip: ) dup . cr
|
||||
\ .( sdr_wr_lat_cal_bitslip_loop, stack: ) .s cr
|
||||
1 4 pick << dphy_dly_sel_wr ( '4 pick' will extract modulenum, needed as we're stacking the '1' )
|
||||
1 dphy_wdly_dq_bitslip_rst_wr
|
||||
\ Forth loop always have a least one iteration
|
||||
dup 0<> if
|
||||
dup 0 do
|
||||
1 dphy_wdly_dq_bitslip_wr
|
||||
loop
|
||||
then
|
||||
0 dphy_dly_sel_wr
|
||||
\ .( sdr_wr_lat_cal_bitslip_loop after bitslip init loop, stack: ) .s cr
|
||||
\ push current score
|
||||
0 ( we should be at 'modulenum bestbitslip bestscore bitslip score' )
|
||||
4 pick sdram_read_leveling_rst_bitslip
|
||||
8 0 do
|
||||
4 pick over sdram_read_leveling_scan_module
|
||||
\ we should be at 'modulenum bestbitslip bestscore bitslip score score', max will merge scores
|
||||
max
|
||||
\ we should be at 'modulenum bestbitslip bestscore bitslip score' again
|
||||
4 pick sdram_read_leveling_inc_bitslip
|
||||
loop
|
||||
.( sdr_wr_lat_cal_bitslip_loop after bitslip check loop, stack: ) .s cr
|
||||
dup 3 pick >
|
||||
if
|
||||
\ .( lat_cal best bitslip was: ) 3 pick . .( with score: ) 2 pick . cr
|
||||
2swap
|
||||
.( lat_cal best bitslip now: ) 3 pick . .( with score: ) 2 pick . cr
|
||||
then
|
||||
2drop
|
||||
\ .( sdr_wr_lat_cal_bitslip_loop end, stack: ) .s cr
|
||||
;
|
||||
|
||||
: sdr_wr_lat_cal_module_loop ( modulenum -- )
|
||||
.( sdr_wr_lat_cal_module_loop for module: ) dup . cr
|
||||
\ push best_bitslip
|
||||
-1
|
||||
\ push best_score
|
||||
0
|
||||
\ we should have 'modulenum 1 0'
|
||||
8 0 do
|
||||
i sdr_wr_lat_cal_bitslip_loop
|
||||
2 +loop
|
||||
\ we should be at 'modulenum bestbitslip bestscore'
|
||||
\ we don't need score anymore
|
||||
drop
|
||||
\ we should be at 'modulenum bestbitslip'
|
||||
1 2 pick << dphy_dly_sel_wr
|
||||
1 dphy_wdly_dq_bitslip_rst_wr
|
||||
.( sdr_wr_lat_cal_module_loop: best bitslip: ) dup . cr
|
||||
\ loop that consumes bestbitslip as the upper bound
|
||||
\ Forth loop always have a least one iteration
|
||||
dup 0<> if
|
||||
0 do
|
||||
1 dphy_wdly_dq_bitslip_wr
|
||||
loop
|
||||
else drop then
|
||||
0 dphy_dly_sel_wr
|
||||
\ drop the modulenum
|
||||
drop
|
||||
;
|
||||
|
||||
: sdram_write_latency_calibration ( -- )
|
||||
.( sdram_write_latency_calibration ) cr
|
||||
2 0 do
|
||||
i sdr_wr_lat_cal_module_loop
|
||||
loop
|
||||
;
|
||||
|
||||
: sdram_leveling_center_module ( modulenum -- )
|
||||
.( sdram_leveling_center_module ) cr
|
||||
dup sdram_read_leveling_rst_delay
|
||||
\ push delay_min
|
||||
-1
|
||||
\ push delay
|
||||
0
|
||||
\ we should be at 'modulenum delay_min delay'
|
||||
begin
|
||||
\ .( starting lvl_center loop with stack: ) .s cr
|
||||
2 pick 42 sdr_wr_rd_check_test_pattern
|
||||
.( we should be at 'modulenum delay_min delay error' stack: ) .s cr
|
||||
3 pick 84 sdr_wr_rd_check_test_pattern
|
||||
.( we should be at 'modulenum delay_min delay error error' stack: ) .s cr
|
||||
+
|
||||
\ we should be at 'modulenum delay_min delay error'
|
||||
\ .( we should be at 'modulenum delay_min delay error' stack: ) .s cr
|
||||
0=
|
||||
\ we should be at 'modulenum delay_min delay working'
|
||||
\ .( we should be at 'modulenum delay_min delay working' stack: ) .s cr
|
||||
2 pick 0< and
|
||||
\ we should be at 'modulenum delay_min delay {working&delay_min<0}'
|
||||
\ .( we should be at 'modulenum delay_min delay {working&delay_min<0}' stack: ) .s cr
|
||||
dup if rot drop 2dup rot drop then
|
||||
not
|
||||
\ we should be at 'modulenum new_delay_min delay !{working&delay_min<0}'
|
||||
\ .( we should be at 'modulenum new_delay_min delay !{working&delay_min<0}' stack: ) .s cr
|
||||
\ test delay before incrementing, if already 31 no point in continuing/incrementing
|
||||
over 31 <
|
||||
\ .( we should be at 'modulenum new_delay_min delay !{working&delay_min<0} <31' stack: ) .s cr
|
||||
dup if rot 1+ -rot then
|
||||
dup if 4 pick sdram_read_leveling_inc_delay then
|
||||
\ and the conditions to signal end-of-loop
|
||||
and
|
||||
\ .( we should be at 'modulenum new_delay_min delay !{working&delay_min<0}&<31' stack: ) .s cr
|
||||
\ .( finishing lvl_center loop with stack: ) .s cr
|
||||
not until
|
||||
\ we should be at 'modulenum new_delay_min delay', the while has consumed the condition
|
||||
.( we should be at 'modulenum new_delay_min delay' stack: ) .s cr
|
||||
1+
|
||||
2 pick sdram_read_leveling_inc_delay
|
||||
\ build a clean stack, startin with a copy of modulenum
|
||||
2 pick
|
||||
\ push delay_max
|
||||
-1
|
||||
\ we're at 'modulenum new_delay_min delay modulenum delay_max'
|
||||
\ push delay
|
||||
2 pick
|
||||
\ we're at 'modulenum new_delay_min delay modulenum delay_max delay'
|
||||
.( we should be at 'modulenum new_delay_min delay modulenum delay_max delay ' stack: ) .s cr
|
||||
\ this is almost the same loop, except with !working instead of working and delay_max instead of delay_min
|
||||
begin
|
||||
2 pick 42 sdr_wr_rd_check_test_pattern
|
||||
3 pick 84 sdr_wr_rd_check_test_pattern
|
||||
+
|
||||
\ we should be at 'modulenum delay_max delay error'
|
||||
0<>
|
||||
\ we should be at 'modulenum delay_max delay !working'
|
||||
2 pick 0< and
|
||||
\ we should be at 'modulenum delay_max delay {!working&delay_max<0}'
|
||||
dup if rot drop 2dup rot drop then
|
||||
not
|
||||
\ we should be at 'modulenum new_delay_max delay !{!working&delay_max<0}'
|
||||
\ test delay before incrementing, if already 31 no point in continuing/incrementing
|
||||
over 31 <
|
||||
dup not if rot 1+ -rot then
|
||||
dup not if 4 pick sdram_read_leveling_inc_delay then
|
||||
\ and the conditions to signal end-of-loop
|
||||
and
|
||||
not until
|
||||
\ we should be at 'modulenum new_delay_min delay modulenum new_delay_max delay', the while has consumed the condition
|
||||
.( we should be at 'modulenum new_delay_min delay modulenum new_delay_max delay ' stack: ) .s cr
|
||||
\ keep delay if new_delay_max<0, new_delay_max otherwise
|
||||
over 0< if nip else drop then
|
||||
\ we should be at 'modulenum new_delay_min delay modulenum new_delay_max'
|
||||
nip
|
||||
nip
|
||||
\ we should be at 'modulenum new_delay_min new_delay_max'
|
||||
.( we should be at 'modulenum new_delay_min new_delay_max' stack: ) .s cr
|
||||
\ compute delay_mid
|
||||
2dup + 2/ 32 mod
|
||||
\ we should be at 'modulenum new_delay_min new_delay_max {{new_delay_min+new_delay_max}/2%32}'
|
||||
\ compute delay_range
|
||||
3dup drop swap - 2/
|
||||
\ we should be at 'modulenum new_delay_min new_delay_max {{new_delay_min+new_delay_max}/2%32} {{new_delay_max-new_delay_min}/2}'
|
||||
.( we should be at 'modulenum new_delay_min new_delay_max delay_mid delay_range ' stack: ) .s cr
|
||||
4 pick sdram_read_leveling_rst_delay
|
||||
100 cdelay
|
||||
\ Forth loop always have a least one iteration
|
||||
over 0<> if
|
||||
over 0 do
|
||||
4 pick sdram_read_leveling_inc_delay
|
||||
100 cdelay
|
||||
loop
|
||||
then
|
||||
drop
|
||||
drop
|
||||
drop
|
||||
drop
|
||||
drop
|
||||
;
|
||||
|
||||
: sdr_rd_lvl_bitslip_loop ( modulenum bestbitslip bestscore bitslip -- modulenum bestbitslip bestscore )
|
||||
\ .( sdr_rd_lvl_bitslip_loop, stack: ) .s cr
|
||||
3 pick over sdram_read_leveling_scan_module
|
||||
\ we should be at 'modulenum bestbitslip bestscore bitslip score'
|
||||
4 pick sdram_leveling_center_module
|
||||
\ preserve a bitslip for the later test
|
||||
over
|
||||
\ (we should be at 'modulenum bestbitslip bestscore bitslip score bitslip') move it out of the way
|
||||
.( we should be at 'modulenum bestbitslip bestscore bitslip score bitslip' stack: ) .s cr
|
||||
5 roll ( 'modulenum bestscore bitslip score bitslip bestbitslip' )
|
||||
5 roll ( 'modulenum bitslip score bitslip bestbitslip bestscore' )
|
||||
5 roll ( 'modulenum score bitslip bestbitslip bestscore bitslip' )
|
||||
5 roll ( 'modulenum bitslip bestbitslip bestscore bitslip score' )
|
||||
.( we should be at 'modulenum bitslip bestbitslip bestscore bitslip score' stack: ) .s cr
|
||||
\ compare the score and bestcore
|
||||
dup 3 pick >
|
||||
if
|
||||
2swap
|
||||
.( rd_lvl best bitslip now: ) 3 pick . .( with score: ) 2 pick . cr
|
||||
then
|
||||
2drop
|
||||
\ we should be at 'modulenum bitslip bestbitslip bestscore'
|
||||
rot
|
||||
\ we should be at 'modulenum bestbitslip bestscore bitslip'
|
||||
.( we should be at 'modulenum bestbitslip bestscore bitslip' stack: ) .s cr
|
||||
7 <> if 2 pick sdram_read_leveling_inc_bitslip then
|
||||
;
|
||||
|
||||
: sdr_rd_lvl_module_loop ( modulenum -- )
|
||||
.( sdr_rd_lvl_module_loop ) cr
|
||||
1 over << sdram_read_leveling_rst_bitslip
|
||||
\ push best_bitslip
|
||||
0
|
||||
\ push best_score
|
||||
0
|
||||
\ we should have 'modulenum 0 0'
|
||||
8 0 do
|
||||
i sdr_rd_lvl_bitslip_loop
|
||||
loop
|
||||
\ don't need the score anymore
|
||||
drop
|
||||
2 pick sdram_read_leveling_rst_bitslip
|
||||
.( sdr_rd_lvl_module_loop, best bitslip: ) dup . cr
|
||||
\ Forth loop always have a least one iteration
|
||||
dup 0<> if
|
||||
\ consume best_bitslip as loop upper bound
|
||||
0 do
|
||||
dup sdram_leveling_center_module
|
||||
loop
|
||||
else drop then
|
||||
drop
|
||||
;
|
||||
|
||||
: sdram_read_leveling ( -- )
|
||||
.( sdram_read_leveling ) cr
|
||||
2 0 do
|
||||
i sdr_rd_lvl_module_loop
|
||||
loop
|
||||
;
|
||||
|
||||
: sdram_leveling ( -- )
|
||||
.( sdram_leveling ) cr
|
||||
sdram_software_control_on
|
||||
2 0 do
|
||||
i sdram_read_leveling_rst_delay
|
||||
i sdram_read_leveling_rst_bitslip
|
||||
loop
|
||||
sdram_write_latency_calibration
|
||||
sdram_read_leveling
|
||||
sdram_software_control_off
|
||||
;
|
||||
|
||||
external
|
||||
|
||||
: init_sdram ( -- )
|
||||
.( init_sdram ) cr
|
||||
\ .( init_sdram ) cr
|
||||
2 dphy_rdphase_wr
|
||||
3 dphy_wrphase_wr
|
||||
sdram_software_control_on
|
||||
@@ -517,17 +99,53 @@ external
|
||||
1 ms
|
||||
0 dphy_rst_wr
|
||||
1 ms
|
||||
.( going to init_sequence ) cr
|
||||
\ .( going to init_sequence ) cr
|
||||
init_sequence
|
||||
.( going to sdram_leveling ) cr
|
||||
sdram_leveling
|
||||
\ redundant
|
||||
\ .( hw ctrl ) cr
|
||||
sdram_software_control_off
|
||||
|
||||
\ .( config module 0 write ) cr
|
||||
1 dphy_dly_sel_wr
|
||||
1 dphy_wdly_dq_bitslip_rst_wr
|
||||
\ 0 bitslip
|
||||
0 dphy_dly_sel_wr
|
||||
|
||||
\ .( config module 1 write ) cr
|
||||
2 dphy_dly_sel_wr
|
||||
1 dphy_wdly_dq_bitslip_rst_wr
|
||||
\ 0 bitslip
|
||||
0 dphy_dly_sel_wr
|
||||
|
||||
\ .( config module 0 read ) cr
|
||||
1 dphy_dly_sel_wr
|
||||
1 dphy_rdly_dq_bitslip_rst_wr
|
||||
1 0 do
|
||||
1 0 do 1 dphy_rdly_dq_bitslip_wr loop
|
||||
loop
|
||||
1 dphy_rdly_dq_rst_wr
|
||||
25 0 do
|
||||
1 dphy_rdly_dq_inc_wr
|
||||
loop
|
||||
|
||||
\ .( config module 1 read ) cr
|
||||
2 dphy_dly_sel_wr
|
||||
1 dphy_rdly_dq_bitslip_rst_wr
|
||||
1 0 do
|
||||
1 0 do 1 dphy_rdly_dq_bitslip_wr loop
|
||||
loop
|
||||
1 dphy_rdly_dq_rst_wr
|
||||
25 0 do
|
||||
1 dphy_rdly_dq_inc_wr
|
||||
loop
|
||||
\ .( finish ) cr
|
||||
0 dphy_dly_sel_wr
|
||||
\ .( done ) cr
|
||||
;
|
||||
|
||||
: init! ( -- )
|
||||
.( init ) cr
|
||||
\ .( init ) cr
|
||||
map-in-mregs
|
||||
init_sdram
|
||||
map-out-mregs
|
||||
;
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@ _sbus_sbus_v1_0 = [
|
||||
("SBUS_3V3_D", 0, Pins("J18 K16 J17 K15 K13 J15 J13 J14 H14 H17 G14 G17 G16 G18 H16 F18 F16 E18 F15 D18 E17 G13 D17 F13 F14 E16 E15 C17 C16 A18 B18 C15"), IOStandard("lvttl")),
|
||||
("SBUS_3V3_PA", 0, Pins("B16 B17 D14 C14 D12 A16 A15 B14 B13 B12 C12 A14 A13 B11 A11 M4 R2 M3 P2 M2 N2 K5 N1 L4 M1 L3 L1 K3"), IOStandard("lvttl")),
|
||||
]
|
||||
|
||||
_sbus_sbus_v1_2 = [
|
||||
("SBUS_3V3_CLK", 0, Pins("D15"), IOStandard("lvttl")),
|
||||
("SBUS_3V3_ASs", 0, Pins("T4"), IOStandard("lvttl")),
|
||||
@@ -160,7 +161,7 @@ _sbus_sbus_v1_2 = [
|
||||
("SBUS_3V3_INT4s", 0, Pins("N5"), IOStandard("lvttl")), # added
|
||||
("SBUS_3V3_INT5s", 0, Pins("L5"), IOStandard("lvttl")), # added
|
||||
("SBUS_3V3_INT6s", 0, Pins("V2"), IOStandard("lvttl")), # added
|
||||
#("SBUS_3V3_INT7s", 0, Pins("N5"), IOStandard("lvttl")),
|
||||
#("SBUS_3V3_INT7s", 0, Pins(""), IOStandard("lvttl")), # removed
|
||||
("SBUS_3V3_PPRD", 0, Pins("N6"), IOStandard("lvttl")),
|
||||
("SBUS_OE", 0, Pins("P5"), IOStandard("lvttl")),
|
||||
("SBUS_3V3_ACKs", 0, Pins("M6 L6 N4"), IOStandard("lvttl")),
|
||||
@@ -182,15 +183,73 @@ _usb_io_v1_0 = [
|
||||
_connectors_v1_0 = [
|
||||
]
|
||||
_connectors_v1_2 = [
|
||||
("P1", "T8 U6 P3 P4 T1 U4 R1 T3"),
|
||||
("P1", "T8 P3 T1 R1 U6 P4 U4 T3"), # swapped line?
|
||||
]
|
||||
|
||||
# I2C ----------------------------------------------------------------------------------------------
|
||||
|
||||
# reusing the UART pins !!!
|
||||
_i2c_v1_0 = [
|
||||
("i2c", 0,
|
||||
Subsignal("scl", Pins("V9")),
|
||||
Subsignal("sda", Pins("U9")),
|
||||
IOStandard("LVCMOS33"))
|
||||
]
|
||||
# reusing the UART pins !!!
|
||||
_i2c_v1_2 = [
|
||||
("i2c", 0,
|
||||
Subsignal("scl", Pins("V9")),
|
||||
Subsignal("sda", Pins("U9")),
|
||||
IOStandard("LVCMOS33"))
|
||||
]
|
||||
|
||||
# VGA ----------------------------------------------------------------------------------------------
|
||||
|
||||
def vga_rgb222_pmod_io(pmod):
|
||||
return [
|
||||
("vga", 0,
|
||||
Subsignal("hsync", Pins(f"{pmod}:3")),
|
||||
Subsignal("vsync", Pins(f"{pmod}:7")),
|
||||
Subsignal("b", Pins(f"{pmod}:0 {pmod}:4")),
|
||||
Subsignal("g", Pins(f"{pmod}:1 {pmod}:5")),
|
||||
Subsignal("r", Pins(f"{pmod}:2 {pmod}:6")),
|
||||
IOStandard("LVCMOS33"),
|
||||
),
|
||||
]
|
||||
_vga_pmod_io_v1_2 = vga_rgb222_pmod_io("P1")
|
||||
|
||||
# Platform -----------------------------------------------------------------------------------------
|
||||
|
||||
class Platform(XilinxPlatform):
|
||||
default_clk_name = "clk48"
|
||||
default_clk_period = 1e9/48e6
|
||||
|
||||
def get_irq(self, device, irq_req, next_down=True, next_up=False):
|
||||
irq = irq_req
|
||||
if (irq in self.avail_irqs):
|
||||
self.avail_irqs.remove(irq)
|
||||
self.irq_device_map[irq] = device
|
||||
self.device_irq_map[device] = irq
|
||||
print("~~~~~ A Requesting SBUS_3V3_INT{}s".format(irq))
|
||||
return self.request("SBUS_3V3_INT{}s".format(irq))
|
||||
if (next_down):
|
||||
for irq in range(irq_req, 0, -1):
|
||||
if (irq in self.avail_irqs):
|
||||
self.avail_irqs.remove(irq)
|
||||
self.irq_device_map[irq] = device
|
||||
self.device_irq_map[device] = irq
|
||||
print("~~~~~ B Requesting SBUS_3V3_INT{}s".format(irq))
|
||||
return self.request("SBUS_3V3_INT{}s".format(irq))
|
||||
if (next_up):
|
||||
for irq in range(irq_req, 7, 1):
|
||||
if (irq in self.avail_irqs):
|
||||
self.avail_irqs.remove(irq)
|
||||
self.irq_device_map[irq] = device
|
||||
self.device_irq_map[device] = irq
|
||||
print("~~~~~ C Requesting SBUS_3V3_INT{}s".format(irq))
|
||||
return self.request("SBUS_3V3_INT{}s".format(irq))
|
||||
return None
|
||||
|
||||
def __init__(self, variant="ztex2.13a", version="V1.0"):
|
||||
device = {
|
||||
"ztex2.13a": "xc7a35tcsg324-1",
|
||||
@@ -211,10 +270,21 @@ class Platform(XilinxPlatform):
|
||||
"V1.0" : _connectors_v1_0,
|
||||
"V1.2" : _connectors_v1_2,
|
||||
}[version]
|
||||
i2c = {
|
||||
"V1.0" : _i2c_v1_0,
|
||||
"V1.2" : _i2c_v1_2,
|
||||
}[version]
|
||||
self.avail_irqs = {
|
||||
"V1.0" : { 1 }, # don't add 7 here, too risky
|
||||
"V1.2" : { 1, 2, 3, 4, 5, 6 },
|
||||
}[version]
|
||||
self.irq_device_map = dict()
|
||||
self.device_irq_map = dict()
|
||||
|
||||
XilinxPlatform.__init__(self, device, _io, connectors, toolchain="vivado")
|
||||
self.add_extension(sbus_io)
|
||||
self.add_extension(sbus_sbus)
|
||||
self.add_extension(i2c)
|
||||
|
||||
self.toolchain.bitstream_commands = \
|
||||
["set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR No [current_design]",
|
||||
|
||||
Reference in New Issue
Block a user