update to first tested version

This commit is contained in:
Romain Dolbeau 2022-04-17 11:25:48 +02:00
parent de1aaf8161
commit 62b2c48b32
71 changed files with 1684 additions and 605 deletions

BIN
Pictures/NuBusFPGA.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

View File

@ -6,4 +6,4 @@ The goal of this repository is to be able to interface a modern (2021 era) [FPGA
## Current status
Early draft version, this has not been built or tested.
First prototype is working, implements a basic single-resolution, 8-bits only framebuffer over HDMI or VGA.

Binary file not shown.

View File

@ -0,0 +1 @@
/* * Hello World for the CodeWarrior * © 1997 Metrowerks Corp. * * Questions and comments to: * <mailto:support@metrowerks.com> * <http://www.metrowerks.com/> */ #include <stdio.h> #include <stdlib.h> /* #include <stdint.h> */ #include <time.h> #include <OSUtils.h> typedef int int32_t; typedef unsigned int uint32_t; struct nubusfpga_leds_softc { uint32_t slotid; }; struct nubusfpga_leds_softc sc; uint32_t csr_read_simple(uint32_t offset); void csr_write_simple(uint32_t value, uint32_t offset); uint32_t rev(uint32_t d); uint32_t csr_read_simple(uint32_t offset) { uint32_t *addr; addr = (uint32_t*)(((0x000000F0 | sc.slotid) << 24) + offset); return *addr; } void csr_write_simple(uint32_t value, uint32_t offset) { uint32_t *addr; addr = (uint32_t*)(((0x000000F0 | sc.slotid) << 24) + offset); *addr = value; } uint32_t rev(uint32_t d) { uint32_t r; r = 0; r |= (d & 0x80808080) >> 7; r |= (d & 0x40404040) >> 5; r |= (d & 0x20202020) >> 3; r |= (d & 0x10101010) >> 1; r |= (d & 0x08080808) << 1; r |= (d & 0x04040404) << 3; r |= (d & 0x02020202) << 5; r |= (d & 0x01010101) << 7; return r; } #define inline #include "nubusfpga_csr_leds.h" #undef inline int main(void) { uint32_t x1 = 0xDEADBEEF, x2 = 0xDEADBEEF; sc.slotid = 0x9; printf("Test Application for NuBusFPGA\n\n"); printf("Machine settings: char %d short %d int %d long %d long long %d\n", sizeof(char), sizeof(short int), sizeof(int), sizeof(long int), sizeof(long long int)); printf("Global access struct is located in 0x%08X\n", &sc); printf("Slot id hardwired to 0x%x, check the ID on the card and the ID allocation for the host.\n", sc.slotid); printf("MMU Mode is: %s\n", (int)GetMMUMode() ? "32-bits" : "24-bits"); printf("Checking HW access by reading Ethernet ROM...\n"); x1 = *(uint32_t*)0x50F08000; x2 = *(uint32_t*)0x50F08004; printf("I got 0x%08x 0x%08x (rev: 0x%08x 0x%08x)\n", x1, x2, rev(x1), rev(x2)); printf("Checking if we see our PROM...\n"); x1 = (0xF0000000 | (sc.slot_id<<24) | 0x00FFFFFC); x2 = *(uint32_t*)x1; printf("I got 0x%08x for 0x%08x (rev: 0x%08x for 0x%08x)\n", x2, x1, rev(x2), rev(x1)); return 0; }

View File

@ -8,15 +8,15 @@ PROCESS_ROM=${NS816DECLROMDIR}/process_rom
APPLEINCS=${NS816DECLROMDIR}/atrap.inc ${NS816DECLROMDIR}/declrom.inc ${NS816DECLROMDIR}/globals.inc
HRES=1152
VRES=870
HRES=1920
VRES=1080
CSRC=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c
CSRC=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c NuBusFPGAPrimaryInit_Primary.c
CSRC_ASM=${CSRC:.c=.s}
all: vid_decl_rom.bin vid_decl_rom.srec
vid_decl_rom.o: vid_decl_rom.s NuBusFPGAPrimaryInit.s NuBusFPGADrvr.s ${APPLEINCS} ${CSRC_ASM} DepVideo.inc
vid_decl_rom.o: vid_decl_rom.s NuBusFPGAPrimaryInit.s NuBusFPGAPrimaryInit_Primary.s NuBusFPGASecondaryInit.s NuBusFPGADrvr.s ${APPLEINCS} ${CSRC_ASM} DepVideo.inc
rm -f res.inc
echo -e "HRES=${HRES}\nVRES=${VRES}\n" | tee res.inc
${AS} -march=68020 -mcpu=68020 -I${NS816DECLROMDIR} $< -o $@ -a > vid_decl_rom.l
@ -36,6 +36,11 @@ NuBusFPGADrvr_Status.s: NuBusFPGADrvr_Status.c NuBusFPGADrvr.h
sed -i -e 's/^\([^a-zA-Z0-9_]*\.globl.*\)/# --- \1/' $@
sed -i -e 's/\.\(L[0-9][0-9]*\)/.Status_\1/g' $@
NuBusFPGAPrimaryInit_Primary.s: NuBusFPGAPrimaryInit_Primary.c NuBusFPGADrvr.h
${CC} -march=68020 -mcpu=68020 -O2 $< -S -o $@ -DHRES=${HRES} -DVRES=${VRES}
sed -i -e 's/^\([^a-zA-Z0-9_]*\.globl.*\)/# --- \1/' $@
sed -i -e 's/\.\(L[0-9][0-9]*\)/.PIPrimary_\1/g' $@
vid_decl_rom.srec: vid_decl_rom.o
${OBJCOPY} $^ $@ --input-target=elf32-m68k --output-target=srec

View File

@ -19,17 +19,30 @@
#define GOBOFB_BASE 0x00900000
//#define GOBOFB_REG_BASE 0x00900000
//#define GOBOFB_MEM_BASE 0x00000000 /* remapped to 0x8f800000 by HW */
#define GOBOFB_MODE 0x0
#define GOBOFB_VBL_MASK 0x4
//#define GOBOFB_VBL_DIS 0x8
#define GOBOFB_VIDEOCTRL 0x8
#define GOBOFB_INTR_CLEAR 0xc
#define GOBOFB_RESET 0x10
#define GOBOFB_LUT_ADDR 0x14
#define GOBOFB_LUT 0x18
#define GOBOFB_DEBUG 0x20
#define GOBOFB_DEBUG 0x1c
//#define GOBOFB_CURSOR_LUT 0x20
//#define GOBOFB_CURSOR_XY 0x24
//#define GOBOFB_MASK_BASE 0x80
//#define GOBOFB_BITS_BASE 0x100
#define GOBOFB_INTR_VBL 0x1
#define GOBOFB_MODE_1BIT 0x0
#define GOBOFB_MODE_2BIT 0x1
#define GOBOFB_MODE_4BIT 0x2
#define GOBOFB_MODE_8BIT 0x3
//#define GOBOFB_MODE_24BIT 0x10
struct MyGammaTbl {
short gVersion; /*gamma version number*/
short gType; /*gamma data type*/
@ -71,4 +84,9 @@ OSErr cNuBusFPGAStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce);
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce);
OSErr cNuBusFPGAClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce);
/* primary init */
UInt32 Primary(SEBlock* block);
#define Check32QDTrap 0xAB03
#endif

View File

@ -104,8 +104,8 @@ OSErr cNuBusFPGACtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
short ret = -1;
char busMode = 1;
write_reg(dce, GOBOFB_DEBUG, 0xBEEF0001);
write_reg(dce, GOBOFB_DEBUG, pb->csCode);
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0001); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
#if 1
switch (pb->csCode)
{

View File

@ -3,8 +3,8 @@
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000);
write_reg(dce, GOBOFB_DEBUG, (unsigned long)dce->dCtlDevBase);
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)dce->dCtlDevBase); */
if (dce->dCtlStorage == nil)
{
@ -47,6 +47,10 @@ OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
linearGamma(*dStoreHdl);
write_reg(dce, GOBOFB_MODE, GOBOFB_MODE_8BIT);
write_reg(dce, GOBOFB_VIDEOCTRL, 1);
ret = changeIRQ(dce, 1, openErr);
}
@ -62,7 +66,8 @@ OSErr cNuBusFPGAClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
if (dce->dCtlStorage != nil)
{
ret = changeIRQ(dce, 0, openErr);
DisposePtr((*(NuBusFPGADriverGlobalsHdl)dce->dCtlStorage)->siqel);
write_reg(dce, GOBOFB_VIDEOCTRL, 0);
DisposePtr((Ptr)(*(NuBusFPGADriverGlobalsHdl)dce->dCtlStorage)->siqel);
DisposeHandle(dce->dCtlStorage);
dce->dCtlStorage = nil;
}

View File

@ -38,8 +38,8 @@ OSErr cNuBusFPGAStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage;
NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl;
short ret = -1;
write_reg(dce, GOBOFB_DEBUG, 0xBEEF0002);
write_reg(dce, GOBOFB_DEBUG, pb->csCode);
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0002); */
/* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */
#if 1
switch (pb->csCode)
{

View File

@ -2,102 +2,12 @@
.byte sExec2 /* Code revision (Primary init) */
.byte sCPU68020 /* CPU type is 68020 */
.short 0 /* Reserved */
.long Begin-. /* Offset to code. */
.long BeginPrimary-. /* Offset to code. */
Begin:
movew #1,%A0@(seStatus) /* VendorStatus <- 1 {Code was executed} */
movel %A0,%A3 /* save param block {A0 is destroyed} */
/* Turn the slot number into a base address. */
moveq #0,%D0 /* D0 <- 00000000 */
MOVE.B %A0@(seSlot),%D0 /* D0 <- 0000000s */
LSL.W #4,%D0 /* D0 <- 000000s0 */
/* OR.B %A0@(seSlot),%D0 /* D0 <- 000000ss */
OR.W #0xF00,%D0 /* D0 <- 00000Fss */
SWAP %D0 /* D0 <- 0Fss0000 */
LSL.L #4,%D0 /* D0 <- Fss00000 */
movel %D0,%A2 /* A2 <- Base address to the slot. */
/* Reset the hardware. */
/* DO YOUR RESET STUFF HERE */
/* Set mode to one bit per pixel. ; */
/* DO YOUR MODE SETTING HERE */
/* Disable interrupts. ; */
movel %A2,%A0 /* get slot base */
ADD.L #0x00900004,%A0 /* Adjust the base */ /* FIXME */
CLR.B (%A0) /* Disable interrupt from card */
/* set the color table to black and white */
/* SET THE TABLE HERE */
/* The Apple Video card configuration ROM has two video sResources conforming to the */
/* two possible different memory configurations. Now we want to figure out which */
/* of the configurations we have, and delete the incorrect video sResource from */
/* the slot resource table. */
/* */
/* size the RAM on the video card. To do this, we look for a nice longword in the second */
/* half of the frame buffer array that doesn't show up on the screen. I've selected the */
/* last longword of the first scanline that is a multiple of 8 in the second RAM bank (line 264). */
/* This alignment guarantees that this memory is off the right edge in all pixel depths */
/* when the frame buffer base addr is on a normal page boundary. */
/* */
/* */
/* */
TestPos = (265*1024)-4 /* */
TestPat = 0x4d434132 /* test bit pattern */
SUBA #smParamBlockSize,%SP /* make an SDM parameter block on stack */
movel %SP,%A0 /* get pointer to parm block now */
MOVE.B seSlot(%A3),spSlot(%A0) /* put slot in pBlock */
CLR.B spExtDev(%A0) /* external device = 0 */
/* movel #TestPos,%D1 /* get offset in %D1 */
/* movel #TestPat,(%A2,%D1.L) /* write to alleged RAM */
/* movel #-1,-(%SP) /* write out some garbage to clear data lines */
/* ADDQ #4,%SP /* and pitch it */
/* movel (%A2,%D1.L),%D0 /* read pattern back */
/* CMP.L #TestPat,%D0 /* did it stick? */
/* BEQ.S ram /* if equal, we have ram */
/* MOVE.B #sRsrc_Video8,spID(%A0) /* if not, remove 8-bit table */
/* BRA.S noram
/*ram:
/* MOVE.B #sRsrc_Video4,spID(%A0) /* remove 4-bit table if we have ram */
/*noram:
/* _sDeleteSRTRec */ /* remove the invalid entry */
/* movel #SDeleteSRTRec,%d0
/* _SlotManager
/* BNE.S done /* */
MOVE #2,seStatus(%A3) /* mark the change */
done: ADDA #smParamBlockSize,%SP /* clean up */
/* Clear video RAM to a nice gray */
movel #0xAAAAAAAA,%D0 /* graypat1 := $AAAAAAAA */
movel %D0,%D1
NOT.L %D1
MOVE.W #defScrnRow,%D4 /* sRow := defScrnRow {Bytes per pixel line} */
MOVE.W #defmBounds_Bs-1,%D3 /* sHei := defScrnHeight {Screen Height in pixels} */
movel %A2,%A1 /* init row pointer /* REPEAT */
NxtRow: movel %A1,%A0 /* get next row */
MOVE.W #defScrnRow/4-1,%D2 /* rowlongs := defScrnRow/4 - 1 {How many Longs there are} */
NxtLong: movel %D0,(%A0)+ /* (%A0) := graypat(1/2) */
DBF %D2,NxtLong /* UNTIL rowlongs < 0 */
EXG %D0,%D1 /* graypat1 <-> graypat2 */
ADD.W %D4,%A1 /* %A1 := %A1 + sRow */
DBF %D3,NxtRow /* UNTIL sHei < 0 */
/* Exit */
Exit: RTS /* Return */
/* <PUT YOUR VALUES FOR INIT TABLE, OTHER TABLES, ETC. HERE IF NEEDED> */
/* END PrimaryInit */
BeginPrimary:
MOVE.L %A0, -(%A7)
JSR Primary
MOVE.L (%A7)+, %a0
rts
.include "NuBusFPGAPrimaryInit_Primary.s"
.text

View File

@ -0,0 +1,100 @@
#include "NuBusFPGADrvr.h"
#include <Traps.h>
#define PRIM_WRITEREG(reg, val) \
*((volatile UInt32*)(a32+GOBOFB_BASE+reg)) = (UInt32)val;
UInt32 Primary(SEBlock* seblock) {
UInt32 a32 = 0xF0000000 | ((UInt32)seblock->seSlot << 24);
UInt32 a32_l0, a32_l1;
UInt32 a32_4p0, a32_4p1;
SpBlock spblock;
UInt8 pram[8];
OSErr err;
UInt16 i,j;
char busMode;
UniversalProcPtr qd32ptr, unimpptr;
busMode = 1;
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
PRIM_WRITEREG(GOBOFB_VBL_MASK, 0);// disable interrupts
/* PRIM_WRITEREG(GOBOFB_DEBUG, busMode);// trace */
/* grey the screen */
a32_l0 = a32;
a32_l1 = a32 + HRES;
for (j = 0 ; j < VRES ; j+= 2) {
a32_4p0 = a32_l0;
a32_4p1 = a32_l1;
for (i = 0 ; i < HRES ; i += 4) {
*((UInt32*)a32_4p0) = 0xAAAAAAAA;
*((UInt32*)a32_4p1) = 0x55555555;
a32_4p0 += 4;
a32_4p1 += 4;
}
a32_l0 += 2*HRES;
a32_l1 += 2*HRES;
}
SwapMMUMode ( &busMode ); // restore
/* call SVersion to figure out if we have a recent SlotManager */
//spblock.spSlot = seblock->seSlot;
//spblock.spExtDev = 0;
err = SVersion(&spblock);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* DCDMF3 p178: if error, old slot manager*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* DCDMF3 p178: new slot manager */
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, spblock.spResult);*/
}
SwapMMUMode ( &busMode ); // restore
/* check for 32-bits QuickDraw */
qd32ptr = GetTrapAddress(Check32QDTrap);
unimpptr = GetTrapAddress(_Unimplemented);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (qd32ptr == unimpptr) {
/* no 32QD */
PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);
PRIM_WRITEREG(GOBOFB_DEBUG, unimpptr);
} else {
/* yes 32QD */
PRIM_WRITEREG(GOBOFB_DEBUG, 0x00C0FFEE);
}
SwapMMUMode ( &busMode ); // restore
/* check the content of the PRAM */
spblock.spSlot = seblock->seSlot;
spblock.spResult = (UInt32)pram;
err = SReadPRAMRec(&spblock);
busMode = 1;
SwapMMUMode ( &busMode ); // to32
if (err) {
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xFFFFFFFF);*/
/* PRIM_WRITEREG(GOBOFB_DEBUG, err);*/
} else {
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0xC0FFEE00);*/
/* for (i = 0 ; i < 8 ; i++) */
/* PRIM_WRITEREG(GOBOFB_DEBUG, pram[i]);*/
}
SwapMMUMode ( &busMode ); // restore
seblock->seStatus = 1;
return 0;
}

View File

@ -0,0 +1,38 @@
.byte sExec2 /* Code revision (Primary init) */
.byte sCPU68020 /* CPU type is 68020 */
.short 0 /* Reserved */
.long BeginSecondary-. /* Offset to code. */
BeginSecondary:
movew #1,%A0@(seStatus) /* VendorStatus <- 1 {Code was executed} */
movel %A0,%A3 /* save param block */
/* Set up a slot parameter block in %A0 */
SUBA #smParamBlockSize,%SP /* make an SDM parameter block on stack */
movel %SP,%A0 /* get pointer to parm block now */
MOVE.B seSlot(%A3),spSlot(%A0) /* put slot in pBlock */
CLR.B spExtDev(%A0) /* external device = 0 */
moveq #8,%D0 /* _sVersion ; find the Slot Manager version */
.word 0xA06E /* _sVersion ; find the Slot Manager version */
MOVEL spResult(%A0),%D1 /* recover result */
ADDA #smParamBlockSize,%SP /* drop the slot Parameter block */
moveq #0,%D0 /* D0 <- 00000000 */
MOVEB %A3@(seSlot),%D0 /* D0 <- 0000000s */
LSLW #4,%D0 /* D0 <- 000000s0 */
/* OR.B %A3@(seSlot),%D0 /* D0 <- 000000ss */
OR.W #0xF00,%D0 /* D0 <- 00000Fs0 */
SWAP %D0 /* D0 <- 0Fs00000 */
LSLL #4,%D0 /* D0 <- Fs000000 */
MOVEAL %D0,%A1
/* param block in %A3, our HW (32-bits mode) in %A1 */
addl #0x00900000, %A1
movel #0x0f0f0f0f,%A1@(0x20) /* marker to qemu */
movel %D1,%A1@(0x20) /*_sVersion spResult to Qemu */
ExitSecondary:
RTS /* Return */

Binary file not shown.

View File

@ -20,7 +20,7 @@ _sRsrc_Board:
DatLstEntry boardId,NuBusFPGAID /* board ID # (assigned by DTS) */
OSLstEntry primaryInit,_sPInitRec /* offset to PrimaryInit exec blk */
OSLstEntry vendorInfo,_VendorInfo /* offset to vendor info record */
/* OSLstEntry SecondaryInit,_sSInitRec */ /* offset to SecondaryInit block */
OSLstEntry secondaryInit,_sSInitRec /* offset to SecondaryInit block */
OSLstEntry sRsrcVidNames, _VModeName
.long EndOfList
@ -40,14 +40,16 @@ _BoardName:
_sPInitRec:
.long _EndsPInitRec-_sPInitRec /* physical block size */
.include "NuBusFPGAPrimaryInit.s" /* the header/code */
.text
ALIGN 2
_EndsPInitRec:
_EndsPInitRec:
/* _sSInitRec */
/* .long _EndsSInitRec-_sSInitRec ; physical block size */
/* INCLUDE "NuBusFPGASecondaryInit.a" ; the header/code */
/* ALIGN 2 */
/* _EndsSInitRec */
_sSInitRec:
.long _EndsSInitRec-_sSInitRec /* physical block size */
.include "NuBusFPGASecondaryInit.s" /* the header/code */
.text
ALIGN 2
_EndsSInitRec:
ALIGN 2
_VendorInfo:
@ -183,7 +185,8 @@ _EndEBVParms:
DeclROMDir:
OSLstEntry 0, _sRsrcDir
.long DeclRomEnd-_sRsrcDir /* Length should be 0x824 */
DeclROMCRC: .long 0x0 /* TODO: calculate this */
DeclROMCRC:
.long 0x0 /* TODO: calculate this */
.byte 1 /* Revision Level */
.byte appleFormat /* Apple Format */
.long testPattern /* magic TestPattern */

View File

@ -0,0 +1 @@
NuBusFPGAID EQU $BEEF defMinorBase EQU 0 ; beginning defMinorLength EQU $C0000 ; 768 KiB Pages8s EQU 1 ; no idea defmBounds_Ts EQU 0 defmBounds_Ls EQU 0 defmBounds_Bs EQU 480 defmBounds_Rs EQU 640 DrHwNuBusFPGA EQU $BEEF ; placeholder defmBaseOffset EQU 0 ; beginning, placeholder devVersion EQU 0 ; placeholder defmHRes EQU $480000 ;Horizontal Pixels/inch defmVRes EQU $480000 ;Vertical pixels/inch defmDevType EQU 0 ;0 = CLUTType defmPlaneBytes EQU 0 ;Offset from one plane to the next. SGammaResID EQU 0 RB8s EQU 640 ChunkyIndexed EQU 0 defVersion EQU 0 ;Version = 0 ROMSize EQU $1000 ;4K byte ROM

View File

View File

@ -0,0 +1 @@
DC.B sExec2 ; code revision DC.B sCPU68020 ; CPU type is 68020 DC.W 0 ; reserved DC.L Begin1stInit-* ; offset to code WITH seBlock,spBlock Begin1stInit MOVE.W #1,seStatus(A0) ; assume a good return MOVE.L #$F0000000,D1 ; Dl <- F0000000 MOVE.B seSlot(A0),D0 ; get slot number BFINS D0,D1{4:4} ; Dl <- Fs000000 MOVE.L D1,A1 ; copy to address reg ;;; INITIALIZE SOME STUFF HERE SUBA #spBlockSize,SP ; make an spB10ck MOVE.L SP,A0 ; get pointer to parms MOVE.B D0,spSlot(A0) ; identify the slot CLR.B SpExtDev(A0) ; external device = 0 RTS ENDWITH

View File

@ -2,7 +2,7 @@
source /opt/Xilinx/Vivado/2020.1/settings64.sh
export LD_LIBRARY_PATH=/opt/Xilinx/Vivado/2020.1/lib/lnx64.o/SuSE
python3 nubus_to_fpga_soc.py --build --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.0 --goblin --goblin-res 1280x1024@60Hz --sys-clk-freq 100e6
python3 nubus_to_fpga_soc.py --build --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.0 --sys-clk-freq 100e6 --goblin --goblin-res 1920x1080@60Hz --hdmi
) 2>&1 | tee build_V1_0.log
# --goblin --goblin-res 1280x1024@60Hz
# --hdmi

View File

@ -1,3 +1,5 @@
from math import log2
from migen import *
from litedram.frontend.dma import LiteDRAMDMAReader;
@ -9,15 +11,21 @@ class LiteDRAMFBDMAReader(LiteDRAMDMAReader):
def __init__(self, port, fifo_depth=16, default_base=0, default_length=0):
LiteDRAMDMAReader.__init__(self = self, port = port, fifo_depth = fifo_depth, fifo_buffered = True, with_csr = False)
enable = self.enable = Signal(reset = 0)
base = self.base = Signal(self.port.address_width, reset = default_base)
offset = self.offset = Signal(self.port.address_width, reset = 0)
length = self.length = Signal(self.port.address_width, reset = default_length)
self.enable = Signal(reset = 0)
self.base = Signal(32, reset = default_base)
self.length = Signal(32, reset = default_length)
shift = log2_int(self.port.data_width//8)
base = Signal(self.port.address_width)
length = Signal(self.port.address_width)
offset = Signal(self.port.address_width, reset = 0)
self.comb += base.eq(self.base[shift:])
self.comb += length.eq(self.length[shift:])
fsm = FSM(reset_state="IDLE")
fsm = ResetInserter()(fsm)
self.submodules.fsm = fsm
self.comb += fsm.reset.eq(~enable)
self.comb += fsm.reset.eq(~self.enable)
fsm.act("IDLE",
NextValue(offset, 0),
NextState("RUN"),

View File

@ -12,12 +12,26 @@ from litex.build.io import SDROutput, DDROutput
from litex.soc.cores.video import *
video_timing_hwcursor_layout = [
# Synchronization signals.
("hsync", 1),
("vsync", 1),
("de", 1),
("hwcursor", 1),
("hwcursorx", 5),
("hwcursory", 5),
# Extended/Optional synchronization signals.
("hres", hbits),
("vres", vbits),
("hcount", hbits),
("vcount", vbits),
]
# FB Video Timing Generator ---------------------------------------------------------------------------
# Same as the normal one except (a) _enable isn't a CSR
class FBVideoTimingGenerator(Module, AutoCSR):
def __init__(self, default_video_timings="800x600@60Hz"):
def __init__(self, default_video_timings="800x600@60Hz", hwcursor=False):
# Check / Get Video Timings (can be str or dict)
if isinstance(default_video_timings, str):
try:
@ -31,7 +45,7 @@ class FBVideoTimingGenerator(Module, AutoCSR):
self.video_timings = vt = default_video_timings
# MMAP Control/Status Registers.
self._enable = Signal(reset = 0)
self.enable = Signal() # external control signal
self._hres = CSRStorage(hbits, vt["h_active"])
self._hsync_start = CSRStorage(hbits, vt["h_active"] + vt["h_sync_offset"])
@ -44,14 +58,19 @@ class FBVideoTimingGenerator(Module, AutoCSR):
self._vscan = CSRStorage(vbits, vt["v_active"] + vt["v_blanking"])
# Video Timing Source
self.source = source = stream.Endpoint(video_timing_layout)
if (hwcursor):
self.source = source = stream.Endpoint(video_timing_hwcursor_layout)
_hwcursor_x = Signal(12) # 12 out of 16 is enough
_hwcursor_y = Signal(12) # 12 out of 16 is enough
self.hwcursor_x = Signal(12)
self.hwcursor_y = Signal(12)
self.specials += MultiReg(self.hwcursor_x, _hwcursor_x)
self.specials += MultiReg(self.hwcursor_y, _hwcursor_y)
else:
self.source = source = stream.Endpoint(video_timing_layout)
# # #
# Resynchronize Enable to Video clock domain.
self.enable = enable = Signal()
self.specials += MultiReg(self._enable, enable)
# Resynchronize Horizontal Timings to Video clock domain.
self.hres = hres = Signal(hbits)
self.hsync_start = hsync_start = Signal(hbits)
@ -78,7 +97,7 @@ class FBVideoTimingGenerator(Module, AutoCSR):
fsm = FSM(reset_state="IDLE")
fsm = ResetInserter()(fsm)
self.submodules.fsm = fsm
self.comb += fsm.reset.eq(~enable)
self.comb += fsm.reset.eq(~self.enable)
fsm.act("IDLE",
NextValue(hactive, 0),
NextValue(vactive, 0),
@ -120,3 +139,12 @@ class FBVideoTimingGenerator(Module, AutoCSR):
)
)
)
if (hwcursor):
self.sync += source.hwcursor.eq((source.hcount >= _hwcursor_x) &
(source.hcount < (_hwcursor_x+32)) &
(source.vcount >= _hwcursor_y) &
(source.vcount < (_hwcursor_y+32)))
self.sync += source.hwcursorx.eq(_hwcursor_x - source.hcount)
self.sync += source.hwcursory.eq(_hwcursor_y - source.vcount)

View File

@ -8,6 +8,8 @@ from litex.soc.cores.code_tmds import TMDSEncoder
from litex.build.io import SDROutput, DDROutput
from migen.genlib.cdc import MultiReg
from litex.soc.cores.video import *
from fb_video import *
@ -27,29 +29,60 @@ omap_layout = [
def goblin_rounded_size(hres, vres):
mib = int(ceil(((hres * vres) + 0) / 1048576))
if (mib == 3):
mib = 4
if (mib > 4 and mib < 8):
if (mib > 0 and mib < 8): # FIXME : NuBus
mib = 8
if (mib > 8 or mib < 1):
#if (mib > 0 and mib < 16): # FIXME : SBus
# mib = 16
if (mib > 16 or mib < 1):
print(f"{mib} mebibytes framebuffer not supported")
assert(False)
return int(1048576 * mib)
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):
class VideoFrameBufferMultiDepth(Module, AutoCSR):
"""Video FrameBufferMultiDepth"""
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, truecolor=True):
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}")
npixelsdiv8 = hres * vres // 8
vga_sync = getattr(self.sync, clock_domain)
npixels = hres * vres
# if 0, 32-bits mode
# should only be changed while in reset
self.use_indexed = Signal(1, reset = 0x1)
# mode, as x in 2^x (so 1, 2, 4, 8 bits)
# should only be changed while in reset
self.mode = Signal(2, reset = 3)
self.indexed_mode = Signal(2, reset = 0x3)
self.vblping = Signal(reset = 0)
if (hwcursor):
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_hwcursor_layout)
upd_omap_fifo_dout = Record(omap_layout)
self.comb += upd_omap_fifo_dout.raw_bits().eq(upd_omap_fifo.dout)
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.color][upd_omap_fifo_dout.address].eq(upd_omap_fifo_dout.data),
).Else(
upd_omap_fifo.re.eq(0),
)
]
else:
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
self.source = source = stream.Endpoint(video_data_layout)
self.underflow = Signal()
@ -58,7 +91,22 @@ class VideoFrameBuffer256c(Module, AutoCSR):
source_buf_de = Signal()
source_buf_hsync = Signal()
source_buf_vsync = Signal()
data_buf = Signal(8)
data_buf_index = Signal(8)
data_buf_direct = Array(Signal(8) for x in range(3))
if (hwcursor):
hwcursor_buf = Signal()
hwcursorx_buf = Signal(5)
hwcursory_buf = Signal(5)
source_buf_b_valid = Signal()
source_buf_b_de = Signal()
source_buf_b_hsync = Signal()
source_buf_b_vsync = Signal()
data_buf_b_index = Signal(8)
if (truecolor):
data_buf_b_direct = Array(Signal(8) for x in range(3))
if (hwcursor):
hwcursor_color_idx = Signal(2)
#source_out_ready = Signal()
source_out_valid = Signal()
@ -70,19 +118,18 @@ class VideoFrameBuffer256c(Module, AutoCSR):
source_out_b = Signal(8)
# # #
# First the Color Look-up Table (for all but 1 bit)
# First the Color Look-up Table (for all but 1 bit & 32 bits)
# updated from the FIFO
# 8-and-less-than-8-bits mode used the 2^x first entries
clut = Array(Array(Signal(8, reset = (255-i)) for i in range(0, 256)) for j in range(0, 3))
### clut = Array(Array(Signal(8, reset = (255-i)) for i in range(0, 256)) for j in range(0, 3))
clut = Array(Array(Signal(8, reset = (255-i)) for j in range(0, 3)) for i in range(0, 256))
upd_clut_fifo_dout = Record(cmap_layout)
self.comb += upd_clut_fifo_dout.raw_bits().eq(upd_clut_fifo.dout)
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.color][upd_clut_fifo_dout.address].eq(upd_clut_fifo_dout.data),
clut[upd_clut_fifo_dout.address][upd_clut_fifo_dout.color].eq(upd_clut_fifo_dout.data),
).Else(
upd_clut_fifo.re.eq(0),
)
@ -94,10 +141,13 @@ class VideoFrameBuffer256c(Module, AutoCSR):
from fb_dma import LiteDRAMFBDMAReader
# length should be changed to match mode
self.submodules.fb_dma = LiteDRAMFBDMAReader(dram_port,
fifo_depth=fifo_depth//(dram_port.data_width//8),
fifo_depth = fifo_depth//(dram_port.data_width//8),
default_base = base,
default_length = npixelsdiv8 * 8)
default_length = npixels)
##self.submodules.fb_dma = ResetInserter()(self._fb_dma)
##self.fb_dma_reset = Signal(reset = 0)
##self.comb += self.fb_dma.reset.eq(self.fb_dma_reset)
# If DRAM Data Width > 8-bit and Video clock is faster than sys_clk:
# actually always use that case to simplify the design
# if (dram_port.data_width > 8) and clock_faster_than_sys:
@ -105,69 +155,148 @@ class VideoFrameBuffer256c(Module, AutoCSR):
self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
self.comb += self.fb_dma.source.connect(self.cdc.sink)
# ... and then Data-Width Conversion.
# we have 4 possible conversion and mux/connect the appropriate one
# we have 5 possible conversion and mux/connect the appropriate one
if (truecolor):
self.submodules.conv32 = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 32))
handle_truecolor_sink = [ self.cdc.source.connect(self.conv32.sink) ]
handle_truecolor_source = [ source_buf_valid.eq(self.conv32.source.valid),
self.conv32.source.connect(source, keep={"ready"}), ]
handle_truecolor_databuf = [ data_buf_direct[0].eq(self.conv32.source.data[24:32]),
data_buf_direct[1].eq(self.conv32.source.data[16:24]),
data_buf_direct[2].eq(self.conv32.source.data[8:16]), ]
handle_truecolor_databuf_b = [ data_buf_b_direct[0].eq(data_buf_direct[0]),
data_buf_b_direct[1].eq(data_buf_direct[1]),
data_buf_b_direct[2].eq(data_buf_direct[2]), ]
handle_truecolor_source = [ source_out_r.eq(data_buf_b_direct[2]),
source_out_g.eq(data_buf_b_direct[1]),
source_out_b.eq(data_buf_b_direct[0]), ]
else:
handle_truecolor_sink = [ ]
handle_truecolor_source = [ ]
handle_truecolor_databuf = [ ]
handle_truecolor_databuf_b = [ ]
handle_truecolor_source = [ ]
self.submodules.conv8 = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 8))
self.submodules.conv4 = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 4))
self.submodules.conv2 = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 2))
self.submodules.conv1 = ClockDomainsRenamer({"sys": clock_domain})(stream.Converter(dram_port.data_width, 1))
self.comb += Case(self.mode, {
0x3: self.cdc.source.connect(self.conv8.sink),
0x2: self.cdc.source.connect(self.conv4.sink),
0x1: self.cdc.source.connect(self.conv2.sink),
0x0: self.cdc.source.connect(self.conv1.sink),
})
self.comb += [
If(self.use_indexed,
Case(self.indexed_mode, {
0x3: self.cdc.source.connect(self.conv8.sink),
0x2: self.cdc.source.connect(self.conv4.sink),
0x1: self.cdc.source.connect(self.conv2.sink),
0x0: self.cdc.source.connect(self.conv1.sink),
})
).Else(
*handle_truecolor_sink
)
]
# Video Generation.
# buffered by 1 cycle to accomodate the look-ups
self.comb += [
vtg_sink.ready.eq(1),
If(vtg_sink.valid & vtg_sink.de,
Case(self.mode, {
0x3: [ source_buf_valid.eq(self.conv8.source.valid),
self.conv8.source.connect(source, keep={"ready"}),
data_buf.eq(self.conv8.source.data),
],
0x2: [ source_buf_valid.eq(self.conv4.source.valid),
self.conv4.source.connect(source, keep={"ready"}),
data_buf.eq(Cat(self.conv4.source.data, Signal(4, reset = 0))),
],
0x1: [ source_buf_valid.eq(self.conv2.source.valid),
self.conv2.source.connect(source, keep={"ready"}),
data_buf.eq(Cat(self.conv2.source.data, Signal(6, reset = 0))),
],
0x0: [ source_buf_valid.eq(self.conv1.source.valid),
self.conv1.source.connect(source, keep={"ready"}),
data_buf.eq(Replicate(self.conv2.source.data, 8)),
],
}),
If(self.use_indexed,
Case(self.indexed_mode, {
0x3: [ source_buf_valid.eq(self.conv8.source.valid),
self.conv8.source.connect(source, keep={"ready"}),
],
0x2: [ source_buf_valid.eq(self.conv4.source.valid),
self.conv4.source.connect(source, keep={"ready"}),
],
0x1: [ source_buf_valid.eq(self.conv2.source.valid),
self.conv2.source.connect(source, keep={"ready"}),
],
0x0: [ source_buf_valid.eq(self.conv1.source.valid),
self.conv1.source.connect(source, keep={"ready"}),
],
}),
).Else(
*handle_truecolor_source,
),
vtg_sink.ready.eq(source_buf_valid & source.ready),
),
source_buf_de.eq(vtg_sink.de),
source_buf_hsync.eq(vtg_sink.hsync),
source_buf_vsync.eq(vtg_sink.vsync),
Case(self.indexed_mode, {
0x3: [ data_buf_index.eq(self.conv8.source.data),
],
0x2: [ data_buf_index.eq(Cat(self.conv4.source.data, Signal(4, reset = 0))),
],
0x1: [ data_buf_index.eq(Cat(self.conv2.source.data, Signal(6, reset = 0))),
],
0x0: [ data_buf_index.eq(Replicate(self.conv1.source.data, 8)),
],
}),
*handle_truecolor_databuf,
]
if (hwcursor):
self.comb += [
hwcursor_buf.eq(vtg_sink.hwcursor),
hwcursorx_buf.eq(vtg_sink.hwcursorx),
hwcursory_buf.eq(vtg_sink.hwcursory),
]
vga_sync += [
source_out_de.eq(source_buf_de),
source_out_hsync.eq(source_buf_hsync),
source_out_vsync.eq(source_buf_vsync),
source_out_valid.eq(source_buf_valid),
#source_buf_ready.eq(source_out_ready), # ready flow the other way
If(source_buf_de,
If(self.mode == 0x0,
source_out_r.eq(data_buf),
source_out_g.eq(data_buf),
source_out_b.eq(data_buf)
).Else(
source_out_r.eq(clut[0][data_buf]),
source_out_g.eq(clut[1][data_buf]),
source_out_b.eq(clut[2][data_buf])
)
).Else(source_out_r.eq(0),
source_out_g.eq(0),
source_out_b.eq(0)
) ]
source_buf_b_de.eq(source_buf_de),
source_buf_b_hsync.eq(source_buf_hsync),
source_buf_b_vsync.eq(source_buf_vsync),
source_buf_b_valid.eq(source_buf_valid),
data_buf_b_index.eq(data_buf_index),
*handle_truecolor_databuf_b,
]
if (hwcursor):
vga_sync += [
If(hwcursor_buf,
hwcursor_color_idx.eq(Cat(overlay[0][hwcursory_buf][hwcursorx_buf], overlay[1][hwcursory_buf][hwcursorx_buf])),
).Else(
hwcursor_color_idx.eq(0),
)
]
vga_sync += [
source_out_de.eq(source_buf_b_de),
source_out_hsync.eq(source_buf_b_hsync),
source_out_vsync.eq(source_buf_b_vsync),
source_out_valid.eq(source_buf_b_valid),
#source_buf_ready.eq(source_out_ready), # ready flow the other way
]
if (hwcursor):
vga_sync += [
If(hwcursor_color_idx != 0,
source_out_r.eq(omap[0][hwcursor_color_idx]),
source_out_g.eq(omap[1][hwcursor_color_idx]),
source_out_b.eq(omap[2][hwcursor_color_idx]),
).Elif(source_buf_b_de,
If(self.use_indexed,
source_out_r.eq(clut[data_buf_b_index][2]),
source_out_g.eq(clut[data_buf_b_index][1]),
source_out_b.eq(clut[data_buf_b_index][0])
).Else(
*handle_truecolor_source,
),
).Else(source_out_r.eq(0),
source_out_g.eq(0),
source_out_b.eq(0)
)
]
else:
vga_sync += [
If(source_buf_b_de,
If(self.use_indexed,
source_out_r.eq(clut[data_buf_b_index][2]),
source_out_g.eq(clut[data_buf_b_index][1]),
source_out_b.eq(clut[data_buf_b_index][0])
).Else(
*handle_truecolor_source,
),
).Else(source_out_r.eq(0),
source_out_g.eq(0),
source_out_b.eq(0)
)
]
self.comb += [
source.de.eq(source_out_de),
source.hsync.eq(source_out_hsync),
@ -180,31 +309,8 @@ class VideoFrameBuffer256c(Module, AutoCSR):
]
# Underflow.
self.comb += self.underflow.eq(~source.valid)
# track mode changes
# in sys cd, not vga cd, as that's where the DMA runs
# whenever the mode change, we fully reset the DMA
# (we also need to reset the VTG at the same time)
old_mode = Signal(2, reset = 3)
force_reset = Signal(reset = 0)
finish_reset = Signal(reset = 0)
old_enable = Signal()
self.sync += [
old_mode.eq(self.mode),
If(old_mode != self.mode,
force_reset.eq(1),),
If(force_reset == 1,
old_enable.eq(self.fb_dma.enable),
self.fb_dma.enable.eq(0),
self.fb_dma.length.eq(npixelsdiv8 << self.mode),
force_reset.eq(0),
finish_reset.eq(1),),
If(finish_reset == 1,
self.fb_dma.enable.eq(old_enable),
finish_reset.eq(0)),
]
self.comb += self.underflow.eq(~source.valid & source.de)
# VBL handling
# create a pulse in self.vlbping in sys at the end of the frame
from migen.genlib.cdc import PulseSynchronizer
@ -223,19 +329,28 @@ class VideoFrameBuffer256c(Module, AutoCSR):
self.comb += self.vblping.eq(self.vbl_ps.o)
class goblin(Module, AutoCSR):
def __init__(self, soc, phy=None, timings = None, clock_domain="sys"):
def __init__(self, soc=None, phy=None, timings=None, clock_domain="sys", irq_line=None, endian="big", truecolor=True):
# 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=layout_len(cmap_layout), depth=8))
self.submodules.upd_cmap_fifo = upd_cmap_fifo = ClockDomainsRenamer({"read": clock_domain, "write": "sys"})(AsyncFIFOBuffered(width=layout_len(cmap_layout), depth=8))
upd_cmap_fifo_din = Record(cmap_layout)
self.comb += self.upd_cmap_fifo.din.eq(upd_cmap_fifo_din.raw_bits())
# hw cursor support
self.submodules.upd_overlay_fifo = upd_overlay_fifo = ClockDomainsRenamer({"read": clock_domain, "write": "sys"})(AsyncFIFOBuffered(width=1+5+32, depth=8))
self.submodules.upd_omap_fifo = upd_omap_fifo = ClockDomainsRenamer({"read": clock_domain, "write": "sys"})(AsyncFIFOBuffered(width=layout_len(omap_layout), depth=8))
upd_omap_fifo_din = Record(omap_layout)
self.comb += self.upd_omap_fifo.din.eq(upd_omap_fifo_din.raw_bits())
name = "video_framebuffer"
# near duplicate of plaform.add_video_framebuffer
# Video Timing Generator.
vtg = FBVideoTimingGenerator(default_video_timings=timings if isinstance(timings, str) else timings[1])
vtg = FBVideoTimingGenerator(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)
vtg_enable = Signal(reset = 0)
#self.specials += MultiReg(vtg_enable, vtg.enable, clock_domain)
self.comb += [ vtg.enable.eq(vtg_enable) ]
# Video FrameBuffer.
timings = timings if isinstance(timings, str) else timings[0]
@ -245,14 +360,22 @@ class goblin(Module, AutoCSR):
vres = int(timings.split("@")[0].split("x")[1])
freq = vtg.video_timings["pix_clk"]
print(f"goblin: 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))
vfb = VideoFrameBufferMultiDepth(dram_port = soc.sdram.crossbar.get_port(),
upd_clut_fifo = upd_cmap_fifo,
hres = hres,
vres = vres,
base = base,
fifo_depth=(64*1024),
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,
truecolor = truecolor,
)
setattr(self.submodules, name, vfb)
##dma_reset = Signal(reset = 0)
##self.comb += self.video_framebuffer.fb_dma_reset.eq(dma_reset)
# Connect Video Timing Generator to Video FrameBuffer.
self.comb += vtg.source.connect(vfb.vtg_sink)
@ -265,34 +388,35 @@ class goblin(Module, AutoCSR):
soc.add_constant("VIDEO_FRAMEBUFFER_HRES", hres)
soc.add_constant("VIDEO_FRAMEBUFFER_VRES", vres)
# goblin 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 */
# };
# HW Cursor
hwcursor_x = Signal(12)
hwcursor_y = Signal(12)
self.comb += vtg.hwcursor_x.eq(hwcursor_x)
self.comb += vtg.hwcursor_y.eq(hwcursor_y)
self.bus = bus = wishbone.Interface()
# current cmap logic for the goblin, similar to the cg6, minus the HW cursor
bt_mode = Signal(4, reset = 0) # 0 is 3, 2 is 0, 4 is 1, 8 is 2, and bit depth is 2^
bt_mode = Signal(8, reset = 0x3) # bit depth is 2^x ; 0x10 is direct mode (32 bits)
bt_addr = Signal(8, reset = 0)
bt_cmap_state = Signal(2, reset = 0)
m_vbl_disable = Signal(reset = 1)
videoctrl = Signal()
vbl_signal = Signal(reset = 0)
vbl_irq = soc.platform.request("nmrq_3v3_n")
self.comb += vbl_irq.eq(~vbl_signal | m_vbl_disable) # active low
#self.comb += Case(bt_mode, {
# 0x0: self.video_framebuffer.mode.eq(3),
# 0x2: self.video_framebuffer.mode.eq(0),
# 0x4: self.video_framebuffer.mode.eq(1),
# 0x8: self.video_framebuffer.mode.eq(2),
# })
self.comb += irq_line.eq(~vbl_signal | m_vbl_disable) # active low
if (endian == "big"):
low_byte = slice(0, 8)
low_bit = slice(0, 1)
else:
low_byte = slice(24, 32)
low_bit = slice(24, 25)
self.submodules.wishbone_fsm = wishbone_fsm = FSM(reset_state = "Reset")
wishbone_fsm.act("Reset",
NextValue(bus.ack, 0),
@ -301,17 +425,25 @@ class goblin(Module, AutoCSR):
If(bus.cyc & bus.stb & bus.we & ~bus.ack & upd_cmap_fifo.writable, #write
# FIXME: should check for prefix?
Case(bus.adr[0:18], {
"default": [],
# gobofb_mode
0x0: [ NextValue(bt_mode, bus.dat_w[0:8]), ],
0x0: [ NextValue(bt_mode, bus.dat_w[low_byte]), ],
# set vbl
0x1: [ NextValue(m_vbl_disable, ~bus.dat_w[low_bit]), ],
# gobofb on/off
0x2: [ NextValue(videoctrl, bus.dat_w[low_bit]), ],
# clear irq
0x3: [ NextValue(vbl_signal, 0), ],
# 0x4: rest in SW
# gobofb_lut_addr
0x5: [ NextValue(bt_addr, bus.dat_w[0:8]),
0x5: [ NextValue(bt_addr, bus.dat_w[low_byte]),
NextValue(bt_cmap_state, 0),
],
# gobofb_lut
0x6: [ upd_cmap_fifo.we.eq(1),
upd_cmap_fifo_din.color.eq(bt_cmap_state),
upd_cmap_fifo_din.address.eq(bt_addr),
upd_cmap_fifo_din.data.eq(bus.dat_w[0:8]),
upd_cmap_fifo_din.data.eq(bus.dat_w[low_byte]),
Case(bt_cmap_state, {
0: [ NextValue(bt_cmap_state, 1), ],
1: [ NextValue(bt_cmap_state, 2), ],
@ -319,17 +451,39 @@ class goblin(Module, AutoCSR):
"default": NextValue(bt_cmap_state, 0),
}),
],
# set vbl
0x1: [ NextValue(m_vbl_disable, ~bus.dat_w[0:1]), ],
# clear irq
0x3: [ NextValue(vbl_signal, 0), ],
# 0x7: debug in SW
# cursor lut
0x8: [ upd_omap_fifo.we.eq(1),
upd_omap_fifo_din.color.eq(bt_cmap_state),
upd_omap_fifo_din.address.eq(bt_addr[0:2]),
upd_omap_fifo_din.data.eq(bus.dat_w[low_byte]),
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),
}),
],
# hw cursor x/y
0x9: [ NextValue(hwcursor_x, bus.dat_w[16:28]), # FIXME: endianess
NextValue(hwcursor_y, bus.dat_w[ 0:12]), # FIXME: endianess
],
}),
Case(bus.adr[5:18], {
"default": [],
0x1 : [ upd_overlay_fifo.we.eq(1), # 1*32 = 32..63 / 0x20..0x3F
upd_overlay_fifo.din.eq(Cat(Signal(1, reset = 0), 31-bus.adr[0:5], bus.dat_w)) # FIXME: endianess
],
0x2 : [ upd_overlay_fifo.we.eq(1), # 2*32 = 64..95 / 0x40..0x5F
upd_overlay_fifo.din.eq(Cat(Signal(1, reset = 1), 31-bus.adr[0:5], bus.dat_w)) # FIXME: endianess
],
}),
NextValue(bus.ack, 1),
).Elif(bus.cyc & bus.stb & ~bus.we & ~bus.ack, #read
Case(bus.adr[0:18], {
# bt_addr
0x0: [ NextValue(bus.dat_r, bt_mode), ],
0x0: [ NextValue(bus.dat_r[low_byte], bt_mode), ],
0x2: [ NextValue(bus.dat_r[low_byte], videoctrl), ],
"default": [ NextValue(bus.dat_r, 0xDEADBEEF)],
}),
NextValue(bus.ack, 1),
@ -338,28 +492,86 @@ class goblin(Module, AutoCSR):
),
)
# mode switch logic
old_bt_mode = Signal(4)
vtg_reset_counter = Signal(4, reset = 0) # to put the VTG in reset for a few cyles so that the DMA can restart
npixels = hres * vres
old_bt_mode = Signal(8) # different from bt_mode
in_reset = Signal()
post_reset_ctr = Signal(3)
previous_videoctrl = Signal()
if (truecolor):
handle_truecolor_bit = [ self.video_framebuffer.use_indexed.eq(~bt_mode[4:5]) ]
else:
handle_truecolor_bit = [ ]
# this has grown complicated and should be a FSM...
self.sync += [ old_bt_mode.eq(bt_mode),
If(old_bt_mode != bt_mode,
Case(bt_mode, {
0x2: self.video_framebuffer.mode.eq(0),
0x4: self.video_framebuffer.mode.eq(1),
0x8: self.video_framebuffer.mode.eq(2),
0x0: self.video_framebuffer.mode.eq(3),
If(old_bt_mode != bt_mode,
in_reset.eq(1),
videoctrl.eq(0), # start a disabling cycle, or stay disabled
previous_videoctrl.eq(videoctrl), # preserve old state for restoration later
),
If(in_reset & ~vtg_enable, # we asked for a reset and by now, the VTG has been turned off (or was off) so we reset the DMA and change the parameters
##dma_reset.eq(1), # hpefully this will clear the FIFO as well
self.video_framebuffer.indexed_mode.eq(bt_mode[0:2] & ~(Replicate(bt_mode[4:5], 2))),
*handle_truecolor_bit,
in_reset.eq(0),
post_reset_ctr.eq(7),
),
##If(post_reset_ctr == 5, # take DMA out of reset
## dma_reset.eq(0),
##),
If(post_reset_ctr == 4, # now reconfigure the DMA
If(bt_mode[4:5],
self.video_framebuffer.fb_dma.length.eq(npixels * 4),
).Else(
Case(bt_mode[0:2], {
3: self.video_framebuffer.fb_dma.length.eq(npixels ),
2: self.video_framebuffer.fb_dma.length.eq(npixels//2),
1: self.video_framebuffer.fb_dma.length.eq(npixels//4),
0: self.video_framebuffer.fb_dma.length.eq(npixels//8),
}),
vtg_reset_counter.eq(15),
vtg._enable.eq(0),),
If(vtg_reset_counter == 1,
vtg._enable.eq(1),),
If(vtg_reset_counter > 0,
vtg_reset_counter.eq(vtg_reset_counter - 1),),
]
),
),
If(post_reset_ctr == 1, # we've waited for the mode switch so restore video mode
videoctrl.eq(previous_videoctrl),
),
If(post_reset_ctr != 0,
post_reset_ctr.eq(post_reset_ctr - 1),
),
]
# videoctrl logic
old_videoctrl = Signal()
videoctrl_starting = Signal()
videoctrl_stopping = Signal()
self.sync += [
If(~videoctrl_starting & ~videoctrl_stopping, # while we're changing state, delay any new request for change
old_videoctrl.eq(videoctrl),
),
# turn on
If(videoctrl & ~old_videoctrl, # pos edge
self.video_framebuffer.fb_dma.enable.eq(1), # enable DMA
videoctrl_starting.eq(1),
),
If(videoctrl & (self.video_framebuffer.fb_dma.rsv_level != 0),
vtg_enable.eq(1), # there's some data requested, good to go
videoctrl_starting.eq(0),
),
# turn off
If(~videoctrl & old_videoctrl, # neg edge
self.video_framebuffer.fb_dma.enable.eq(0), # disable DMA
videoctrl_stopping.eq(1),
),
If(~videoctrl & (self.video_framebuffer.fb_dma.rsv_level == 0) & (self.video_framebuffer.underflow),
vtg_enable.eq(0), # the DMA FIFO is purged, stop vtg
videoctrl_stopping.eq(0),
),
]
# VBL logic
self.sync += [
If(self.video_framebuffer.vblping == 1,
vbl_signal.eq(1),
),]

View File

@ -22,18 +22,17 @@ class NuBus(Module):
self.mem_tryagain = Signal()
# cpu
#self.cpu_valid = Signal(reset = 0)
#self.cpu_addr = Signal(32)
#self.cpu_wdata = Signal(32)
#self.cpu_ready = Signal()
#self.cpu_write = Signal(4)
#self.cpu_rdata = Signal(32)
#self.cpu_lock = Signal()
#self.cpu_eclr = Signal()
#self.cpu_errors = Signal(4)
self.cpu_valid = Signal(reset = 0)
self.cpu_addr = Signal(32)
self.cpu_wdata = Signal(32)
self.cpu_ready = Signal()
self.cpu_write = Signal(4)
self.cpu_rdata = Signal(32)
self.cpu_lock = Signal()
self.cpu_eclr = Signal()
self.cpu_errors = Signal(4)
# utilities
self.tmoen = Signal()
# utilities (unused)
self.mem_stdslot = Signal()
self.mem_super = Signal()
self.mem_local = Signal()
@ -48,7 +47,6 @@ class NuBus(Module):
p_SUPERSLOTS_ADDRESS = 0x9,
p_WDT_W = 0x8,
p_LOCAL_SPACE_EXPOSED_TO_NUBUS = 0,
p_NON_ECC_PARITY = 0,
i_nub_clkn = ClockSignal(cd_nubus),
i_nub_resetn = ~ResetSignal(cd_nubus),
i_nub_idn = platform.request("id_3v3_n"),
@ -60,10 +58,11 @@ class NuBus(Module):
io_nub_rqstn = platform.request("rqst_3v3_n"),
io_nub_ackn = platform.request("ack_3v3_n"),
# io_nub_arbn = platform.request("nubus_arb_n"),
o_arb = platform.request("arb"),
o_arbcy_n = platform.request("arbcy_n"),
i_grant = platform.request("grant"),
o_tmoen = platform.request("tmoen"),
o_NUBUS_AD_DIR = platform.request("nubus_ad_dir"),
o_nubus_master_dir = platform.request("nubus_master_dir"),
# io_nub_nmrqn = platform.request("nmrq_3v3_n"),
# io_nub_spn = self.nubus_sp_n,
# io_nub_spvn = self.nubus_spv_n,
@ -75,19 +74,21 @@ class NuBus(Module):
i_mem_rdata = self.mem_rdata,
i_mem_error = self.mem_error,
i_mem_tryagain = self.mem_tryagain,
#i_cpu_valid = self.cpu_valid,
#i_cpu_addr = self.cpu_addr,
#i_cpu_wdata = self.cpu_wdata,
#o_cpu_ready = self.cpu_ready,
#i_cpu_write = self.cpu_write,
#o_cpu_rdata = self.cpu_rdata,
#i_cpu_lock = self.cpu_lock,
#i_cpu_eclr = self.cpu_eclr,
#o_cpu_errors = self.cpu_errors,
i_cpu_valid = self.cpu_valid,
i_cpu_addr = self.cpu_addr,
i_cpu_wdata = self.cpu_wdata,
o_cpu_ready = self.cpu_ready,
i_cpu_write = self.cpu_write,
o_cpu_rdata = self.cpu_rdata,
i_cpu_lock = self.cpu_lock,
i_cpu_eclr = self.cpu_eclr,
o_cpu_errors = self.cpu_errors,
o_mem_stdslot = self.mem_stdslot,
o_mem_super = self.mem_super,
o_mem_local = self.mem_local,
o_fpga_to_cpld_signal = platform.request("fpga_to_cpld_signal"),
i_nub_clk2xn = ClockSignal(cd_nubus90),
io_nub_tm2n = platform.request("tm2_3v3_n"),
)
@ -98,10 +99,10 @@ class NuBus(Module):
def add_sources(self, platform):
platform.add_source("nubus.v", "verilog")
platform.add_source("/home/dolbeau/XiBus/nubus.svh", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_arbiter.v", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_cpubus.v", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_arbiter.v", "verilog") # in the CPLD
platform.add_source("/home/dolbeau/XiBus/nubus_cpubus.v", "verilog")
platform.add_source("/home/dolbeau/XiBus/nubus_driver.v", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_errors.v", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_errors.v", "verilog") # unused
platform.add_source("/home/dolbeau/XiBus/nubus_membus.v", "verilog")
#platform.add_source("/home/dolbeau/XiBus/nubus_master.v", "verilog")
platform.add_source("/home/dolbeau/XiBus/nubus_master.v", "verilog")
platform.add_source("/home/dolbeau/XiBus/nubus_slave.v", "verilog")

View File

@ -2,72 +2,103 @@
* NuBus controller
*
* Autor: Valeriya Pudova (hww.github.io)
* Adapted by Romain Dolbeau <romain@dolbeau.org> for the NuBusFPGA
* Copyright (c) 2021-2022
*/
/* This module is running on the FPGA */
module nubus
#(
// All slots area starts with addrss $FXXX XXXX
// All slots area starts with address $FXXX XXXX
parameter SLOTS_ADDRESS = 'hF,
// All superslots starts at $9000 0000
parameter SUPERSLOTS_ADDRESS = 'h9,
// Watch dog timer bits. Master controller will terminate transfer
// after (2 ^ WDT_W) clocks
parameter WDT_W = 8,
// Local space of card start and end addres. For example 0-5
// Local space of card start and end address. For example 0-5
// makes local space address $00000000-$50000000
// UNUSED in NuBusFPGA
parameter LOCAL_SPACE_EXPOSED_TO_NUBUS = 0,
parameter LOCAL_SPACE_START = 0,
parameter LOCAL_SPACE_END = 5,
// Generate parity without ECC memory
parameter NON_ECC_PARITY = 0
parameter LOCAL_SPACE_END = 5
)
(
/* NuBus signals */
/* *** NuBus signals *** */
/* those are connected to the FPGA */
/* connected via the CPLD */
input nub_clkn, // Clock (rising is driving edge, faling is sampling)
input nub_resetn, // Reset
input [ 3:0] nub_idn, // Slot Identificatjon
// inout nub_pfwn, // Power Fail Warning
inout [31:0] nub_adn, // Address/Data
input [ 3:0] nub_idn, // Slot Identification
inout nub_tm0n, // Transfer Mode
inout nub_tm1n, // Transfer Mode
inout nub_startn, // Start
inout nub_rqstn, // Request
inout nub_ackn, // Acknowledge
// inout [ 3:0] nub_arbn, // Arbitration
output arb,
input grant,
output tmoen,
output NUBUS_AD_DIR,
//inout nub_nmrqn, // Non-Master Request, handled in the Litex code
// connected via the CPLD but NuBus90 (unimplemented)
input nub_clk2xn,
inout nub_tm2n,
/* connected via the 74LVT245 */
inout [31:0] nub_adn, // Address/Data
/* those are not used, and not even connected in the board */
// inout nub_pfwn, // Power Fail Warning
// inout nub_spn, // System Parity
// inout nub_spvn, // System Parity Valid
/* Memory bus signals connected to a memory, accesible by nubus or processor */
/* those ared used but handled in directly in the Litex code */
// output nub_nmrqn, // Non-Master Request, handled in the Litex code
/* those are used but connected only to the CPLD */
/* we deal with the CPLD via 'arbcy_n' and 'grant'
// inout [ 3:0] nub_arbn, // Arbitration
/* *** CPLD <-> FPGA signals, not in NuBus */
output arbcy_n, // request arbitration
input grant, // arbitration won
output tmoen, // output enable for tm0/1
/* *** CPLD <-> FPGA signals, spare, currently unused */
output fpga_to_cpld_signal, // regular signal
// inout fpga_to_cpld_signal_2, // regular signal
// inout fpga_to_cpld_clk, // clk input on CPLD or regular signal
/* FPGA -> drivers */
output NUBUS_AD_DIR, // direction for the LS245 (input/output for A/D lines)
output nubus_master_dir, // are we in master mode (to drive the proper signals)
/* 'memory bus' signals; those are used to interface with the Wishbone to access the FPGA resources from NuBus */
output mem_valid,
output [31:0] mem_addr,
output [31:0] mem_wdata,
output [ 3:0] mem_write,
input mem_ready,
input [31:0] mem_rdata,
input mem_error,
input mem_tryagain,
input mem_error, // ignored
input mem_tryagain, // ignored
/* 'processor bus' signals; those are used to interface with the Wishbone to access NuBus resources from the FPGA */
input cpu_valid,
input [31:0] cpu_addr,
input [31:0] cpu_wdata,
input [ 3:0] cpu_write,
output cpu_ready,
output [31:0] cpu_rdata,
input cpu_lock,
input cpu_eclr, // ignored
output [3:0] cpu_errors, // ignored
/* utilities signal from the NuBus stuff, currently unused */
// Access to slot area
output mem_stdslot,
// Access to superslot area ($sXXXXXXX where <s> is card id)
output mem_super,
// Access to local memory on the card
output mem_local,
// NuBus90 (unimplemented)
input nub_clk2xn,
inout nub_tm2n
output mem_local
);
`include "nubus.svh"
@ -83,46 +114,66 @@ module nubus
// Global signals
// ==========================================================================
wire slv_master, slv_slave, slv_tm1n, slv_tm0n, slv_ackcyn, slv_myslotcy;
wire unsigned [31:0] slv_addr;
wire drv_tmoen, drv_mstdn;
// ===== SLAVE =====
//wire slv_master;
wire slv_slave; // output nubus_slave module; input internal ; active during slave cycle
wire slv_tm1n; // output nubus_slave module; input internal & nubus_membus
wire slv_tm0n; // output nubus_slave module; input nubus_membus
wire slv_ackcyn; // output nubus_slave module; input nubus_driver
wire slv_myslotcy; // output nubus_slave module; input internal & nubus_driver
wire unsigned [31:0] slv_addr;// output nubus_slave module; input nubus_membus
wire mst_timeout;
// ===== CPU ====
wire unsigned [31:0] cpu_ad; // output nubus_master; input MUX to A/D lines 'nub_ad' (nub_ad then as an OE and an iverter to reach nub_adn)
wire cpu_tm1n; // R(h)/W(l); output nubus_cpu; input nubus_driver & internal
wire cpu_tm0n; // byte size(l); idem
wire cpu_masterd; // ignored
// ===== DRIVER =====
wire drv_tmoen; // output enable for tm0n/tm1n (== tmoen) by nubus_driver
wire drv_mstdn; // ??? only connected to driver as an output
// ===== MASTER ===
wire mst_timeout; // timeout???; output nubus_master; input nubus_driver & nubus_slave
wire mst_arbcyn; // req. arb; output nubus_master; input internal & to CPLD & nubus_driver
assign arbcy_n = mst_arbcyn;
wire mst_adrcyn; // during the address cycle for master; output nubus_master; input nubus_driver & nubus_cpubus
wire mst_lockedn; // for locked accesses (?); output nubus_master; input nubus_driver
wire mst_arbdn; // delay during arbitration; output nubus_master; input [NULL] ???
wire mst_busyn; // busy during transfer; output nubus_master; input [NULL] ???
wire mst_ownern; // master is bus owner; output nubus_master; input nubus_driver & internal
wire mst_dtacyn; // during the data cycle for master; output nubus_master; input nubus_driver & internal
// ==========================================================================
// Drive NuBus address-data line
// ==========================================================================
// Select nubus data signals
wire [31:0] nub_ad = mem_rdata;
// Should we be putting the address (instead of data) on the bus [see also nub_adoe]
// yes during address cycle, or if we're reading (not writing) data
// actually during write the CPU puts data in cpu_ad so also when writing
// nub_adoe takes care of the enablement
wire cpu_adsel = ~mst_adrcyn | ~mst_dtacyn;// & ~cpu_tm1n;
// Select nubus address or data signals
wire [31:0] nub_ad = cpu_adsel ? cpu_ad : mem_rdata;
// When 1 - drive the NuBus AD lines
wire nub_adoe = slv_slave & slv_tm1n
/*SLAVE read of card*/
// Tri-state control for the A/D line
// nub_adoe is the output enable, when 0 A/D lines are high-impedance
// Slave: only drive the A/D lines to return data on a read (slave cycle with tm1n high)
// Master: drives during (a) address cycle
// (b) data cycle when writing
wire nub_adoe = slv_slave & slv_tm1n /* SLAVE read of card */
| cpu_valid & ~mst_adrcyn /* MASTER address cycle*/
| ~mst_ownern & ~mst_dtacyn & ~cpu_tm1n /* MASTER data cycle, when writing*/
;
wire rqst_n, rqst_oe_n;
assign rqst_n = 'b1; // no master yet
assign nub_rqstn = ~rqst_oe_n ? rqst_n : 'bZ;
// Output to nubus the
assign nub_adn = nub_adoe ? ~nub_ad : 'bZ;
assign mem_valid = slv_myslotcy;
/* for direction */
assign NUBUS_AD_DIR = ~nub_adoe;
//assign nubus_master_dir = grant | ~mst_adrcyn | ~mst_arbdn | ~mst_ownern | ~mst_dtacyn;
assign nubus_master_dir = ~mst_ownern;
// ==========================================================================
// Parity checking
// ==========================================================================
//wire parity = ~^nub_adn;
//wire nub_noparity = NON_ECC_PARITY & ~nub_adoe & ~nub_spvn & nub_spn == parity;
//assign nub_spn = NON_ECC_PARITY & nub_adoe ? parity : 'bZ;
//assign nub_spvn = NON_ECC_PARITY & nub_adoe ? 0 : 'bZ;
/* for slave access, enable the access during slv_myslotcy*/
assign mem_valid = slv_myslotcy;
// ==========================================================================
// Slave FSM
@ -133,10 +184,10 @@ module nubus
.SLOTS_ADDRESS (SLOTS_ADDRESS),
.SUPERSLOTS_ADDRESS(SUPERSLOTS_ADDRESS),
.SIMPLE_MAP(0),
// UNUSED in NuBusFPGA
.LOCAL_SPACE_EXPOSED_TO_NUBUS(LOCAL_SPACE_EXPOSED_TO_NUBUS),
.LOCAL_SPACE_START(LOCAL_SPACE_START),
.LOCAL_SPACE_END(LOCAL_SPACE_END)
)
USlave
(
@ -149,7 +200,7 @@ module nubus
.nub_tm1n(nub_tm1n), // Transition mode 1 (Read/Write)
.nub_tm0n(nub_tm0n),
.mem_ready(mem_ready),
.mst_timeout(0),
.mst_timeout(mst_timeout),
.slv_slave_o(slv_slave), // Slave mode
.slv_tm1n_o(slv_tm1n), // Latched transition mode 1 (Read/Write)
@ -161,6 +212,35 @@ module nubus
.slv_local_o(mem_local), // Local area
.slv_myslotcy_o(slv_myslotcy) // Any slot
);
// ==========================================================================
// Master FSM
// ==========================================================================
nubus_master
#(
.WDT_W(WDT_W)
)
UMaster
(
.nub_clkn(nub_clkn), // Clock
.nub_resetn(nub_resetn), // Reset
.nub_rqstn(nub_rqstn), // Bus request
.nub_startn(nub_startn), // Start transfer
.nub_ackn(nub_ackn), // End of transfer
.arb_grant(grant), // Grant access
.cpu_lock(cpu_lock), // Address line
.cpu_masterd(cpu_valid), // Master mode (delayed) // FIXME: ignoring cpu_masterd which is always 0 (see below)
.mst_lockedn_o(mst_lockedn), // Locked or not tranfer
.mst_arbdn_o(mst_arbdn),
.mst_busyn_o(mst_busyn),
.mst_ownern_o(mst_ownern), // Address or data transfer
.mst_dtacyn_o(mst_dtacyn), // Data strobe
.mst_adrcyn_o(mst_adrcyn), // Address strobe
.mst_arbcyn_o(mst_arbcyn), // Arbiter enabled
.mst_timeout_o(mst_timeout)
);
// ==========================================================================
// Driver Nubus
@ -170,26 +250,49 @@ module nubus
nubus_driver UNDriver
(
.slv_ackcyn(slv_ackcyn), // Achnowlege
.mst_arbcyn(1), // Arbiter enabled
.mst_adrcyn(1), // Address strobe
.mst_dtacyn(1), // Data strobe
.mst_ownern(1), // Master is owner of the bus
.mst_lockedn(1), // Locked or not transfer
.mst_tm1n(1), // Address ines
.mst_tm0n(1), // Address ines
.mst_timeout(0),
.slv_ackcyn(slv_ackcyn), // Acknowlege
.mst_arbcyn(mst_arbcyn), // Arbiter enabled
.mst_adrcyn(mst_adrcyn), // Address strobe
.mst_dtacyn(mst_dtacyn), // Data strobe
.mst_ownern(mst_ownern), // Master is owner of the bus
.mst_lockedn(mst_lockedn), // Locked or not transfer
.mst_tm1n(cpu_tm1n), // Address lines
.mst_tm0n(cpu_tm0n), // Address lines
.mst_timeout(mst_timeout),
.mis_errorn(TMN_COMPLETE),
.nub_tm0n_o(nub_tm0n), // Transfer mode
.nub_tm1n_o(nub_tm1n), // Transfer mode
.nub_ackn_o(nub_ackn), // Achnowlege
.nub_startn_o(nub_startn), // Transfer start
.nub_rqstn_o(nub_rqstn), // Bus request
.nub_rqstoen_o(rqst_oe_n), // Bus request enable
.nub_rqstoen_o(fpga_to_cpld_signal), // Bus request enable
.drv_tmoen_o(drv_tmoen), // Transfer mode enable
.drv_mstdn_o(drv_mstdn) // Guess: Slave sends /ACK. Master responds with /MSTDN, which allows slave to clear /ACK and listen for next transaction.
);
// ==========================================================================
// CPU Interface
// ==========================================================================
assign cpu_rdata = ~nub_adn;
assign cpu_ready = ~nub_ackn & nub_startn;
nubus_cpubus UCPUBus
(
.nub_clkn(nub_clkn),
.nub_resetn(nub_resetn),
.mst_adrcyn(mst_adrcyn),
.cpu_valid(cpu_valid),
.cpu_write(cpu_write),
.cpu_addr(cpu_addr),
.cpu_wdata(cpu_wdata),
.cpu_ad_o(cpu_ad),
.cpu_tm1n_o(cpu_tm1n),
.cpu_tm0n_o(cpu_tm0n),
.cpu_error_o(cpu_errors),
.cpu_masterd_o(cpu_masterd) // FIXME, set to 0 in Xibus nubus_cpubus
);
// ==========================================================================
// Memory Interface
// ==========================================================================

View File

@ -6,16 +6,18 @@
* generation of lower ARB<3:0> bits.
* The GRANT signal must be timed externally to determine proper
* NuBus constraints.
* This version uses a new technique to minimize skews .
* This version uses a new technique to minimize skews.
*
* Modified from the XiBus version to support external drivers in the NuBusFPGA
*/
module nubus_arbiter
(
input [3:0] idn, // ID of this card
input [3:0] arbn, // NuBus arbiter's lines (input)
output [3:0] arbon, // NuBus arbiter's lines (control)
input arbcyn, // enable arbitter
output grant // Grant access
input [3:0] idn, // ID of this card
input [3:0] arbn, // NuBus arbiter's lines (input)
output [3:0] arbon, // NuBus arbiter's lines (control)
input arbcyn, // enable arbitter
output grant // Grant access
);
wire arb2oen, arb1oen, arb0oen;

View File

@ -55,7 +55,7 @@ NET "reset_n_3v3" LOC = "S:PIN48";
NET "nubus_master_dir" LOC = "S:PIN49";
NET "fpga_to_cpld_signal_2" LOC = "S:PIN50";
NET "tmoen" LOC = "S:PIN51";
NET "arb" LOC = "S:PIN52";
NET "arbcy_n" LOC = "S:PIN52";
// PIN53: JTAG_TDO
// PIN24: GND
// PIN55: VCCIO

View File

@ -13,7 +13,7 @@ module nubus_cpld
// Spares
input fpga_to_cpld_clk, // unused (extra line from FPGA to CPLD, pin is a clk input)
inout fpga_to_cpld_signal, // unused (extra line from FPGA to CPLD)
input fpga_to_cpld_signal, // unused (extra line from FPGA to CPLD)
inout fpga_to_cpld_signal_2, // unused (extra line from FPGA to CPLD)
// NuBus (output to FPGA)
@ -23,7 +23,7 @@ module nubus_cpld
output clk2x_n_3v3, // nubus90 clk to FPGA
// NuBus Arbiter
input arb, // enable arbitter
input arbcy_n, // enable arbitter
input [3:0] arb_n_5v, // NuBus arbiter's lines
output [3:0] arb_o_n, // NuBus arbiter's control lines
output grant, // Grant access
@ -56,12 +56,12 @@ module nubus_cpld
// Master Request (OC)
input rqst_n_5v, // rqst from NuBus; needs monitoring before driving
inout rqst_n_3v3, // rqst from/to FPGA; needs monitoring before driving?; needed? or is arb enough?
inout rqst_n_3v3, // rqst from/to FPGA
output rqst_o_n // rqst to NuBus
);
// placeholder to make pretend we use the signals
assign fpga_to_cpld_signal_2 = fpga_to_cpld_signal ^ fpga_to_cpld_clk;
assign fpga_to_cpld_signal_2 = fpga_to_cpld_clk;
// placeholders
assign clk2x_n_3v3 = clk2x_n_5v;
assign tm2_n_3v3 = tm2_n_5v;
@ -80,28 +80,28 @@ module nubus_cpld
assign start_n_3v3 = nubus_oe ? 'bZ : (~nubus_master_dir ? start_n_5v : 'bZ); // master in
// rqst_o_n is always driven (the 74lvt125 wired as open collector will convert 1 to Z) and is active low
assign rqst_o_n = nubus_oe ? 1 : ( nubus_master_dir ? rqst_n_3v3 : 1); // master out
assign rqst_n_3v3 = nubus_oe ? 'bZ : (~nubus_master_dir ? rqst_n_5v : 'bZ); // master in
assign rqst_o_n = nubus_oe ? 1 : (~fpga_to_cpld_signal ? rqst_n_3v3 : 1); // master out
assign rqst_n_3v3 = nubus_oe ? 'bZ : ( fpga_to_cpld_signal ? rqst_n_5v : 'bZ); // master in
//assign ack_o_5v = nubus_oe ? 'bZ : ((nubus_master_dir ^ ~tmoen) ? ack_n_3v3 : 'bZ); // slave out/in
assign ack_o_n = nubus_oe ? 1 : ((nubus_master_dir ^ ~tmoen) ? ack_n_3v3 : 1); // slave out/in
assign ack_oe_n = nubus_oe ? 1 : ((nubus_master_dir ^ ~tmoen) ? 0 : 1); // slave out/in
assign ack_n_3v3 = nubus_oe ? 'bZ : ((nubus_master_dir ^ tmoen) ? ack_n_5v : 'bZ); // slave out/in
assign ack_o_n = nubus_oe ? 1 : (( ~tmoen) ? ack_n_3v3 : 1); // slave out/in
assign ack_oe_n = nubus_oe ? 1 : (( ~tmoen) ? 0 : 1); // slave out/in
assign ack_n_3v3 = nubus_oe ? 'bZ : (( tmoen) ? ack_n_5v : 'bZ); // slave out/in
//assign tm0_n_5v = nubus_oe ? 'bZ : ((nubus_master_dir ^ ~tmoen) ? tm0_n_3v3 : 'bZ); // slave out/in
//assign tm1_n_5v = nubus_oe ? 'bZ : ((nubus_master_dir ^ ~tmoen) ? tm1_n_3v3 : 'bZ); // slave out/in
assign tm0_o_n = nubus_oe ? 1 : ((nubus_master_dir ^ ~tmoen) ? tm0_n_3v3 : 1); // slave out/in
assign tm1_o_n = nubus_oe ? 1 : ((nubus_master_dir ^ ~tmoen) ? tm1_n_3v3 : 1); // slave out/in
assign tmx_oe_n = nubus_oe ? 1 : ((nubus_master_dir ^ ~tmoen) ? 0 : 1); // slave out/in
assign tm0_n_3v3 = nubus_oe ? 'bZ : ((nubus_master_dir ^ tmoen) ? tm0_n_5v : 'bZ); // slave in/out
assign tm1_n_3v3 = nubus_oe ? 'bZ : ((nubus_master_dir ^ tmoen) ? tm1_n_5v : 'bZ); // slave in/out
assign tm0_o_n = nubus_oe ? 1 : (( ~tmoen) ? tm0_n_3v3 : 1); // slave out/in
assign tm1_o_n = nubus_oe ? 1 : (( ~tmoen) ? tm1_n_3v3 : 1); // slave out/in
assign tmx_oe_n = nubus_oe ? 1 : (( ~tmoen) ? 0 : 1); // slave out/in
assign tm0_n_3v3 = nubus_oe ? 'bZ : (( tmoen) ? tm0_n_5v : 'bZ); // slave in/out
assign tm1_n_3v3 = nubus_oe ? 'bZ : (( tmoen) ? tm1_n_5v : 'bZ); // slave in/out
nubus_arbiter UArbiter
(
.idn(id_n_5v),
.arbn(arb_n_5v),
.arbon(arb_o_n),
.arbcyn(arb),
.arbcyn(arbcy_n),
.grant(grant)
);

View File

@ -0,0 +1,32 @@
from migen import *
from migen.genlib.fifo import *
import litex
from litex.soc.interconnect import wishbone
from migen.genlib.cdc import BusSynchronizer
class Wishbone2NuBus(Module):
def __init__(self, nubus, wb):
# cpu
# input cpu_valid,
# input [31:0] cpu_addr,
# input [31:0] cpu_wdata,
# input [ 3:0] cpu_write,
# output cpu_ready,
# output [31:0] cpu_rdata,
#input cpu_lock,
#input cpu_eclr,
#output [3:0] cpu_errors,
self.comb += nubus.cpu_valid.eq(wb.cyc & wb.stb)
self.comb += nubus.cpu_addr.eq(Cat(Signal(2, reset = 0), wb.adr))
self.comb += nubus.cpu_wdata.eq(wb.dat_w)
self.comb += If(wb.we == 1,
nubus.cpu_write.eq(wb.sel)).Else(
nubus.cpu_write.eq(0))
self.comb += wb.ack.eq(nubus.cpu_ready)
self.comb += wb.dat_r.eq(nubus.cpu_rdata)
self.comb += nubus.cpu_lock.eq(0) # FIXME: TODO: ???
self.comb += nubus.cpu_eclr.eq(0) # FIXME: TODO: ???

View File

@ -0,0 +1,130 @@
set_input_delay -clock nubus_clk -min 2.404 [get_ports {rqst_3v3_n}]
set_input_delay -clock nubus_clk -max 52.456 [get_ports {rqst_3v3_n}]
set_output_delay -clock nubus_clk -min -6.155 [get_ports {rqst_3v3_n}]
set_output_delay -clock nubus_clk -max 53.627 [get_ports {rqst_3v3_n}]
set_input_delay -clock nubus_clk -min 2.457 [get_ports {start_3v3_n}]
set_input_delay -clock nubus_clk -max 52.526 [get_ports {start_3v3_n}]
set_output_delay -clock nubus_clk -min -6.102 [get_ports {start_3v3_n}]
set_output_delay -clock nubus_clk -max 53.697 [get_ports {start_3v3_n}]
set_input_delay -clock nubus_clk -min 2.525 [get_ports {ack_3v3_n}]
set_input_delay -clock nubus_clk -max 52.617 [get_ports {ack_3v3_n}]
set_output_delay -clock nubus_clk -min -6.034 [get_ports {ack_3v3_n}]
set_output_delay -clock nubus_clk -max 53.788 [get_ports {ack_3v3_n}]
set_input_delay -clock nubus_clk -min 2.285 [get_ports {ad_3v3_n[31]}]
set_input_delay -clock nubus_clk -max 52.296 [get_ports {ad_3v3_n[31]}]
set_output_delay -clock nubus_clk -min -6.274 [get_ports {ad_3v3_n[31]}]
set_output_delay -clock nubus_clk -max 53.468 [get_ports {ad_3v3_n[31]}]
set_input_delay -clock nubus_clk -min 2.274 [get_ports {ad_3v3_n[30]}]
set_input_delay -clock nubus_clk -max 52.282 [get_ports {ad_3v3_n[30]}]
set_output_delay -clock nubus_clk -min -6.285 [get_ports {ad_3v3_n[30]}]
set_output_delay -clock nubus_clk -max 53.453 [get_ports {ad_3v3_n[30]}]
set_input_delay -clock nubus_clk -min 2.261 [get_ports {ad_3v3_n[29]}]
set_input_delay -clock nubus_clk -max 52.265 [get_ports {ad_3v3_n[29]}]
set_output_delay -clock nubus_clk -min -6.298 [get_ports {ad_3v3_n[29]}]
set_output_delay -clock nubus_clk -max 53.436 [get_ports {ad_3v3_n[29]}]
set_input_delay -clock nubus_clk -min 2.259 [get_ports {ad_3v3_n[28]}]
set_input_delay -clock nubus_clk -max 52.262 [get_ports {ad_3v3_n[28]}]
set_output_delay -clock nubus_clk -min -6.300 [get_ports {ad_3v3_n[28]}]
set_output_delay -clock nubus_clk -max 53.433 [get_ports {ad_3v3_n[28]}]
set_input_delay -clock nubus_clk -min 2.257 [get_ports {ad_3v3_n[27]}]
set_input_delay -clock nubus_clk -max 52.260 [get_ports {ad_3v3_n[27]}]
set_output_delay -clock nubus_clk -min -6.302 [get_ports {ad_3v3_n[27]}]
set_output_delay -clock nubus_clk -max 53.431 [get_ports {ad_3v3_n[27]}]
set_input_delay -clock nubus_clk -min 2.239 [get_ports {ad_3v3_n[26]}]
set_input_delay -clock nubus_clk -max 52.236 [get_ports {ad_3v3_n[26]}]
set_output_delay -clock nubus_clk -min -6.320 [get_ports {ad_3v3_n[26]}]
set_output_delay -clock nubus_clk -max 53.407 [get_ports {ad_3v3_n[26]}]
set_input_delay -clock nubus_clk -min 2.244 [get_ports {ad_3v3_n[25]}]
set_input_delay -clock nubus_clk -max 52.242 [get_ports {ad_3v3_n[25]}]
set_output_delay -clock nubus_clk -min -6.315 [get_ports {ad_3v3_n[25]}]
set_output_delay -clock nubus_clk -max 53.414 [get_ports {ad_3v3_n[25]}]
set_input_delay -clock nubus_clk -min 2.246 [get_ports {ad_3v3_n[23]}]
set_input_delay -clock nubus_clk -max 52.244 [get_ports {ad_3v3_n[23]}]
set_output_delay -clock nubus_clk -min -6.313 [get_ports {ad_3v3_n[23]}]
set_output_delay -clock nubus_clk -max 53.416 [get_ports {ad_3v3_n[23]}]
set_input_delay -clock nubus_clk -min 2.291 [get_ports {ad_3v3_n[24]}]
set_input_delay -clock nubus_clk -max 52.305 [get_ports {ad_3v3_n[24]}]
set_output_delay -clock nubus_clk -min -6.268 [get_ports {ad_3v3_n[24]}]
set_output_delay -clock nubus_clk -max 53.476 [get_ports {ad_3v3_n[24]}]
set_input_delay -clock nubus_clk -min 2.239 [get_ports {ad_3v3_n[21]}]
set_input_delay -clock nubus_clk -max 52.235 [get_ports {ad_3v3_n[21]}]
set_output_delay -clock nubus_clk -min -6.320 [get_ports {ad_3v3_n[21]}]
set_output_delay -clock nubus_clk -max 53.406 [get_ports {ad_3v3_n[21]}]
set_input_delay -clock nubus_clk -min 2.218 [get_ports {ad_3v3_n[22]}]
set_input_delay -clock nubus_clk -max 52.207 [get_ports {ad_3v3_n[22]}]
set_output_delay -clock nubus_clk -min -6.341 [get_ports {ad_3v3_n[22]}]
set_output_delay -clock nubus_clk -max 53.378 [get_ports {ad_3v3_n[22]}]
set_input_delay -clock nubus_clk -min 2.211 [get_ports {ad_3v3_n[18]}]
set_input_delay -clock nubus_clk -max 52.198 [get_ports {ad_3v3_n[18]}]
set_output_delay -clock nubus_clk -min -6.348 [get_ports {ad_3v3_n[18]}]
set_output_delay -clock nubus_clk -max 53.370 [get_ports {ad_3v3_n[18]}]
set_input_delay -clock nubus_clk -min 2.202 [get_ports {ad_3v3_n[20]}]
set_input_delay -clock nubus_clk -max 52.185 [get_ports {ad_3v3_n[20]}]
set_output_delay -clock nubus_clk -min -6.357 [get_ports {ad_3v3_n[20]}]
set_output_delay -clock nubus_clk -max 53.357 [get_ports {ad_3v3_n[20]}]
set_input_delay -clock nubus_clk -min 2.251 [get_ports {ad_3v3_n[16]}]
set_input_delay -clock nubus_clk -max 52.252 [get_ports {ad_3v3_n[16]}]
set_output_delay -clock nubus_clk -min -6.308 [get_ports {ad_3v3_n[16]}]
set_output_delay -clock nubus_clk -max 53.423 [get_ports {ad_3v3_n[16]}]
set_input_delay -clock nubus_clk -min 2.205 [get_ports {ad_3v3_n[19]}]
set_input_delay -clock nubus_clk -max 52.190 [get_ports {ad_3v3_n[19]}]
set_output_delay -clock nubus_clk -min -6.354 [get_ports {ad_3v3_n[19]}]
set_output_delay -clock nubus_clk -max 53.361 [get_ports {ad_3v3_n[19]}]
set_input_delay -clock nubus_clk -min 2.147 [get_ports {ad_3v3_n[14]}]
set_input_delay -clock nubus_clk -max 52.113 [get_ports {ad_3v3_n[14]}]
set_output_delay -clock nubus_clk -min -6.412 [get_ports {ad_3v3_n[14]}]
set_output_delay -clock nubus_clk -max 53.284 [get_ports {ad_3v3_n[14]}]
set_input_delay -clock nubus_clk -min 2.178 [get_ports {ad_3v3_n[17]}]
set_input_delay -clock nubus_clk -max 52.154 [get_ports {ad_3v3_n[17]}]
set_output_delay -clock nubus_clk -min -6.381 [get_ports {ad_3v3_n[17]}]
set_output_delay -clock nubus_clk -max 53.326 [get_ports {ad_3v3_n[17]}]
set_input_delay -clock nubus_clk -min 2.148 [get_ports {ad_3v3_n[15]}]
set_input_delay -clock nubus_clk -max 52.113 [get_ports {ad_3v3_n[15]}]
set_output_delay -clock nubus_clk -min -6.411 [get_ports {ad_3v3_n[15]}]
set_output_delay -clock nubus_clk -max 53.285 [get_ports {ad_3v3_n[15]}]
set_input_delay -clock nubus_clk -min 2.145 [get_ports {ad_3v3_n[12]}]
set_input_delay -clock nubus_clk -max 52.110 [get_ports {ad_3v3_n[12]}]
set_output_delay -clock nubus_clk -min -6.414 [get_ports {ad_3v3_n[12]}]
set_output_delay -clock nubus_clk -max 53.281 [get_ports {ad_3v3_n[12]}]
set_input_delay -clock nubus_clk -min 2.134 [get_ports {ad_3v3_n[13]}]
set_input_delay -clock nubus_clk -max 52.095 [get_ports {ad_3v3_n[13]}]
set_output_delay -clock nubus_clk -min -6.425 [get_ports {ad_3v3_n[13]}]
set_output_delay -clock nubus_clk -max 53.267 [get_ports {ad_3v3_n[13]}]
set_input_delay -clock nubus_clk -min 2.139 [get_ports {ad_3v3_n[10]}]
set_input_delay -clock nubus_clk -max 52.103 [get_ports {ad_3v3_n[10]}]
set_output_delay -clock nubus_clk -min -6.420 [get_ports {ad_3v3_n[10]}]
set_output_delay -clock nubus_clk -max 53.274 [get_ports {ad_3v3_n[10]}]
set_input_delay -clock nubus_clk -min 2.120 [get_ports {ad_3v3_n[11]}]
set_input_delay -clock nubus_clk -max 52.077 [get_ports {ad_3v3_n[11]}]
set_output_delay -clock nubus_clk -min -6.439 [get_ports {ad_3v3_n[11]}]
set_output_delay -clock nubus_clk -max 53.248 [get_ports {ad_3v3_n[11]}]
set_input_delay -clock nubus_clk -min 2.163 [get_ports {ad_3v3_n[8]}]
set_input_delay -clock nubus_clk -max 52.134 [get_ports {ad_3v3_n[8]}]
set_output_delay -clock nubus_clk -min -6.396 [get_ports {ad_3v3_n[8]}]
set_output_delay -clock nubus_clk -max 53.306 [get_ports {ad_3v3_n[8]}]
set_input_delay -clock nubus_clk -min 2.146 [get_ports {ad_3v3_n[6]}]
set_input_delay -clock nubus_clk -max 52.111 [get_ports {ad_3v3_n[6]}]
set_input_delay -clock nubus_clk -min 2.128 [get_ports {ad_3v3_n[9]}]
set_input_delay -clock nubus_clk -max 52.087 [get_ports {ad_3v3_n[9]}]
set_input_delay -clock nubus_clk -min 2.166 [get_ports {ad_3v3_n[4]}]
set_input_delay -clock nubus_clk -max 52.138 [get_ports {ad_3v3_n[4]}]
set_input_delay -clock nubus_clk -min 2.142 [get_ports {ad_3v3_n[7]}]
set_input_delay -clock nubus_clk -max 52.106 [get_ports {ad_3v3_n[7]}]
set_input_delay -clock nubus_clk -min 2.189 [get_ports {ad_3v3_n[5]}]
set_input_delay -clock nubus_clk -max 52.169 [get_ports {ad_3v3_n[5]}]
set_output_delay -clock nubus_clk -min -6.370 [get_ports {ad_3v3_n[5]}]
set_output_delay -clock nubus_clk -max 53.340 [get_ports {ad_3v3_n[5]}]
set_input_delay -clock nubus_clk -min 2.614 [get_ports {tm2_3v3_n}]
set_input_delay -clock nubus_clk -max 52.736 [get_ports {tm2_3v3_n}]
set_input_delay -clock nubus_clk -min 2.168 [get_ports {ad_3v3_n[3]}]
set_input_delay -clock nubus_clk -max 52.141 [get_ports {ad_3v3_n[3]}]
set_input_delay -clock nubus_clk -min 2.136 [get_ports {ad_3v3_n[2]}]
set_input_delay -clock nubus_clk -max 52.097 [get_ports {ad_3v3_n[2]}]
set_input_delay -clock nubus_clk -min 2.250 [get_ports {ad_3v3_n[0]}]
set_input_delay -clock nubus_clk -max 52.250 [get_ports {ad_3v3_n[0]}]
set_input_delay -clock nubus_clk -min 2.264 [get_ports {ad_3v3_n[1]}]
set_input_delay -clock nubus_clk -max 52.269 [get_ports {ad_3v3_n[1]}]
set_input_delay -clock nubus_clk -min 2.508 [get_ports {tm1_3v3_n}]
set_input_delay -clock nubus_clk -max 52.594 [get_ports {tm1_3v3_n}]
set_input_delay -clock nubus_clk -min 2.498 [get_ports {tm0_3v3_n}]
set_input_delay -clock nubus_clk -max 52.581 [get_ports {tm0_3v3_n}]

View File

@ -0,0 +1,55 @@
from migen import *
from migen.genlib.fifo import *
import litex
from litex.soc.interconnect import wishbone
class PingMaster(Module):
def __init__(self):
self.bus_slv = bus_slv = wishbone.Interface()
self.bus_mst = bus_mst = wishbone.Interface()
valu_reg = Signal(32)
addr_reg = Signal(32)
writ_del = Signal(6)
self.sync += If(writ_del != 0,
writ_del.eq(writ_del - 1))
self.submodules.wishbone_fsm = wishbone_fsm = FSM(reset_state = "Reset")
wishbone_fsm.act("Reset",
NextValue(bus_slv.ack, 0),
NextState("Idle"))
wishbone_fsm.act("Idle",
If(bus_slv.cyc & bus_slv.stb & bus_slv.we & ~bus_slv.ack, #write
# FIXME: should check for prefix?
Case(bus_slv.adr[0:1], {
0x0: [ NextValue(valu_reg, bus_slv.dat_w[0:32]), ],
0x1: [ NextValue(addr_reg, bus_slv.dat_w[0:32]),
NextValue(writ_del, 63), ],
}),
NextValue(bus_slv.ack, 1),
).Elif(bus_slv.cyc & bus_slv.stb & ~bus_slv.we & ~bus_slv.ack, #read
Case(bus_slv.adr[0:1], {
0x0: [ NextValue(bus_slv.dat_r, valu_reg), ],
0x1: [ NextValue(bus_slv.dat_r, addr_reg), ],
}),
NextValue(bus_slv.ack, 1),
).Else(
NextValue(bus_slv.ack, 0),
),
If(writ_del == 1,
NextState("Write"),),
)
wishbone_fsm.act("Write",
bus_mst.cyc.eq(1),
bus_mst.stb.eq(1),
bus_mst.we.eq(1),
bus_mst.dat_w.eq(valu_reg),
bus_mst.adr.eq(addr_reg[2:32]),
bus_mst.sel.eq(0xf),
If(bus_mst.ack,
NextState("Idle")),
)

View File

@ -7,7 +7,6 @@ from litex.soc.interconnect import wishbone
from migen.genlib.cdc import BusSynchronizer
class NuBus2Wishbone(Module):
"""Wishbone Clock Domain Crossing [Master]"""
def __init__(self, nubus, wb):
# memory
@ -20,15 +19,30 @@ class NuBus2Wishbone(Module):
#nubus.mem_error
#nubus.mem_tryagain
#nubus_mem_addr_revb = Signal(32)
#self.comb += nubus_mem_addr_revb.eq(Cat(nubus.mem_addr[24:32], nubus.mem_addr[16:24], nubus.mem_addr[8:16], nubus.mem_addr[0:8]))
self.comb += wb.cyc.eq(nubus.mem_valid)
self.comb += wb.stb.eq(nubus.mem_valid)
self.comb += If(nubus.mem_write == 0,
wb.sel.eq(0xF)).Else(
wb.sel.eq(nubus.mem_write))
self.comb += wb.we.eq(nubus.mem_write != 0)
self.comb += wb.adr.eq(Cat(nubus.mem_addr[2:24], Signal(8, reset = 0))) # 24 bits, a.k.a 22 bits of words
self.comb += wb.dat_w.eq(nubus.mem_wdata)
self.comb += nubus.mem_rdata.eq(wb.dat_r)
self.comb += [
If(~nubus.mem_addr[23], # first 8 MiB of slot space: remap to last 8 Mib of SDRAM
wb.adr.eq(Cat(nubus.mem_addr[2:23], Signal(1, reset=1), Signal(8, reset = 0x8f))), # 0x8f8...
).Else( # second 8 MiB: direct access
wb.adr.eq(Cat(nubus.mem_addr[2:24], Signal(8, reset = 0)))), # 24 bits, a.k.a 22 bits of words
]
self.comb += [
wb.dat_w.eq(nubus.mem_wdata),
nubus.mem_rdata.eq(wb.dat_r),
#wb.dat_w.eq(Cat(nubus.mem_wdata[24:32], nubus.mem_wdata[16:24], nubus.mem_wdata[8:16], nubus.mem_wdata[0:8])),
#nubus.mem_rdata.eq(Cat(wb.dat_r[24:32], wb.dat_r[16:24], wb.dat_r[8:16], wb.dat_r[0:8])),
]
self.comb += nubus.mem_ready.eq(wb.ack)
self.comb += nubus.mem_error.eq(0)
self.comb += nubus.mem_tryagain.eq(0)
self.comb += nubus.mem_error.eq(0) # FIXME: TODO: ???
self.comb += nubus.mem_tryagain.eq(0) # FIXME: TODO: ???

View File

@ -26,12 +26,15 @@ from litedram.frontend.dma import *
from migen.genlib.cdc import BusSynchronizer
from migen.genlib.resetsync import AsyncResetSynchronizer
from litex.soc.cores.video import VideoS7HDMIPHY
from litex.soc.cores.video import VideoVGAPHY
from litex.soc.cores.video import video_timings
import goblin_fb
# Wishbone stuff
from sbus_wb import WishboneDomainCrossingMaster
from nubus_mem_wb import NuBus2Wishbone
from nubus_cpu_wb import Wishbone2NuBus
# CRG ----------------------------------------------------------------------------------------------
class _CRG_MINI_SIM(Module):
@ -78,10 +81,10 @@ class _CRG_MINI_SIM(Module):
num_adv = 0
num_clk = 0
platform.add_platform_command("create_clock -name sysclk -period 20.8333 [get_nets clk48]")
self.sys_bufg = Signal()
self.specials += Instance("BUFG", i_I=clk48, o_O=self.sys_bufg)
self.comb += self.cd_native.clk.eq(self.sys_bufg)
#platform.add_platform_command("create_clock -name sysclk -period 20.8333 [get_nets clk48]")
#self.sys_bufg = Signal()
#self.specials += Instance("BUFG", i_I=clk48, o_O=self.sys_bufg)
#self.comb += self.cd_native.clk.eq(self.sys_bufg)
class _CRG(Module):
@ -179,8 +182,8 @@ class _CRG(Module):
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
else:
video_pll.create_clkout(self.cd_hdmi, pix_clk, margin = 0.0005)
video_pll.create_clkout(self.cd_hdmi5x, 5*pix_clk, margin = 0.0005)
video_pll.create_clkout(self.cd_hdmi, pix_clk, margin = 0.005)
video_pll.create_clkout(self.cd_hdmi5x, 5*pix_clk, margin = 0.005)
platform.add_platform_command("create_generated_clock -name hdmi_clk [get_pins {{{{MMCME2_ADV_{}/CLKOUT{}}}}}]".format(num_adv, num_clk))
num_clk = num_clk + 1
platform.add_platform_command("create_generated_clock -name hdmi5x_clk [get_pins {{{{MMCME2_ADV_{}/CLKOUT{}}}}}]".format(num_adv, num_clk))
@ -232,29 +235,35 @@ class NuBusFPGA(SoCCore):
# * $A through $E for the Macintosh Quadra 900; $9 through $B for the Macintosh IIcx;
# * $C through $E for the Macintosh IIci; $D and $E for the Macintosh Quadra 700; and
# * $9 for the Macintosh IIsi).
# So at best we get 16 MiB in 32-bits moden unless using "super slot space"
# the Q650 is $C through $E like the IIci, $E is the one with the PDS.
# So at best we get 16 MiB in 32-bits mode, unless using "super slot space"
# in 24 bits it's only one megabyte, $s0 0000 through $sF FFFF
# they are translated: '$s0 0000-$sF FFFF' to '$Fs00 0000-$Fs0F FFFF' (for s in range $9 through $E)
# let's assume we have 32-bits mode, this can be requested in the DeclROM apparently
self.wb_mem_map = wb_mem_map = {
"goblin_mem": 0x00000000, # up to 8 MiB of FB memory
#"END OF FIRST MB" : 0x000FFFFF,
#"END OF 8 MB": 0x007FFFFF,
"goblin_bt" : 0x00900000, # BT for goblin
"csr" : 0x00a00000, # CSR
"pingmaster": 0x00b00000,
"rom": 0x00FF8000, # ROM at the end (32 KiB of it ATM)
"END OF FIRST MB" : 0x000FFFFF,
"END OF SLOT SPACE": 0x00FFFFFF,
#"END OF SLOT SPACE": 0x00FFFFFF,
"main_ram": 0x80000000, # not directly reachable from NuBus
"video_framebuffer": 0x80000000 + 0x10000000 - goblin_fb_size, # Updated later
"fixme_master": 0xF0000000,
}
self.mem_map.update(wb_mem_map)
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, goblin=goblin, pix_clk=litex.soc.cores.video.video_timings[goblin_res]["pix_clk"])
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, goblin=goblin, hdmi=hdmi, pix_clk=litex.soc.cores.video.video_timings[goblin_res]["pix_clk"])
## add our custom timings after the clocks have been defined
xdc_timings_filename = None;
#if (version == "V1.0"):
# xdc_timings_filename = "/home/dolbeau/nubus-to-ztex-gateware/nubus-to-ztex-timings.xdc"
if (version == "V1.0"):
xdc_timings_filename = "/home/dolbeau/nubus-to-ztex-gateware/nubus_fpga_V1_0_timings.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"):
@ -263,7 +272,7 @@ class NuBusFPGA(SoCCore):
platform.add_platform_command(fix_line)
rom_file = "rom_{}.bin".format(version.replace(".", "_"))
rom_data = soc_core.get_mem_data(rom_file, "big")
rom_data = soc_core.get_mem_data(rom_file, "little") # "big"
# rom = Array(rom_data)
#print("\n****************************************\n")
#for i in range(len(rom)):
@ -271,26 +280,34 @@ class NuBusFPGA(SoCCore):
#print("\n****************************************\n")
self.add_ram("rom", origin=self.mem_map["rom"], size=2**15, contents=rom_data, mode="r") ## 32 KiB, must match mmap
avail_sdram = 0
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
from sdram_init import DDR3FBInit
self.submodules.sdram_init = DDR3FBInit(sys_clk_freq=sys_clk_freq, bitslip=1, delay=25)
self.bus.add_master(name="DDR3Init", master=self.sdram_init.bus)
#avail_sdram = 256 * 1024 * 1024
#from wb_test import WA2D
#self.submodules.wa2d = WA2D(self.platform)
#self.bus.add_slave("WA2D", self.wa2d.bus, SoCRegion(origin=0x00C00000, size=0x00400000, cached=False))
self.submodules.leds = LedChaser(
pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq)
self.add_csr("leds")
notsimul = 1
if (notsimul):
avail_sdram = 0
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
from sdram_init import DDR3FBInit
self.submodules.sdram_init = DDR3FBInit(sys_clk_freq=sys_clk_freq, bitslip=1, delay=25)
self.bus.add_master(name="DDR3Init", master=self.sdram_init.bus)
else:
avail_sdram = 256 * 1024 * 1024
self.add_ram("ram", origin=self.mem_map["goblin_mem"], size=2**16, mode="rw")
#self.submodules.leds = ClockDomainsRenamer("nubus")(LedChaser(
# pads = platform.request_all("user_led"),
# sys_clk_freq = 10e6))
#self.add_csr("leds")
base_fb = self.wb_mem_map["main_ram"] + avail_sdram - 1048576 # placeholder
if (goblin):
@ -298,6 +315,7 @@ class NuBusFPGA(SoCCore):
avail_sdram = avail_sdram - goblin_fb_size
base_fb = self.wb_mem_map["main_ram"] + avail_sdram
self.wb_mem_map["video_framebuffer"] = base_fb
print(f"FrameBuffer base_fb @ {base_fb:x}")
else:
print("***** ERROR ***** Can't have a FrameBuffer without main ram\n")
assert(False)
@ -307,13 +325,16 @@ class NuBusFPGA(SoCCore):
# requires us to reset the Macintosh afterward so the FPGA board
# is properly identified
# This is in the 'native' ClockDomain that is never reset
# not needed, FPGA initializes fast enough, works on cold boots
#hold_reset_ctr = Signal(30, reset=960000000)
hold_reset_ctr = Signal(5, reset=31)
self.sync.native += If(hold_reset_ctr>0, hold_reset_ctr.eq(hold_reset_ctr - 1))
hold_reset = Signal(reset=1)
hold_reset = Signal()
self.comb += hold_reset.eq(~(hold_reset_ctr == 0))
pad_nubus_oe = platform.request("nubus_oe")
self.comb += pad_nubus_oe.eq(hold_reset)
#pad_user_led_0 = platform.request("user_led", 0)
#self.comb += pad_user_led_0.eq(~hold_reset)
# Interface NuBus to wishbone
# we need to cross clock domains
@ -325,14 +346,30 @@ class NuBusFPGA(SoCCore):
self.submodules.nubus = nubus.NuBus(platform=platform, cd_nubus="nubus")
self.submodules.nubus2wishbone = ClockDomainsRenamer("nubus")(NuBus2Wishbone(nubus=self.nubus,wb=self.wishbone_master_nubus))
wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width)
self.submodules.wishbone2nubus = ClockDomainsRenamer("nubus")(Wishbone2NuBus(nubus=self.nubus,wb=wishbone_slave_nubus))
self.submodules.wishbone_slave_sys = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_slave_nubus, cd_master="sys", cd_slave="nubus")
self.bus.add_slave("DMA", self.wishbone_slave_sys, SoCRegion(origin=self.mem_map.get("fixme_master", None), size=0x0fffffff, cached=False))
if (goblin):
if (not hdmi):
self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga")
self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="vga") # clock_domain for the VGA side, goblin is running in cd_sys
self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="vga", irq_line=self.platform.request("nmrq_3v3_n"), endian="little", truecolor=False) # clock_domain for the VGA side, goblin is running in cd_sys
else:
self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi"), clock_domain="hdmi")
self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="hdmi") # clock_domain for the VGA side, goblin is running in cd_sys
self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="hdmi", irq_line=self.platform.request("nmrq_3v3_n"), endian="little", truecolor=False) # clock_domain for the HDMI side, goblin is running in cd_sys
self.bus.add_slave("goblin_bt", self.goblin.bus, SoCRegion(origin=self.mem_map.get("goblin_bt", None), size=0x1000, cached=False))
pad_user_led_0 = platform.request("user_led", 0)
pad_user_led_1 = platform.request("user_led", 1)
self.comb += pad_user_led_0.eq(self.goblin.video_framebuffer.underflow)
self.comb += pad_user_led_1.eq(self.goblin.video_framebuffer.fb_dma.enable)
# for testing
#from nubus_master_tst import PingMaster
#self.submodules.pingmaster = PingMaster()
#self.bus.add_slave("pingmaster_slv", self.pingmaster.bus_slv, SoCRegion(origin=self.mem_map.get("pingmaster", None), size=0x010, cached=False))
#self.bus.add_master(name="pingmaster_mst", master=self.pingmaster.bus_mst)
def main():

View File

@ -0,0 +1,15 @@
#!/bin/bash
FILE=$1
sed -e 's/ad_n\([0-9]*\)/ad_3v3_n[\1]/' \
-e 's/clk_n/clk_3v3_n/' \
-e 's/rqst_n/rqst_3v3_n/' \
-e 's/start_n/start_3v3_n/' \
-e 's/ack_n/ack_3v3_n/' \
-e 's/clk_n/clk_3v3_n/' \
-e 's/tm_n\([0-9]*\)/tm\1_3v3_n/' \
-e 's/clk_3v3_n/nubus_clk/g' \
$FILE | grep -v 'nubus_clk.*nubus_clk' | grep '^set' | tee $2

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,139 @@
#!/usr/bin/env python3
from migen import *
from wb_master import *
from wb_master import _WRITE_CMD, _WAIT_CMD, _DONE_CMD
dfii_control_sel = 0x01
dfii_control_cke = 0x02
dfii_control_odt = 0x04
dfii_control_reset_n = 0x08
dfii_command_cs = 0x01
dfii_command_we = 0x02
dfii_command_cas = 0x04
dfii_command_ras = 0x08
dfii_command_wrdata = 0x10
dfii_command_rddata = 0x20
# /!\ keep up to date with csr /!\
sdram_dfii_base = 0x00a01000
sdram_dfii_control = sdram_dfii_base + 0x000
sdram_dfii_pi0_command = sdram_dfii_base + 0x004
sdram_dfii_pi0_command_issue = sdram_dfii_base + 0x008
sdram_dfii_pi0_address = sdram_dfii_base + 0x00c
sdram_dfii_pi0_baddress = sdram_dfii_base + 0x010
# /!\ keep up to date with csr /!\
ddrphy_base = 0x00a00000
ddrphy_rst = ddrphy_base + 0x000
ddrphy_dly_sel = ddrphy_base + 0x010
ddrphy_rdly_dq_rst = ddrphy_base + 0x014
ddrphy_rdly_dq_inc = ddrphy_base + 0x018
ddrphy_rdly_dq_bitslip_rst = ddrphy_base + 0x01c
ddrphy_rdly_dq_bitslip = ddrphy_base + 0x020
ddrphy_wdly_dq_bitslip_rst = ddrphy_base + 0x024
ddrphy_wdly_dq_bitslip = ddrphy_base + 0x028
ddrphy_rdphase = ddrphy_base + 0x02c
ddrphy_wdphase = ddrphy_base + 0x030
def period_to_cycles(sys_clk_freq, period):
return int(period*sys_clk_freq)
def ddr3_init_instructions(sys_clk_freq):
return [
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001),
# phase
_WRITE_CMD, ddrphy_rdphase, 2,
_WRITE_CMD, ddrphy_wdphase, 3,
# software control
_WRITE_CMD, sdram_dfii_control, dfii_control_reset_n | dfii_control_odt | dfii_control_cke,
# reset
_WRITE_CMD, ddrphy_rst, 1,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001),
_WRITE_CMD, ddrphy_rst, 0,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001),
# release reset
_WRITE_CMD, sdram_dfii_pi0_address, 0x0,
_WRITE_CMD, sdram_dfii_pi0_baddress, 0,
_WRITE_CMD, sdram_dfii_control, dfii_control_odt|dfii_control_reset_n,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.005),
# bring cke high
_WRITE_CMD, sdram_dfii_pi0_address, 0x0,
_WRITE_CMD, sdram_dfii_pi0_baddress, 0,
_WRITE_CMD, sdram_dfii_control, dfii_control_cke|dfii_control_odt|dfii_control_reset_n,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.001),
# load mode register 2, CWL = 5
_WRITE_CMD, sdram_dfii_pi0_address, 0x200,
_WRITE_CMD, sdram_dfii_pi0_baddress, 2,
_WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs,
_WRITE_CMD, sdram_dfii_pi0_command_issue, 1,
# load mode register 3
_WRITE_CMD, sdram_dfii_pi0_address, 0x0,
_WRITE_CMD, sdram_dfii_pi0_baddress, 3,
_WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs,
_WRITE_CMD, sdram_dfii_pi0_command_issue, 1,
# load mode register 1
_WRITE_CMD, sdram_dfii_pi0_address, 0x6,
_WRITE_CMD, sdram_dfii_pi0_baddress, 1,
_WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs,
_WRITE_CMD, sdram_dfii_pi0_command_issue, 1,
# load mode register 0, CL=6, BL=8
_WRITE_CMD, sdram_dfii_pi0_address, 0x920,
_WRITE_CMD, sdram_dfii_pi0_baddress, 0,
_WRITE_CMD, sdram_dfii_pi0_command, dfii_command_ras|dfii_command_cas|dfii_command_we|dfii_command_cs,
_WRITE_CMD, sdram_dfii_pi0_command_issue, 1,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.0002),
# zq calibration
_WRITE_CMD, sdram_dfii_pi0_address, 0x400,
_WRITE_CMD, sdram_dfii_pi0_baddress, 0,
_WRITE_CMD, sdram_dfii_pi0_command, dfii_command_we|dfii_command_cs,
_WRITE_CMD, sdram_dfii_pi0_command_issue, 1,
_WAIT_CMD | period_to_cycles(sys_clk_freq, 0.0002),
# hardware control
_WRITE_CMD, sdram_dfii_control, dfii_control_sel,
]
def ddr3_config_instructions(bitslip, delay):
r = []
for module in range(2):
r += [_WRITE_CMD, ddrphy_dly_sel, 1<<module ]
r += [_WRITE_CMD, ddrphy_wdly_dq_bitslip_rst, 1<<module ]
r += [_WRITE_CMD, ddrphy_dly_sel, 0 ]
for module in range(2):
r += [_WRITE_CMD, ddrphy_dly_sel, 1<<module ]
r += [_WRITE_CMD, ddrphy_rdly_dq_bitslip_rst, 1]
for i in range(bitslip):
r += [_WRITE_CMD, ddrphy_rdly_dq_bitslip, 1]
r += [_WRITE_CMD, ddrphy_rdly_dq_rst, 1]
for i in range(delay):
r += [_WRITE_CMD, ddrphy_rdly_dq_inc, 1]
r += [_WRITE_CMD, ddrphy_dly_sel, 0 ]
return r
class DDR3Init(WishboneMaster):
def __init__(self, sys_clk_freq, bitslip, delay):
WishboneMaster.__init__(self,
ddr3_init_instructions(sys_clk_freq) +
ddr3_config_instructions(bitslip, delay) +
[_DONE_CMD])
class DDR3FBInit(WishboneMaster):
def __init__(self, sys_clk_freq, bitslip, delay):
WishboneMaster.__init__(self,
ddr3_init_instructions(sys_clk_freq) +
ddr3_config_instructions(bitslip, delay) +
[_DONE_CMD])

View File

@ -4,12 +4,13 @@ module nubus_slave_tb ();
`include "nubus_tb.svh"
parameter TEST_CARD_ID = 'h0;
parameter TEST_ADDR = 'hF0000000;
parameter TEST_CARD_ID = 'hc;
parameter TEST_ADDR = 'hFc000000;
parameter TEST_DATA = 'h87654321;
parameter [1:0] MEMORY_WAIT_CLOCKS = 1;
parameter DEBUG_NUBUS_START = 0;
parameter ROM_ADDR = 'hF0FFF000;
parameter ROM_ADDR = 'hFcFFF000;
parameter PING_ADDR = 'hFcB00000;
// Clock (rising is driving edge, faling is sampling)
tri1 bd_clk48;
@ -48,16 +49,18 @@ module nubus_slave_tb ();
tri1 [1:0] leds;
tri unused0, tmoen, unused1, unused2;
tri arb, grant;
tri arbcy_n;
tri grant;
tri nubus_oe, nubus_master_dir, nubus_ad_dir;
tri reset_n_3v3, clk_n_3v3, tm0_n_3v3, tm1_n_3v3, start_n_3v3, ack_n_3v3, rqst_n_3v3;
tri1 [3:0] id_n_3v3;
tri [3:0] id_n_3v3;
tri [31:0] ad_n_3v3;
tri [3:0] arb_o_n;
tri tm0_o_n, tm1_o_n, tmx_oe_n;
tri start_o_n, start_oe_n;
tri ack_o_n, ack_oe_n;
tri rqst_o_n;
tri rqst_o_n;
tri fpga_to_cpld_signal;
tri clk2x_n_3v3;
@ -66,9 +69,7 @@ module nubus_slave_tb ();
assign nub_idn = ~ TEST_CARD_ID;
assign nubus_master_dir = 0;
assign nub_arbn = 'b1111;
//assign nub_arbn = 'b1111;
nubus_cpld UCPLD (
.nubus_oe(nubus_oe),
@ -81,7 +82,7 @@ module nubus_slave_tb ();
.clk2x_n_5v(nub_clk2xn),
.fpga_to_cpld_clk(unused0),
.fpga_to_cpld_signal(unused1),
.fpga_to_cpld_signal(fpga_to_cpld_signal),
.fpga_to_cpld_signal_2(unused2),
.id_n_3v3(id_n_3v3),
@ -89,7 +90,7 @@ module nubus_slave_tb ();
.clk_n_3v3(clk_n_3v3),
.clk2x_n_3v3(clk2x_n_3v3),
.arb(arb),
.arbcy_n(arbcy_n),
.arb_n_5v(nub_arbn),
.arb_o_n(arb_o_n),
.grant(grant),
@ -141,6 +142,8 @@ module nubus_slave_tb ();
.nubus_ad_dir(nubus_ad_dir));
tri1 nmrq_3v3_n;
assign nmrq_3v3_n = 1;
sn74lvt145_quarter driver_u1a(.oe_n(nmrq_3v3_n),
.in(0),
@ -196,14 +199,15 @@ module nubus_slave_tb ();
.rqst_3v3_n(rqst_n_3v3),
.ack_3v3_n(ack_n_3v3),
// .nubus_arb_n(nub_arbn),
.arb(arb),
.arbcy_n(arbcy_n),
.grant(grant),
.tmoen(tmoen),
.nubus_ad_dir(nubus_ad_dir),
.nmrq_3v3_n(nmrq_3v3_n),
.nubus_master_dir(nubus_master_dir),
.nubus_oe(nubus_oe),
.clk2x_3v3_n(clk2x_n_3v3),
.tm2_3v3_n(tm2_n_3v3)
.tm2_3v3_n(tm2_n_3v3),
.fpga_to_cpld_signal(fpga_to_cpld_signal)
);
@ -220,19 +224,22 @@ module nubus_slave_tb ();
reg [31:0] tst_wdatan;
reg [31:0] tst_rdatan;
// Drive NuBus signals
reg mastermode_start;
reg mastermode_tmack;
assign nub_clkn = tst_clkn;
assign nub_clk2xn = tst_clk2xn;
assign bd_clk48 = tst_clk48;
assign nub_resetn = tst_resetn;
assign nub_startn = tst_startn;
assign nub_tm0n = tst_startn ? 'bZ : tst_tmn[0];
assign nub_tm1n = tst_startn ? 'bZ : tst_tmn[1];
assign nub_ackn = tst_startn ? 'bZ : tst_ackn;
// Drive NuBus signals
assign nub_startn = mastermode_start ? 'bZ: tst_startn;
assign nub_tm0n = (tst_startn & ~mastermode_tmack) ? 'bZ : tst_tmn[0];
assign nub_tm1n = (tst_startn & ~mastermode_tmack) ? 'bZ : tst_tmn[1];
assign nub_ackn = (tst_startn & ~mastermode_tmack) ? 'bZ : tst_ackn;
// Drive NuBus address/data lines
wire [31:0] tst_adn = tst_startn ? tst_wdatan : tst_addrn;
wire tst_nuboen = tst_startn & tst_tmn[1];
wire tst_nuboen = (tst_startn & tst_tmn[1]) | mastermode_start;
assign nub_adn = tst_nuboen ? 'bZ : tst_adn;
// Inverted verions of registers
@ -243,6 +250,10 @@ module nubus_slave_tb ();
$display ("Start virtual master (vm) writes and reads to/from NuBus slave memory module");
$dumpfile("nubus_slave_tb.vcd");
$dumpvars;
#1;
mastermode_start <= 0;
mastermode_tmack <= 0;
tst_clkn <= 1;
tst_resetn <= 0;
@ -311,6 +322,40 @@ module nubus_slave_tb ();
#1000;
// check PingMaster
$display ("PING ---------------------------");
write_word(TMADN_WR_WORD, PING_ADDR+0, 'hC0FFEE00);
read_word (TMADN_RD_WORD, PING_ADDR+0);
write_word(TMADN_WR_WORD, PING_ADDR+4, 'hF0F0F0F0);
mastermode_start <= 1;
mastermode_tmack <= 0;
tst_ackn <= 1;
@ (negedge nub_startn);
#1
$display ("GOT START ---------------------------");
$display ("%g (received ) address: $%h", $time, ~nub_adn);
@ (negedge nub_clkn);
#1
@ (negedge nub_clkn);
#1
@ (negedge nub_clkn);
#1
$display ("%g (received ) data: $%h", $time, ~nub_adn);
@ (posedge nub_clkn);
mastermode_tmack <= 1;
tst_ackn <= 0;
tst_tmn <= TMN_COMPLETE;
@ (posedge nub_clkn);
mastermode_start <= 0;
mastermode_tmack <= 0;
#2000;
$finish;
end

View File

@ -111,7 +111,7 @@ _nubus_nubus_v1_0 = [
"D12 D13 D14 C14 B16 B17 D15 C15 "
"B18 A18 C16 C17 E15 E16 F14 F13 "
"D17 D18 E17 E18 F15 F18 F16 G18 "), IOStandard("lvttl")),
# ("nubus_arb_n", 0, Pins(""), IOStandard("lvttl")), # CPLD only, we have 'arb'/'grant' instead
# ("nubus_arb_n", 0, Pins(""), IOStandard("lvttl")), # CPLD only, we have 'arbcy_n'/'grant' instead
("id_3v3_n", 0, Pins("U7 V6 V7 U8"), IOStandard("lvttl")),
("tm0_3v3_n", 0, Pins("K15"), IOStandard("lvttl")),
("tm1_3v3_n", 0, Pins("J17"), IOStandard("lvttl")),
@ -121,7 +121,7 @@ _nubus_nubus_v1_0 = [
("nubus_ad_dir", 0, Pins("G16"), IOStandard("lvttl")),
("nubus_master_dir", 0, Pins("H17"), IOStandard("lvttl")),
("grant", 0, Pins("H15"), IOStandard("lvttl")),
("arb", 0, Pins("J13"), IOStandard("lvttl")),
("arbcy_n", 0, Pins("J13"), IOStandard("lvttl")), # arb in the schematics
("fpga_to_cpld_clk", 0, Pins("H14"), IOStandard("lvttl")),
("tmoen", 0, Pins("U6"), IOStandard("lvttl")),
("fpga_to_cpld_signal",0, Pins("J14"), IOStandard("lvttl")),

BIN
nubus-to-ztex/691037.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,158 @@
THICKNESS_MAX=2.44;
THICKNESS=2.4;
ORIGINAL_THICKNESS=25.4/32;
NUBUS_HEIGHT_BELOW_OUTER_LIP=92; // NuBus p57, max is 97.25
NUBUS_HEIGHT_ABOVE_OUTER_LIP=6; // NuBus p57
NUBUS_BETWEEN_NOTCHES=87.25; // DCDMF3 p625 & p635, bottom of low to top of high?
NUBUS_HIGH_NOTCH_TO_TOP=10.35;// DCDMF3 p635, top of high to bottom of inner lip ?
NUBUS_BASE_WIDTH=18.57;
NUBUS_EXTRA_WIDTH=2.93;
NUBUS_FULL_WIDTH=NUBUS_BASE_WIDTH+NUBUS_EXTRA_WIDTH;
NUBUS_TOP_WIDTH=21.82;
NUBUS_OVERHANG_WIDTH=NUBUS_TOP_WIDTH-NUBUS_BASE_WIDTH;
NUBUS_EXTRA_FROM_TOP=20.5;
NUBUS_ANGLE_SECTION_LACK_OF_WIDTH=2.57;
NUBUS_ANGLE_SECTION_WIDTH_REDUCTION=NUBUS_EXTRA_WIDTH+NUBUS_ANGLE_SECTION_LACK_OF_WIDTH;
NUBUS_HEIGHT_NARROW_BOTTOM_TO_TOP=94.6;
NUBUS_FULL_HEIGHT=(NUBUS_BETWEEN_NOTCHES+NUBUS_HIGH_NOTCH_TO_TOP);
NUBUS_NARROW_BOTTOM_HEIGHT=NUBUS_FULL_HEIGHT-NUBUS_HEIGHT_NARROW_BOTTOM_TO_TOP;
NUBUS_EXTRA_NARROW_BOTTOM=1.5;
NUBUS_OVERHANG_MIN_HEIGHT=8.4;
NUBUS_OVERHANG_MAX_HEIGHT=12.18;
NUBUS_OVERHANG_RADIUS=3.2;
NUBUS_TOP_BIT_WIDTH=9.57-2.57;
FRONT_NOTCH_FROM_TOP=85.9;
FRONT_NOTCH_STRAIGHT_WIDTH=2;
FRONT_NOTCH_STRAIGHT_HEIGHT=6;
FRONT_NOTCH_ANGLE_HEIGHT=(NUBUS_BETWEEN_NOTCHES+NUBUS_HIGH_NOTCH_TO_TOP)-(FRONT_NOTCH_FROM_TOP+FRONT_NOTCH_STRAIGHT_HEIGHT);
FRONT_NOTCH_ANGLE_WIDTH=FRONT_NOTCH_ANGLE_HEIGHT*sin(23);
points=[[0,0],
[NUBUS_BASE_WIDTH-7.82-FRONT_NOTCH_STRAIGHT_WIDTH/2-FRONT_NOTCH_ANGLE_WIDTH,0],
[NUBUS_BASE_WIDTH-7.82-FRONT_NOTCH_STRAIGHT_WIDTH/2,FRONT_NOTCH_ANGLE_HEIGHT],
[NUBUS_BASE_WIDTH-7.82-FRONT_NOTCH_STRAIGHT_WIDTH/2,FRONT_NOTCH_ANGLE_HEIGHT+FRONT_NOTCH_STRAIGHT_HEIGHT],
[NUBUS_BASE_WIDTH-7.82+FRONT_NOTCH_STRAIGHT_WIDTH/2,FRONT_NOTCH_ANGLE_HEIGHT+FRONT_NOTCH_STRAIGHT_HEIGHT],
[NUBUS_BASE_WIDTH-7.82+FRONT_NOTCH_STRAIGHT_WIDTH/2,FRONT_NOTCH_ANGLE_HEIGHT],
[NUBUS_BASE_WIDTH-7.82+FRONT_NOTCH_STRAIGHT_WIDTH/2+FRONT_NOTCH_ANGLE_WIDTH,0],
[NUBUS_BASE_WIDTH-NUBUS_EXTRA_NARROW_BOTTOM,0],
[NUBUS_BASE_WIDTH-NUBUS_EXTRA_NARROW_BOTTOM,NUBUS_NARROW_BOTTOM_HEIGHT],
[NUBUS_FULL_WIDTH,NUBUS_NARROW_BOTTOM_HEIGHT],
[NUBUS_FULL_WIDTH,NUBUS_FULL_HEIGHT-NUBUS_EXTRA_FROM_TOP],
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION,(NUBUS_FULL_HEIGHT-NUBUS_EXTRA_FROM_TOP)+(NUBUS_ANGLE_SECTION_WIDTH_REDUCTION*2)],
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS],
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION-NUBUS_TOP_BIT_WIDTH,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS],
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION-NUBUS_TOP_BIT_WIDTH,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS-6], //6: measurement
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION-NUBUS_TOP_BIT_WIDTH-2,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS-6], //2&6: measurement
[NUBUS_FULL_WIDTH-NUBUS_ANGLE_SECTION_WIDTH_REDUCTION-NUBUS_TOP_BIT_WIDTH-2,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS-NUBUS_HIGH_NOTCH_TO_TOP+5], // 5 is the diustance between top notch and top screw hole
[-NUBUS_OVERHANG_WIDTH,NUBUS_FULL_HEIGHT+ORIGINAL_THICKNESS-NUBUS_HIGH_NOTCH_TO_TOP+5],
[-NUBUS_OVERHANG_WIDTH,NUBUS_FULL_HEIGHT-NUBUS_OVERHANG_MAX_HEIGHT+NUBUS_OVERHANG_RADIUS],
[0,NUBUS_FULL_HEIGHT-NUBUS_OVERHANG_MAX_HEIGHT]
];
module backplate() {
linear_extrude(height = ORIGINAL_THICKNESS, center = true) { polygon(points); };
}
// PCB, don't print
PCB_THICKNESS=1.6;
PCB_OFFSET=(NUBUS_FULL_WIDTH-2.93)-PCB_THICKNESS/2;
module pcb() {
color("green") translate([PCB_OFFSET,0,-50]) linear_extrude(height = 100, center = true) { polygon ([[-PCB_THICKNESS,-5.08],[0,-5.08],[0,91.52],[-PCB_THICKNESS,91.52]]); };
}
// NuBusFPGA
BOTTOM_HOLE_Y=8-1.08;
TOP_HOLE_Y=87.52;
FIRST_HOLE_X=-6.44;
SECOND_HOLE_X=-16.44;
module holders() {
difference() {
union() {
color("red") translate([0,0,-11]) linear_extrude(height = 22, center = true) { polygon([
[PCB_OFFSET-PCB_THICKNESS,BOTTOM_HOLE_Y-4],
[PCB_OFFSET-PCB_THICKNESS,BOTTOM_HOLE_Y+4],
[PCB_OFFSET-PCB_THICKNESS-2,BOTTOM_HOLE_Y+4],
[PCB_OFFSET-PCB_THICKNESS-2,BOTTOM_HOLE_Y-4],
]); };
color("red") translate([0,0,-11]) linear_extrude(height = 22, center = true) { polygon([
[PCB_OFFSET-PCB_THICKNESS,TOP_HOLE_Y-4],
[PCB_OFFSET-PCB_THICKNESS,TOP_HOLE_Y+4],
[PCB_OFFSET-PCB_THICKNESS-2,TOP_HOLE_Y+4],
[PCB_OFFSET-PCB_THICKNESS-2,TOP_HOLE_Y-4],
]); };
}
union() {
color("blue") translate([0,BOTTOM_HOLE_Y,FIRST_HOLE_X]) rotate([0,90,0]) cylinder(r1=1.6,r2=1.6,h=20);
color("blue") translate([0,BOTTOM_HOLE_Y,SECOND_HOLE_X]) rotate([0,90,0]) cylinder(r1=1.6,r2=1.6,h=20);
color("blue") translate([0,TOP_HOLE_Y,FIRST_HOLE_X]) rotate([0,90,0]) cylinder(r1=1.6,r2=1.6,h=20);
color("blue") translate([0,TOP_HOLE_Y,SECOND_HOLE_X]) rotate([0,90,0]) cylinder(r1=1.6,r2=1.6,h=20);
}
}
}
//cube ([16.5+4, 12, 9.5+4 /* 14.8 max */], center = true);
USB_HOLDER_HEIGHT=5;
USB_HOLDER_WIDTH=10;
USB_HOLDER_DEPTH=5;
module usb_pos() {
translate([-1-USB_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(74.67+(83.47-74.67)/2),-USB_HOLDER_DEPTH/2]) cube([2+USB_HOLDER_HEIGHT,2+USB_HOLDER_WIDTH,USB_HOLDER_DEPTH], center = true);
}
module usb_neg() {
translate([-0.499-USB_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(74.67+(83.47-74.67)/2),-USB_HOLDER_DEPTH/2]) cube([1.001+USB_HOLDER_HEIGHT,USB_HOLDER_WIDTH,USB_HOLDER_DEPTH*4], center = true);
}
VGA_HOLDER_HEIGHT=14.8;
VGA_HOLDER_WIDTH=31.8;
VGA_HOLDER_DEPTH=2;
module vga_pos() {
translate([-VGA_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(18.21+(49.05-18.21)/2),-VGA_HOLDER_DEPTH/2+VGA_HOLDER_DEPTH]) cube ([VGA_HOLDER_HEIGHT, 6+VGA_HOLDER_WIDTH, VGA_HOLDER_DEPTH], center = true);
}
module vga_neg() {
translate([-VGA_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(18.21+(49.05-18.21)/2),-VGA_HOLDER_DEPTH/2]) cube ([10, 18, 10+0.001], center = true);
translate([-VGA_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(18.21+(49.05-18.21)/2)-12.5,-VGA_HOLDER_DEPTH/2]) color("black") rotate([0,0,90]) cylinder (h = 10, r1 = 1.6, r2 = 1.6, center = true);
translate([-VGA_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(18.21+(49.05-18.21)/2)+12.5,-VGA_HOLDER_DEPTH/2]) color("black") rotate([0,0,90]) cylinder (h = 10, r1 = 1.6, r2 = 1.6, center = true);
}
HDMI_HOLDER_HEIGHT=8;
HDMI_HOLDER_WIDTH=18;
HDMI_HOLDER_DEPTH=2;
module hdmi_pos() {
translate([-1-HDMI_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(53.3+(71.3-53.3)/2),-HDMI_HOLDER_DEPTH/2]) cube ([2+HDMI_HOLDER_HEIGHT, 2+HDMI_HOLDER_WIDTH, HDMI_HOLDER_DEPTH], center = true);
}
module hdmi_neg() {
translate([-0.499-HDMI_HOLDER_HEIGHT/2+PCB_OFFSET-PCB_THICKNESS,100-(53.3+(71.3-53.3)/2),-HDMI_HOLDER_DEPTH/2]) cube ([1.001+HDMI_HOLDER_HEIGHT, HDMI_HOLDER_WIDTH, 5+0.001], center = true);
}
//pcb();
module complete() {
difference() {
union() {
backplate();
holders();
usb_pos();
vga_pos();
hdmi_pos();
}
union() {
usb_neg();
vga_neg();
hdmi_neg();
}
}
}
complete();

View File

@ -0,0 +1,9 @@
Hello,
About the DFA status:
(1) Molex 87831-1420 does not include a 'peg' and so does not need the hole for it if I understand the datasheet correctly; I think this is the issue raised? See <https://www.molex.com/pdm_docs/sd/878311420_sd.pdf> page 10 for the mention of a lack of 'peg', the 'peg' is pointed out in the picture on page 1.
(2) The measure in the schematics seem to be for the connector-side pins (the VGA plug), not for the solder-side pins. Datasgheet <https://cdn.amphenol-icc.com/media/wysiwyg/files/drawing/l77hde15sd1ch4fvga.pdf> has a 'recommended PCB layout' that shows the pins at 2.54mm interval.
(3) Yes, some files were left out, my bad, new upload

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L4,Bot*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,11 +1,11 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Profile,NP*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L1,Top*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Soldermask,Top*
G04 #@! TF.FilePolarity,Negative*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Paste,Top*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Legend,Top*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L2,Inr*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,12 +1,12 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.0.2+dfsg1-1~bpo9+1*
G04 #@! TF.CreationDate,2022-02-05T15:09:40+01:00*
G04 #@! TF.CreationDate,2022-02-11T12:22:13+01:00*
G04 #@! TF.ProjectId,nubus-to-ztex,6e756275-732d-4746-9f2d-7a7465782e6b,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L3,Inr*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Sat Feb 5 15:09:40 2022*
G04 Created by KiCad (PCBNEW 5.0.2+dfsg1-1~bpo9+1) date Fri Feb 11 12:22:13 2022*
%MOMM*%
%LPD*%
G01*

View File

@ -1,6 +1,6 @@
%!PS-Adobe-3.0
%%Creator: PCBNEW
%%CreationDate: Sat Feb 5 15:09:37 2022
%%CreationDate: Fri Feb 11 12:24:04 2022
%%Title: /home/dolbeau/MAC/NuBusFPGA/nubus-to-ztex/nubus-to-ztex-NPTH-drl_map.ps
%%Pages: 1
%%PageOrder: Ascend

View File

@ -1,5 +1,5 @@
M48
;DRILL file {KiCad 5.0.2+dfsg1-1~bpo9+1} date Sat Feb 5 15:09:36 2022
;DRILL file {KiCad 5.0.2+dfsg1-1~bpo9+1} date Fri Feb 11 12:24:04 2022
;FORMAT={-:-/ absolute / inch / decimal}
FMAT,2
INCH,TZ

View File

@ -1,6 +1,6 @@
%!PS-Adobe-3.0
%%Creator: PCBNEW
%%CreationDate: Sat Feb 5 15:09:37 2022
%%CreationDate: Fri Feb 11 12:24:04 2022
%%Title: /home/dolbeau/MAC/NuBusFPGA/nubus-to-ztex/nubus-to-ztex-PTH-drl_map.ps
%%Pages: 1
%%PageOrder: Ascend
@ -1397,104 +1397,6 @@ newpath
90545.1 46713.9 lineto
poly0
newpath
25983.9 54058.1 moveto
26171.5 54245.7 lineto
25983.9 54433.2 lineto
25796.4 54245.7 lineto
25983.9 54058.1 lineto
poly0
newpath
25983.9 53224.5 moveto
26171.5 53412.1 lineto
25983.9 53599.7 lineto
25796.4 53412.1 lineto
25983.9 53224.5 lineto
poly0
newpath
25983.9 52390.9 moveto
26171.5 52578.5 lineto
25983.9 52766.1 lineto
25796.4 52578.5 lineto
25983.9 52390.9 lineto
poly0
newpath
25983.9 51557.3 moveto
26171.5 51744.9 lineto
25983.9 51932.5 lineto
25796.4 51744.9 lineto
25983.9 51557.3 lineto
poly0
newpath
25983.9 50723.7 moveto
26171.5 50911.3 lineto
25983.9 51098.9 lineto
25796.4 50911.3 lineto
25983.9 50723.7 lineto
poly0
newpath
25983.9 49890.2 moveto
26171.5 50077.7 lineto
25983.9 50265.3 lineto
25796.4 50077.7 lineto
25983.9 49890.2 lineto
poly0
newpath
25983.9 49056.6 moveto
26171.5 49244.1 lineto
25983.9 49431.7 lineto
25796.4 49244.1 lineto
25983.9 49056.6 lineto
poly0
newpath
26817.5 54058.1 moveto
27005.1 54245.7 lineto
26817.5 54433.2 lineto
26630 54245.7 lineto
26817.5 54058.1 lineto
poly0
newpath
26817.5 53224.5 moveto
27005.1 53412.1 lineto
26817.5 53599.7 lineto
26630 53412.1 lineto
26817.5 53224.5 lineto
poly0
newpath
26817.5 52390.9 moveto
27005.1 52578.5 lineto
26817.5 52766.1 lineto
26630 52578.5 lineto
26817.5 52390.9 lineto
poly0
newpath
26817.5 51557.3 moveto
27005.1 51744.9 lineto
26817.5 51932.5 lineto
26630 51744.9 lineto
26817.5 51557.3 lineto
poly0
newpath
26817.5 50723.7 moveto
27005.1 50911.3 lineto
26817.5 51098.9 lineto
26630 50911.3 lineto
26817.5 50723.7 lineto
poly0
newpath
26817.5 49890.2 moveto
27005.1 50077.7 lineto
26817.5 50265.3 lineto
26630 50077.7 lineto
26817.5 49890.2 lineto
poly0
newpath
26817.5 49056.6 moveto
27005.1 49244.1 lineto
26817.5 49431.7 lineto
26630 49244.1 lineto
26817.5 49056.6 lineto
poly0
newpath
68343.1 69187.9 moveto
68530.7 69375.5 lineto
68343.1 69563 lineto
@ -1593,6 +1495,104 @@ newpath
73344.7 68354.3 lineto
poly0
newpath
25983.9 54058.1 moveto
26171.5 54245.7 lineto
25983.9 54433.2 lineto
25796.4 54245.7 lineto
25983.9 54058.1 lineto
poly0
newpath
25983.9 53224.5 moveto
26171.5 53412.1 lineto
25983.9 53599.7 lineto
25796.4 53412.1 lineto
25983.9 53224.5 lineto
poly0
newpath
25983.9 52390.9 moveto
26171.5 52578.5 lineto
25983.9 52766.1 lineto
25796.4 52578.5 lineto
25983.9 52390.9 lineto
poly0
newpath
25983.9 51557.3 moveto
26171.5 51744.9 lineto
25983.9 51932.5 lineto
25796.4 51744.9 lineto
25983.9 51557.3 lineto
poly0
newpath
25983.9 50723.7 moveto
26171.5 50911.3 lineto
25983.9 51098.9 lineto
25796.4 50911.3 lineto
25983.9 50723.7 lineto
poly0
newpath
25983.9 49890.2 moveto
26171.5 50077.7 lineto
25983.9 50265.3 lineto
25796.4 50077.7 lineto
25983.9 49890.2 lineto
poly0
newpath
25983.9 49056.6 moveto
26171.5 49244.1 lineto
25983.9 49431.7 lineto
25796.4 49244.1 lineto
25983.9 49056.6 lineto
poly0
newpath
26817.5 54058.1 moveto
27005.1 54245.7 lineto
26817.5 54433.2 lineto
26630 54245.7 lineto
26817.5 54058.1 lineto
poly0
newpath
26817.5 53224.5 moveto
27005.1 53412.1 lineto
26817.5 53599.7 lineto
26630 53412.1 lineto
26817.5 53224.5 lineto
poly0
newpath
26817.5 52390.9 moveto
27005.1 52578.5 lineto
26817.5 52766.1 lineto
26630 52578.5 lineto
26817.5 52390.9 lineto
poly0
newpath
26817.5 51557.3 moveto
27005.1 51744.9 lineto
26817.5 51932.5 lineto
26630 51744.9 lineto
26817.5 51557.3 lineto
poly0
newpath
26817.5 50723.7 moveto
27005.1 50911.3 lineto
26817.5 51098.9 lineto
26630 50911.3 lineto
26817.5 50723.7 lineto
poly0
newpath
26817.5 49890.2 moveto
27005.1 50077.7 lineto
26817.5 50265.3 lineto
26630 50077.7 lineto
26817.5 49890.2 lineto
poly0
newpath
26817.5 49056.6 moveto
27005.1 49244.1 lineto
26817.5 49431.7 lineto
26630 49244.1 lineto
26817.5 49056.6 lineto
poly0
newpath
28551.4 41483.3 moveto
28968.2 41066.5 lineto
stroke

View File

@ -1,5 +1,5 @@
M48
;DRILL file {KiCad 5.0.2+dfsg1-1~bpo9+1} date Sat Feb 5 15:09:36 2022
;DRILL file {KiCad 5.0.2+dfsg1-1~bpo9+1} date Fri Feb 11 12:24:04 2022
;FORMAT={-:-/ absolute / inch / decimal}
FMAT,2
INCH,TZ
@ -175,20 +175,6 @@ T4
X10.5983Y-3.0146
X10.5983Y-3.2114
T5
X4.5118Y-2.5118
X4.5118Y-2.5906
X4.5118Y-2.6693
X4.5118Y-2.748
X4.5118Y-2.8268
X4.5118Y-2.9055
X4.5118Y-2.9843
X4.5906Y-2.5118
X4.5906Y-2.5906
X4.5906Y-2.6693
X4.5906Y-2.748
X4.5906Y-2.8268
X4.5906Y-2.9055
X4.5906Y-2.9843
X8.513Y-1.0827
X8.513Y-1.1614
X8.5917Y-1.0827
@ -203,6 +189,20 @@ X8.9067Y-1.0827
X8.9067Y-1.1614
X8.9854Y-1.0827
X8.9854Y-1.1614
X4.5118Y-2.5118
X4.5118Y-2.5906
X4.5118Y-2.6693
X4.5118Y-2.748
X4.5118Y-2.8268
X4.5118Y-2.9055
X4.5118Y-2.9843
X4.5906Y-2.5118
X4.5906Y-2.5906
X4.5906Y-2.6693
X4.5906Y-2.748
X4.5906Y-2.8268
X4.5906Y-2.9055
X4.5906Y-2.9843
T6
X4.774Y-3.737
X4.774Y-3.837

View File

@ -1,4 +1,4 @@
### Module positions - created on Sat Feb 5 15:09:58 2022 ###
### Module positions - created on Fri Feb 11 12:23:56 2022 ###
### Printed by Pcbnew version kicad 5.0.2+dfsg1-1~bpo9+1
## Unit = mm, Angle = deg.
## Side : bottom

View File

@ -1,5 +1,5 @@
Drill report for /home/dolbeau/MAC/NuBusFPGA/nubus-to-ztex/nubus-to-ztex.kicad_pcb
Created on Sat Feb 5 15:09:39 2022
Created on Fri Feb 11 12:24:06 2022
Copper Layer Stackup:
=============================================================

View File

@ -1,4 +1,4 @@
### Module positions - created on Sat Feb 5 15:09:58 2022 ###
### Module positions - created on Fri Feb 11 12:23:56 2022 ###
### Printed by Pcbnew version kicad 5.0.2+dfsg1-1~bpo9+1
## Unit = mm, Angle = deg.
## Side : top

View File

@ -15,9 +15,13 @@
(1 In1.Cu signal)
(2 In2.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
@ -27,6 +31,7 @@
(45 Margin user)
(46 B.CrtYd user)
(47 F.CrtYd user)
(48 B.Fab user)
(49 F.Fab user)
)
@ -59,7 +64,7 @@
(aux_axis_origin 0 0)
(visible_elements FFFFFF7F)
(pcbplotparams
(layerselection 0x010a8_ffffffff)
(layerselection 0x010fc_ffffffff)
(usegerberextensions false)
(usegerberattributes false)
(usegerberadvancedattributes false)
@ -21104,7 +21109,7 @@
(segment (start 185.3125 71.8875) (end 184.7 72.5) (width 0.1524) (layer F.Cu) (net 230))
(segment (start 156.4375 22) (end 158.7125 22) (width 0.1524) (layer F.Cu) (net 231))
(zone (net 1) (net_name GND) (layer In1.Cu) (tstamp 620A815F) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer In1.Cu) (tstamp 620AA96B) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -22116,7 +22121,7 @@
)
)
)
(zone (net 3) (net_name +3V3) (layer In2.Cu) (tstamp 620A815C) (hatch edge 0.508)
(zone (net 3) (net_name +3V3) (layer In2.Cu) (tstamp 620AA968) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -22756,7 +22761,7 @@
)
)
)
(zone (net 1) (net_name GND) (layer F.Cu) (tstamp 620A8159) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer F.Cu) (tstamp 620AA965) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -24812,7 +24817,7 @@
)
)
)
(zone (net 1) (net_name GND) (layer B.Cu) (tstamp 620A8156) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer B.Cu) (tstamp 620AA962) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))

View File

@ -15,9 +15,13 @@
(1 In1.Cu signal)
(2 In2.Cu signal)
(31 B.Cu signal)
(32 B.Adhes user)
(33 F.Adhes user)
(34 B.Paste user)
(35 F.Paste user)
(36 B.SilkS user)
(37 F.SilkS user)
(38 B.Mask user)
(39 F.Mask user)
(40 Dwgs.User user)
(41 Cmts.User user)
@ -27,6 +31,7 @@
(45 Margin user)
(46 B.CrtYd user)
(47 F.CrtYd user)
(48 B.Fab user)
(49 F.Fab user)
)
@ -59,7 +64,7 @@
(aux_axis_origin 0 0)
(visible_elements FFFFFF7F)
(pcbplotparams
(layerselection 0x010a8_ffffffff)
(layerselection 0x010fc_ffffffff)
(usegerberextensions false)
(usegerberattributes false)
(usegerberadvancedattributes false)
@ -21104,7 +21109,7 @@
(segment (start 185.3125 71.8875) (end 184.7 72.5) (width 0.1524) (layer F.Cu) (net 230))
(segment (start 156.4375 22) (end 158.7125 22) (width 0.1524) (layer F.Cu) (net 231))
(zone (net 1) (net_name GND) (layer In1.Cu) (tstamp 620A6580) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer In1.Cu) (tstamp 620AA96B) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -22116,7 +22121,7 @@
)
)
)
(zone (net 3) (net_name +3V3) (layer In2.Cu) (tstamp 620A657D) (hatch edge 0.508)
(zone (net 3) (net_name +3V3) (layer In2.Cu) (tstamp 620AA968) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -22756,7 +22761,7 @@
)
)
)
(zone (net 1) (net_name GND) (layer F.Cu) (tstamp 61FD3B36) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer F.Cu) (tstamp 620AA965) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
@ -24812,7 +24817,7 @@
)
)
)
(zone (net 1) (net_name GND) (layer B.Cu) (tstamp 61FD3B37) (hatch edge 0.508)
(zone (net 1) (net_name GND) (layer B.Cu) (tstamp 620AA962) (hatch edge 0.508)
(connect_pads (clearance 0.508))
(min_thickness 0.254)
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))

View File

@ -1,4 +1,4 @@
## Footprint report - date Sat Feb 5 15:10:10 2022
## Footprint report - date Fri Feb 11 12:24:13 2022
## Created by Pcbnew version kicad 5.0.2+dfsg1-1~bpo9+1
## Unit = mm, Angle = deg.

View File

@ -2,7 +2,7 @@
<export version="D">
<design>
<source>/home/dolbeau/MAC/NuBusFPGA/nubus-to-ztex/nubus-to-ztex.sch</source>
<date>Sat Feb 5 15:10:52 2022</date>
<date>Fri Feb 11 12:24:26 2022</date>
<tool>Eeschema 5.0.2+dfsg1-1~bpo9+1</tool>
<sheet number="1" name="/" tstamps="/">
<title_block>

Binary file not shown.

View File

@ -1,8 +1,6 @@
#!/bin/bash
GERBER_FILES="nubus-to-ztex-B.Cu.gbr nubus-to-ztex-Edge.Cuts.gbr nubus-to-ztex-F.Cu.gbr nubus-to-ztex-F.Mask.gbr nubus-to-ztex-F.Paste.gbr nubus-to-ztex-F.SilkS.gbr nubus-to-ztex-In1.Cu.gbr nubus-to-ztex-In2.Cu.gbr"
# nubus-to-ztex-B.Mask.gbr nubus-to-ztex-B.Paste.gbr nubus-to-ztex-B.SilkS.gbr
GERBER_FILES="nubus-to-ztex-B.Cu.gbr nubus-to-ztex-B.Mask.gbr nubus-to-ztex-B.Paste.gbr nubus-to-ztex-B.SilkS.gbr nubus-to-ztex-Edge.Cuts.gbr nubus-to-ztex-F.Cu.gbr nubus-to-ztex-F.Mask.gbr nubus-to-ztex-F.Paste.gbr nubus-to-ztex-F.SilkS.gbr nubus-to-ztex-In1.Cu.gbr nubus-to-ztex-In2.Cu.gbr"
POS_FILES="nubus-to-ztex-top.pos"
# nubus-to-ztex-bottom.pos

Binary file not shown.