1
0
mirror of synced 2026-03-21 08:18:35 +00:00

Merge branch 'main' of github.com:rdolbeau/SBusFPGA into main

This commit is contained in:
Romain Dolbeau
2021-10-09 10:25:47 +02:00
22 changed files with 1534 additions and 2043 deletions

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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 *);

View File

@@ -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) {

View 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

View 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")))

View 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
;

View File

@@ -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",

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)")

View File

@@ -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

View File

@@ -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],

View 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

View File

@@ -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()

View File

@@ -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!
;

View File

@@ -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
;

View File

@@ -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]",