proto CG6
This commit is contained in:
6189
sbus-to-ztex-gateware-migen/VexRiscv_FbAccel.v
Normal file
6189
sbus-to-ztex-gateware-migen/VexRiscv_FbAccel.v
Normal file
File diff suppressed because it is too large
Load Diff
1164
sbus-to-ztex-gateware-migen/blit.c
Normal file
1164
sbus-to-ztex-gateware-migen/blit.c
Normal file
File diff suppressed because it is too large
Load Diff
6
sbus-to-ztex-gateware-migen/blit.lds
Normal file
6
sbus-to-ztex-gateware-migen/blit.lds
Normal file
@@ -0,0 +1,6 @@
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00410000;
|
||||
.text : { *(.text) }
|
||||
}
|
||||
22
sbus-to-ztex-gateware-migen/blit.sh
Executable file
22
sbus-to-ztex-gateware-migen/blit.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
GCCDIR=~/LITEX/riscv64-unknown-elf-gcc-10.1.0-2020.08.2-x86_64-linux-ubuntu14
|
||||
GCCPFX=riscv64-unknown-elf-
|
||||
|
||||
#GCCDIR=/opt/rv32bk
|
||||
#GCCPFX=riscv32-buildroot-linux-gnu-
|
||||
|
||||
#GCCDIR=~dolbeau/LITEX/buildroot-32SF/output/host
|
||||
#GCCPFX=riscv32-buildroot-linux-gnu-
|
||||
|
||||
GCC=${GCCDIR}/bin/${GCCPFX}gcc
|
||||
OBJCOPY=${GCCDIR}/bin/${GCCPFX}objcopy
|
||||
|
||||
if test "x$1" == "xASM"; then
|
||||
$GCC -Os -o blit -march=rv32ib -mabi=ilp32 -T blit.lds -nostartfiles blit.s &&
|
||||
$OBJCOPY -O binary -j .text blit blit.raw
|
||||
else
|
||||
$GCC -Os -S blit.c -march=rv32ib -mabi=ilp32 -mstrict-align -fno-builtin-memset -nostdlib -ffreestanding -nostartfiles &&
|
||||
$GCC -Os -o blit -march=rv32ib -mabi=ilp32 -T blit.lds -nostartfiles blit.s &&
|
||||
$OBJCOPY -O binary -j .text blit blit.raw
|
||||
fi
|
||||
@@ -16,7 +16,7 @@
|
||||
h# SBUSFPGA_CG3_WIDTH
|
||||
;
|
||||
|
||||
h# 400000 constant cg3-off-dac
|
||||
h# sbusfpga_regionaddr_cg3_bt constant cg3-off-dac
|
||||
h# 20 constant /cg3-off-dac
|
||||
|
||||
h# 800000 constant cg3-off-fb
|
||||
@@ -86,7 +86,7 @@ headerless
|
||||
|
||||
" cgthree" device-name
|
||||
" display" device-type
|
||||
" SUNW,501-1415" model
|
||||
" RDOL,sbusfpga" model
|
||||
|
||||
: qemu-cg3-driver-install ( -- )
|
||||
cg3-dac -1 = if
|
||||
|
||||
@@ -32,7 +32,7 @@ def cg3_rounded_size(hres, vres):
|
||||
|
||||
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):
|
||||
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, hwcursor=False, upd_overlay_fifo=False, upd_omap_fifo=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}")
|
||||
@@ -46,8 +46,29 @@ class VideoFrameBuffer256c(Module, AutoCSR):
|
||||
upd_clut_fifo.re.eq(0),
|
||||
)
|
||||
]
|
||||
|
||||
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
||||
|
||||
if (hwcursor):
|
||||
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_hwcursor_layout)
|
||||
overlay = Array(Array(Array(Signal(1) for x in range(0,32)) for y in range(0,32)) for i in range(0, 2))
|
||||
omap = Array(Array(Signal(8, reset = (255-i)) for i in range(0, 4)) for j in range(0, 3))
|
||||
vga_sync += [
|
||||
If(upd_overlay_fifo.readable,
|
||||
upd_overlay_fifo.re.eq(1),
|
||||
[ overlay[upd_overlay_fifo.dout[0]][upd_overlay_fifo.dout[1:6]][x].eq(upd_overlay_fifo.dout[6+x]) for x in range(0, 32)],
|
||||
).Else(
|
||||
upd_overlay_fifo.re.eq(0),
|
||||
)
|
||||
]
|
||||
vga_sync += [
|
||||
If(upd_omap_fifo.readable,
|
||||
upd_omap_fifo.re.eq(1),
|
||||
omap[upd_omap_fifo.dout[0:2]][upd_omap_fifo.dout[2:4]].eq(upd_omap_fifo.dout[4:12]),
|
||||
).Else(
|
||||
upd_omap_fifo.re.eq(0),
|
||||
)
|
||||
]
|
||||
else:
|
||||
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
|
||||
self.source = source = stream.Endpoint(video_data_layout)
|
||||
self.underflow = Signal()
|
||||
|
||||
@@ -107,7 +128,11 @@ class VideoFrameBuffer256c(Module, AutoCSR):
|
||||
vtg_sink.ready.eq(source.valid & source.ready),
|
||||
),
|
||||
vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
|
||||
If(vtg_sink.de,
|
||||
If(vtg_sink.hwcursor & (overlay[0][vtg_sink.hwcursory][vtg_sink.hwcursorx] | overlay[1][vtg_sink.hwcursory][vtg_sink.hwcursorx]),
|
||||
source.r.eq(omap[0][Cat(overlay[0][vtg_sink.hwcursory][vtg_sink.hwcursorx], overlay[1][vtg_sink.hwcursory][vtg_sink.hwcursorx])]),
|
||||
source.g.eq(omap[0][Cat(overlay[0][vtg_sink.hwcursory][vtg_sink.hwcursorx], overlay[1][vtg_sink.hwcursory][vtg_sink.hwcursorx])]),
|
||||
source.b.eq(omap[0][Cat(overlay[0][vtg_sink.hwcursory][vtg_sink.hwcursorx], overlay[1][vtg_sink.hwcursory][vtg_sink.hwcursorx])]),
|
||||
).Elif(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])
|
||||
@@ -197,9 +222,9 @@ class cg3(Module, AutoCSR):
|
||||
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?)
|
||||
# current cmap logic for the CG3
|
||||
# (the CG6 takes 32 bits write but only use the top 8 bits, for bt_addr & bt_cmap
|
||||
# also 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",
|
||||
|
||||
149
sbus-to-ztex-gateware-migen/cg6.fth
Normal file
149
sbus-to-ztex-gateware-migen/cg6.fth
Normal file
@@ -0,0 +1,149 @@
|
||||
\ simplified version of the OpenBIOS cgthree code
|
||||
\ ... for the cg6
|
||||
|
||||
: openbios-video-width
|
||||
h# SBUSFPGA_CG3_WIDTH
|
||||
;
|
||||
|
||||
: openbios-video-height
|
||||
h# SBUSFPGA_CG3_HEIGHT
|
||||
;
|
||||
|
||||
: depth-bits
|
||||
h# 8
|
||||
;
|
||||
|
||||
: line-bytes
|
||||
h# SBUSFPGA_CG3_WIDTH
|
||||
;
|
||||
|
||||
sbusfpga_regionaddr_cg6_bt constant cg6-off-dac
|
||||
h# 20 constant /cg6-off-dac
|
||||
|
||||
h# 800000 constant cg6-off-fb
|
||||
h# SBUSFPGA_CG3_BUFSIZE constant /cg6-off-fb
|
||||
|
||||
: >cg6-reg-spec ( offset size -- encoded-reg )
|
||||
>r 0 my-address d+ my-space encode-phys r> encode-int encode+
|
||||
;
|
||||
|
||||
: cg6-reg
|
||||
\ A real cg6 rom appears to just map the entire region with a
|
||||
\ single entry
|
||||
h# 0 h# 1000000 >cg6-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 cg6-dac
|
||||
-1 value fb-addr
|
||||
|
||||
: dac! ( data reg# -- )
|
||||
cg6-dac + l!
|
||||
;
|
||||
|
||||
external
|
||||
|
||||
: color! ( r g b c# -- )
|
||||
h# 18 << 0 dac! ( r g b )
|
||||
swap rot ( b g r )
|
||||
h# 18 << 4 dac! ( b g )
|
||||
h# 18 << 4 dac! ( b )
|
||||
h# 18 << 4 dac! ( )
|
||||
;
|
||||
|
||||
headerless
|
||||
|
||||
\
|
||||
\ Mapping
|
||||
\
|
||||
|
||||
: dac-map
|
||||
cg6-off-dac /cg6-off-dac do-map-in to cg6-dac
|
||||
;
|
||||
|
||||
: fb-map
|
||||
cg6-off-fb /cg6-off-fb do-map-in to fb-addr
|
||||
;
|
||||
|
||||
: map-regs
|
||||
dac-map fb-map
|
||||
;
|
||||
|
||||
fload fbc_init.fth
|
||||
|
||||
\
|
||||
\ Installation
|
||||
\
|
||||
|
||||
" cgsix" device-name
|
||||
" display" device-type
|
||||
" RDOL,sbusfpga" model
|
||||
|
||||
: qemu-cg6-driver-install ( -- )
|
||||
cg6-dac -1 = if
|
||||
map-regs
|
||||
|
||||
map-in-fbc
|
||||
init-fbc
|
||||
|
||||
\ 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
|
||||
['] cg6-blink-screen is blink-screen
|
||||
['] cg6-reset-screen is reset-screen
|
||||
['] cg6-draw-char is draw-character
|
||||
['] cg6-toggle-cursor is toggle-cursor
|
||||
['] cg6-invert-screen is invert-screen
|
||||
['] cg6-insert-characters is insert-characters
|
||||
['] cg6-delete-characters is delete-characters
|
||||
['] fbc-erase-screen is erase-screen
|
||||
['] fbc-delete-lines is delete-lines
|
||||
['] fbc-insert-lines is insert-lines
|
||||
then
|
||||
;
|
||||
|
||||
: qemu-cg6-driver-init
|
||||
|
||||
cg6-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
|
||||
|
||||
h# SBUSFPGA_CG3_BUFSIZE encode-int " fbmapped" property
|
||||
|
||||
['] qemu-cg6-driver-install is-install
|
||||
;
|
||||
|
||||
qemu-cg6-driver-init
|
||||
344
sbus-to-ztex-gateware-migen/cg6_accel.py
Normal file
344
sbus-to-ztex-gateware-migen/cg6_accel.py
Normal file
@@ -0,0 +1,344 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
|
||||
from litex.soc.interconnect.csr import *
|
||||
|
||||
from litex.soc.interconnect import wishbone
|
||||
|
||||
class CG6Accel(Module): # AutoCSR ?
|
||||
def __init__(self, platform):
|
||||
|
||||
# for FBC and TEC - where we just ignore TEC
|
||||
self.bus = bus = wishbone.Interface()
|
||||
|
||||
|
||||
fbc_config = Signal(32, reset = (0x60000000)) # bit 11-12 are for resolution, see the GX manual
|
||||
fbc_mode = Signal(32)
|
||||
fbc_clip = Signal(32)
|
||||
fbc_s = Signal(32)
|
||||
#fbc_font = Signal(32)
|
||||
fbc_x = Array(Signal(32) for a in range(0, 4))
|
||||
fbc_y = Array(Signal(32) for a in range(0, 4))
|
||||
fbc_offx = Signal(32)
|
||||
fbc_offy = Signal(32)
|
||||
fbc_incx = Signal(32)
|
||||
fbc_incy = Signal(32)
|
||||
fbc_clipminx = Signal(32)
|
||||
fbc_clipminy = Signal(32)
|
||||
fbc_clipmaxx = Signal(32)
|
||||
fbc_clipmaxy = Signal(32)
|
||||
fbc_fg = Signal(32)
|
||||
fbc_bg = Signal(32)
|
||||
fbc_alu = Signal(32)
|
||||
fbc_arectx = Signal(32)
|
||||
fbc_arecty = Signal(32)
|
||||
|
||||
# extra stuff for compatibility
|
||||
fbc_arectx_prev = Signal(32) # after fbc_arecty (600) - R/O
|
||||
fbc_arecty_prev = Signal(32) # after fbc_arectx_prev (601) - R/O
|
||||
fbc_r5_cmd = Signal(32) # to communicate with Vex (602)
|
||||
fbc_r5_status = Array(Signal(32) for a in range(0, 4))
|
||||
fbc_next_font = Signal(32)
|
||||
fbc_next_x0 = Signal(12)
|
||||
fbc_next_x1 = Signal(12)
|
||||
fbc_next_y0 = Signal(12)
|
||||
|
||||
fbc_do_draw = Signal()
|
||||
fbc_do_blit = Signal()
|
||||
|
||||
font_layout = [
|
||||
("font", 32),
|
||||
("x0", 12),
|
||||
("x1", 12),
|
||||
("y0", 12),
|
||||
]
|
||||
# depth is because the current 'font' is a bit slow, so we need to buffer a lot...
|
||||
self.submodules.fbc_fifo_font = SyncFIFOBuffered(width=layout_len(font_layout),depth=1024)
|
||||
fbc_fifo_font_in = Record(font_layout)
|
||||
fbc_fifo_font_out = Record(font_layout)
|
||||
self.comb += [
|
||||
self.fbc_fifo_font.din.eq(fbc_fifo_font_in.raw_bits()),
|
||||
fbc_fifo_font_out.raw_bits().eq(self.fbc_fifo_font.dout)
|
||||
]
|
||||
|
||||
self.submodules.wishbone_fsm = wishbone_fsm = FSM(reset_state = "Reset")
|
||||
wishbone_fsm.act("Reset",
|
||||
NextValue(bus.ack, 0),
|
||||
NextState("Idle"))
|
||||
wishbone_fsm.act("Idle",
|
||||
If(bus.cyc & bus.stb & bus.we & ~bus.ack, #write
|
||||
Case(bus.adr[0:10], {
|
||||
"default": [ ],
|
||||
# 0: fbc_config R/O
|
||||
1: [ NextValue(fbc_mode, bus.dat_w) ],
|
||||
2: [ NextValue(fbc_clip, bus.dat_w) ],
|
||||
# 3: <nothing>, pad2
|
||||
4: [ NextValue(fbc_s, bus.dat_w) ], # 0x010
|
||||
# 5: fbc_draw R/O
|
||||
# 6: fbc_blit R/O
|
||||
7: [ self.fbc_fifo_font.we.eq(1),
|
||||
fbc_fifo_font_in.font.eq(bus.dat_w),
|
||||
fbc_fifo_font_in.x0.eq(fbc_x[0][0:12]),
|
||||
fbc_fifo_font_in.x1.eq(fbc_x[1][0:12]),
|
||||
fbc_fifo_font_in.y0.eq(fbc_y[0][0:12]),
|
||||
NextValue(fbc_x[0], fbc_x[0] + fbc_incx),
|
||||
NextValue(fbc_x[1], fbc_x[1] + fbc_incx),
|
||||
NextValue(fbc_y[0], fbc_y[0] + fbc_incy),
|
||||
#NextValue(fbc_y[1], fbc_y[1] + fbc_incy),
|
||||
],
|
||||
# 8-31: <nothing>, pad3
|
||||
32: [ NextValue(fbc_x[0], bus.dat_w) ],
|
||||
33: [ NextValue(fbc_y[0], bus.dat_w) ],
|
||||
#34: presumably fbc_z0
|
||||
36: [ NextValue(fbc_x[1], bus.dat_w) ],
|
||||
37: [ NextValue(fbc_y[1], bus.dat_w) ],
|
||||
#38: presumably fbc_z1
|
||||
40: [ NextValue(fbc_x[2], bus.dat_w) ],
|
||||
41: [ NextValue(fbc_y[2], bus.dat_w) ],
|
||||
#42: presumably fbc_z2
|
||||
44: [ NextValue(fbc_x[3], bus.dat_w) ],
|
||||
45: [ NextValue(fbc_y[3], bus.dat_w) ],
|
||||
#46: presumably fbc_z3
|
||||
48: [ NextValue(fbc_offx, bus.dat_w) ],
|
||||
49: [ NextValue(fbc_offy, bus.dat_w) ],
|
||||
52: [ NextValue(fbc_incx, bus.dat_w) ],
|
||||
53: [ NextValue(fbc_incy, bus.dat_w) ],
|
||||
# 54-55: pad81
|
||||
56: [ NextValue(fbc_clipminx, bus.dat_w) ],
|
||||
57: [ NextValue(fbc_clipminy, bus.dat_w) ],
|
||||
# 58-59: pad9
|
||||
60: [ NextValue(fbc_clipmaxx, bus.dat_w) ],
|
||||
61: [ NextValue(fbc_clipmaxy, bus.dat_w) ],
|
||||
# 62-63: pad10
|
||||
64: [ NextValue(fbc_fg, bus.dat_w) ],
|
||||
65: [ NextValue(fbc_bg, bus.dat_w) ],
|
||||
66: [ NextValue(fbc_alu, bus.dat_w) ],
|
||||
# 67: planemask reg
|
||||
# 68: pixelmask reg
|
||||
# 69-70: <nothing>
|
||||
# 71: pattalign reg
|
||||
# 72-79: pattern0-7
|
||||
# 80-543: big empty space ?
|
||||
# 544-546, 548-550: itri[abs,rel][xyz]
|
||||
# 560-562, 564-566: iquad[abs,rel][xyz]
|
||||
576: [ NextValue(fbc_arectx_prev, fbc_arectx), # 900
|
||||
NextValue(fbc_arectx, bus.dat_w),
|
||||
],
|
||||
577: [ NextValue(fbc_arecty_prev, fbc_arecty),
|
||||
NextValue(fbc_arecty, bus.dat_w),
|
||||
],
|
||||
# 578: fbc_arectz
|
||||
# 579: <nothing>
|
||||
# 580-582: fbc_relrect[xyz] -> update absolute
|
||||
580: [ NextValue(fbc_arectx_prev, fbc_arectx),
|
||||
NextValue(fbc_arectx, fbc_arectx + bus.dat_w),
|
||||
],
|
||||
581: [ NextValue(fbc_arecty_prev, fbc_arecty),
|
||||
NextValue(fbc_arecty, fbc_arecty + bus.dat_w),
|
||||
],
|
||||
# 600-601: fbc_arect[xy]next, not directly writable
|
||||
602: [ NextValue(fbc_r5_cmd, bus.dat_w) ],
|
||||
604: [ NextValue(fbc_r5_status[0], bus.dat_w) ], # 0x970
|
||||
605: [ NextValue(fbc_r5_status[1], bus.dat_w) ], # 0x971
|
||||
606: [ NextValue(fbc_r5_status[2], bus.dat_w) ], # 0x972
|
||||
607: [ NextValue(fbc_r5_status[3], bus.dat_w) ], # 0x973
|
||||
# 608: fbc_next_font, R/O
|
||||
}),
|
||||
NextValue(bus.ack, 1),
|
||||
).Elif(bus.cyc & bus.stb & ~bus.we & ~bus.ack, #read
|
||||
Case(bus.adr[0:10], {
|
||||
"default": [ NextValue(bus.dat_r, 0xDEADBEEF) ],
|
||||
0: [ NextValue(bus.dat_r, fbc_config) ],
|
||||
1: [ NextValue(bus.dat_r, fbc_mode) ],
|
||||
2: [ NextValue(bus.dat_r, fbc_clip) ],
|
||||
# 3: pad2
|
||||
4: [ NextValue(bus.dat_r, fbc_s) ],
|
||||
# 5: fbc_draw R/O -> start a "draw" on R
|
||||
5: [ NextValue(fbc_do_draw, 1),
|
||||
NextValue(bus.dat_r, 0)
|
||||
],
|
||||
# 6: fbc_blit R/O -> start a "blit" on R
|
||||
6: [ NextValue(fbc_do_blit, 1),
|
||||
NextValue(bus.dat_r, 0)
|
||||
],
|
||||
# 7: fbc_font W/O -> start a "font" on W
|
||||
# 7: [ NextValue(bus.dat_r, fbc_font) ],
|
||||
# 8-31: pad3
|
||||
32: [ NextValue(bus.dat_r, fbc_x[0]) ], # 0x080
|
||||
33: [ NextValue(bus.dat_r, fbc_y[0]) ],
|
||||
36: [ NextValue(bus.dat_r, fbc_x[1]) ], # 0x090
|
||||
37: [ NextValue(bus.dat_r, fbc_y[1]) ],
|
||||
40: [ NextValue(bus.dat_r, fbc_x[2]) ], # 0x0a0
|
||||
41: [ NextValue(bus.dat_r, fbc_y[2]) ],
|
||||
44: [ NextValue(bus.dat_r, fbc_x[3]) ], # 0x0b0
|
||||
45: [ NextValue(bus.dat_r, fbc_y[3]) ], # 0x0b4
|
||||
48: [ NextValue(bus.dat_r, fbc_offx) ],
|
||||
49: [ NextValue(bus.dat_r, fbc_offy) ],
|
||||
52: [ NextValue(bus.dat_r, fbc_incx) ], # 0x0d0
|
||||
53: [ NextValue(bus.dat_r, fbc_incy) ],
|
||||
# 54-55: pad81
|
||||
56: [ NextValue(bus.dat_r, fbc_clipminx) ],
|
||||
57: [ NextValue(bus.dat_r, fbc_clipminy) ],
|
||||
# 58-59: pad9
|
||||
60: [ NextValue(bus.dat_r, fbc_clipmaxx) ],
|
||||
61: [ NextValue(bus.dat_r, fbc_clipmaxy) ],
|
||||
# 62-63: pad10
|
||||
64: [ NextValue(bus.dat_r, fbc_fg) ], # 0x100
|
||||
65: [ NextValue(bus.dat_r, fbc_bg) ], # 0x104
|
||||
66: [ NextValue(bus.dat_r, fbc_alu) ],
|
||||
576: [ NextValue(bus.dat_r, fbc_arectx),
|
||||
],
|
||||
577: [ NextValue(bus.dat_r, fbc_arecty),
|
||||
],
|
||||
600: [ NextValue(bus.dat_r, fbc_arectx_prev), # 0x960
|
||||
],
|
||||
601: [ NextValue(bus.dat_r, fbc_arecty_prev),
|
||||
],
|
||||
602: [ NextValue(bus.dat_r, fbc_r5_cmd), # 0x968
|
||||
],
|
||||
# 603
|
||||
604: [ NextValue(bus.dat_r, fbc_r5_status[0]), # 0x970
|
||||
],
|
||||
605: [ NextValue(bus.dat_r, fbc_r5_status[1]), # 0x971
|
||||
],
|
||||
606: [ NextValue(bus.dat_r, fbc_r5_status[2]), # 0x972
|
||||
],
|
||||
607: [ NextValue(bus.dat_r, fbc_r5_status[3]), # 0x973
|
||||
],
|
||||
608: [ NextValue(bus.dat_r, fbc_next_font),
|
||||
],
|
||||
609: [ NextValue(bus.dat_r, Cat(fbc_next_x0, Signal(20, reset = 0))),
|
||||
],
|
||||
610: [ NextValue(bus.dat_r, Cat(fbc_next_x1, Signal(20, reset = 0))),
|
||||
],
|
||||
611: [ NextValue(bus.dat_r, Cat(fbc_next_y0, Signal(20, reset = 0))),
|
||||
],
|
||||
}),
|
||||
NextValue(bus.ack, 1),
|
||||
).Else(
|
||||
NextValue(bus.ack, 0),
|
||||
)
|
||||
)
|
||||
|
||||
# also in blit.c, for r5-cmd
|
||||
FUN_MASK = 0x0000000F
|
||||
FUN_DRAW = 0x00000001
|
||||
FUN_BLIT = 0x00000002
|
||||
FUN_FONT = 0x40000004 # include FUN_FONT_NEXT_RDY_BIT
|
||||
FUN_DONE_BIT = 31
|
||||
FUN_FONT_NEXT_RDY_BIT = 30
|
||||
FUN_FONT_NEXT_REQ_BIT = 29
|
||||
FUN_FONT_NEXT_DONE_BIT = 28
|
||||
|
||||
# for GX global status register
|
||||
#GX_FULL_BIT = 29
|
||||
GX_INPROGRESS_BIT = 28
|
||||
|
||||
# to hold the Vex in reset
|
||||
# could be sent to fbc_s[GX_INPROGRESS_BIT] ?
|
||||
local_reset = Signal(reset = 1)
|
||||
#timeout_rst = 0xFFFFFFF
|
||||
#timeout = Signal(28, reset = timeout_rst)
|
||||
|
||||
#pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(~local_reset);
|
||||
|
||||
self.sync += [
|
||||
self.fbc_fifo_font.re.eq(0),
|
||||
If(fbc_r5_cmd[FUN_DONE_BIT],
|
||||
fbc_r5_cmd.eq(0),
|
||||
fbc_s[GX_INPROGRESS_BIT].eq(0),
|
||||
#fbc_s[GX_FULL_BIT].eq(0),
|
||||
local_reset.eq(1),
|
||||
#timeout.eq(timeout_rst),
|
||||
).Elif(self.fbc_fifo_font.readable & fbc_s[GX_INPROGRESS_BIT] & fbc_r5_cmd[FUN_FONT_NEXT_REQ_BIT] & (fbc_r5_cmd[0:4] == 0x4),
|
||||
# the font code request the next line, and one is available: give it
|
||||
self.fbc_fifo_font.re.eq(1),
|
||||
fbc_next_font.eq(fbc_fifo_font_out.font),
|
||||
fbc_next_x0.eq(fbc_fifo_font_out.x0),
|
||||
fbc_next_x1.eq(fbc_fifo_font_out.x1),
|
||||
fbc_next_y0.eq(fbc_fifo_font_out.y0),
|
||||
fbc_r5_cmd[FUN_FONT_NEXT_REQ_BIT].eq(0),
|
||||
fbc_r5_cmd[FUN_FONT_NEXT_RDY_BIT].eq(1),
|
||||
#timeout.eq(timeout_rst),
|
||||
).Elif(~self.fbc_fifo_font.readable & fbc_s[GX_INPROGRESS_BIT] & fbc_r5_cmd[FUN_FONT_NEXT_REQ_BIT] & (fbc_r5_cmd[0:4] == 0x4),
|
||||
# the font code request the next line, but none is available; stop
|
||||
fbc_r5_cmd[FUN_FONT_NEXT_REQ_BIT].eq(0),
|
||||
fbc_r5_cmd[FUN_FONT_NEXT_DONE_BIT].eq(1),
|
||||
#timeout.eq(timeout_rst),
|
||||
).Elif(self.fbc_fifo_font.readable & ~fbc_s[GX_INPROGRESS_BIT],
|
||||
self.fbc_fifo_font.re.eq(1),
|
||||
fbc_next_font.eq(fbc_fifo_font_out.font),
|
||||
fbc_next_x0.eq(fbc_fifo_font_out.x0),
|
||||
fbc_next_x1.eq(fbc_fifo_font_out.x1),
|
||||
fbc_next_y0.eq(fbc_fifo_font_out.y0),
|
||||
fbc_r5_cmd.eq(FUN_FONT), # includes FUN_FONT_NEXT_RDY_BIT
|
||||
fbc_s[GX_INPROGRESS_BIT].eq(1),
|
||||
#fbc_s[GX_FULL_BIT].eq(1),
|
||||
local_reset.eq(0),
|
||||
#timeout.eq(timeout_rst),
|
||||
).Elif(fbc_do_draw & ~fbc_s[GX_INPROGRESS_BIT],
|
||||
fbc_do_draw.eq(0),
|
||||
fbc_r5_cmd.eq(FUN_DRAW),
|
||||
fbc_s[GX_INPROGRESS_BIT].eq(1),
|
||||
#fbc_s[GX_FULL_BIT].eq(1),
|
||||
local_reset.eq(0),
|
||||
#timeout.eq(timeout_rst),
|
||||
).Elif(fbc_do_blit & ~fbc_s[GX_INPROGRESS_BIT],
|
||||
fbc_do_blit.eq(0),
|
||||
fbc_r5_cmd.eq(FUN_BLIT),
|
||||
fbc_s[GX_INPROGRESS_BIT].eq(1),
|
||||
#fbc_s[GX_FULL_BIT].eq(1),
|
||||
local_reset.eq(0),
|
||||
#timeout.eq(timeout_rst),
|
||||
)
|
||||
#).Elif((timeout == 0) & fbc_s[GX_INPROGRESS_BIT], # OUPS
|
||||
# fbc_r5_cmd.eq(0),
|
||||
# fbc_s[GX_INPROGRESS_BIT].eq(0),
|
||||
# #fbc_s[GX_FULL_BIT].eq(0),
|
||||
# local_reset.eq(1),
|
||||
# timeout.eq(timeout_rst),
|
||||
#),
|
||||
#If(fbc_s[GX_INPROGRESS_BIT] & (timeout != 0),
|
||||
# timeout.eq(timeout - 1)
|
||||
#)
|
||||
]
|
||||
|
||||
self.ibus = ibus = wishbone.Interface()
|
||||
self.dbus = dbus = wishbone.Interface()
|
||||
vex_reset = Signal()
|
||||
|
||||
self.comb += vex_reset.eq(ResetSignal("sys") | local_reset)
|
||||
self.specials += Instance(self.get_netlist_name(),
|
||||
i_clk = ClockSignal("sys"),
|
||||
i_reset = vex_reset,
|
||||
o_iBusWishbone_CYC = ibus.cyc,
|
||||
o_iBusWishbone_STB = ibus.stb,
|
||||
i_iBusWishbone_ACK = ibus.ack,
|
||||
o_iBusWishbone_WE = ibus.we,
|
||||
o_iBusWishbone_ADR = ibus.adr,
|
||||
i_iBusWishbone_DAT_MISO = ibus.dat_r,
|
||||
o_iBusWishbone_DAT_MOSI = ibus.dat_w,
|
||||
o_iBusWishbone_SEL = ibus.sel,
|
||||
i_iBusWishbone_ERR = ibus.err,
|
||||
o_iBusWishbone_CTI = ibus.cti,
|
||||
o_iBusWishbone_BTE = ibus.bte,
|
||||
o_dBusWishbone_CYC = dbus.cyc,
|
||||
o_dBusWishbone_STB = dbus.stb,
|
||||
i_dBusWishbone_ACK = dbus.ack,
|
||||
o_dBusWishbone_WE = dbus.we,
|
||||
o_dBusWishbone_ADR = dbus.adr,
|
||||
i_dBusWishbone_DAT_MISO = dbus.dat_r,
|
||||
o_dBusWishbone_DAT_MOSI = dbus.dat_w,
|
||||
o_dBusWishbone_SEL = dbus.sel,
|
||||
i_dBusWishbone_ERR = dbus.err,
|
||||
o_dBusWishbone_CTI = dbus.cti,
|
||||
o_dBusWishbone_BTE = dbus.bte,)
|
||||
|
||||
self.add_sources(platform)
|
||||
|
||||
def get_netlist_name(self):
|
||||
return "VexRiscv"
|
||||
|
||||
def add_sources(self, platform):
|
||||
platform.add_source("/home/dolbeau/SBusFPGA/sbus-to-ztex-gateware-migen/VexRiscv_FbAccel.v", "verilog")
|
||||
191
sbus-to-ztex-gateware-migen/cg6_fb.py
Normal file
191
sbus-to-ztex-gateware-migen/cg6_fb.py
Normal file
@@ -0,0 +1,191 @@
|
||||
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;
|
||||
|
||||
# reuse the simple 8-bits DAC from cg3
|
||||
# we will be missing the HW cursor
|
||||
import cg3_fb;
|
||||
|
||||
# a lot of that is identical to cg3_fb.cg3
|
||||
class cg6(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))
|
||||
self.submodules.upd_overlay_fifo = upd_overlay_fifo = ClockDomainsRenamer({"read": "vga", "write": "sys"})(AsyncFIFOBuffered(width=1+5+32, depth=8))
|
||||
self.submodules.upd_omap_fifo = upd_omap_fifo = ClockDomainsRenamer({"read": "vga", "write": "sys"})(AsyncFIFOBuffered(width=2+2+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], hwcursor=True)
|
||||
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"CG6: 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"CG6: using {hres} x {vres}, {freq/1e6} MHz pixclk")
|
||||
vfb = cg3_fb.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),
|
||||
hwcursor = True,
|
||||
upd_overlay_fifo = upd_overlay_fifo,
|
||||
upd_omap_fifo = upd_omap_fifo)
|
||||
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)
|
||||
|
||||
# cg6 ramdac registers - same as cg3, but used a bit differently...
|
||||
# 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 */
|
||||
# };
|
||||
|
||||
# for BT
|
||||
self.bus = bus = wishbone.Interface()
|
||||
|
||||
bt_addr = Signal(8)
|
||||
bt_cmap_state = Signal(2)
|
||||
|
||||
# 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",
|
||||
NextValue(bus.ack, 0),
|
||||
NextState("Idle"))
|
||||
wishbone_fsm.act("Idle",
|
||||
If(bus.cyc & bus.stb & bus.we & ~bus.ack & upd_cmap_fifo.writable, #write
|
||||
# FIXME: should check for prefix?
|
||||
Case(bus.adr[0:3], {
|
||||
# bt_addr
|
||||
0: [ NextValue(bt_addr, bus.dat_w[24:32]),
|
||||
NextValue(bt_cmap_state, 0),
|
||||
],
|
||||
# bt_cmap
|
||||
1: [ upd_cmap_fifo.we.eq(1),
|
||||
upd_cmap_fifo.din.eq(Cat(bt_cmap_state, bt_addr, 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_addr, (bt_addr+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
],
|
||||
# bt_ctrl
|
||||
# NetBSD driver adds 0x03<<24 to enable the cursor
|
||||
2: [],
|
||||
# bt_omap
|
||||
# NetBSD driver write the cursor color in there
|
||||
3: [ upd_omap_fifo.we.eq(1),
|
||||
upd_omap_fifo.din.eq(Cat(bt_cmap_state, bt_addr, 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_addr, (bt_addr+1) & 0xFF), ],
|
||||
"default": NextValue(bt_cmap_state, 0),
|
||||
}),
|
||||
],
|
||||
"default": [],
|
||||
}),
|
||||
NextValue(bus.ack, 1),
|
||||
).Elif(bus.cyc & bus.stb & ~bus.we & ~bus.ack, #read
|
||||
Case(bus.adr[0:3], {
|
||||
# bt_addr
|
||||
0: [ NextValue(bus.dat_r, 0) ],
|
||||
# bt_cmap
|
||||
1: [ NextValue(bus.dat_r, 0)],
|
||||
# bt_ctrl: unused ??
|
||||
2: [ NextValue(bus.dat_r, 0)],
|
||||
# bt_omap: unused ??
|
||||
3: [ NextValue(bus.dat_r, 0)],
|
||||
"default": [],
|
||||
}),
|
||||
NextValue(bus.ack, 1),
|
||||
).Else(
|
||||
NextValue(bus.ack, 0),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
# for FHC/THC
|
||||
# fhc @ 0x300000
|
||||
# thc @ 0x301000
|
||||
# thc_cursxy # 0x8fc from THC
|
||||
# thc_cursmask[32] @ 0x900 from THC
|
||||
# thc_cursbits[32] @ 0x980 from THC
|
||||
|
||||
hwcursor_x = Signal(12)
|
||||
hwcursor_y = Signal(12)
|
||||
|
||||
self.comb += vtg.hwcursor_x.eq(hwcursor_x)
|
||||
self.comb += vtg.hwcursor_y.eq(hwcursor_y)
|
||||
|
||||
pad_SBUS_DATA_OE_LED = soc.platform.request("SBUS_DATA_OE_LED")
|
||||
self.comb += pad_SBUS_DATA_OE_LED.eq((hwcursor_x < 1280) & (hwcursor_y < 1024));
|
||||
|
||||
self.bus2 = bus2 = wishbone.Interface()
|
||||
self.submodules.wishbone_fsm2 = wishbone_fsm2 = FSM(reset_state = "Reset")
|
||||
wishbone_fsm2.act("Reset",
|
||||
NextValue(bus2.ack, 0),
|
||||
NextState("Idle"))
|
||||
wishbone_fsm2.act("Idle",
|
||||
If(bus2.cyc & bus2.stb & bus2.we & ~bus2.ack, #write
|
||||
Case(bus2.adr[0:11], {
|
||||
"default": [ ],
|
||||
1599: [ NextValue(hwcursor_x, bus2.dat_w[16:28]),
|
||||
NextValue(hwcursor_y, bus2.dat_w[ 0:12]),
|
||||
],
|
||||
}),
|
||||
Case(bus2.adr[5:11], {
|
||||
"default": [ ],
|
||||
50 : [ upd_overlay_fifo.we.eq(1), # 50*32 = 1600..1631
|
||||
upd_overlay_fifo.din.eq(Cat(Signal(1, reset = 0), 31-bus2.adr[0:5], bus2.dat_w))
|
||||
],
|
||||
51 : [ upd_overlay_fifo.we.eq(1), # 51*32 = 1632..1663
|
||||
upd_overlay_fifo.din.eq(Cat(Signal(1, reset = 1), 31-bus2.adr[0:5], bus2.dat_w))
|
||||
],
|
||||
}),
|
||||
NextValue(bus2.ack, 1),
|
||||
).Elif(bus2.cyc & bus2.stb & ~bus2.we & ~bus2.ack, #read
|
||||
Case(bus2.adr[0:10], {
|
||||
"default": [ NextValue(bus2.dat_r, 0xDEADBEEF) ],
|
||||
0: [ NextValue(bus2.dat_r, 0x60500000) ], # claim revision 5
|
||||
}),
|
||||
NextValue(bus2.ack, 1),
|
||||
).Else(
|
||||
NextValue(bus2.ack, 0),
|
||||
)
|
||||
)
|
||||
|
||||
24
sbus-to-ztex-gateware-migen/cg6_init.fth
Normal file
24
sbus-to-ztex-gateware-migen/cg6_init.fth
Normal file
@@ -0,0 +1,24 @@
|
||||
: cg6_vid_fb_vtg_enable_rd ( -- csr_value)
|
||||
cg6-virt h# 0000 + l@
|
||||
;
|
||||
|
||||
: cg6_vid_fb_dma_enable_rd ( -- csr_value)
|
||||
cg6-virt h# 002c + l@
|
||||
;
|
||||
|
||||
: cg6_vid_fb_vtg_enable_wr ( value -- )
|
||||
cg6-virt h# 0000 + l!
|
||||
;
|
||||
|
||||
: cg6_vid_fb_dma_enable_wr ( value -- )
|
||||
cg6-virt h# 002c + l!
|
||||
;
|
||||
|
||||
: cg6_init!
|
||||
map-in-cg6extraregs
|
||||
0 cg6_vid_fb_vtg_enable_wr
|
||||
0 cg6_vid_fb_dma_enable_wr
|
||||
1 cg6_vid_fb_vtg_enable_wr
|
||||
1 cg6_vid_fb_dma_enable_wr
|
||||
map-out-cg6extraregs
|
||||
;
|
||||
425
sbus-to-ztex-gateware-migen/fbc_init.fth
Normal file
425
sbus-to-ztex-gateware-migen/fbc_init.fth
Normal file
@@ -0,0 +1,425 @@
|
||||
|
||||
-1 instance value fbc-virt
|
||||
: map-in-fbc ( -- ) my-sbus-address sbusfpga_regionaddr_cg6_fbc + my-sbus-space h# 2000 map-in is fbc-virt ;
|
||||
: map-out-fbc ( -- ) fbc-virt h# 2000 map-out ;
|
||||
|
||||
: fbc! ( val off -- )
|
||||
fbc-virt + l!
|
||||
;
|
||||
: fbc@ ( off -- val )
|
||||
fbc-virt + l@
|
||||
;
|
||||
|
||||
\ a.k.a. 'rasterops'
|
||||
: fbc_alu! ( val -- )
|
||||
h# 108 fbc!
|
||||
;
|
||||
|
||||
\ a.k.a. 'misc'
|
||||
: fbc_mode! ( val -- )
|
||||
h# 4 fbc!
|
||||
;
|
||||
|
||||
: fbc_clip! ( val -- )
|
||||
h# 8 fbc!
|
||||
;
|
||||
|
||||
: fbc_offx! ( val -- )
|
||||
h# c0 fbc!
|
||||
;
|
||||
: fbc_offy! ( val -- )
|
||||
h# c4 fbc!
|
||||
;
|
||||
|
||||
: fbc_x0! ( val -- )
|
||||
h# 80 fbc!
|
||||
;
|
||||
: fbc_y0! ( val -- )
|
||||
h# 84 fbc!
|
||||
;
|
||||
: fbc_x1! ( val -- )
|
||||
h# 90 fbc!
|
||||
;
|
||||
: fbc_y1! ( val -- )
|
||||
h# 94 fbc!
|
||||
;
|
||||
: fbc_x2! ( val -- )
|
||||
h# a0 fbc!
|
||||
;
|
||||
: fbc_y2! ( val -- )
|
||||
h# a4 fbc!
|
||||
;
|
||||
: fbc_x3! ( val -- )
|
||||
h# b0 fbc!
|
||||
;
|
||||
: fbc_y3! ( val -- )
|
||||
h# b4 fbc!
|
||||
;
|
||||
|
||||
: fbc_incx! ( val -- )
|
||||
h# d0 fbc!
|
||||
;
|
||||
: fbc_incy! ( val -- )
|
||||
h# d4 fbc!
|
||||
;
|
||||
|
||||
: fbc_clipminx! ( val -- )
|
||||
h# e0 fbc!
|
||||
;
|
||||
: fbc_clipminy! ( val -- )
|
||||
h# e4 fbc!
|
||||
;
|
||||
|
||||
: fbc_clipmaxx! ( val -- )
|
||||
h# f0 fbc!
|
||||
;
|
||||
: fbc_clipmaxy! ( val -- )
|
||||
h# f4 fbc!
|
||||
;
|
||||
|
||||
: fbc_fg! ( val -- )
|
||||
h# 100 fbc!
|
||||
;
|
||||
|
||||
: fbc_bg! ( val -- )
|
||||
h# 104 fbc!
|
||||
;
|
||||
|
||||
: fbc_arectx! ( val --)
|
||||
h# 900 fbc!
|
||||
;
|
||||
|
||||
: fbc_arecty! ( val --)
|
||||
h# 904 fbc!
|
||||
;
|
||||
|
||||
: fbc_s@ ( -- val )
|
||||
h# 10 fbc@
|
||||
;
|
||||
|
||||
: fbc_draw@ ( -- val )
|
||||
h# 14 fbc@
|
||||
;
|
||||
: fbc_blit@ ( -- val )
|
||||
h# 18 fbc@
|
||||
;
|
||||
|
||||
h# ff constant fground-color
|
||||
h# 00 constant bground-color
|
||||
|
||||
: init-fbc
|
||||
h# 0 fbc_clip!
|
||||
h# 0 fbc_offx!
|
||||
h# 0 fbc_offy!
|
||||
h# 0 fbc_incx!
|
||||
h# 0 fbc_incy!
|
||||
h# 0 fbc_clipminx!
|
||||
h# 0 fbc_clipmaxy!
|
||||
openbios-video-width 1 - fbc_clipmaxx!
|
||||
openbios-video-height 1 - fbc_clipmaxy!
|
||||
h# ff fbc_fg!
|
||||
h# 0 fbc_bg!
|
||||
\ a9806c60 = 1010_1001__1000_0000__0110_1100__0110_0000
|
||||
\ from the doc:
|
||||
\ 31-30 Override Plane Mask Select
|
||||
\ (OO=Ignore, Ol=Use zeroes, 10=Use ones, ll=Use PLANEMASK)
|
||||
\ 29-28 Override Pixel Mask Select
|
||||
\ (OO=Ignore, 01-Use zeroes, 10=Use ones, ll=Use PIXELMASK)
|
||||
\ 27-26 Override Pattern Select
|
||||
\ (OO=Ignore, Ol=Use zeroes, 10=Use ones, ll=Use PATTERN)
|
||||
\ 25-24 Polygon Draw Select
|
||||
\ (OO=Ignore, 01=0verlapping, lO=Nonoverlapping, Il=Illegal)
|
||||
\ 23-22 UNSUPPORTED-ATTR
|
||||
\ (OO=Ignore, Ol=Unsupported, lO=Supported, ll=Illegal)
|
||||
\ 17 Rasterop Mode (()=BOOLEAN, l=LINEAR)
|
||||
\ 16 Plot/Unplot Mode (O=PLOT, l=UNPLOT)
|
||||
\ 15-12 Rasterop used when FCOLOR[p]=l and BCOLOR[pl=l
|
||||
\ 11-8 Rasterop used when FCOLOR[p]=l and BCOLOR[pl=O
|
||||
\ 7-4 Rasterop used when FCOLOR[p]=O and BCOLOR[pl=l
|
||||
\ 3-0 Rasterop used when FCOLOR[p]=O and BCOLOR[p]=O
|
||||
\
|
||||
\ so: => all 3 override are 'use 1'
|
||||
\ polygon draw => overlapping
|
||||
\ unsup attr => supported
|
||||
\ rop mode => boolean
|
||||
\ plot/unplot => plot
|
||||
\ rops => four groups of <whatever> (still don't understand it)
|
||||
h# a9806c60 fbc_alu!
|
||||
|
||||
\ ff for planemask (unimp)
|
||||
\ ffffffff for pixelmask (unimp)
|
||||
\ 0 for patalign (unimp)
|
||||
\ ffffffff for pattern0-7 (unimp)
|
||||
|
||||
|
||||
\ 229540 = 0000_0000__0010_0010__1001_0101__0100_0000
|
||||
\ from the doc:
|
||||
\ 31-22 0000_0000_00
|
||||
\ 21-20 BLIT-SRC-CHK
|
||||
\ (OO=ignore, 01-Exclude Src, lO=Include Src, ll=Illegal)
|
||||
\ 19 VBLANK OCCURED (l=VBLANK has occurred)
|
||||
\ 18-17 Anti-Aliasing/Color Mode Select
|
||||
\ (00=ignore, Ol=COLOR8, lO=COLORl, ll=HRMONO)
|
||||
\ 16-15 Render/Pick Mode Select
|
||||
\ (OO=ignore, Ol=RENDER, 10=PICK, 11-Illegal)
|
||||
\ 14-13 Buffer 0 Write Enable
|
||||
\ (OO=ignore, Ol=Enable, lO=Disable, ll=Illegal)
|
||||
\ 12-11 Buffer 1 Write Enable
|
||||
\ (00-ignore, Ol=Enable, lO-Disable, ll=Illegal)
|
||||
\ 10-9 Buffer Read Enable
|
||||
\ (OO=ignore, 01-Read from BufferO, lO=Read Bufferl, ll=Illegal)
|
||||
\ 8-7 Buffer Display Enable
|
||||
\ (OO=ignore, Ol=Display BufferO, lO=Display Bufferl, ll=Illegal)
|
||||
\ 6 Modify Address INDEX (l=Modify Address Index)
|
||||
\ 5-4 Address INDEX
|
||||
\ 3-0 0000
|
||||
\
|
||||
\ so: BLIT-SRC-CHECK => include src
|
||||
\ VBLANK => no (guessig this is RO?)
|
||||
\ aa/color: => COLOR8
|
||||
\ render/pick => render
|
||||
\ buf 0 wr ena => ignore
|
||||
\ buf 1 wr ena => disable
|
||||
\ buf read ena => buffer 1
|
||||
\ buf dis ena => buffer 1
|
||||
\ mod. addr inx => 1 (always)
|
||||
\ addr idx => 0
|
||||
h# 229540 fbc_mode!
|
||||
;
|
||||
|
||||
\ this reads 'draw' until no longer full
|
||||
\ (we're never full..)
|
||||
: fbc-draw-wait ( -- )
|
||||
begin
|
||||
fbc_draw@
|
||||
h# 20000000
|
||||
and
|
||||
0=
|
||||
until
|
||||
;
|
||||
\ this reads 'blit' until no longer full
|
||||
\ (we're never full..)
|
||||
: fbc-blit-wait ( -- )
|
||||
begin
|
||||
fbc_blit@
|
||||
h# 20000000
|
||||
and
|
||||
0=
|
||||
until
|
||||
;
|
||||
\ busy-wait on PROGRESS in 's(tatus)'
|
||||
: fbc-busy-wait ( -- )
|
||||
begin
|
||||
fbc_s@
|
||||
h# 10000000
|
||||
and
|
||||
0=
|
||||
until
|
||||
;
|
||||
|
||||
\ convert char pos to pixel pos
|
||||
: >pixel ( cx cy -- px py )
|
||||
swap
|
||||
char-width
|
||||
*
|
||||
window-left
|
||||
+
|
||||
swap
|
||||
char-height
|
||||
*
|
||||
window-top
|
||||
+
|
||||
;
|
||||
|
||||
: fbc-rect-fill ( x0 y0 x1 y1 fg_color -- )
|
||||
fbc-busy-wait
|
||||
fbc_fg!
|
||||
\ fix the registers to what we currently expect
|
||||
h# a980ff00 fbc_alu!
|
||||
h# 00220000 fbc_mode!
|
||||
\ we start with x0/y0
|
||||
2swap
|
||||
fbc_arecty!
|
||||
fbc_arectx!
|
||||
fbc_arecty!
|
||||
fbc_arectx!
|
||||
fbc-draw-wait
|
||||
fbc-busy-wait
|
||||
\ reset fg_color
|
||||
fground-color fbc_fg!
|
||||
;
|
||||
|
||||
: fbc-blit ( cx0 cy0 cx1 cy1 cx2 cy2 cx3 cy3 -- )
|
||||
fbc-busy-wait
|
||||
\ fix the registers to what we currently expect
|
||||
h# a980cccc fbc_alu!
|
||||
h# 00220000 fbc_mode!
|
||||
>pixel
|
||||
1
|
||||
-
|
||||
fbc_y3!
|
||||
1
|
||||
-
|
||||
fbc_x3!
|
||||
>pixel
|
||||
fbc_y2!
|
||||
fbc_x2!
|
||||
>pixel
|
||||
1
|
||||
-
|
||||
fbc_y1!
|
||||
1
|
||||
-
|
||||
fbc_x1!
|
||||
>pixel
|
||||
fbc_y0!
|
||||
fbc_x0!
|
||||
fbc-blit-wait
|
||||
fbc-busy-wait
|
||||
;
|
||||
|
||||
\ fill a rectangle of char with background-color
|
||||
: fbc-char-fill ( cw0 ch0 cw1 ch1 -- )
|
||||
2swap
|
||||
>pixel
|
||||
2swap
|
||||
>pixel
|
||||
bground-color
|
||||
fbc-rect-fill
|
||||
;
|
||||
|
||||
: fbc-erase-screen ( -- )
|
||||
\ x0
|
||||
0
|
||||
\ y0
|
||||
0
|
||||
\ x1
|
||||
openbios-video-width 1 -
|
||||
\ y1
|
||||
openbios-video-height 1 -
|
||||
\ fg_col
|
||||
bground-color
|
||||
fbc-rect-fill
|
||||
;
|
||||
|
||||
: fbc-delete-lines ( n -- )
|
||||
\ check if we move the whole screen
|
||||
dup #lines < if
|
||||
>r
|
||||
0
|
||||
line#
|
||||
r@
|
||||
+
|
||||
#columns
|
||||
#lines
|
||||
0
|
||||
line#
|
||||
#columns
|
||||
#lines
|
||||
r@
|
||||
-
|
||||
line#
|
||||
\ check if there's some lines at the bottom to blit
|
||||
r@ + #lines < if
|
||||
fbc-blit
|
||||
else
|
||||
2drop
|
||||
2drop
|
||||
2drop
|
||||
2drop
|
||||
then
|
||||
0
|
||||
#lines
|
||||
r>
|
||||
-
|
||||
#columns
|
||||
#lines
|
||||
fbc-char-fill
|
||||
else
|
||||
0
|
||||
swap
|
||||
#lines
|
||||
swap
|
||||
-
|
||||
#columns
|
||||
#lines
|
||||
fbc-char-fill
|
||||
then
|
||||
;
|
||||
|
||||
: fbc-insert-lines ( n -- )
|
||||
dup #lines < if
|
||||
>r
|
||||
0
|
||||
line#
|
||||
#columns
|
||||
#lines
|
||||
r@
|
||||
-
|
||||
0
|
||||
line#
|
||||
r@
|
||||
+
|
||||
#columns
|
||||
#lines
|
||||
fbc-blit
|
||||
0
|
||||
line#
|
||||
#columns
|
||||
line#
|
||||
r>
|
||||
+
|
||||
fbc-char-fill
|
||||
else
|
||||
0
|
||||
swap
|
||||
line#
|
||||
swap
|
||||
#columns
|
||||
swap
|
||||
line#
|
||||
swap
|
||||
+
|
||||
fbc-char-fill
|
||||
then
|
||||
;
|
||||
|
||||
\ unaccelerated placeholders, we need to wait before drawing
|
||||
: cg6-blink-screen
|
||||
\ FIXME
|
||||
;
|
||||
: cg6-reset-screen
|
||||
\ FIXME
|
||||
;
|
||||
: cg6-draw-char
|
||||
fbc-busy-wait
|
||||
fb8-draw-character
|
||||
;
|
||||
: cg6-toggle-cursor
|
||||
fbc-busy-wait
|
||||
fb8-toggle-cursor
|
||||
;
|
||||
: cg6-invert-screen
|
||||
fbc-busy-wait
|
||||
fb8-invert-screen
|
||||
;
|
||||
: cg6-erase-screen
|
||||
fbc-busy-wait
|
||||
fb8-erase-screen
|
||||
;
|
||||
: cg6-insert-characters
|
||||
fbc-busy-wait
|
||||
fb8-insert-characters
|
||||
;
|
||||
: cg6-delete-characters
|
||||
fbc-busy-wait
|
||||
fb8-delete-characters
|
||||
;
|
||||
: cg6-delete-lines
|
||||
fbc-busy-wait
|
||||
fb8-delete-lines
|
||||
;
|
||||
: cg6-insert-lines
|
||||
fbc-busy-wait
|
||||
fb8-insert-lines
|
||||
;
|
||||
@@ -31,7 +31,12 @@ 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)
|
||||
CG6_BT_ADDR_PFX = Signal(12, reset = 0x020)
|
||||
CG6_FHC_ADDR_PFX = Signal(12, reset = 0x030)
|
||||
CG3_BT_ADDR_PFX = Signal(12, reset = 0x040)
|
||||
FBC_ROM_ADDR_PFX = Signal(12, reset = 0x041)
|
||||
#FBC_RAM_ADDR_PFX = Signal(12, reset = 0x042)
|
||||
CG6_FBC_ADDR_PFX = Signal(12, reset = 0x070)
|
||||
|
||||
ADDR_BIGPFX_HIGH = ADDR_PHYS_HIGH
|
||||
ADDR_BIGPFX_LOW = 20 ## 1 MiB per bigprefix
|
||||
@@ -464,11 +469,15 @@ class SBusFPGABus(Module):
|
||||
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] == WISHBONE_CSR_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == FBC_ROM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FBC_ADDR_PFX) |
|
||||
(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] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_BT_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FHC_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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
|
||||
@@ -532,7 +541,7 @@ class SBusFPGABus(Module):
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
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] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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
|
||||
@@ -602,7 +611,7 @@ class SBusFPGABus(Module):
|
||||
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] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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
|
||||
@@ -679,11 +688,15 @@ 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] == WISHBONE_CSR_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == FBC_ROM_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FBC_ADDR_PFX) |
|
||||
(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] == CG3_REGISTERS_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_BT_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FHC_ADDR_PFX) |
|
||||
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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,
|
||||
@@ -729,7 +742,7 @@ class SBusFPGABus(Module):
|
||||
(SBUS_3V3_PPRD_i == 0)),
|
||||
NextValue(sbus_oe_master_in, 1),
|
||||
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_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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,
|
||||
@@ -781,7 +794,7 @@ 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] == 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_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_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,
|
||||
|
||||
@@ -7,6 +7,7 @@ from sysconfig import get_platform
|
||||
from migen import *
|
||||
|
||||
import cg3_fb
|
||||
import cg6_fb
|
||||
|
||||
|
||||
def get_header_map_stuff(gname, name, size, type="csr", reg=True):
|
||||
@@ -75,6 +76,7 @@ def get_prom(soc,
|
||||
engine=False,
|
||||
i2c=False,
|
||||
cg3=False,
|
||||
cg6=False,
|
||||
cg3_res=None):
|
||||
|
||||
r = "fcode-version2\nfload prom_csr_{}.fth\n".format(version.replace(".", "_"))
|
||||
@@ -97,7 +99,7 @@ def get_prom(soc,
|
||||
r += " map-out-trng\n"
|
||||
r += ";\n"
|
||||
r += "disabletrng!\n"
|
||||
if (usb or sdram or engine or i2c or cg3):
|
||||
if (usb or sdram or engine or i2c or cg3 or cg6):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (usb):
|
||||
@@ -117,14 +119,14 @@ def get_prom(soc,
|
||||
r += " map-out-usb_host_ctrl\n"
|
||||
r += ";\n"
|
||||
r += "my-reset!\n"
|
||||
if (sdram or engine or i2c or cg3):
|
||||
if (sdram or engine or i2c or cg3 or cg6):
|
||||
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):
|
||||
if (engine or i2c or cg3 or cg6):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (engine):
|
||||
@@ -132,21 +134,24 @@ def get_prom(soc,
|
||||
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):
|
||||
if (i2c or cg3 or cg6):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (i2c):
|
||||
r += "\" RDOL,i2c\" device-name\n"
|
||||
r += get_header_map_stuff("i2c", "i2c", 64)
|
||||
if (cg3):
|
||||
if (cg3 or cg6):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (cg3):
|
||||
if (cg3 or cg6):
|
||||
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")
|
||||
if (cg3):
|
||||
cg3_file = open("cg3.fth")
|
||||
else:
|
||||
cg3_file = open("cg6.fth")
|
||||
cg3_lines = cg3_file.readlines()
|
||||
buf_size=cg3_fb.cg3_rounded_size(hres, vres)
|
||||
for line in cg3_lines:
|
||||
@@ -154,10 +159,13 @@ def get_prom(soc,
|
||||
#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"
|
||||
if (cg3):
|
||||
r += get_header_map_stuff("cg3extraregs", "cg3", 4096, reg=False)
|
||||
r += "fload cg3_init.fth\ncg3_init!\n"
|
||||
if (cg6):
|
||||
r += get_header_map_stuff("cg6extraregs", "cg6", 4096, reg=False)
|
||||
r += "fload cg6_init.fth\ncg6_init!\n"
|
||||
|
||||
r += "end0\n"
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ import sbus_to_fpga_prom;
|
||||
|
||||
from litex.soc.cores.video import VideoVGAPHY
|
||||
import cg3_fb;
|
||||
import cg6_fb;
|
||||
import cg6_accel;
|
||||
#import cgtrois;
|
||||
|
||||
# CRG ----------------------------------------------------------------------------------------------
|
||||
@@ -209,7 +211,7 @@ class SBusFPGA(SoCCore):
|
||||
#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):
|
||||
def __init__(self, version, sys_clk_freq, usb, sdram, engine, i2c, cg3, cg6, cg3_res, **kwargs):
|
||||
print(f"Building SBusFPGA for board version {version}")
|
||||
|
||||
kwargs["cpu_type"] = "None"
|
||||
@@ -221,14 +223,14 @@ class SBusFPGA(SoCCore):
|
||||
|
||||
self.platform = platform = ztex213_sbus.Platform(variant="ztex2.13a", version = version)
|
||||
|
||||
if (cg3 and (version == "V1.2")):
|
||||
if ((cg3 or cg6) and (version == "V1.2")):
|
||||
platform.add_extension(ztex213_sbus._vga_pmod_io_v1_2)
|
||||
|
||||
if (cg3):
|
||||
if (cg3 or cg6):
|
||||
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")
|
||||
print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the CG3/CG6")
|
||||
else:
|
||||
hres = 0
|
||||
vres = 0
|
||||
@@ -252,22 +254,27 @@ 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, # 256 Kib ought to be enough for anybody (we're using < 2.5 Kib now...)
|
||||
"prom": 0x00000000, # 256 Kib ought to be enough for anybody (we're using < 8 Kib now...)
|
||||
"csr" : 0x00040000,
|
||||
"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)
|
||||
"cg6_bt": 0x00200000, # required for compatibility, bt_regs for cg6
|
||||
#"cg6_dhc": 0x00240000, # required for compatibility, unused
|
||||
"cg6_fhc": 0x00300000, # required for compatibility
|
||||
#"cg6_thc": 0x00301000, # required for compatibility
|
||||
"cg3_bt": 0x00400000, # required for compatibility, bt_regs for cg3
|
||||
"cg6_accel_rom": 0x00410000, # R5 microcode
|
||||
"cg6_accel_ram": 0x00420000, # R5 microcode working space (stack)
|
||||
"cg6_fbc": 0x00700000, # required for compatibility
|
||||
#"cg6_tec": 0x00701000, # required for compatibility
|
||||
"cg3_pixels": 0x00800000, # required for compatibility, 1-2 MiB for now (2nd MiB is 0x00900000) (cg3 and cg6 idem)
|
||||
"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, usb_clk_freq=48e6, sdram=sdram, engine=engine, cg3=cg3, pix_clk=litex.soc.cores.video.video_timings[cg3_res]["pix_clk"])
|
||||
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, usb_clk_freq=48e6, sdram=sdram, engine=engine, cg3=(cg3 or cg6), 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
|
||||
@@ -319,7 +326,7 @@ class SBusFPGA(SoCCore):
|
||||
#for i in range(len(prom)):
|
||||
# print(hex(prom[i]))
|
||||
#print("\n****************************************\n")
|
||||
self.add_ram("prom", origin=self.mem_map["prom"], size=2**16, contents=prom_data, mode="r")
|
||||
self.add_ram("prom", origin=self.mem_map["prom"], size=2**14, contents=prom_data, mode="r") ### FIXME: round up the prom_data size & check for <= 2**16!
|
||||
#getattr(self,"prom").mem.init = prom_data
|
||||
#getattr(self,"prom").mem.depth = 2**14
|
||||
|
||||
@@ -337,7 +344,7 @@ class SBusFPGA(SoCCore):
|
||||
else:
|
||||
avail_sdram = 0
|
||||
|
||||
if (cg3):
|
||||
if (cg3 or cg6):
|
||||
if (avail_sdram >= cg3_fb_size):
|
||||
avail_sdram = avail_sdram - cg3_fb_size
|
||||
else:
|
||||
@@ -435,19 +442,26 @@ class SBusFPGA(SoCCore):
|
||||
if (i2c):
|
||||
self.submodules.i2c = i2c.RTLI2C(platform, pads=platform.request("i2c"))
|
||||
|
||||
if (cg3):
|
||||
if (cg3 or cg6):
|
||||
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)
|
||||
if (cg3):
|
||||
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_bt", self.cg3.bus, SoCRegion(origin=self.mem_map.get("cg3_bt", None), size=0x1000, cached=False))
|
||||
else:
|
||||
self.submodules.cg6 = cg6_fb.cg6(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga") # clock_domain for the VGA side, cg6 is running in cd_sys
|
||||
self.bus.add_slave("cg6_bt", self.cg6.bus, SoCRegion(origin=self.mem_map.get("cg6_bt", None), size=0x1000, cached=False))
|
||||
|
||||
|
||||
if (cg6):
|
||||
self.submodules.cg6_accel = cg6_accel.CG6Accel(self.platform)
|
||||
self.bus.add_slave("cg6_fbc", self.cg6_accel.bus, SoCRegion(origin=self.mem_map.get("cg6_fbc", None), size=0x2000, cached=False))
|
||||
self.bus.add_slave("cg6_fhc", self.cg6.bus2, SoCRegion(origin=self.mem_map.get("cg6_fhc", None), size=0x2000, cached=False))
|
||||
self.bus.add_master(name="cg6_accel_r5_i", master=self.cg6_accel.ibus)
|
||||
self.bus.add_master(name="cg6_accel_r5_d", master=self.cg6_accel.dbus)
|
||||
cg6_rom_file = "blit.raw"
|
||||
cg6_rom_data = soc_core.get_mem_data(cg6_rom_file, "little")
|
||||
self.add_ram("cg6_accel_rom", origin=self.mem_map["cg6_accel_rom"], size=2**12, contents=cg6_rom_data, mode="r")
|
||||
self.add_ram("cg6_accel_ram", origin=self.mem_map["cg6_accel_ram"], size=2**12, mode="rw")
|
||||
|
||||
print("IRQ to Device map:\n")
|
||||
print(platform.irq_device_map)
|
||||
@@ -474,7 +488,8 @@ def main():
|
||||
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")
|
||||
parser.add_argument("--cg3-res", default="1152x900@76Hz", help="Specify the CG3/CG6 resolution")
|
||||
parser.add_argument("--cg6", action="store_true", help="add a CG6 framebuffer [V1.2+VGA_RGB222 pmod]")
|
||||
builder_args(parser)
|
||||
vivado_build_args(parser)
|
||||
args = parser.parse_args()
|
||||
@@ -486,8 +501,11 @@ def main():
|
||||
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")
|
||||
if ((args.cg3 or args.cg6) and (args.version == "V1.0")):
|
||||
print(" ***** ERROR ***** : VGA not supported on V1.0\n")
|
||||
assert(False)
|
||||
if (args.cg3 and args.cg6):
|
||||
print(" ***** ERROR ***** : can't have both CG3 and CG6\n")
|
||||
assert(False)
|
||||
|
||||
soc = SBusFPGA(**soc_core_argdict(args),
|
||||
@@ -498,6 +516,7 @@ def main():
|
||||
engine=args.engine,
|
||||
i2c=args.i2c,
|
||||
cg3=args.cg3,
|
||||
cg6=args.cg6,
|
||||
cg3_res=args.cg3_res)
|
||||
#soc.add_uart(name="uart", baudrate=115200, fifo_depth=16)
|
||||
|
||||
@@ -542,6 +561,7 @@ def main():
|
||||
engine=args.engine,
|
||||
i2c=args.i2c,
|
||||
cg3=args.cg3,
|
||||
cg6=args.cg6,
|
||||
cg3_res=args.cg3_res)
|
||||
write_to_file(os.path.join(f"prom_{version_for_filename}.fth"), prom_content)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user