mirror of
https://github.com/rdolbeau/VintageBusFPGA_Common.git
synced 2026-03-09 20:18:17 +00:00
Merge branch 'main' of github.com:rdolbeau/VintageBusFPGA_Common into main
This commit is contained in:
41
RomPatcher/IIsiExtraMemory/Makefile
Normal file
41
RomPatcher/IIsiExtraMemory/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
RETRO68=/home/dolbeau/Retro68/build/toolchain
|
||||
AS=${RETRO68}/bin/m68k-apple-macos-as
|
||||
CC=${RETRO68}/bin/m68k-apple-macos-gcc
|
||||
LD=${RETRO68}/bin/m68k-apple-macos-ld
|
||||
STRIP=${RETRO68}/bin/m68k-apple-macos-strip
|
||||
OBJCOPY=${RETRO68}/bin/m68k-apple-macos-objcopy
|
||||
NM=${RETRO68}/bin/m68k-apple-macos-nm
|
||||
|
||||
HOSTCC=gcc
|
||||
HOSTCFLAGS=-O2
|
||||
|
||||
ARCHFLAGS=-march=68020 -mcpu=68020
|
||||
CFLAGS=-O2 -mpcrel
|
||||
|
||||
GENLINK=../patcher/genlink
|
||||
PATCHER=../patcher/patcher
|
||||
|
||||
all: IIsi.ROM
|
||||
|
||||
show: rompatch.elf
|
||||
$(NM) $< | sort
|
||||
|
||||
IIsi.ROM: ../IIsiRemoveChecksumCheck/IIsi.ROM rompatch.raw input.txt
|
||||
/bin/cp ../IIsiRemoveChecksumCheck/IIsi.ROM IIsi.ROM
|
||||
${PATCHER} -i rompatch.raw -p IIsi.ROM -d input.txt
|
||||
|
||||
linker.ld: input.txt rompatch.s
|
||||
${GENLINK} -d $< >| $@
|
||||
echo $(shell for X in `grep .section rompatch.s | awk '{ print $$2 }' `; do grep -q $$X linker.ld || echo " $$X has no entry in linker.ld" && /bin/false; done)
|
||||
|
||||
rompatch.o: rompatch.s
|
||||
${AS} ${ARCHFLAGS} $< -o $@ -a > rompatch.l
|
||||
|
||||
rompatch.elf: linker.ld rompatch.o ${CSRC:.c=.o} # linker script must be first
|
||||
${LD} -o $@ -T $^
|
||||
|
||||
rompatch.raw: rompatch.elf
|
||||
${OBJCOPY} $^ $@ --input-target=elf32-m68k --output-target=binary
|
||||
|
||||
clean:
|
||||
rm -f res.inc ${CSRC_ASM} *.o rompatch.srec rompatch.raw rompatch.dir rompatch.l linker.ld rompatch.elf
|
||||
3
RomPatcher/IIsiExtraMemory/input.txt
Normal file
3
RomPatcher/IIsiExtraMemory/input.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
0x00396e, 32, raminfo
|
||||
0x003cc4, 316, gary
|
||||
0x0419e8, 20, findinfopatch
|
||||
51
RomPatcher/IIsiExtraMemory/rompatch.s
Normal file
51
RomPatcher/IIsiExtraMemory/rompatch.s
Normal file
@@ -0,0 +1,51 @@
|
||||
MAPBASE=0x20000000
|
||||
MAPSIZE=0x0f000000
|
||||
MAPEND=MAPBASE+MAPSIZE
|
||||
|
||||
/* ************************************************************************ */
|
||||
/* updated table */
|
||||
.section .text.raminfo
|
||||
.long MAPBASE
|
||||
.long MAPEND
|
||||
.long 0x04000000
|
||||
.long 0x08000000
|
||||
.long 0x00000000
|
||||
.long 0x04000000
|
||||
.long 0xFFFFFFFF
|
||||
.long 0xFFFFFFFF
|
||||
|
||||
/* ************************************************************************ */
|
||||
.section .text.gary
|
||||
fixchunk: /* 316 bytes available */
|
||||
/* recreate the table but with one more chunk, as the original code assumes two chunks and turns them into three */
|
||||
|
||||
move.l %D4,(%A1)+
|
||||
move.l %D5,(%A1)+
|
||||
move.l %D2,(%A1)+
|
||||
move.l %D3,(%A1)+
|
||||
|
||||
add.l %D5,%D4
|
||||
move.l %D4,(%A1)+
|
||||
move.l %D1,(%A1)+
|
||||
|
||||
/* here comes the bonus */
|
||||
move.l #MAPBASE,(%A1)+
|
||||
move.l #MAPSIZE,(%A1)+
|
||||
/* here ends the bonus */
|
||||
|
||||
moveq #-1,%D4
|
||||
move.l %D4,(%A1)+
|
||||
move.l %D4,(%A1)+
|
||||
|
||||
jmp (%pc,returnfindinfopatch)
|
||||
|
||||
/* ************************************************************************ */
|
||||
.section .text.findinfopatch
|
||||
findinfopatch: /* 20 bytes available */
|
||||
jmp (%pc,fixchunk)
|
||||
|
||||
.section .text.returnfindinfopatch
|
||||
returnfindinfopatch:
|
||||
/* */
|
||||
|
||||
.end
|
||||
41
RomPatcher/IIsiRemoveChecksumCheck/Makefile
Normal file
41
RomPatcher/IIsiRemoveChecksumCheck/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
RETRO68=/home/dolbeau/Retro68/build/toolchain
|
||||
AS=${RETRO68}/bin/m68k-apple-macos-as
|
||||
CC=${RETRO68}/bin/m68k-apple-macos-gcc
|
||||
LD=${RETRO68}/bin/m68k-apple-macos-ld
|
||||
STRIP=${RETRO68}/bin/m68k-apple-macos-strip
|
||||
OBJCOPY=${RETRO68}/bin/m68k-apple-macos-objcopy
|
||||
NM=${RETRO68}/bin/m68k-apple-macos-nm
|
||||
|
||||
HOSTCC=gcc
|
||||
HOSTCFLAGS=-O2
|
||||
|
||||
ARCHFLAGS=-march=68020 -mcpu=68020
|
||||
CFLAGS=-O2 -mpcrel
|
||||
|
||||
GENLINK=../patcher/genlink
|
||||
PATCHER=../patcher/patcher
|
||||
|
||||
all: IIsi.ROM
|
||||
|
||||
show: rompatch.elf
|
||||
$(NM) $< | sort
|
||||
|
||||
IIsi.ROM: ../IIsi.ROM rompatch.raw input.txt
|
||||
/bin/cp ../IIsi.ROM IIsi.ROM
|
||||
${PATCHER} -i rompatch.raw -p IIsi.ROM -d input.txt
|
||||
|
||||
linker.ld: input.txt rompatch.s
|
||||
${GENLINK} -d $< >| $@
|
||||
echo $(shell for X in `grep .section rompatch.s | awk '{ print $$2 }' `; do grep -q $$X linker.ld || echo " $$X has no entry in linker.ld" && /bin/false; done)
|
||||
|
||||
rompatch.o: rompatch.s
|
||||
${AS} ${ARCHFLAGS} $< -o $@ -a > rompatch.l
|
||||
|
||||
rompatch.elf: linker.ld rompatch.o ${CSRC:.c=.o} # linker script must be first
|
||||
${LD} -o $@ -T $^
|
||||
|
||||
rompatch.raw: rompatch.elf
|
||||
${OBJCOPY} $^ $@ --input-target=elf32-m68k --output-target=binary
|
||||
|
||||
clean:
|
||||
rm -f res.inc ${CSRC_ASM} *.o rompatch.srec rompatch.raw rompatch.dir rompatch.l linker.ld rompatch.elf
|
||||
1
RomPatcher/IIsiRemoveChecksumCheck/input.txt
Normal file
1
RomPatcher/IIsiRemoveChecksumCheck/input.txt
Normal file
@@ -0,0 +1 @@
|
||||
0x0464e2, 10, removecheksumcheck
|
||||
12
RomPatcher/IIsiRemoveChecksumCheck/rompatch.s
Normal file
12
RomPatcher/IIsiRemoveChecksumCheck/rompatch.s
Normal file
@@ -0,0 +1,12 @@
|
||||
.section .text.removecheksumcheck
|
||||
|
||||
nops:
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.section .text.returnremovecheksumcheck
|
||||
|
||||
.end
|
||||
12
RomPatcher/README.md
Normal file
12
RomPatcher/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# RomPatcher
|
||||
|
||||
This is a small set of tools to help with ROM patching. A single input file made up of lines \<address\>,\<size\>,\<name\> describes which area need patching. <size> can be 0 for e.g. calls to exsiting functions.
|
||||
|
||||
One tool generates linked file to place things where they need to be in the compiled binary.
|
||||
One tool copies the relevant area from the generated binary to the file that needs to be patched.
|
||||
|
||||
An assembly source file can then be used to write the patch, placing code in the appropriate sections as per the linker file. They are then patched into the final file.
|
||||
|
||||
Example:
|
||||
* IIsiRemoveChecksumCheck: replace a few instructions in a Macintosh IIsi ROM file to disable the checksum test (thus allowing further patching)
|
||||
* IIsiExtraMemoryi: patch the memory chunk table and some code to enable an extra area of memory in a IIsi ROM, usable with e.g. the IIsiFPGA
|
||||
50
RomPatcher/patcher/Makefile
Normal file
50
RomPatcher/patcher/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
PATCHERSRC=patcher.c
|
||||
PATCHEROBJ=$(PATCHERSRC:.cpp=.o)
|
||||
PATCHERDEP=$(PATCHERSRC:.cpp=.d)
|
||||
GENLINKSRC=genlink.c
|
||||
GENLINKOBJ=$(GENLINKSRC:.cpp=.o)
|
||||
GENLINKDEP=$(GENLINKSRC:.cpp=.d)
|
||||
OOBJ=parser_par.o parser_lex.o
|
||||
LEX=flex
|
||||
YACC=bison -d #--report-file=bison.log --report=all
|
||||
CC=gcc
|
||||
CFLAGS=-O2
|
||||
|
||||
all: patcher genlink
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $< -c -o $@
|
||||
|
||||
patcher: $(PATCHEROBJ) $(OOBJ)
|
||||
$(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
genlink: $(GENLINKOBJ) $(OOBJ)
|
||||
$(CC) $(CFLAGS) $^ -o $@
|
||||
|
||||
parser_par.h: parser_par.o
|
||||
|
||||
parser_par.o: parser_par.y
|
||||
$(YACC) -o $(<:%.y=%.c) $<
|
||||
$(CC) $(CFLAGS) $(<:%.y=%.c) -c -o $@
|
||||
|
||||
parser_lex.o: parser_lex.l parser_par.h
|
||||
$(LEX) -o $(<:%.l=%.c) $<
|
||||
$(CC) $(CFLAGS) $(<:%.l=%.c) -c -o $@
|
||||
|
||||
%.d: %.cpp
|
||||
$(CXX) -MM $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(PATCHEROBJ) patcher
|
||||
|
||||
veryclean:
|
||||
rm -f $(PATCHEROBJ) patcher *~ parser_lex.c parser_par.c *.d
|
||||
|
||||
ultraclean:
|
||||
rm -f $(PATCHEROBJ) patcher *~ parser_lex.c parser_par.c *.d *.scala
|
||||
|
||||
|
||||
## avoid builtin rule for .o
|
||||
.SUFFIXES:
|
||||
SUFFIXES :=
|
||||
%.o:
|
||||
76
RomPatcher/patcher/genlink.c
Normal file
76
RomPatcher/patcher/genlink.c
Normal file
@@ -0,0 +1,76 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "parser.h"
|
||||
#include "parser_par.h"
|
||||
|
||||
extern FILE *yyin, *yyout;
|
||||
extern int yydebug;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char* descfile = NULL;
|
||||
FILE *myfile;
|
||||
int c;
|
||||
azone zones[32];
|
||||
int nz = 0, i;
|
||||
|
||||
while ((c = getopt(argc, argv, "d:")) != -1) {
|
||||
switch(c) {
|
||||
default:
|
||||
fprintf(stderr, "oups : %c\n", c);
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
descfile = strndup(optarg, 512);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (descfile == NULL) {
|
||||
fprintf(stderr, "no desc\n");
|
||||
exit(-4);
|
||||
}
|
||||
|
||||
{
|
||||
myfile = fopen(descfile, "r");
|
||||
if (!myfile) {
|
||||
fprintf(stderr, "no desc file\n");
|
||||
exit(-5);
|
||||
}
|
||||
yyin = myfile;
|
||||
yyparse(zones, &nz);
|
||||
|
||||
fclose(myfile);
|
||||
|
||||
fprintf(stderr, "Found %d entries\n", nz);
|
||||
}
|
||||
|
||||
fprintf(stdout,
|
||||
"OUTPUT_FORMAT(\"elf32-m68k\");\n"
|
||||
"SECTIONS {\n"
|
||||
" .text : {\n");
|
||||
|
||||
for (i = 0 ; i < nz; i++) {
|
||||
fprintf(stdout, " . = 0x%06x;\n", zones[i].address);
|
||||
fprintf(stdout, " *(.text.%s)\n", zones[i].name);
|
||||
if (zones[i].size > 0) {
|
||||
fprintf(stdout, " . = 0x%06x;\n", zones[i].address + zones[i].size);
|
||||
fprintf(stdout, " *(.text.return%s)\n", zones[i].name);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, " }\n}\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
RomPatcher/patcher/parser.h
Normal file
10
RomPatcher/patcher/parser.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef __PATCHER_H__
|
||||
#define __PATCHER_H__
|
||||
|
||||
typedef struct {
|
||||
unsigned long address;
|
||||
unsigned long size;
|
||||
char* name;
|
||||
} azone;
|
||||
|
||||
#endif // __PATCHER_H__
|
||||
34
RomPatcher/patcher/parser_lex.l
Normal file
34
RomPatcher/patcher/parser_lex.l
Normal file
@@ -0,0 +1,34 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2023 Romain Dolbeau <romain@dolbeau.org>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "parser.h"
|
||||
#include "parser_par.h"
|
||||
%}
|
||||
|
||||
DIGIT [0-9]
|
||||
HEXPREFIX "0x"
|
||||
HEXDIGIT [0-9a-fA-F]
|
||||
SPACE [ \t]
|
||||
FCHARNAME [[:alpha:]]
|
||||
CHARNAME [[:alnum:]_]
|
||||
|
||||
%%
|
||||
|
||||
{HEXPREFIX}{HEXDIGIT}{HEXDIGIT}* { yylval.num = strtol(yytext, NULL, 16); return NUM; }
|
||||
|
||||
{DIGIT}{DIGIT}* { yylval.num = strtol(yytext, NULL, 10); return NUM; }
|
||||
|
||||
{FCHARNAME}{CHARNAME}* { yylval.string = strdup(yytext); return NAME; }
|
||||
|
||||
, { return yytext[0]; }
|
||||
|
||||
\n { return yytext[0]; }
|
||||
|
||||
{SPACE}+ { }
|
||||
|
||||
%%
|
||||
46
RomPatcher/patcher/parser_par.y
Normal file
46
RomPatcher/patcher/parser_par.y
Normal file
@@ -0,0 +1,46 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2023 Romain Dolbeau <romain@dolbeau.org>
|
||||
* MIT License
|
||||
* See the LICENSE file at the top level of this software distribution for details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define YYDEBUG 1
|
||||
#include "parser.h"
|
||||
%}
|
||||
|
||||
%parse-param {azone *zones} {int *nz}
|
||||
|
||||
%union
|
||||
{
|
||||
unsigned long num;
|
||||
char* string;
|
||||
}
|
||||
|
||||
%token <num> NUM
|
||||
%token <num> NAME
|
||||
|
||||
%%
|
||||
input: /* empty */ { }
|
||||
| zone input { }
|
||||
;
|
||||
|
||||
zone:
|
||||
NUM ',' NUM ',' NAME { /* printf("0x%08lx %ld\n", $1, $3); */ zones[*nz].address = $1; zones[*nz].size = $3; zones[*nz].name = $5; (*nz)++; }
|
||||
| '\n'
|
||||
;
|
||||
%%
|
||||
|
||||
int
|
||||
yyerror(char *s)
|
||||
{
|
||||
fprintf(stderr, "error: %s\n", s);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
yywrap(void)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
146
RomPatcher/patcher/patcher.c
Normal file
146
RomPatcher/patcher/patcher.c
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "parser.h"
|
||||
#include "parser_par.h"
|
||||
|
||||
extern FILE *yyin, *yyout;
|
||||
extern int yydebug;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char* descfile = NULL;
|
||||
char* patchedfile = NULL;
|
||||
char* inputfile = NULL;
|
||||
FILE *myfile;
|
||||
int c;
|
||||
azone zones[32];
|
||||
int nz = 0, i;
|
||||
unsigned long j;
|
||||
char *input;
|
||||
size_t input_size;
|
||||
char *patched;
|
||||
size_t patched_size;
|
||||
|
||||
while ((c = getopt(argc, argv, "d:i:p:")) != -1) {
|
||||
switch(c) {
|
||||
default:
|
||||
fprintf(stderr, "oups : %c\n", c);
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
descfile = strndup(optarg, 512);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
inputfile = strndup(optarg, 512);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
patchedfile = strndup(optarg, 512);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (descfile == NULL) {
|
||||
fprintf(stderr, "no desc\n");
|
||||
exit(-4);
|
||||
}
|
||||
if (inputfile == NULL) {
|
||||
fprintf(stderr, "no input\n");
|
||||
exit(-2);
|
||||
}
|
||||
if (patchedfile == NULL) {
|
||||
fprintf(stderr, "nothing to patch\n");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
{
|
||||
myfile = fopen(descfile, "r");
|
||||
if (!myfile) {
|
||||
fprintf(stderr, "no desc file\n");
|
||||
exit(-5);
|
||||
}
|
||||
yyin = myfile;
|
||||
yyparse(zones, &nz);
|
||||
|
||||
fclose(myfile);
|
||||
|
||||
fprintf(stdout, "Found %d entries\n", nz);
|
||||
}
|
||||
|
||||
{
|
||||
int fd;
|
||||
fd = open(inputfile, O_RDONLY | O_EXCL);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "no input file\n");
|
||||
exit(-6);
|
||||
}
|
||||
struct stat statbuf;
|
||||
int err = fstat(fd, &statbuf);
|
||||
if (err < 0){
|
||||
fprintf(stderr, "no input file stat\n");
|
||||
close(fd);
|
||||
exit(-7);
|
||||
}
|
||||
input_size = statbuf.st_size;
|
||||
input = mmap(NULL, input_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (input == MAP_FAILED){
|
||||
fprintf(stderr, "no input file map (%p for %s %zd: %d / %s)\n", input, inputfile, input_size, errno, strerror(errno));
|
||||
close(fd);
|
||||
exit(-8);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
{
|
||||
int fd;
|
||||
fd = open(patchedfile, O_RDWR | O_EXCL);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "no patched file\n");
|
||||
exit(-6);
|
||||
}
|
||||
struct stat statbuf;
|
||||
int err = fstat(fd, &statbuf);
|
||||
if (err < 0){
|
||||
fprintf(stderr, "no patched file stat\n");
|
||||
close(fd);
|
||||
exit(-7);
|
||||
}
|
||||
|
||||
patched_size = statbuf.st_size;
|
||||
patched = mmap(NULL, patched_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (patched == MAP_FAILED){
|
||||
fprintf(stderr, "no patched file map\n");
|
||||
close(fd);
|
||||
exit(-8);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < nz; i++) {
|
||||
if (zones[i].size > 0) {
|
||||
fprintf(stdout, "Patching [%08p:%08p[ (%s)\n", (void*)zones[i].address, (void*)(zones[i].address + zones[i].size), zones[i].name);
|
||||
for (j = zones[i].address; j < zones[i].address + zones[i].size; j++) {
|
||||
patched[j] = input[j];
|
||||
}
|
||||
} else {
|
||||
fprintf(stdout, "Not patching [%08p[ (%s)\n", (void*)zones[i].address, zones[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
munmap(input, input_size);
|
||||
munmap(patched, patched_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
152
Ziscreen.py
Normal file
152
Ziscreen.py
Normal file
@@ -0,0 +1,152 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
from litex.soc.interconnect.csr import *
|
||||
|
||||
class Ziscreen(Module, AutoCSR):
|
||||
def __init__(self, platform, wb, width=1920, height=1080, depth=8, fifo=None):
|
||||
|
||||
default_address = (0x8f800000) // 4
|
||||
last_address = (0x8f800000 + (width-8) + width*1080) // 4
|
||||
address_increment = (width) // 4
|
||||
base_address = Signal(30, reset = default_address)
|
||||
cur_address = Signal(30)
|
||||
rowcnt = Signal(5)
|
||||
|
||||
print(f"TRACE: displaying @ 0x{default_address*4:08x}")
|
||||
|
||||
cur_nib_idx = Signal(3)
|
||||
cur_line_idx = Signal(3)
|
||||
|
||||
wrapped = Signal()
|
||||
|
||||
val = Signal(32)
|
||||
|
||||
cur_nib = Signal(4)
|
||||
self.comb += [
|
||||
Case((cur_nib_idx ^ 1), { ## nibble-swap for proper order
|
||||
x: cur_nib.eq(val[(4*x):(4*x+4)]) for x in range(0, 8)
|
||||
}),
|
||||
]
|
||||
cur_nib_decoded = Signal(8)
|
||||
self.submodules.fsm = fsm = FSM(reset_state="Reset")
|
||||
|
||||
|
||||
if (True):
|
||||
#saw_ongoing = Signal()
|
||||
#saw_readable= Signal()
|
||||
#self.sync += [
|
||||
# If(~fsm.ongoing("Idle"),
|
||||
# saw_ongoing.eq(1),
|
||||
# ),
|
||||
# If(fifo.readable,
|
||||
# saw_readable.eq(1),
|
||||
# ),
|
||||
#]
|
||||
|
||||
led0 = platform.request("user_led", 0)
|
||||
led1 = platform.request("user_led", 1)
|
||||
led2 = platform.request("user_led", 2)
|
||||
led3 = platform.request("user_led", 3)
|
||||
led4 = platform.request("user_led", 4)
|
||||
led5 = platform.request("user_led", 5)
|
||||
led6 = platform.request("user_led", 6)
|
||||
led7 = platform.request("user_led", 7)
|
||||
|
||||
self.comb += [
|
||||
led0.eq(~fsm.ongoing("Idle")),
|
||||
led1.eq(fifo.readable),
|
||||
led2.eq(0),
|
||||
led3.eq(0),
|
||||
|
||||
#led4.eq(saw_ongoing),
|
||||
#led5.eq(saw_readable),
|
||||
led4.eq(0),
|
||||
led5.eq(wb.ack),
|
||||
led6.eq(wb.stb),
|
||||
led7.eq(wb.cyc),
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
wb.we.eq(1),
|
||||
wb.sel.eq(0xF),
|
||||
wb.adr.eq(cur_address),
|
||||
]
|
||||
|
||||
fsm.act("Reset",
|
||||
NextState("Idle"),
|
||||
)
|
||||
fsm.act("Idle",
|
||||
If(base_address >= last_address,
|
||||
NextValue(base_address, default_address),
|
||||
NextValue(wrapped, 1 ^ wrapped),
|
||||
NextValue(rowcnt, 0),
|
||||
).Elif(rowcnt == 30,
|
||||
NextValue(rowcnt, 0),
|
||||
NextValue(base_address, base_address + 7*address_increment),
|
||||
).Elif(fifo.readable,
|
||||
NextValue(val, fifo.dout),
|
||||
NextValue(cur_line_idx, 0),
|
||||
NextValue(cur_nib_idx, 0),
|
||||
NextValue(cur_address, base_address),
|
||||
fifo.re.eq(1),
|
||||
NextState("StartWriteLow"),
|
||||
),
|
||||
)
|
||||
fsm.act("StartWriteLow",
|
||||
wb.cyc.eq(1),
|
||||
wb.stb.eq(1),
|
||||
wb.dat_w.eq(Cat(Replicate(wrapped ^ cur_nib_decoded[7], 8), Replicate(wrapped ^ cur_nib_decoded[6], 8), Replicate(wrapped ^ cur_nib_decoded[5], 8), Replicate(wrapped ^ cur_nib_decoded[4], 8))),
|
||||
If(wb.ack,
|
||||
NextValue(cur_address, cur_address + 1),
|
||||
NextState("StartWriteHigh"),
|
||||
),
|
||||
)
|
||||
fsm.act("StartWriteHigh",
|
||||
wb.cyc.eq(1),
|
||||
wb.stb.eq(1),
|
||||
wb.dat_w.eq(Cat(Replicate(wrapped ^ cur_nib_decoded[3], 8), Replicate(wrapped ^ cur_nib_decoded[2], 8), Replicate(wrapped ^ cur_nib_decoded[1], 8), Replicate(wrapped ^ cur_nib_decoded[0], 8))),
|
||||
If(wb.ack,
|
||||
If((cur_line_idx == 7) & (cur_nib_idx == 7),
|
||||
NextValue(base_address, base_address + 16 - (address_increment*7) ),
|
||||
NextValue(rowcnt, rowcnt + 1),
|
||||
NextState("Idle"),
|
||||
).Elif(cur_nib_idx == 7,
|
||||
NextValue(base_address, base_address + address_increment),
|
||||
NextValue(cur_address, base_address + address_increment),
|
||||
NextValue(cur_nib_idx, 0),
|
||||
NextValue(cur_line_idx, cur_line_idx + 1),
|
||||
NextState("StartWriteLow"),
|
||||
).Else(
|
||||
NextValue(cur_address, cur_address + 1),
|
||||
NextValue(cur_nib_idx, cur_nib_idx + 1),
|
||||
NextState("StartWriteLow"),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
Case((cur_line_idx), {
|
||||
0: cur_nib_decoded.eq(0),
|
||||
7: cur_nib_decoded.eq(0),
|
||||
1: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x18), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x18), 3:cur_nib_decoded.eq(0x38), 4:cur_nib_decoded.eq(0x20), 5:cur_nib_decoded.eq(0x3c), 6:cur_nib_decoded.eq(0x1c), 7:cur_nib_decoded.eq(0x3c), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x18), 10:cur_nib_decoded.eq(0x18), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x18), 13:cur_nib_decoded.eq(0x38), 14:cur_nib_decoded.eq(0x3c), 15:cur_nib_decoded.eq(0x3c),
|
||||
}),
|
||||
2: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x24), 1:cur_nib_decoded.eq(0x30), 2:cur_nib_decoded.eq(0x24), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x28), 5:cur_nib_decoded.eq(0x20), 6:cur_nib_decoded.eq(0x20), 7:cur_nib_decoded.eq(0x04), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x24), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x24), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
3: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x2c), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x04), 3:cur_nib_decoded.eq(0x18), 4:cur_nib_decoded.eq(0x28), 5:cur_nib_decoded.eq(0x38), 6:cur_nib_decoded.eq(0x38), 7:cur_nib_decoded.eq(0x08), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x24), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x20), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x38), 15:cur_nib_decoded.eq(0x38),
|
||||
}),
|
||||
4: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x34), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x18), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x3c), 5:cur_nib_decoded.eq(0x04), 6:cur_nib_decoded.eq(0x24), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x1c), 10:cur_nib_decoded.eq(0x3c), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x20), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
5: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x24), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x20), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x08), 5:cur_nib_decoded.eq(0x04), 6:cur_nib_decoded.eq(0x24), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x04), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x24), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
6: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x18), 1:cur_nib_decoded.eq(0x38), 2:cur_nib_decoded.eq(0x3c), 3:cur_nib_decoded.eq(0x38), 4:cur_nib_decoded.eq(0x08), 5:cur_nib_decoded.eq(0x38), 6:cur_nib_decoded.eq(0x18), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x38), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x18), 13:cur_nib_decoded.eq(0x38), 14:cur_nib_decoded.eq(0x3c), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
}
|
||||
),
|
||||
]
|
||||
|
||||
106
Zled.py
Normal file
106
Zled.py
Normal file
@@ -0,0 +1,106 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
from litex.soc.interconnect.csr import *
|
||||
|
||||
class Zled(Module, AutoCSR):
|
||||
def __init__(self, platform):
|
||||
|
||||
self.data0 = data0 = CSRStorage(32, description = "data 0")
|
||||
self.data1 = data1 = CSRStorage(32, description = "data 1")
|
||||
|
||||
ctr_hundredth = Signal(20)
|
||||
ctr_count = Signal(7)
|
||||
|
||||
leds = platform.request_all("user_led")
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="Reset")
|
||||
|
||||
self.sync += [
|
||||
If(ctr_hundredth != 0,
|
||||
ctr_hundredth.eq(ctr_hundredth - 1),
|
||||
).Else(
|
||||
ctr_hundredth.eq(1000000),
|
||||
If(ctr_count != 0,
|
||||
ctr_count.eq(ctr_count - 1),
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
display_idx = Signal(5, reset = 0x1F)
|
||||
self.comb += [
|
||||
Case(display_idx, {
|
||||
0x00: [ leds.eq(data0.storage[ 0: 8]), ],
|
||||
0x01: [ leds.eq(data0.storage[ 8:16]), ],
|
||||
0x02: [ leds.eq(data0.storage[16:24]), ],
|
||||
0x03: [ leds.eq(data0.storage[24:32]), ],
|
||||
0x04: [ leds.eq(data1.storage[ 0: 8]), ],
|
||||
0x05: [ leds.eq(data1.storage[ 8:16]), ],
|
||||
0x06: [ leds.eq(data1.storage[16:24]), ],
|
||||
0x07: [ leds.eq(data1.storage[24:32]), ],
|
||||
0x08: [ leds.eq(0x00), ],
|
||||
0x10: [ leds.eq(0x01), ],
|
||||
0x11: [ leds.eq(0x02), ],
|
||||
0x12: [ leds.eq(0x04), ],
|
||||
0x13: [ leds.eq(0x08), ],
|
||||
0x14: [ leds.eq(0x10), ],
|
||||
0x15: [ leds.eq(0x20), ],
|
||||
0x16: [ leds.eq(0x40), ],
|
||||
0x17: [ leds.eq(0x80), ],
|
||||
0x18: [ leds.eq(0xFF), ],
|
||||
"default": [ leds.eq(0x00), ],
|
||||
}),
|
||||
]
|
||||
|
||||
bytenum = Signal(3)
|
||||
flashes = Signal(4)
|
||||
|
||||
fsm.act("Reset",
|
||||
NextValue(ctr_count, 12),
|
||||
NextValue(display_idx, 0x10),
|
||||
NextState("March"),
|
||||
)
|
||||
###################
|
||||
# must arrive with ctr_count == 12, display_idx == 0x10
|
||||
fsm.act("March",
|
||||
If((ctr_hundredth == 0) & (ctr_count == 0),
|
||||
If(display_idx == 0x17, # finished
|
||||
NextValue(ctr_count, 100),
|
||||
NextValue(display_idx, 0x00),
|
||||
NextValue(bytenum, 0),
|
||||
NextState("Byte"),
|
||||
).Else(
|
||||
NextValue(display_idx, display_idx + 1),
|
||||
NextValue(ctr_count, 12),
|
||||
)
|
||||
),
|
||||
)
|
||||
###################
|
||||
fsm.act("Byte",
|
||||
If((ctr_hundredth == 0) & (ctr_count == 0),
|
||||
If(bytenum == 0x7,
|
||||
NextValue(ctr_count, 12),
|
||||
NextValue(display_idx, 0x10),
|
||||
NextState("March"),
|
||||
).Else(
|
||||
NextValue(bytenum, bytenum + 1),
|
||||
NextValue(ctr_count, 5),
|
||||
NextValue(display_idx, 0x08),
|
||||
NextValue(flashes, 5),
|
||||
NextState("Flash"),
|
||||
)
|
||||
),
|
||||
)
|
||||
###################
|
||||
fsm.act("Flash",
|
||||
If((ctr_hundredth == 0) & (ctr_count == 0),
|
||||
If(flashes == 0, # finished
|
||||
NextValue(ctr_count, 100),
|
||||
NextValue(display_idx, Cat(bytenum, Signal(len(display_idx) - len(bytenum), reset = 0))),
|
||||
NextState("Byte"),
|
||||
).Else(
|
||||
NextValue(display_idx, display_idx ^ 0x10),
|
||||
NextValue(flashes, flashes - 1),
|
||||
NextValue(ctr_count, 5),
|
||||
)
|
||||
),
|
||||
)
|
||||
162
Zscreen.py
Normal file
162
Zscreen.py
Normal file
@@ -0,0 +1,162 @@
|
||||
from migen import *
|
||||
from migen.genlib.fifo import *
|
||||
from litex.soc.interconnect.csr import *
|
||||
|
||||
class Zscreen(Module, AutoCSR):
|
||||
def __init__(self, platform, wb, width=1920, height=1080, depth=8):
|
||||
|
||||
self.trace_data = trace_data = CSRStorage(32, description = "trace_data")
|
||||
|
||||
self.submodules.fifo = fifo = SyncFIFOBuffered(width=32,depth=128)
|
||||
|
||||
self.comb += [
|
||||
fifo.din.eq(trace_data.storage),
|
||||
fifo.we.eq(trace_data.re),
|
||||
]
|
||||
|
||||
#curx = Signal(12, reset = (width-136))
|
||||
#cury = Signal(12, reset = (8))
|
||||
|
||||
default_address = (0x8f800000 + (width-138) + (width*24) ) // 4 # FIXME: for 8 MiB FB only IMPROVEME: assumes 32-bits WB
|
||||
last_address = (0x8f800000 + (width-138) + (width*1072)) // 4 # FIXME: for 8 MiB FB only IMPROVEME: assumes 32-bits WB
|
||||
address_increment = (width) // 4
|
||||
#default_address = (0x8f800000 + width//2 + width*height//2) // 4
|
||||
#last_address = (0x8f800000 + width//2 + width*(height-8)) // 4
|
||||
#address_increment = (width) // 4
|
||||
base_address = Signal(30, reset = default_address) # IMPROVEME: assumes 32-bits WB
|
||||
cur_address = Signal(30)
|
||||
|
||||
print(f"TRACE: displaying @ 0x{default_address*4:08x} with increment {address_increment*4}")
|
||||
|
||||
cur_nib_idx = Signal(3)
|
||||
cur_line_idx = Signal(3)
|
||||
|
||||
val = Signal(32)
|
||||
|
||||
cur_nib = Signal(4)
|
||||
self.comb += [
|
||||
Case((cur_nib_idx ^ 1), { ## nibble-swap for proper order
|
||||
x: cur_nib.eq(val[(4*x):(4*x+4)]) for x in range(0, 8)
|
||||
}),
|
||||
]
|
||||
cur_nib_decoded = Signal(8)
|
||||
self.submodules.fsm = fsm = FSM(reset_state="Reset")
|
||||
|
||||
saw_ongoing = Signal()
|
||||
saw_re = Signal()
|
||||
saw_readable= Signal()
|
||||
self.sync += [
|
||||
If(~fsm.ongoing("Idle"),
|
||||
saw_ongoing.eq(1),
|
||||
),
|
||||
If(trace_data.re,
|
||||
saw_re.eq(1),
|
||||
),
|
||||
If(fifo.readable,
|
||||
saw_readable.eq(1),
|
||||
),
|
||||
]
|
||||
|
||||
if (False):
|
||||
led0 = platform.request("user_led", 0)
|
||||
led1 = platform.request("user_led", 1)
|
||||
led2 = platform.request("user_led", 2)
|
||||
led3 = platform.request("user_led", 3)
|
||||
led4 = platform.request("user_led", 4)
|
||||
led5 = platform.request("user_led", 5)
|
||||
led6 = platform.request("user_led", 6)
|
||||
led7 = platform.request("user_led", 7)
|
||||
|
||||
self.comb += [
|
||||
led0.eq(~fsm.ongoing("Idle")),
|
||||
led1.eq(trace_data.re),
|
||||
led2.eq(fifo.readable),
|
||||
led3.eq(0),
|
||||
|
||||
led4.eq(saw_ongoing),
|
||||
led5.eq(saw_re),
|
||||
led6.eq(saw_readable),
|
||||
led7.eq(trace_data.storage[0]),
|
||||
]
|
||||
|
||||
# set up wishbone
|
||||
self.comb += [
|
||||
wb.we.eq(1),
|
||||
wb.sel.eq(0xF),
|
||||
wb.adr.eq(cur_address),
|
||||
]
|
||||
|
||||
fsm.act("Reset",
|
||||
NextState("Idle"),
|
||||
)
|
||||
fsm.act("Idle",
|
||||
If(fifo.readable,
|
||||
NextValue(val, fifo.dout),
|
||||
NextValue(cur_line_idx, 0),
|
||||
NextValue(cur_nib_idx, 0),
|
||||
NextValue(cur_address, base_address),
|
||||
fifo.re.eq(1),
|
||||
NextState("StartWriteLow"),
|
||||
),
|
||||
)
|
||||
fsm.act("StartWriteLow",
|
||||
wb.cyc.eq(1),
|
||||
wb.stb.eq(1),
|
||||
wb.dat_w.eq(Cat(Replicate(cur_nib_decoded[7], 8), Replicate(cur_nib_decoded[6], 8), Replicate(cur_nib_decoded[5], 8), Replicate(cur_nib_decoded[4], 8))),
|
||||
If(wb.ack,
|
||||
NextValue(cur_address, cur_address + 1),
|
||||
NextState("StartWriteHigh"),
|
||||
),
|
||||
)
|
||||
fsm.act("StartWriteHigh",
|
||||
wb.cyc.eq(1),
|
||||
wb.stb.eq(1),
|
||||
wb.dat_w.eq(Cat(Replicate(cur_nib_decoded[3], 8), Replicate(cur_nib_decoded[2], 8), Replicate(cur_nib_decoded[1], 8), Replicate(cur_nib_decoded[0], 8))),
|
||||
If(wb.ack,
|
||||
If((cur_line_idx == 7) & (cur_nib_idx == 7),
|
||||
#If(base_address == last_address,
|
||||
# NextValue(base_address, default_address),
|
||||
#).Else(
|
||||
NextValue(base_address, base_address + address_increment),
|
||||
#),
|
||||
NextState("Idle"),
|
||||
).Elif(cur_nib_idx == 7,
|
||||
NextValue(base_address, base_address + address_increment),
|
||||
NextValue(cur_address, base_address + address_increment),
|
||||
NextValue(cur_nib_idx, 0),
|
||||
NextValue(cur_line_idx, cur_line_idx + 1),
|
||||
NextState("StartWriteLow"),
|
||||
).Else(
|
||||
NextValue(cur_address, cur_address + 1),
|
||||
NextValue(cur_nib_idx, cur_nib_idx + 1),
|
||||
NextState("StartWriteLow"),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
Case((cur_line_idx), {
|
||||
0: cur_nib_decoded.eq(0),
|
||||
7: cur_nib_decoded.eq(0),
|
||||
1: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x18), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x18), 3:cur_nib_decoded.eq(0x38), 4:cur_nib_decoded.eq(0x20), 5:cur_nib_decoded.eq(0x3c), 6:cur_nib_decoded.eq(0x1c), 7:cur_nib_decoded.eq(0x3c), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x18), 10:cur_nib_decoded.eq(0x18), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x18), 13:cur_nib_decoded.eq(0x38), 14:cur_nib_decoded.eq(0x3c), 15:cur_nib_decoded.eq(0x3c),
|
||||
}),
|
||||
2: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x24), 1:cur_nib_decoded.eq(0x30), 2:cur_nib_decoded.eq(0x24), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x28), 5:cur_nib_decoded.eq(0x20), 6:cur_nib_decoded.eq(0x20), 7:cur_nib_decoded.eq(0x04), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x24), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x24), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
3: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x2c), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x04), 3:cur_nib_decoded.eq(0x18), 4:cur_nib_decoded.eq(0x28), 5:cur_nib_decoded.eq(0x38), 6:cur_nib_decoded.eq(0x38), 7:cur_nib_decoded.eq(0x08), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x24), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x20), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x38), 15:cur_nib_decoded.eq(0x38),
|
||||
}),
|
||||
4: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x34), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x18), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x3c), 5:cur_nib_decoded.eq(0x04), 6:cur_nib_decoded.eq(0x24), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x1c), 10:cur_nib_decoded.eq(0x3c), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x20), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
5: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x24), 1:cur_nib_decoded.eq(0x10), 2:cur_nib_decoded.eq(0x20), 3:cur_nib_decoded.eq(0x04), 4:cur_nib_decoded.eq(0x08), 5:cur_nib_decoded.eq(0x04), 6:cur_nib_decoded.eq(0x24), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x24), 9:cur_nib_decoded.eq(0x04), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x24), 12:cur_nib_decoded.eq(0x24), 13:cur_nib_decoded.eq(0x24), 14:cur_nib_decoded.eq(0x20), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
6: Case(cur_nib, {
|
||||
0:cur_nib_decoded.eq(0x18), 1:cur_nib_decoded.eq(0x38), 2:cur_nib_decoded.eq(0x3c), 3:cur_nib_decoded.eq(0x38), 4:cur_nib_decoded.eq(0x08), 5:cur_nib_decoded.eq(0x38), 6:cur_nib_decoded.eq(0x18), 7:cur_nib_decoded.eq(0x10), 8:cur_nib_decoded.eq(0x18), 9:cur_nib_decoded.eq(0x38), 10:cur_nib_decoded.eq(0x24), 11:cur_nib_decoded.eq(0x38), 12:cur_nib_decoded.eq(0x18), 13:cur_nib_decoded.eq(0x38), 14:cur_nib_decoded.eq(0x3c), 15:cur_nib_decoded.eq(0x20),
|
||||
}),
|
||||
}
|
||||
),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user