From 951140467ace90fd891e0e549cf9a0e342af48ee Mon Sep 17 00:00:00 2001 From: slederer Date: Thu, 12 Sep 2024 21:00:33 +0200 Subject: [PATCH] Some additions to the README file tridoraemu: fix crash on invalid vmem addresses examples: removed 5cubes due to unclear licensing add stuff to gitignore, licenses, README import Vivado project added missing assembly files, extended .gitignore stdlib: use DEL instead of BS --- .gitignore | 15 +- README.md | 19 +- examples/5cubes.pas | 253 ---- examples/LICENSES.md | 2 + lib/corelib.s | 1501 ++++++++++++++++++++++ lib/coreloader.s | 279 +++++ lib/float32.s | 1053 ++++++++++++++++ lib/rommon.s | 805 ++++++++++++ lib/sdcardboot.s | 613 +++++++++ lib/sdcardlib.s | 795 ++++++++++++ lib/stdlib.pas | 2 +- pcomp/make.bat | 5 +- rtl/arty-a7/Arty-A7-35-Master.xdc | 218 ++++ rtl/arty-a7/Arty_C_mig.ucf | 48 + rtl/arty-a7/mig_dram_0/mig_a.prj | 148 +++ rtl/arty-a7/mig_dram_0/mig_b.prj | 148 +++ rtl/arty-a7/mig_dram_0/mig_dram_0.xci | 1572 ++++++++++++++++++++++++ rtl/arty-a7/sdspi_testbench_behav.wcfg | 176 +++ rtl/arty-a7/testbench_behav1.wcfg | 88 ++ rtl/arty-a7/tridoracpu.tcl | 683 ++++++++++ rtl/src/bram_tdp.v | 46 + rtl/src/cpuclk.v | 83 ++ rtl/src/display_clock.v | 96 ++ rtl/src/dram_bridge.v | 165 +++ rtl/src/fifo.v | 53 + rtl/src/fifo_testbench.v | 116 ++ rtl/src/irqctrl.v | 73 ++ rtl/src/mem.v | 161 +++ rtl/src/palette.v | 28 + rtl/src/sdspi.v | 372 ++++++ rtl/src/sdspi_testbench.v | 199 +++ rtl/src/stack.v | 42 + rtl/src/stackcpu.v | 427 +++++++ rtl/src/testbench.v | 54 + rtl/src/top.v | 288 +++++ rtl/src/uart.v | 262 ++++ rtl/src/uart_tb.v | 100 ++ rtl/src/vgafb.v | 292 +++++ tridoraemu/README.md | 2 +- tridoraemu/framebuffer.go | 9 +- 40 files changed, 11021 insertions(+), 270 deletions(-) delete mode 100644 examples/5cubes.pas create mode 100644 lib/corelib.s create mode 100644 lib/coreloader.s create mode 100644 lib/float32.s create mode 100644 lib/rommon.s create mode 100644 lib/sdcardboot.s create mode 100644 lib/sdcardlib.s create mode 100644 rtl/arty-a7/Arty-A7-35-Master.xdc create mode 100644 rtl/arty-a7/Arty_C_mig.ucf create mode 100644 rtl/arty-a7/mig_dram_0/mig_a.prj create mode 100644 rtl/arty-a7/mig_dram_0/mig_b.prj create mode 100644 rtl/arty-a7/mig_dram_0/mig_dram_0.xci create mode 100644 rtl/arty-a7/sdspi_testbench_behav.wcfg create mode 100644 rtl/arty-a7/testbench_behav1.wcfg create mode 100644 rtl/arty-a7/tridoracpu.tcl create mode 100644 rtl/src/bram_tdp.v create mode 100644 rtl/src/cpuclk.v create mode 100644 rtl/src/display_clock.v create mode 100644 rtl/src/dram_bridge.v create mode 100644 rtl/src/fifo.v create mode 100644 rtl/src/fifo_testbench.v create mode 100644 rtl/src/irqctrl.v create mode 100644 rtl/src/mem.v create mode 100644 rtl/src/palette.v create mode 100644 rtl/src/sdspi.v create mode 100644 rtl/src/sdspi_testbench.v create mode 100644 rtl/src/stack.v create mode 100644 rtl/src/stackcpu.v create mode 100644 rtl/src/testbench.v create mode 100644 rtl/src/top.v create mode 100644 rtl/src/uart.v create mode 100644 rtl/src/uart_tb.v create mode 100644 rtl/src/vgafb.v diff --git a/.gitignore b/.gitignore index 103618f..10e7f57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ -*.s +pcomp/*.s +progs/*.s +tests/*.s +examples/*.s *.o *.exe *.bin @@ -10,6 +13,7 @@ *.sasmout *.lib *.img +*.mem *.lsym *.zip go.sum @@ -17,5 +21,12 @@ sine.pas graph.pas graph2.pas chase.pas -*.img !runtime.s +**/tridoracpu.*/ +rtl/arty-a7/mig_dram_0/_tmp/* +rtl/arty-a7/mig_dram_0/doc/* +rtl/arty-a7/mig_dram_0/mig_dram_0* +rtl/arty-a7/mig_dram_0/xil_txt.* +rtl/arty-a7/mig_dram_0/*.veo +rtl/arty-a7/mig_dram_0/*.tcl +rtl/arty-a7/mig_dram_0/*.xml diff --git a/README.md b/README.md index 25fa0c1..e5d2bd7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ -# Tridora -- the Tridora CPU and the Tridora System -- creating everything from the ground up (except soldering stuff) -- make it useful, but as simple as possible +# Tridora System +Tridora is a homebrew CPU written in Verilog and a matching software environment, +including a Pascal compiler and assembler. +Everything was created from the ground up (except soldering stuff). +Everything is as simple as possible while still being reasonably useful. +Everything is open source, so you can read, understand and modify the whole system, hardware and software. ## Overview - Homebrew CPU -- Verilog/FPGA SoC +- Verilog FPGA SoC - 32-bit word-oriented stack machine architecture +- running at 83 MHz on an Arty-A7 board with four clocks per instruction - has its own instruction set architecture, compatible with nothing - additional IO controllers on FPGA: UART (serial console), SD-Card, VGA - Pascal compiler written from zero @@ -28,8 +31,8 @@ - (Screenshot image viewer) ## Supported Boards -- Arty A7 -- Nexys A7? +- Arty A7 (with two PMODs for microSD cards and VGA output) +- Nexys A7 (not ready yet) ## Pascal Language - Wirth Pascal @@ -55,4 +58,4 @@ - one program image loaded at a time at a fixed address - most parts of the operating system are contained in the program image - file system is very primitive: only contiguous blocks, no subdirectories -- Simple shell reminiscent of TP3.0, edit, compile, run programs +- simple shell reminiscent of TP3.0, edit, compile, run programs diff --git a/examples/5cubes.pas b/examples/5cubes.pas deleted file mode 100644 index edaecaa..0000000 --- a/examples/5cubes.pas +++ /dev/null @@ -1,253 +0,0 @@ -program five_cubes_in_a_row; -const MAX_Y = 400; - pi = 3.1415926; - -type pointtype = record x,y:integer end; - -var cube:array[1..6] of record - position:array[1..5] of record x,y,z:real end; - end; - c:char; - pcos,ncos,psin,nsin:real; - -procedure rotx(dir:integer); -var y1,z1:real;i,o:integer; -begin - if dir=1 then - for i:=1 to 6 do - for o:=1 to 5 do - begin - y1:=pcos*cube[i].position[o].y-psin*cube[i].position[o].z; - z1:=psin*cube[i].position[o].y+pcos*cube[i].position[o].z; - cube[i].position[o].y:=y1; - cube[i].position[o].z:=z1; - end - else - for i:=1 to 6 do - for o:=1 to 5 do - begin - y1:=ncos*cube[i].position[o].y-nsin*cube[i].position[o].z; - z1:=nsin*cube[i].position[o].y+ncos*cube[i].position[o].z; - cube[i].position[o].y:=y1; - cube[i].position[o].z:=z1 - end -end; - -procedure roty(dir:integer); -var x1,z1:real;i,o:integer; -begin - if dir=1 then - for i:=1 to 6 do - for o:=1 to 5 do - begin - x1:=pcos*cube[i].position[o].x-psin*cube[i].position[o].z; - z1:=psin*cube[i].position[o].x+pcos*cube[i].position[o].z; - cube[i].position[o].x:=x1; - cube[i].position[o].z:=z1; - end - else - for i:=1 to 6 do - for o:=1 to 5 do - begin - x1:=ncos*cube[i].position[o].x-nsin*cube[i].position[o].z; - z1:=nsin*cube[i].position[o].x+ncos*cube[i].position[o].z; - cube[i].position[o].x:=x1; - cube[i].position[o].z:=z1 - end -end; - -procedure rotz(dir:integer); -var y1,x1:real;i,o:integer; -begin - if dir=1 then - for i:=1 to 6 do - for o:=1 to 5 do - begin - y1:=pcos*cube[i].position[o].y-psin*cube[i].position[o].x; - x1:=psin*cube[i].position[o].y+pcos*cube[i].position[o].x; - cube[i].position[o].y:=y1; - cube[i].position[o].x:=x1; - end - else - for i:=1 to 6 do - for o:=1 to 5 do - begin - y1:=ncos*cube[i].position[o].y-nsin*cube[i].position[o].x; - x1:=nsin*cube[i].position[o].y+ncos*cube[i].position[o].x; - cube[i].position[o].y:=y1; - cube[i].position[o].x:=x1 - end -end; - -procedure display_cube(col:integer); -var i,o,a:integer;c:integer; - stran:array[1..4] of pointtype; - color:integer; -begin - for i:=1 to 6 do - if cube[i].position[5].z>0 then - with cube[i] do - begin - for a:=1 to 5 do - begin - if col>0 then c:=a else c:=0; - if((a=4)and(c>0))then color :=6 else color:= c; - for o:=1 to 4 do - begin - stran[o].x:=a*100+round(position[o].x); - stran[o].y:=MAX_Y div 2+round(position[o].y); - end; - drawline(stran[1].x,stran[1].y,stran[2].x,stran[2].y,color); - drawline(stran[2].x,stran[2].y,stran[3].x,stran[3].y,color); - drawline(stran[3].x,stran[3].y,stran[4].x,stran[4].y,color); - drawline(stran[4].x,stran[4].y,stran[1].x,stran[1].y,color); - end; - end; -end; - -procedure init; -var i,gm,gd:integer; - entrance:array[1..11]of integer; -begin - entrance := [ 1,2,3,4,5,20,7,56,57,58,59 ]; - InitGraphics; - ClearGraphics; - pcos:=cos(6*2*pi/360); - ncos:=cos(-6*2*pi/360); - psin:=sin(6*2*pi/360); - nsin:=sin(-6*2*pi/360); - setpalette(1,$700); - with cube[1] do - begin - position[1].x:=-25; - position[1].y:=-25; - position[1].z:=+25; - position[2].x:=+25; - position[2].y:=-25; - position[2].z:=+25; - position[3].x:=+25; - position[3].y:=+25; - position[3].z:=+25; - position[4].x:=-25; - position[4].y:=+25; - position[4].z:=+25; - position[5].x:=0; - position[5].y:=0; - position[5].z:=25; - end; - with cube[2] do - begin - position[1].x:=-25; - position[1].y:=-25; - position[1].z:=-25; - position[2].x:=+25; - position[2].y:=-25; - position[2].z:=-25; - position[3].x:=+25; - position[3].y:=-25; - position[3].z:=+25; - position[4].x:=-25; - position[4].y:=-25; - position[4].z:=+25; - position[5].x:=0; - position[5].z:=0; - position[5].y:=-25; - end; - with cube[3] do - begin - position[1].x:=-25; - position[1].y:=+25; - position[1].z:=+25; - position[2].x:=+25; - position[2].y:=+25; - position[2].z:=+25; - position[3].x:=+25; - position[3].y:=+25; - position[3].z:=-25; - position[4].x:=-25; - position[4].y:=+25; - position[4].z:=-25; - position[5].x:=0; - position[5].z:=0; - position[5].y:=25; - end; - with cube[4] do - begin - position[1].x:=-25; - position[1].y:=-25; - position[1].z:=-25; - position[2].x:=-25; - position[2].y:=-25; - position[2].z:=+25; - position[3].x:=-25; - position[3].y:=+25; - position[3].z:=+25; - position[4].x:=-25; - position[4].y:=+25; - position[4].z:=-25; - position[5].y:=0; - position[5].z:=0; - position[5].x:=-25; - end; - with cube[5] do - begin - position[1].x:=+25; - position[1].y:=-25; - position[1].z:=+25; - position[2].x:=+25; - position[2].y:=-25; - position[2].z:=-25; - position[3].x:=+25; - position[3].y:=+25; - position[3].z:=-25; - position[4].x:=+25; - position[4].y:=+25; - position[4].z:=+25; - position[5].x:=25; - position[5].y:=0; - position[5].z:=0; - end; - with cube[6] do - begin - position[1].x:=-25; - position[1].y:=+25; - position[1].z:=-25; - position[2].x:=+25; - position[2].y:=+25; - position[2].z:=-25; - position[3].x:=+25; - position[3].y:=-25; - position[3].z:=-25; - position[4].x:=-25; - position[4].y:=-25; - position[4].z:=-25; - position[5].x:=0; - position[5].y:=0; - position[5].z:=-25; - end; -end; - -begin - init; - repeat - display_cube(1); - repeat - c:=conin; - until(upcase(c)in['E','Q','S','W','D','A','J','K','L','U','I','O'])or(c=#27); - display_cube(0); - case upcase(c) of - 'E':rotz(0); - 'Q':rotz(1); - 'S':rotx(0); - 'W':rotx(1); - 'D':roty(0); - 'A':roty(1); - 'J':begin rotx(1);roty(1);rotz(1);end; - 'L':begin rotx(0);roty(0);rotz(0);end; - 'K':begin rotx(1);roty(0);rotz(1);end; - 'I':begin rotx(0);roty(1);rotz(0);end; - 'U':begin rotx(0);roty(1);rotz(1);end; - 'O':begin rotx(1);roty(0);rotz(0);end; - end; - until c=#27; -end. diff --git a/examples/LICENSES.md b/examples/LICENSES.md index 32ad7df..8992b88 100644 --- a/examples/LICENSES.md +++ b/examples/LICENSES.md @@ -1,3 +1,5 @@ +# rtpair.pas +originally from [https://github.com/Postrediori/Pascal-Raytracer](https://github.com/Postrediori/Pascal-Raytracer), no license specified there # Attributions for included media files * ara.pict: Tuxyso / Wikimedia Commons / CC-BY-SA-3.0 https://commons.wikimedia.org/wiki/File:Ara-Zoo-Muenster-2013.jpg diff --git a/lib/corelib.s b/lib/corelib.s new file mode 100644 index 0000000..57f35a8 --- /dev/null +++ b/lib/corelib.s @@ -0,0 +1,1501 @@ +; Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details + + .EQU CR 13 + .EQU LF 10 + .EQU UART_REG 2048 + .EQU IRQC_REG 2432 + + .EQU PROG_START 24576 + .EQU FP_START 24060 + .EQU RP_START 24064 +NEWLINE: + LOADC CR + LOADCP CONOUT + CALL + LOADC LF + LOADCP CONOUT + CALL + RET + +; print string of byte characters +; takes pointer to string on eval stack +PRINTLINE: + DUP ; duplicate address as arg to printchar + LOADCP _PRINTCHAR + CALL + CBRANCH.Z PRINTLINE_EXIT ; if char is zero, exit + INC 1 ; increment address + BRANCH PRINTLINE +PRINTLINE_EXIT: + DROP ; remove address from stack + RET + +; print a single character +; takes a byte pointer on eval stack +; returns character on eval stack +_PRINTCHAR: + LOADI.S1.X2Y ; load word, keep address on stack + BSEL ; select byte of a word via address + DUP ; check for null byte + CBRANCH.Z _PRINTCHAR_XT + DUP + LOADCP CONOUT + CALL +_PRINTCHAR_XT: + RET + +; print a 32-bit hexadecimal number +; takes the value on the stack +PRINTHEXW: + BROT + DUP + LOADCP _PRINTHEXB + CALL + BROT + DUP + LOADCP _PRINTHEXB + CALL + BROT + DUP + LOADCP _PRINTHEXB + CALL + BROT + LOADCP _PRINTHEXB + CALL + RET + +_PRINTHEXB: + DUP + SHR + SHR + SHR + SHR + LOADCP _PRINTNIBBLE + CALL + LOADCP _PRINTNIBBLE + CALL + RET + +_PRINTNIBBLE: + LOADC 15 ; isolate nibble + AND + LOADC 10 + CMPU.S0 GE ; nibble >= 10 ? + CBRANCH.NZ _PRINTNIBBLE_1 ; then print a-f + LOADC '0' ; else print 0-9 + BRANCH _PRINTNIBBLE_2 +_PRINTNIBBLE_1: + LOADC 55 ; 55 + 10 == 'A' +_PRINTNIBBLE_2: + ADD + LOADCP CONOUT + CALL + RET + +_MUL10: + SHL ; x * 2 + DUP + SHL 2 ; x * 8 + ADD ; x * 2 + x * 8 = x * 10 + RET + +; shift left multiple times +; parameters: value, count +; returns: shifted value +_SHLM: + DUP + CBRANCH.Z _SHLM_X ; if count is zero, exit + LOADC 8 + CMPU.S0 LT ; count is less than 8? + CBRANCH _SHLM_1 + ; if >= 8, continue here + DEC 8 ; decrement counter by 8 + SWAP ; swap counter and value + BROT ; byte rotate value + LOADCP $FFFFFF00 ; and mask the lowest 8 bits + AND ; to get a shift left by 8 + SWAP ; swap back counter and value + BRANCH _SHLM +_SHLM_1: + DEC 1 + SWAP + SHL + SWAP + BRANCH _SHLM +_SHLM_X: + DROP ; drop counter + RET + +; shift right multiple times +; parameters: value, count +; returns: shifted value +_SHRM: + DUP + CBRANCH.Z _SHRM_X ; if count is zero, exit + DEC 1 + SWAP + SHR + SWAP + BRANCH _SHRM +_SHRM_X: + DROP ; remove counter + RET + + +; --- print signed integer as decimal +; parameter: value +PRINTDEC: + DUP + LOADC 0 + CMP GE + CBRANCH PRINTDECU + LOADC '-' + LOADCP CONOUT + CALL + NOT + INC 1 ; negate value + ; fallthrough to PRINTDECU + +; print unsigned integer as decimal +; parameter: value +; local vars: +; 0: current value +; 4: pointer to digit value table +; 8: digit counter +; 12: flag for leading zeroes +PRINTDECU: + FPADJ -16 + STORE 0 + LOADCP CONVDEC_TAB + STORE 4 + LOADC 0 + STORE 12 +PRDEC_NEXTDIGIT: + LOADC 0 + STORE 8 + LOAD 4 + LOADI ; load via pointer + CBRANCH.Z PRDECU_DONE ; if digit value is 0, we are done +DIGIT_LOOP: + LOAD 4 + LOADI + LOAD 0 + CMPU GT + CBRANCH DIGIT_DONE + LOAD 0 + LOAD 4 + LOADI + SUB + STORE 0 + LOAD 8 + INC 1 + STORE 8 + BRANCH DIGIT_LOOP +DIGIT_DONE: + LOAD 8 + CBRANCH.NZ DIGIT_OUT ; if digit is not 0, print it + LOAD 12 ; is it a leading zero, ignore it + CBRANCH.Z DIGIT_NEXT +DIGIT_OUT: + LOADC 1 ; set leading zero flag + STORE 12 + LOAD 8 + LOADCP _PRINTDIGIT + CALL +DIGIT_NEXT: + LOAD 4 ; increment digit value pointer + INC 4 + STORE 4 + BRANCH PRDEC_NEXTDIGIT +PRDECU_DONE: + LOAD 0 + LOADCP _PRINTDIGIT + CALL + FPADJ 16 + RET + +_PRINTDIGIT: + LOADC '0' + ADD + LOADCP CONOUT + CALL + RET +CONVDEC_TAB: + .WORD 1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,0 + +; ------ read a 8-digit hexadecimal number from the console +; stores variables on the user stack, so the FP register must be +; inizialized. +; returns two values on the eval stack: +; - return code (topmost) +; 0 - no valid number +; 1 - valid number +; 2 - valid number and enter was pressed +; - result value +_READHEX: + FPADJ -8 + LOADC 0 ; current value + STORE 0 + LOADC 8 ; max number of digits + STORE 4 ; remaining digits counter +_READHEX_1: + LOADCP CONIN + CALL + LOADC CR ; RETURN pressed? + CMP.S0 EQ + CBRANCH _READHEX_RT + DUP + LOADCP CONOUT ; echo character + CALL + LOADCP _CONVHEXDIGIT + CALL + LOADC -1 + CMP.S0 EQ ; invalid character? + CBRANCH.NZ _READHEX_XT + LOAD 0 + SHL 1 ; shift previous nibble + SHL 1 + SHL 1 + SHL 1 + OR ; combine with last digit + STORE 0 + LOAD 4 + DEC 1 + DUP + STORE 4 + CBRANCH.NZ _READHEX_1 + BRANCH _READHEX_XT1 +_READHEX_RT: ; if no digits were entered, set return code + DROP ; drop read character + LOAD 4 ;remaining digits counter + LOADC 8 + CMP NE + CBRANCH _READHEX_RT2 + LOADC 0 ; no valid input + BRANCH _READHEX_XT3 +_READHEX_RT2: + LOADC 2 ; valid input and return pressed + BRANCH _READHEX_XT3 +_READHEX_XT: + DROP + LOAD 4 + LOADC 8 + CMP EQ ; if no digits were entered + CBRANCH _READHEX_XT0 +_READHEX_XT1: + LOADC 1 ; valid input flag + BRANCH _READHEX_XT3 +_READHEX_XT0: + LOADC 0 +_READHEX_XT3: + LOAD 0 + SWAP + FPADJ 8 + RET + +; ------ convert character on the eval stack to upper case +UPCASE: + LOADC 'a' + CMP.S0 LT + CBRANCH UPCASE_XT + LOADC 'z' + CMP.S0 GT + CBRANCH UPCASE_XT + LOADC 32 + SUB +UPCASE_XT: + RET + +; ------ convert hexadecimal digit to integer +; ------ takes an ascii character as parameter on the eval stack +; ------ returns an integer value from 0-15 on the eval stack, +; ------ or -1 if the character was not a valid hexadecimal digit +_CONVHEXDIGIT: + LOADCP UPCASE + CALL + LOADC '0' + CMP.S0 LT ; character < '0'? + CBRANCH.NZ _CONVHEXDIGIT_ERR + LOADC '9' + CMP.S0 GT ; character > '9'? + CBRANCH.NZ _CONVHEXDIGIT_ISALPHA + LOADC '0' ; character is between '0' and '9', subtract '0' + SUB + BRANCH _CONVHEXDIGIT_NBL +_CONVHEXDIGIT_ISALPHA: + LOADC 'A' + CMP.S0 LT ; character < 'A'? + CBRANCH.NZ _CONVHEXDIGIT_ERR + LOADC 'F' + CMP.S0 GT ; character > 'F'? + CBRANCH.NZ _CONVHEXDIGIT_ERR + LOADC 55 ; character is between 'A' and 'F', subtract ('A' - 10) + SUB +_CONVHEXDIGIT_NBL: + RET +_CONVHEXDIGIT_ERR: + DROP ; remove character from stack + LOADC -1 ; error + RET + +; --------- output a character on serial console +; --------- takes a character (as the lsb of a word) on the eval stack +CONOUT: + LOADC UART_REG ; address of UART register + LOADI ; load status + LOADC 256 ; check bit 8 (tx_busy) + AND + CBRANCH.NZ CONOUT ; loop if bit 8 is not zero + + ; transmitter is idle now, write character + LOADC 1024 ; TX enable bit + OR + LOADC UART_REG ; I/O address + SWAP ; swap addr and value as args for STOREI + STOREI + DROP + RET + +; ---------- check if a character has been received +; returns: 1 if a character has been received, 0 otherwise +CONAVAIL: + LOADC 0 ; preliminary result + LOADC UART_REG ; address of UART register + LOADI ; load status + LOADC 512 ; check bit 9 (rx_avail) + AND + CBRANCH.Z CONAVAIL_0 ; if bit is zero, we are done + INC 1 ; add 1 to preliminary result +CONAVAIL_0: + RET + +; ---------- wait until a character is received and return it on eval stack +CONIN: + LOADC UART_REG ; address of UART register + LOADI ; load status + LOADC 512 ; check bit 9 (rx_avail) + AND + CBRANCH.Z CONIN ; loop if bit 9 is zero + LOADC UART_REG + LOADI ; read register again + LOADC 255 ; mask status bits + AND + LOADC UART_REG ; I/O address + LOADC 512 ; set bit 9 (rx_clear) + STOREI ; write register + DROP + RET + +; return absolute value +; parameters: value +; returns: abs(value) +ABS: + LOADC 0 + CMP.S0 GE + CBRANCH ABS_XT + DEC 1 ; negate + NOT +ABS_XT: + RET + +; signed multiplication +_MUL: + ; fallthrough to MULU + +; unsigned multiplication: x * y +; parameters: [x, y] +; returns: x * y +_MULU: + FPADJ -16 + STORE 0 ; x + STORE 4 ; y + LOADC 32 + STORE 8 ; bit count + LOADC 0 + STORE 12 ; result +MULU_LOOP: + LOAD 8 + CBRANCH.Z MULU_XT ; if count is zero, exit + LOAD 0 + LOADC 1 + AND.S0 ; get bit 0 + CBRANCH.Z MULU_1 ; if bit 0 is zero, next binary digit + LOAD 12 + LOAD 4 + ADD ; result = result + y + STORE 12 +MULU_1: + SHR ; x = x >> 1 + STORE 0 + LOAD 4 + SHL ; y = y << 1 + STORE 4 + LOAD 8 + DEC 1 ; count = count -1 + STORE 8 + BRANCH MULU_LOOP +MULU_XT: + LOAD 12 + FPADJ 16 + RET + +; signed integer division +; parameters: [x,y] +; result: x/y +_DIV: + FPADJ -4 + LOADC 0 + STORE 0 ; clear negate flag + DUP + LOADC 0 + CMP GE ; is y positive? + CBRANCH DIV_ISPOS + ; y is negative + NOT + INC 1 ; negate y + LOADC -1 + STORE 0 ; set negate flag +DIV_ISPOS: + SWAP ; swap x and y + DUP + LOADC 0 + CMP GE ; is x positive? + CBRANCH DIV_ISPOS2 + ; x is negative + NOT + INC 1 ; negate x + LOAD 0 + NOT ; invert negate flag + STORE 0 +DIV_ISPOS2: + SWAP ; swap back y and x + LOADCP _DIVMODU + CALL + DROP ; throw away remainder + LOAD 0 + CBRANCH.Z DIV_XT ; negate flag set? + NOT + INC 1 ; negate value +DIV_XT: + FPADJ 4 + RET + +; signed integer modulo +; the result is negative if x is negative. +; the sign of y is ignored. +; parameters: [x,y] +; returns: remainder of x/y +_MOD: + FPADJ -4 + LOADC 0 + STORE 0 ; clear negate flag + DUP + LOADC 0 + CMP GE ; is y positive? + CBRANCH MOD_ISPOS + ; y is negative + NOT + INC 1 ; negate y +MOD_ISPOS: + SWAP ; swap x and y + DUP + LOADC 0 + CMP GE ; is x positive? + CBRANCH MOD_ISPOS2 + ; x is negative + NOT + INC 1 ; negate x + LOAD 0 + NOT ; invert negate flag + STORE 0 +MOD_ISPOS2: + SWAP ; swap back y and x + LOADCP _DIVMODU + CALL + NIP ; throw away quotient + LOAD 0 + CBRANCH.Z MOD_XT ; negate flag set? + NOT + INC 1 ; negate value +MOD_XT: + + FPADJ 4 + RET + +; unsigned integer division +; parameters: [x,y] +; result: x/y +_DIVU: + LOADCP _DIVMODU ; just call DIVMODU and throw away the remainder + CALL + DROP + RET + +; unsigned integer division with remainder +; parameters: [x,y] +; result: [ quotient, remainder ] +_DIVMODU: + FPADJ -20 + STORE 0 ; y + STORE 4 ; x + LOADC 32 + STORE 8 ; bit count + LOADC 0 + STORE 12 ; tmp value + LOADC 0 + STORE 16 ; result +DIVU_LOOP: + LOAD 8 + CBRANCH.Z DIVU_END ; if count is zero, exit + LOAD 16 + SHL ; result = result << 1 + STORE 16 + LOAD 12 + SHL ; tmp << 1 + LOAD 4 + LOADCP $80000000 ; msb of x + AND + CBRANCH.Z DIVU_1 + INC 1 ; tmp[0] is 0, so +1 means tmp[0] = 1 +DIVU_1: + DUP + STORE 12 ; tmp = tmp << 1 | msb + LOAD 0 + CMPU GE ; tmp >= y? + CBRANCH.Z DIVU_2 + LOAD 16 + INC 1 ; result = result | 1 + STORE 16 + LOAD 12 + LOAD 0 + SUB + STORE 12 ; tmp = tmp - y +DIVU_2: + LOAD 4 + SHL + STORE 4 + LOAD 8 + DEC 1 + STORE 8 + BRANCH DIVU_LOOP +DIVU_END: + LOAD 16 ; result (quotient) + LOAD 12 ; remainder + FPADJ 20 + RET + + .CPOOL + +; wait approx. 1 millisecond +; +; 83.333 MHz Clock, three instructions a 4 cycles +; 83333 / 12 = 6944.4166 +; works only if executed without wait states (i.e. +; from BRAM/SRAM) +WAIT1MSEC: + LOADCP 6944 +WAIT1LOOP: + DEC 1 + DUP + CBRANCH.NZ WAIT1LOOP + DROP + RET + +; clear a memory block +; parameters: addr, length in bytes +; length must be multiple of wordsize. +; if it is not, the last (partial) word is not cleared. +_CLEARMEM: + SHR + SHR ; calculate length in words + +CLEARMEM_L: + DUP + CBRANCH.Z CLEARMEM_X ; if zero words to do, exit + SWAP ; swap counter and addr + LOADC 0 + STOREI 4 ; store with post-increment + SWAP ; swap counter and addr back + DEC 1 ; decrement counter + BRANCH CLEARMEM_L +CLEARMEM_X: + DROP + DROP + RET + +; copy a number of words from source to destination +; parameters: [ dest, source, count ] +; source and destination may not overlap + .EQU COPYWORDS_COUNT 0 + .EQU COPYWORDS_SRC 4 + .EQU COPYWORDS_DEST 8 +_COPYWORDS: + FPADJ -12 + STORE COPYWORDS_COUNT ; store args to local vars + STORE COPYWORDS_SRC + STORE COPYWORDS_DEST + LOAD COPYWORDS_COUNT ; we will keep count on the stack inside the loop +COPYWORDS_L0: + DUP ; count is on tos, duplicate it + CBRANCH.Z COPYWORDS_XT ; check if count is zero + DEC 1 ; if not, decrement + LOAD COPYWORDS_DEST ; load dest addr for STOREI below + LOAD COPYWORDS_SRC ; load src addr + INC.S1.X2Y 4 ; increment by 4 and put as new value on tos + STORE COPYWORDS_SRC ; store again, old addr is now on tos + LOADI ; load value by old addr + STOREI 4 ; store value and post-increment + STORE COPYWORDS_DEST ; store post-incremented addr + BRANCH COPYWORDS_L0 +COPYWORDS_XT: + DROP ; drop count value + FPADJ 12 + RET + +; compare a number of words +; parameters: [ dest, source, count ] +; returns: 1 if all words are equal, 0 otherwise + .EQU CMPWORDS_COUNT 0 + .EQU CMPWORDS_SRC 4 + .EQU CMPWORDS_DEST 8 +_CMPWORDS: + FPADJ -12 + STORE CMPWORDS_COUNT ; store args to local vars + STORE CMPWORDS_SRC + STORE CMPWORDS_DEST + LOAD CMPWORDS_COUNT +CMPWORDS_L0: + DUP ; count is on tos, duplicate it + CBRANCH.Z CMPWORDS_XT ; check if count is zero + DEC 1 ; if not, decrement + LOAD CMPWORDS_SRC ; load src addr + INC.S1.X2Y 4 ; increment by 4 and put as new value on tos + STORE CMPWORDS_SRC ; store again, old addr is now on tos + LOADI ; load src value + LOAD CMPWORDS_DEST ; load dest addr + INC.S1.X2Y 4 ; increment by 4 and put as new value on tos + STORE CMPWORDS_DEST ; store again, old addr is now on tos + LOADI ; load dest value + CMPU EQ + CBRANCH CMPWORDS_L0 ; if words are equal, continue loop + DROP ; drop count value + LOADC 0 ; load exit code 0 + BRANCH CMPWORDS_XT2 +CMPWORDS_XT: + DROP ; drop count value + LOADC 1 ; load exit code 1 +CMPWORDS_XT2: + FPADJ 12 + RET + + .CPOOL +; --------- Graphics Library --------------- + ; vga controller registers + .EQU FB_RA $900 + .EQU FB_WA $901 + .EQU FB_IO $902 + .EQU FB_PS $903 + .EQU FB_PD $904 + .EQU FB_CTL $905 +; set a pixel in fb memory +; parameters: x,y - coordinates +PUTPIXEL_1BPP: + ; calculate vmem address: + OVER ; duplicate x + ; divide x by 32 + SHR + SHR + SHR + SHR + SHR + SWAP + ; multiply y by words per line + SHL 2 + SHL 2 + SHL + + ADD ; add results together for vmem addr + + DUP + LOADCP FB_WA + SWAP + STOREI ; store to framebuffer write addr register + DROP + LOADCP FB_RA ; and to framebuffer read addr register + SWAP + STOREI + DROP + + ; x is now at top of stack + ; get bit value from x modulo 32 + LOADC 31 + AND + SHL 2 ; (x & 31) * 4 = offset into table + LOADCP INT_TO_PIX_TABLE + ADD + LOADI + + LOADCP FB_IO + ; read old vmem value + LOADCP FB_IO + LOADI + ; or in new bit + OR + ; write new value + STOREI + DROP + + RET + +INT_TO_PIX_TABLE: + .WORD %10000000_00000000_00000000_00000000 + .WORD %01000000_00000000_00000000_00000000 + .WORD %00100000_00000000_00000000_00000000 + .WORD %00010000_00000000_00000000_00000000 + .WORD %00001000_00000000_00000000_00000000 + .WORD %00000100_00000000_00000000_00000000 + .WORD %00000010_00000000_00000000_00000000 + .WORD %00000001_00000000_00000000_00000000 + .WORD %00000000_10000000_00000000_00000000 + .WORD %00000000_01000000_00000000_00000000 + .WORD %00000000_00100000_00000000_00000000 + .WORD %00000000_00010000_00000000_00000000 + .WORD %00000000_00001000_00000000_00000000 + .WORD %00000000_00000100_00000000_00000000 + .WORD %00000000_00000010_00000000_00000000 + .WORD %00000000_00000001_00000000_00000000 + .WORD %00000000_00000000_10000000_00000000 + .WORD %00000000_00000000_01000000_00000000 + .WORD %00000000_00000000_00100000_00000000 + .WORD %00000000_00000000_00010000_00000000 + .WORD %00000000_00000000_00001000_00000000 + .WORD %00000000_00000000_00000100_00000000 + .WORD %00000000_00000000_00000010_00000000 + .WORD %00000000_00000000_00000001_00000000 + .WORD %00000000_00000000_00000000_10000000 + .WORD %00000000_00000000_00000000_01000000 + .WORD %00000000_00000000_00000000_00100000 + .WORD %00000000_00000000_00000000_00010000 + .WORD %00000000_00000000_00000000_00001000 + .WORD %00000000_00000000_00000000_00000100 + .WORD %00000000_00000000_00000000_00000010 + .WORD %00000000_00000000_00000000_00000001 + +PUTMPIXEL: + LOADC 1 +; set a pixel in fb memory +; parameters: x,y,color - coordinates, color value (0-15) +PUTPIXEL: +PUTPIXEL_4BPP: + .EQU PUTPIXEL_X 0 + .EQU PUTPIXEL_Y 4 + .EQU PUTPIXEL_COLOR 8 + .EQU PUTPIXEL_PIXPOS 12 + .EQU PUTPIXEL_FS 16 + + FPADJ -PUTPIXEL_FS + + STORE PUTPIXEL_COLOR + STORE PUTPIXEL_Y + STORE PUTPIXEL_X + + + ; calculate vmem address: (x / 8) + (y * 80) + LOAD PUTPIXEL_X + ; divide x by 8 + SHR + SHR + SHR + + LOAD PUTPIXEL_Y + ; multiply y by words per line + SHL 2 + SHL 2 ; * 16 + DUP + SHL 2; * 64 + ADD ; x*16 + x*64 + + ADD ; add results together for vmem addr + + LOADCP FB_WA + OVER + STOREI ; store to framebuffer write addr register + DROP + LOADCP FB_RA ; and to framebuffer read addr register + SWAP ; swap addr and value for STOREI + STOREI + DROP + + LOAD PUTPIXEL_X + ; |0000.0000|0000.0000|0000.0000|0000.1111| + LOADC 7 + AND ; calculate pixel position in word + LOADC 7 + SWAP + SUB ; pixpos = 7 - (x & 7) + STORE PUTPIXEL_PIXPOS + + LOAD PUTPIXEL_COLOR + LOAD PUTPIXEL_PIXPOS + SHR ; rcount = pixpos / 2 +ROTLOOP_: + DUP ; exit loop if rcount is 0 + CBRANCH.Z ROTLOOP_END + SWAP ; pixel value is now on top of stack + BROT ; value = value << 8 + SWAP ; rcount is now on top of stack + DEC 1 ; rcount = rcount - 1 + BRANCH ROTLOOP_ +ROTLOOP_END: + DROP ; drop rcount + ; shifted pixel value is now at top of stack + LOAD PUTPIXEL_PIXPOS + LOADC 1 + AND + CBRANCH.Z EVEN_PIXPOS + SHL 2 ; if pixpos is odd, shift by 4 bits + SHL 2 +EVEN_PIXPOS: + LOAD PUTPIXEL_X + ; get bit value from x modulo 8 + LOADC 7 + AND + SHL 2 ; (x & 7) * 4 = offset into table + LOADCP INT_TO_MASK_TABLE + ADD + LOADI + + ; read old vmem value + LOADCP FB_IO + LOADI + ; mask bits + AND + ; or in shifted pixel value + OR + + ; write new value + LOADCP FB_IO + SWAP + STOREI + DROP + + FPADJ PUTPIXEL_FS + RET + + .CPOOL + +INT_TO_MASK_TABLE: + .WORD %00001111_11111111_11111111_11111111 + .WORD %11110000_11111111_11111111_11111111 + .WORD %11111111_00001111_11111111_11111111 + .WORD %11111111_11110000_11111111_11111111 + .WORD %11111111_11111111_00001111_11111111 + .WORD %11111111_11111111_11110000_11111111 + .WORD %11111111_11111111_11111111_00001111 + .WORD %11111111_11111111_11111111_11110000 + +; draw a line between two points +; parameters: x0, y0, x1, y1, color + .EQU DL_X0 0 + .EQU DL_Y0 4 + .EQU DL_X1 8 + .EQU DL_Y1 12 + .EQU DL_DX 16 + .EQU DL_DY 20 + .EQU DL_ERR 24 + .EQU DL_E2 28 + .EQU DL_SX 32 + .EQU DL_SY 36 + .EQU DL_COL 40 + .EQU STACKFRAME_SIZE 44 + +DRAWLINE_M: + LOADC 1 +DRAWLINE: + FPADJ -STACKFRAME_SIZE + + STORE DL_COL ; store args + STORE DL_Y1 + STORE DL_X1 + STORE DL_Y0 + STORE DL_X0 + + LOAD DL_X1 ; dx = abs(x1-x0) + LOAD DL_X0 + SUB + LOADCP ABS + CALL + STORE DL_DX + + LOAD DL_Y1 ; dy = -abs(y1-y0) + LOAD DL_Y0 + SUB + LOADCP ABS + CALL + DEC 1 + NOT + STORE DL_DY + + LOAD DL_X0 ; sx = (x0 dy + LOAD DL_DY + CMP GT + CBRANCH.Z DL_SKIP1 + + LOAD DL_ERR ; err += dy + LOAD DL_DY + ADD + STORE DL_ERR + + LOAD DL_X0 ; x0 += sx + LOAD DL_SX + ADD + STORE DL_X0 + +DL_SKIP1: + LOAD DL_E2 ; if e2 < dx + LOAD DL_DX + CMP LT + CBRANCH.Z DL_SKIP2 + + LOAD DL_ERR ; err += dx + LOAD DL_DX + ADD + STORE DL_ERR + + LOAD DL_Y0 ; y0 += sy + LOAD DL_SY + ADD + STORE DL_Y0 + +DL_SKIP2: + BRANCH DL_LOOP +DL_END: + FPADJ STACKFRAME_SIZE + RET + +; initialize the palette registers +INITPALETTE: + LOADCP DEFAULT_PALETTE ; load pointer to color table + LOADC 0 ; load counter +INITPAL_0: + DUP + LOADC FB_PS ; store counter to palette select register + SWAP ; swap addr and value for STOREI + STOREI + DROP + + SWAP ; pointer on top of stack + DUP + LOADI ; load color value + LOADC FB_PD + SWAP ; swap addr and value for STOREI + STOREI ; store to palette data register + DROP + INC 4 ; increment pointer + + SWAP ; counter on top of stack + DUP + LOADC 15 + CMPU EQ + CBRANCH INITPAL_X ; exit if counter is 15 + + INC 1 ; increment counter + BRANCH INITPAL_0 + +INITPAL_X: + DROP ; remove counter and pointer + DROP + RET + +; set a palette register +; parameters [ palette slot nr, color value ] +SETPALETTE: + SWAP ; slot nr to top + LOADC FB_PS ; load address of palette select register + SWAP ; swap addr and slot nr for STOREI + STOREI + DROP ; remove addr from STOREI + ; left on stack now: color value + LOADC FB_PD ; load address of palette data register + SWAP ; swap addr and color value for STOREI + STOREI + DROP ; remove addr + + RET + +DEFAULT_PALETTE: + .WORD 0, $FFF, $F00, $0F0, $00F, $0FF, $F0F, $FF0 + .WORD $777, $777, $700, $070, $007, $077, $707, $770 + +; set whole video memory to zero +CLEARGRAPHICS: + LOADC 0 +CL_LOOP: + LOADC FB_WA + OVER ; duplicate value + STOREI + DROP + + LOADC FB_IO + LOADC 0 + STOREI + DROP + + INC 1 + + LOADCP 32768 + CMP.S0 NE + CBRANCH CL_LOOP + + DROP + + RET + +INITGRAPHICS: + LOADCP CLEARGRAPHICS + CALL + LOADCP INITPALETTE + CALL + RET + +; wait for vertical blank +; we first wait for the VBLANK bit +; to become zero to make sure we +; catch the beginning of the vertical blank +WAITVSYNC: + ; wait for VBLANK to become zero + LOADC FB_CTL + LOADI ; read control register + LOADC 1 ; check bit 0 (VBLANK) + AND + CBRANCH.NZ WAITVSYNC ; if set, loop +VSYNC_WAIT1: + ; wait for VBLANK to become one + LOADC FB_CTL + LOADI ; read control register + LOADC 1 ; check bit 0 (VBLANK) + AND + CBRANCH.Z VSYNC_WAIT1 ; if not set, loop + RET + +; args: number of bytes, pointer to buf, +HEXDUMP: + DUP + LOADI + LOADCP PRINTHEXW + CALL + LOADC ' ' + LOADCP CONOUT + CALL + INC 4 + + DUP + LOADI + LOADCP PRINTHEXW + CALL + LOADC ' ' + LOADCP CONOUT + CALL + INC 4 + + DUP + LOADI + LOADCP PRINTHEXW + CALL + LOADC ' ' + LOADCP CONOUT + CALL + INC 4 + + DUP + LOADI + LOADCP PRINTHEXW + CALL + LOADC ' ' + LOADCP CONOUT + CALL + INC 4 + + LOADCP NEWLINE + CALL + + SWAP ; swap pointer and counter + LOADC 16 + SUB + DUP + CBRANCH.Z HEXDUMP_END ; end if counter is zero + SWAP ; swap back counter and pointer + BRANCH HEXDUMP + +HEXDUMP_END: + DROP + DROP + RET + +; inquire cursor position +; args: pointer to columns variable, pointer to rows variable +GETCURSORPOS: + LOADCP TERM_CPR_STR + LOADCP PRINTLINE + CALL + + LOADCP CONIN ; skip ESC + CALL + DROP + LOADCP CONIN ; and '[' + CALL + DROP + + LOADC ';' + LOADCP _TERMRCVINT + CALL + STOREI + DROP + + LOADC 'R' + LOADCP _TERMRCVINT + CALL + STOREI + DROP + + RET + +; receive digits and compose an integer value +; up to a termination character or an ';' +; args: termination character +; returns: -1 on error (invalid digit) + +_TERMRCVINT: + FPADJ -4 + STORE 0 + + LOADC 0 ; start with 0 value +RCVINT_L: + LOADCP CONIN + CALL + + DUP ; duplicate received char + LOAD 0 ; compare with terminator + CMP EQ ; if equal, + CBRANCH RCVINT_XT ; exit + + LOADC '0' ; subtract ascii value to get + SUB ; numerical value + + DUP + LOADC 0 ; check if less than zero + CMP LT + CBRANCH RCVINT_ERR ; if yes, error + + DUP + LOADC 9 + CMP GT ; check if > 9 + CBRANCH RCVINT_ERR ; if yes, error + + SWAP + LOADCP _MUL10 ; old value * 10 (shift digits to the left) + CALL + + ADD ; add to value + BRANCH RCVINT_L ; next digit +RCVINT_ERR: + DROP + DROP + LOADC -1 + BRANCH RCVINT_XT2 +RCVINT_XT: + DROP +RCVINT_XT2: + FPADJ 4 + RET + +TERM_CPR_STR: .BYTE 27, "[6n", 0 ; ANSI Cursor Position Report + + .CPOOL + +GETTICKS: + LOADC IRQC_REG + LOADI + LOADC -256 + AND + BROT + BROT + BROT + RET + + .EQU CRLD_BLOCK 0 + .EQU CRLD_BYTES 4 + .EQU CRLD_ADDR 8 + .EQU CRLD_FS 12 + +; load a program image from sd card +; args: device id, block no, size in bytes +CORELOAD: + ; We need to set the FP and RP registers, + ; because we might overwrite that + ; memory area where the calling program + ; has its user and return stack + + LOADCP FP_START + STOREREG FP + LOADCP RP_START + STOREREG RP + + FPADJ -CRLD_FS + STORE CRLD_BYTES + STORE CRLD_BLOCK + DROP ; ignore device ID, + ; we support only one sd card + + ; divide bytes by 512 and add one + ; to get block count + LOAD CRLD_BYTES + LOADC 9 + LOADCP _SHRM + CALL + INC 1 + ; keep block count on stack + + ; start at address 24576 + LOADCP PROG_START + STORE CRLD_ADDR + +CRLD_LP: + ; read a block + LOAD CRLD_BLOCK + LOADCP CARDREADBLK + CALL + DROP ; ignore error for now + + LOAD CRLD_ADDR + LOADCP CARD_BUF + LOADC 128 + LOADCP _COPYWORDS + CALL + + ; advance dest pointer + LOAD CRLD_ADDR + LOADC 512 + ADD + STORE CRLD_ADDR + + ; increment block number + LOAD CRLD_BLOCK + INC 1 + STORE CRLD_BLOCK + + ; decrement block count on stack + DEC 1 + DUP + CBRANCH.NZ CRLD_LP ; if block count not zero, loop + DROP ; remove block count +CRLD_CLEAN: + ; clean up partial block + LOADC 512 + LOAD CRLD_BYTES + INC 3 ; round up to next word + LOADC -4 + AND + LOADC 511 ; get remainder by 512 + AND + SUB ; subtract to get number of remaining bytes + ; in last block + + LOAD CRLD_ADDR ; this is now the addr of the last + ; byte in the last block + 1 + OVER ; duplicate number of remaining bytes + SUB ; and subtract from addr + + SWAP ; swap addr and number of remaining bytes + LOADCP _CLEARMEM + CALL + + ; clear estack + + ; release our stack frame + FPADJ CRLD_FS + + ; jump to program start address + LOADCP PROG_START + JUMP + + ; no RET + + .CPOOL + +READDIRBLK: +; parameters: [ blkno, ptr to DirBlock, ptr to error return value, device id ] +; same routine as READBLOCK, is referenced by two names to convert buffer types + +; parameters: [ blkno, ptr to PartitionTableBlock, ptr to error return value, device id ] +READPARTBLK: +; same routine as READBLOCK, is referenced by two names to convert buffer types + +READBLOCK: +; parameters: [ blkno, ptr to IOBlock, ptr to error return value, device id ] + DROP ; ignore device id + + LOADC 0 + STOREI ; set return value to zero + DROP + SWAP ; swap blkno and ptr + LOADCP CARDREADBLK ; read that block number + CALL + DROP ; ignore error for now + ; TODO: store it via error ptr + ; ptr to PartitionTableBlock is now on ToS + LOADCP CARD_BUF + LOADC 128 + LOADCP _COPYWORDS ; copy block to destination buffer + CALL + + RET + +WRITEPARTBLK: +WRITEDIRBLK: +; parameters: [ blkno, ptr to IOBlock, ptr to error return value, device id ] +WRITEBLOCK: + DROP ; ignore device id + + LOADC 0 + STOREI ; set return value to zero + DROP + + LOADCP CARD_BUF + SWAP + LOADC 128 + LOADCP _COPYWORDS ; copy block to card_buf + CALL + + LOADCP CARDWRITEBLK ; write that block number + CALL + DROP ; ignore error for now + ; TODO: store it via error ptr + ; ptr to PartitionTableBlock is now on ToS + RET + +%include "sdcardlib.s" + + .CPOOL + +SHELLWORKFILE: .WORD 0,68 + .BLOCK 17 +SHELLCMD: .WORD 0,40 + .BLOCK 8 +SHELLARG: .WORD 0 +PARGCOUNT: .WORD 0 +PARGS: .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + .WORD 0,80 + .BLOCK 20 + +DEFAULTVOLUME: .WORD 0,32 + .BLOCK 8 + +SYSCLOCK: + .BLOCK 6 +SYSBOOTTICKS: + .WORD 0 +SYSLASTTICKS: + .WORD 0 + +; copy words to screen memory +; args: pointer to 32000 words of pixel data +PUTSCREEN: + LOADC FB_WA + LOADC 0 ; initialize write address register + STOREI + DROP + + LOADCP 32000 ; word count +PUTSCREEN_L0: + SWAP ; [ count, addr ] + DUP + LOADI ; load pixel word + LOADC FB_IO + SWAP ; swap addr and value for STOREI + STOREI ; store to vmem io register + DROP + + INC 4 ; next word + + SWAP ; swap addr and count + DEC 1 ; decrement count + + DUP + CBRANCH.NZ PUTSCREEN_L0 ; loop if count is not zero + + DROP ; remove counter and addr + DROP + + RET + + +%export _MUL +%export _MULU +%export _DIV +%export _DIVU +%export _MOD +%export _DIVMODU +%export _SHRM +%export _SHLM +%export _COPYWORDS +%export _CMPWORDS +%export _CLEARMEM diff --git a/lib/coreloader.s b/lib/coreloader.s new file mode 100644 index 0000000..542b667 --- /dev/null +++ b/lib/coreloader.s @@ -0,0 +1,279 @@ +; Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details + .ORG 4096 + +CORELOADER: + ; initialize program stack and + ; return stack pointers + LOADCP 24060 + STOREREG FP + LOADCP 24064 + STOREREG RP + + LOADCP SYSBOOTTICKS + LOADCP GETTICKS + CALL + STOREI + DROP + + LOADCP INITSDCARD + CALL + + ;LOADCP FIND_SYSPART ; no need to call, it never + ;CALL ; returns, so just fall through + + .EQU PART_START 0 + .EQU EXTENT_SIZE 4 + .EQU DIR_SIZE 8 + .EQU SLOT_NO 12 + .EQU SIZE_BYTES 16 + .EQU PRG_START_BLK 20 + .EQU FIND_FS 24 + + .EQU PARTENTRY_SIZE 64 + .EQU DIRENTRY_SIZE 64 +FIND_SYSPART: + FPADJ -FIND_FS + ; load block 0 + LOADC 0 + LOADCP CARDREADBLK + CALL + + DUP ; non-zero return code means error + CBRANCH.Z FIND_1 + + LOADCP PRINTHEXW + CALL + LOADCP NEWLINE + CALL + LOADC 0 + JUMP + +FIND_1: + DROP ; remove return code + + ;LOADC 512 + ;LOADCP CARD_BUF + ;LOADCP HEXDUMP + ;CALL + + ; address of the first partition entry + LOADCP CARD_BUF +FIND_L: + DUP ; dup addr for comparison + LOADCP SYSPART_NAME + LOADC SYSNAME_WORDS + LOADCP _CMPWORDS + CALL + CBRANCH.NZ FIND_FOUND + ; go to next entry + LOADC PARTENTRY_SIZE + ADD + + ; check if address is still + ; within the data block + DUP + LOADCP CARD_BUF,512 + CMP LT + CBRANCH FIND_L + + ; remove address + DROP + + ; not found, complain and + ; go back to ROM monitor + LOADCP SYSPART_ERR + LOADCP PRINTLINE + CALL + + LOADC 0 + JUMP + +FIND_FOUND: + ; address of the part entry is on stack + + ; check if partition is enabled + DUP ; duplicate address + LOADC 40 ; add PartFlags field offset + ADD + LOADI + LOADC 1 + AND ; check bit 0 (PartEnabled) + CBRANCH.Z FIND_L ; if not set, continue loop + + + ; address of part entry is still on stack + DUP + LOADC 44 ; add startBlock field offset + ADD + LOADI ; get start block number + STORE PART_START + + ; address of part entry is still on stack + DUP + LOADC 52 ; move to extentSize field + ADD + LOADI ; get value + STORE EXTENT_SIZE + + ; address of part entry is still on stack + LOADC 56 ; move to dirSize field + ADD + LOADI ; get value + STORE DIR_SIZE + + LOADC 0 + STORE SLOT_NO ; start with dirslot 0 + + LOAD PART_START ; start with first block of the partition +FIND_FILE: + DUP ; duplicate block number + LOADCP CARDREADBLK ; read that block + CALL + DROP ; ignore error + + ; scan directory entries for shell file name + LOADCP CARD_BUF +FIND_FILE_L: + DUP + LOADCP SHELL_NAME + LOADC SHELLNAME_WORDS + LOADCP _CMPWORDS ; compare names + CALL + CBRANCH.NZ FIND_F_FOUND ; exit loop if names match + + ; check if current dirslot no + ; is below maximum number of slots + LOAD SLOT_NO + LOAD DIR_SIZE + CMP GE + CBRANCH FIND_F_NOTFOUND ; max slots reached, exit + + ; add 1 to SLOT_NO + LOAD SLOT_NO + INC 1 + STORE SLOT_NO + + ; address is still on stack + LOADC DIRENTRY_SIZE + ADD ; go to next dir entry + + ; check if address is still + ; below end of data block + DUP + LOADCP CARD_BUF,512 + CMP LT + CBRANCH FIND_FILE_L ; if it is below, loop + + DROP ; remove dir entry addr + + ; block no is still on stack + INC 1 + BRANCH FIND_FILE ; read next block + +FIND_F_NOTFOUND: + LOADCP SHELL_ERR + LOADCP PRINTLINE + CALL + + ; remove entry addr and block number + DROP + DROP + LOADC 0 + JUMP + +FIND_F_FOUND: + ; found the file name, now check if it has the right flags + + ; address of dir entry is still on stack + DUP + LOADC 40 ; add flags field offset + ADD + LOADI ; load flags + LOADC 16 ; test for SlotFirst flag + AND + CBRANCH.Z FIND_FILE_L ; if not set, continue loop + + ;LOADCP FOUND_MSG + ;LOADCP PRINTLINE + ;CALL + + ; we got the right file, now calculate start block + ; and get file size from dir entry + + ; address of dir entry is still on stack + ; phys start block = part start + slot_no * (extent_size/512) + LOAD EXTENT_SIZE + LOADC 9 + LOADCP _SHRM + CALL + LOAD SLOT_NO + LOADCP _MUL + CALL + LOAD PART_START + ADD + + ;DUP + ;LOADCP PRINTHEXW + ;CALL + ;LOADC ' ' + ;LOADCP CONOUT + ;CALL + + STORE PRG_START_BLK + + ; address of dir entry is still on stack + LOADC 44 + ADD ; add sizeBytes field offset + LOADI ; get size in bytes + + ;DUP + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + STORE SIZE_BYTES + + ; remove block number + DROP + + ; set argument count to 0 + ; in case this gets called + ; by a terminating program + LOADCP PARGCOUNT + LOADC 0 + STOREI + DROP + + LOADC 0 ; device id is always 0 + LOAD PRG_START_BLK + LOAD SIZE_BYTES + ; release our stack frame + FPADJ FIND_FS + + ; load program + LOADCP CORELOAD + CALL + + LOADC 0 + JUMP + + .CPOOL + + .EQU SYSNAME_WORDS 4 +SYSPART_NAME: + .WORD 6, 32 + .BYTE "SYSTEM" +SYSPART_ERR: + .BYTE "No ""SYSTEM"" partition.",13,10,10,0 + .EQU SHELLNAME_WORDS 5 +SHELL_NAME: + .WORD 10,32 + .BYTE "shell.prog" +SHELL_ERR: + .BYTE "No shell on ""SYSTEM"" partition.",13,10,10,0 + +FOUND_MSG: + .BYTE " shell.prog ",0 + +%include corelib.s diff --git a/lib/float32.s b/lib/float32.s new file mode 100644 index 0000000..4b0ad9c --- /dev/null +++ b/lib/float32.s @@ -0,0 +1,1053 @@ +; Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details + +; FLOAT32 format: +;| 31 | 30-8 | 7-0 | +;|sign| fraction | exp | + +; exp has a bias of 128 +; sign = 1: negative number + + .EQU FLOAT32_EXPMASK %00000000000000000000000011111111 + .EQU FLOAT32_FRCMASK %01111111111111111111111100000000 + .EQU FLOAT32_SGNMASK %10000000000000000000000000000000 + .EQU FLOAT32_FRCMSBM %01000000000000000000000000000000 + .EQU FLOAT32_OVRFLOW %10000000000000000000000000000000 + .EQU FLOAT32_RNDMASK %00000000000000000000000010000000 + .EQU FLOAT32_RNDINCR %00000000000000000000000100000000 + .EQU FLOAT32_FRCLSB %00000000000000000000000100000000 + + .EQU FLOAT32_MAX_EXP 255 + .EQU FLOAT32_BIAS 127 + .EQU FLOAT32_FRCBITS 23 + .EQU FLOAT32_EXP_BITS 8 + +; unpack a float32 value into +; three fields: exponent, fraction, sign +; ptr is a pointer to an array with the three fields +; the sign flag is 0 or 1. + +; parameters: [ floatval, ptr ] +_UNPACKFLOAT32: + OVER ; [ float, ptr, float ] + LOADC FLOAT32_EXPMASK ; [ float, ptr, float, mask ] + AND ; [ float, ptr, exp ] + STOREI 4 ; [ float, ptr + 4 ] + OVER ; [ float, ptr + 4, float ] + LOADCP FLOAT32_FRCMASK ; [ float, ptr + 4 , float, mask ] + AND ; [ float, ptr + 4 , frac ] + STOREI 4 ; [ float, ptr + 8 ] + SWAP ; [ ptr + 8, float ] + LOADCP FLOAT32_SGNMASK ; [ ptr + 8, float, mask ] + AND ; [ ptr + 8, signbit ] + LOADC 0 ; [ ptr + 8, signbit, 0 ] + CMPU NE ; [ ptr + 8, sign ] + STOREI ; [ ptr + 8 ] + DROP ; [] + RET + +; pack exponent, fraction, sign into a single 32-bit value +; ptr is a pointer to an array with the three fields +; parameters: [ ptr ] +; returns: float value +_PACKFLOAT32: + LOADI.S1.X2Y ; [ ptr, exp ] + OVER ; [ ptr, exp, ptr ] + INC 4 ; [ ptr, exp, ptr + 4 ] + LOADI ; [ ptr, exp, frac ] + LOADCP FLOAT32_FRCMASK ; [ ptr, exp, frac, mask ] + AND ; [ ptr, exp, frac ] + OR ; [ ptr, exp|frac ] + OVER ; [ ptr, exp|frac, ptr ] + INC 8 ; [ ptr, exp|frac, ptr + 8] + LOADI ; [ ptr, exp|frac, signflag ] + CBRANCH.Z PACKFL_1 ; [ ptr, exp | frac ] + LOADCP FLOAT32_SGNMASK ; [ ptr, exp|frac, signmask ] + ADD ; [ ptr, floatval ] +PACKFL_1: + SWAP ; [ floatval, ptr ] + DROP ; [ floatval ] + RET + +; adds to floating point values a and b +; parameters: [ a, b ] +; returns: sum of a and b + .EQU FL_E_A 0 + .EQU FL_F_A 4 + .EQU FL_S_A 8 + .EQU FL_E_B 12 + .EQU FL_F_B 16 + .EQU FL_S_B 20 + .EQU FL_E_R 24 + .EQU FL_F_R 28 + .EQU FL_S_R 32 + .EQU ADDFL_SUB 36 + .EQU ADDFL_FS 40 + +_ADDFLOAT32: + FPADJ -ADDFL_FS + ; unpack b into e_b and f_b + LOADREG FP + LOADC FL_E_B + ADD ; addr of FL_E_B + LOADCP _UNPACKFLOAT32 + CALL + ; unpack a into e_a and f_a + LOADREG FP ; addr of FL_E_A + LOADCP _UNPACKFLOAT32 + CALL + + + ; if abs(a) < abs(b), swap a and b (this includes e_a < e_b) + LOAD FL_E_A + LOAD FL_E_B + CMPU GT + CBRANCH ADDFL_1 ; don't swap if e_a > e_b + ; e_a <= e_b + ; check if e_a < e_b + LOAD FL_E_A + LOAD FL_E_B + CMPU LT + CBRANCH ADDFL_1_1 ; swap if e_a < e_b + ; e_a = e_b + ; check fractions + LOAD FL_F_A + LOAD FL_F_B + CMPU GE + CBRANCH ADDFL_1 ; dont't swap if f_a >= f_b + +ADDFL_1_1: + ;LOADC '"' + ;LOADCP CONOUT + ;CALL + + LOAD FL_E_A + LOAD FL_E_B + STORE FL_E_A + STORE FL_E_B + LOAD FL_F_A + LOAD FL_F_B + STORE FL_F_A + STORE FL_F_B + LOAD FL_S_A + LOAD FL_S_B + STORE FL_S_A + STORE FL_S_B +ADDFL_1: + ; e_r := e_a, result exp is exp from a + LOAD FL_E_A + STORE FL_E_R + + LOAD FL_S_A ; take result sign from a (which might be swapped with b here) + STORE FL_S_R + + LOAD FL_S_A ; check if the signs of a and b differ + LOAD FL_S_B + XOR ; if the xor of both sign flags is 1, signs are not the same + STORE ADDFL_SUB ; then we do a subtraction later + + ; ? if (e_a - e_b) > precision +1: + ; ? set f_r to f_a + + ; shift right f_b by (e_a - e_b) bits + LOAD FL_E_A + LOAD FL_E_B + SUB + + ;LOADCP NEWLINE + ;CALL + ;LOADC 'e' + ;LOADCP CONOUT + ;CALL + ;DUP + ;LOADCP PRINTDEC + ;CALL + ;LOADCP NEWLINE + ;CALL + + LOAD FL_F_B ; on stack now: [ counter, f_b ] +ADDFL_L1: + OVER ; check counter for zero + CBRANCH.Z ADDFL_2 ; if yes, loop is done + SHR ; shift right + SWAP ; swap counter and value + DEC 1 ; decrement counter + SWAP ; swap back + BRANCH ADDFL_L1 ; next +ADDFL_2: + STORE FL_F_B ; store result + DROP ; remove counter + + ;LOADC 'a' + ;LOADCP CONOUT + ;CALL + ;LOAD FL_F_A + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + ;LOADC 'b' + ;LOADCP CONOUT + ;CALL + ;LOAD FL_F_B + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + ; set f_r to f_a + f_b + ; (or f_r = f_a - f_b if we have a negative sign somewhere) + LOAD FL_F_A + LOAD FL_F_B + LOAD ADDFL_SUB ; do we need a subtract? + CBRANCH ADDFL_2_1 ; yes, skip add instruction + ADD ; no, do add and skip sub instruction + BRANCH ADDFL_2_2 +ADDFL_2_1: + ;LOADC '-' + ;LOADCP CONOUT + ;CALL + ;LOADCP NEWLINE + ;CALL + + SUB +ADDFL_2_2: + ;DUP + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + ; normalize: + ; if overflow bit of f_r is set, scale right + DUP + LOADCP FLOAT32_OVRFLOW ; isolate overflow bit + AND + + CBRANCH.Z ADDFL_3 + + ;LOADC 'V' + ;LOADCP CONOUT + ;CALL + + ; scale right: shift right f_r by one, increment e_r by one + SHR + LOAD FL_E_R + INC 1 + STORE FL_E_R +ADDFL_3: + ; check if result is zero + DUP + CBRANCH.NZ ADDFL_3_1 + ; set exponent to something useful + LOADC 0 + STORE FL_E_R + ; clear sign, we don't want -0 + LOADC 0 + STORE FL_S_R + + BRANCH ADDFL_4 + +ADDFL_3_1: + ; if bit 30 of f_r is zero, scale left + DUP + LOADCP FLOAT32_FRCMSBM ; isolate msb of fraction + AND + CBRANCH.NZ ADDFL_4 + + ;LOADC '<' + ;LOADCP CONOUT + ;CALL + ;LOADCP NEWLINE + ;CALL + + ; scale left and repeat previous step + SHL ; shift fraction + LOAD FL_E_R ; decrement exponent + DEC 1 + STORE FL_E_R + BRANCH ADDFL_3 ; repeat +ADDFL_4: + ; round: + ; simple round algorithm: if the bit below + ; the least significat bit is 1, round up + ; and check the overflow bit again + + DUP + LOADC FLOAT32_RNDMASK ; test rounding bit + AND + CBRANCH.Z ADDFL_5 ; if not set, skip rounding + + ;LOADC '~' + ;LOADCP CONOUT + ;CALL + ;LOADCP NEWLINE + ;CALL + + LOADC FLOAT32_RNDINCR + ADD + + LOADCP FLOAT32_FRCMASK ; remove rounded off bits + AND + + BRANCH ADDFL_3_1 ; check for overflow again +ADDFL_5: + + STORE FL_F_R + + ;LOADCP NEWLINE + ;CALL + ;LOADC 'E' + ;LOADCP CONOUT + ;CALL + + ;LOAD FL_E_R + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + ; check exponent range overflow + LOADCP FLOAT32_EXP_CHECK + CALL +ADDFL_6: + ; pack e_r,f_r,s_r into r + LOADREG FP + LOADC FL_E_R + ADD + LOADCP _PACKFLOAT32 + CALL + + FPADJ ADDFL_FS + RET + +; check exponent value of local var FL_E_R +; for overflow and issue runtime error on failure. +; uses stack frame of caller. +FLOAT32_EXP_CHECK: + ; check exponent range overflow + LOAD FL_E_R + LOADC FLOAT32_MAX_EXP + CMPU LE + CBRANCH FLOAT32_EXP_XT + + LOADCP FLOAT32_ERR_OVR + LOADCP _RUNTIME_ERR + JUMP +FLOAT32_EXP_XT: + RET + +; subtract floating point value b from a +; parameters: [ a, b ] +; returns: a - b +_SUBFLOAT32: + ; just flip sign bit of b and continue with _ADDFLOAT32 + LOADCP $80000000 + XOR + BRANCH _ADDFLOAT32 + +; multiply two floating point values a and b +; parameters: [ a, b ] +; returns: a * b + .EQU MULFL_FS 36 +_MULFLOAT32: + FPADJ -MULFL_FS ; same stack frame layout as _ADDFLOAT32 + + DUP + CBRANCH.NZ _MULFLOAT32_1 ; check if b is zero + ; if yes, just return zero + NIP ; remove a, take b (which is zero) as return value + BRANCH _MULFLOAT32_X +_MULFLOAT32_1: + ; unpack b into e_b and f_b + LOADREG FP + LOADC FL_E_B + ADD ; addr of FL_E_B + LOADCP _UNPACKFLOAT32 + CALL + + DUP + CBRANCH.NZ _MULFLOAT32_2 ; check if a is zero + ; if yes, return zero + ; take a (which is zero) as return value + BRANCH _MULFLOAT32_X +_MULFLOAT32_2: + ; unpack a into e_a and f_a + LOADREG FP ; addr of FL_E_A + LOADCP _UNPACKFLOAT32 + CALL + + ; s_r = s_a xor s_b + LOAD FL_S_A + LOAD FL_S_B + XOR + STORE FL_S_R + + ; e_r = e_a + e_b - bias + LOAD FL_E_A + LOAD FL_E_B + ADD + LOADC FLOAT32_BIAS + SUB + STORE FL_E_R + + ; check exponent range overflow + LOADCP FLOAT32_EXP_CHECK + CALL + ; f_r = fractmult(f_a, f_b) + LOADCP _FRACTMULT + CALL + + LOADCP NORMROUND_FL ; normalize and round + CALL + + ; pack result + LOADREG FP + LOADC FL_E_R + ADD + LOADCP _PACKFLOAT32 + CALL +_MULFLOAT32_X: + ; 32 bit float result is now on stack + FPADJ MULFL_FS + RET + +; multiply fractions. +; uses stack frame/local variables from caller. +; FL_F_B is destroyed. +; result is written to FL_R +_FRACTMULT: + LOADC FLOAT32_FRCBITS ; this is the counter which we keep on stack + + LOADC 0 ; start with result zero + STORE FL_F_R + + ; for each digit of the fraction of b, from right to left, + ; the fraction of a is added to the result, if that digit is 1. + ; on each iteration, the result is shifted right. +_FRACTMULT_1: + LOAD FL_F_R + SHR + STORE FL_F_R ; shift result frac for next iteration + + LOAD FL_F_B + LOADC FLOAT32_FRCLSB + AND ; isolate lowest bit + + CBRANCH.Z _FRACTMULT_2 ; if not set, don't add in this iteration + + LOAD FL_F_R ; otherwise, add fraction of a to result + LOAD FL_F_A + ADD + STORE FL_F_R + +_FRACTMULT_2: + LOAD FL_F_B + SHR + STORE FL_F_B ; shift fraction b for next digit + + DEC 1 ; decrease counter + DUP + CBRANCH _FRACTMULT_1 ; if not zero, next loop iteration + + DROP ; drop counter + RET + +; divide floating point value a by b +; parameters: [ a, b ] +; returns: a / b + .EQU DIVFL_FS 36 +_DIVFLOAT32: + FPADJ -DIVFL_FS ; same stack frame layout as _ADDFLOAT32 + DUP + CBRANCH.NZ _DIVFLOAT32_0 ; check b for zero + LOADCP FLOAT32_ERR_DIVZ ; if it is, we have a division by zero + LOADCP _RUNTIME_ERR ; and we issue a runtime error + JUMP +_DIVFLOAT32_0: + OVER ; check a for zero + CBRANCH.NZ _DIVFLOAT32_0_1 + ; if it is we just return zero + DROP ; remove args + DROP + LOADC 0 + BRANCH _DIVFLOAT32_XT + +_DIVFLOAT32_0_1: + ; unpack b into e_b and f_b + LOADREG FP + LOADC FL_E_B + ADD ; addr of FL_E_B + LOADCP _UNPACKFLOAT32 + CALL + ; unpack a into e_a and f_a + LOADREG FP ; addr of FL_E_A + LOADCP _UNPACKFLOAT32 + CALL + + ; s_r = s_a xor s_b + LOAD FL_S_A + LOAD FL_S_B + XOR + STORE FL_S_R + + ; e_r = e_a - e_b + bias + LOAD FL_E_A + LOAD FL_E_B + SUB + LOADC FLOAT32_BIAS + ADD + STORE FL_E_R + + ; check exponent range overflow + LOADCP FLOAT32_EXP_CHECK + CALL + ; f_r = fractdiv(f_a, f_b) + LOADCP _FRACTDIV + CALL + + LOADCP NORMROUND_FL ; normalize and round + CALL + + ; pack result + LOADREG FP + LOADC FL_E_R + ADD + LOADCP _PACKFLOAT32 + CALL +_DIVFLOAT32_XT: + ; 32 bit float result is now on stack + FPADJ DIVFL_FS + RET + +; divide fraction of a by b. +; uses stackframe of caller. +; FL_F_A is destroyed. +; places result into FL_F_R. +_FRACTDIV: + LOADC 0 + STORE FL_F_R + + LOADC FLOAT32_FRCBITS ; load counter +_FRACTDIV_1: + LOAD FL_F_R ; load result for later + LOAD FL_F_B + LOAD FL_F_A + CMPU GT + CBRANCH _FRACTDIV_2 ; if b > a, skip next section + INC 1 ; a fits into b, so add 1 to result + LOAD FL_F_A ; subtract divisor from dividend + LOAD FL_F_B + SUB + STORE FL_F_A + +_FRACTDIV_2: + SHL ; shift result left for next digit + STORE FL_F_R ; and store it again + LOAD FL_F_A ; shift the dividend left for next digit + SHL + STORE FL_F_A + + DEC 1 ; decrement counter + DUP + CBRANCH.NZ _FRACTDIV_1 ; loop if it is not zero + + DROP ; remove counter + + LOAD FL_F_R ; undo the last shift of the result + SHR + BROT ; and shift left again to make room for the exponent + STORE FL_F_R + RET + + +; normalize and round f_r. +; uses stack frame of caller. +NORMROUND_FL: + LOAD FL_F_R +NORMFL_0: + ; if overflow bit of f_r is set, scale right + DUP + LOADCP FLOAT32_OVRFLOW ; isolate overflow bit + AND + CBRANCH.Z NORMFL_1 ; if bit is zero, skip the scaling + + ; scale right: shift right f_r by one, increment e_r by one + SHR + LOAD FL_E_R + INC 1 + STORE FL_E_R + +NORMFL_1: + ; check if result is zero + DUP + CBRANCH.NZ NORMFL_1_1 + ; set exponent to something useful + LOADC 0 + STORE FL_E_R + ; clear sign flag, we don't want -0 + LOADC 0 + STORE FL_S_R + + BRANCH NORMFL_2 + + ; normalize: + ; if bit 30 of f_r is zero, scale left +NORMFL_1_1: + DUP + LOADCP FLOAT32_FRCMSBM ; isolate msb of fraction + AND + CBRANCH.NZ NORMFL_2 ; skip if bit is set + ; scale left and repeat previous step + SHL ; shift fraction + LOAD FL_E_R ; decrement exponent + DEC 1 + STORE FL_E_R + BRANCH NORMFL_1_1 ; repeat + +NORMFL_2: + ; round: + ; simple round algorithm: if the bit below + ; the least significat bit is 1, round up + ; and check the overflow bit again + DUP + LOADC FLOAT32_RNDMASK ; test rounding bit + AND + CBRANCH.Z NORMFL_3 ; if not set, skip rounding + + LOADC FLOAT32_RNDINCR + ADD + + LOADCP FLOAT32_FRCMASK ; remove rounded off bits + AND + + BRANCH NORMFL_0 ; check for overflow again +NORMFL_3: + STORE FL_F_R + RET + +; return the fractional part of a floating point number +; parameters: float32 value +; returns: float32 value + .EQU FRACTFL_EXP 12 + .EQU FRACTFL_FS 20 +_FRACTFLOAT32: + FPADJ -FRACTFL_FS + DUP ; check for zero + CBRANCH.Z FRACTFL_XT ; if yes, just return zero + LOADREG FP + LOADCP _UNPACKFLOAT32 + CALL + + LOAD FL_E_A ; remove bias from exponent + LOADC FLOAT32_BIAS + SUB + DUP + STORE FRACTFL_EXP + + LOADC 0 ; if the exponent is negative, + CMP LT ; there are no digits before the point + CBRANCH FRACTFL_PK ; and we just return the same value + + LOAD FRACTFL_EXP ; the exponent indicates how far + ; we need to shift the fraction to the left + INC 1 ; at exp 0 we need to shift by 1 + + LOADC FLOAT32_BIAS - 1 + STORE FL_E_A ; the new exponent is -1 because we + ; shifted by (old exp + 1) bits + + LOAD FL_F_A ; load fraction, shift count is already on stack +FRACTFL_L: + SHL ; shift fraction + SWAP ; swap fraction and shift count + DEC 1 ; decrement count + SWAP ; swap back shift count and fraction + OVER ; check count for zero + CBRANCH FRACTFL_L ; if not, loop + + NIP ; remove count + LOADCP FLOAT32_FRCMASK + AND ; remove superfluous bits + + DUP ; check if fraction is zero + CBRANCH.NZ FRACTFL_1 + ; if yes, directly return + BRANCH FRACTFL_XT + + ; normalize +FRACTFL_1: + DUP + LOADCP FLOAT32_FRCMSBM ; isolate msb of fraction + AND + CBRANCH.NZ FRACTFL_2 ; skip if bit is set + ; scale left and repeat previous step + SHL ; shift fraction + LOAD FL_E_A ; decrement exponent + DEC 1 + STORE FL_E_A + BRANCH FRACTFL_1 ; repeat +FRACTFL_2: + STORE FL_F_A +FRACTFL_PK: + LOADREG FP + LOADCP _PACKFLOAT32 + CALL +FRACTFL_XT: + FPADJ FRACTFL_FS + RET + +; truncate a floating point number - return +; the integer value before the decimal point. +; issues a runtime error if the integer value +; does not fit into a signed 32-bit integer. +; parameters: float32 value +; returns: integer + .EQU TRUNCFL_SHIFT 12 + .EQU TRUNCFL_FS 16 +_TRUNCFLOAT32: + FPADJ -TRUNCFL_FS + LOADREG FP + LOADCP _UNPACKFLOAT32 + CALL + + LOAD FL_E_A ; remove bias from exponent + LOADC FLOAT32_BIAS + SUB + DUP + STORE FL_E_A + + ; if the exponent + LOADC 0 ; is negative, + CMP LT ; our result is zero + CBRANCH TRUNCFL_ZERO + + ; shift fraction all the way to the right + LOAD FL_F_A ; shift fraction right by 8 bits + BROT ; by rotating 3*8 bits left + BROT ; we know that the original bits 7-0 + BROT ; are zero + + ; calculate number of bits to shift: + ; fraction bits - 1 - exponent + LOADC FLOAT32_FRCBITS - 1 + LOAD FL_E_A + SUB + DUP + STORE TRUNCFL_SHIFT + LOADC 0 ; is shift count >= 0? + CMP GE + CBRANCH TRUNCFL_2 + + ; shift count is negative, need to shift left + ; check for integer overflow first + LOAD TRUNCFL_SHIFT + NOT ; negate shift count + INC 1 + + DUP ; shift count >= bits in a word - bits in the fraction? + LOADC 32 - FLOAT32_FRCBITS + CMP GE + CBRANCH TRUNCFL_ERR ; then we have an overflow + + ; otherwise, shift n bits left +TRUNCFL_1: + DUP + CBRANCH.Z TRUNCFL_3 ; if zero, we are done + + DEC 1 ; decrement shift count + SWAP ; swap shift count and fraction + SHL ; shift fraction left + SWAP ; swap back + BRANCH TRUNCFL_1 ; and loop + +TRUNCFL_2: ; shift right, fraction is on ToS + LOAD TRUNCFL_SHIFT ; bits to shift +TRUNCFL_L1: + DUP + CBRANCH.Z TRUNCFL_3 ; if zero, we are done + + DEC 1 ; decrement shift count + SWAP ; swap shift count and fraction + SHR ; shift fraction right + SWAP ; swap back + BRANCH TRUNCFL_L1 ; and loop +TRUNCFL_3: + DROP ; drop shift count + BRANCH TRUNCFL_EXIT +TRUNCFL_ZERO: + LOADC 0 +TRUNCFL_EXIT: + LOAD FL_S_A ; check sign + CBRANCH.Z TRUNCFL_EXIT1 + ; if not zero, negate result + NOT + INC 1 +TRUNCFL_EXIT1: + FPADJ TRUNCFL_FS + RET + +TRUNCFL_ERR: + DROP + LOADCP FLOAT32_ERR_TRUNC + LOADCP _RUNTIME_ERR + JUMP + +; like _TRUNCFLOAT32, but return a float32 value +; parameters [ float value ] +; returns: float value +; TODO: write a real routine which might be faster +; than just calling _TRUNCFLOAT32 and INTTOFLOAT32. +; Also, _TRUNCFLOAT32 can cause an integer overflow +; where INT should not. +_INTFLOAT32: + LOADCP _TRUNCFLOAT32 + CALL + LOADCP _INTTOFLOAT32 + CALL + RET + + .CPOOL + +; multiply/divide a float value by a multitude of 2 +; shift count < 1: shift right (divide) +; shuft count > 0: shift left (multiply) +; parameters: [ float value, shift count ] +; returns: float value + .EQU SHF32_FS 36 + .EQU SHF32_COUNT 12 +SHIFTFLOAT32: + FPADJ -SHF32_FS + + ; store shift count parameter + STORE SHF32_COUNT + ; Unpack float value. + ; We use the result variable slot + ; because EXP_CHECK uses that. + LOADREG FP + LOADC FL_E_R + ADD + LOADCP _UNPACKFLOAT32 + CALL + + ; we just add the shift count to + ; the exponent + LOAD FL_E_R + LOAD SHF32_COUNT + ADD + STORE FL_E_R + + ; and check for overflow + LOADCP FLOAT32_EXP_CHECK + CALL + + ; pack up the result + LOADREG FP + LOADC FL_E_R + ADD + LOADCP _PACKFLOAT32 + CALL + + FPADJ SHF32_FS + RET + +; convert an integer to a float32 +; parameters: an integer +; returns: a float32 value + .EQU INTF32_FS 12 +_INTTOFLOAT32: + FPADJ -INTF32_FS + + ; is intval zero? + DUP + CBRANCH.Z INTTOFLOAT32_XT ; if yes, we are done, float zero has the same + ; representation as integer zero + + ; is intval < 0? + LOADC 0 + CMP.S0 LT + DUP + STORE FL_S_A ; store cmp result as sign flag + CBRANCH.Z INTF32_1 ; skip negate if cmp result is 0 + ; negate + NOT + INC 1 +INTF32_1: + LOADC 30 ; set counter +INTF32_L: + ; loop if bit 31 is not set: + SWAP ; swap counter and value (value is now ToS) + + LOADCP $40000000 + AND.S0 + CBRANCH INTF32_2 + ; shift left + SHL + ; swap counter and value again (counter is now ToS) + SWAP + ; decrease counter + DEC 1 + BRANCH INTF32_L +INTF32_2: + ; store shifted value as fraction + STORE FL_F_A + ; set exponent to counter + bias + LOADC FLOAT32_BIAS + ADD + STORE FL_E_A + ; pack components + LOADREG FP + LOADCP _PACKFLOAT32 + CALL + BRANCH INTTOFLOAT32_XT +INTTOFLOAT32_XT: + FPADJ INTF32_FS + RET + +; get the binary exponent of a floating point value +; (without the bias) +; parameters: [ float value ] +; returns: exponent (-128..128) +_GETFLOAT32EXP: + LOADC FLOAT32_EXPMASK + AND + LOADC FLOAT32_BIAS + SUB + RET + +; compare an integer to a floating point value +; parameters: a:integer, b: float +; calls INTTOFLOAT32 on a, then calls CMPFLOAT32 +; returns: -1 if a < b +; 0 if a = b +_CMPINTFLOAT32: + SWAP ; swap a and b, a is now on top of stack + LOADCP _INTTOFLOAT32 + CALL ; a is now a float + SWAP ; swap a and b back, b is on top of stack again + ; fallthrough to CMPFLOAT32 + +; compare two floating point values +; parameters: two floating point values a and b +; returns: -1 if a < b +; 0 if a = b +; 1 if a > b + .EQU CMPFL_FS 24 +_CMPFLOAT32: + FPADJ -CMPFL_FS + ; unpack b + LOADREG FP + LOADC FL_E_B + ADD + LOADCP _UNPACKFLOAT32 + CALL + ;unpack a + LOADREG FP + LOADCP _UNPACKFLOAT32 + CALL + + ;if sign(a) and not sign(b): + ; return -1 + ;if not sign(a) and sign(b): + ; return 1 + LOAD FL_S_A + LOAD FL_S_B + XOR + CBRANCH.Z CMPFL_2 ; jump if signs are the same + ; signs are not the same + LOAD FL_S_A + CBRANCH.Z CMPFL_1 ; jump if a is positive + ; a is negative, b must be positive, so a < b +CMPFL_M1: + LOADC -1 + BRANCH CMPFL_XT +CMPFL_1: + ; a is positive, b must be negative, so a > b + LOADC 1 + BRANCH CMPFL_XT +CMPFL_2: + ; signs are the same, compare exponents now. + ; we can compare the exponent values directly without + ; subtracting the bias because negative exponents + ; are smaller than positive exponents due to the added + ; bias. + ; if we determine a result, from now on the result + ; must be inverted if the sign of a and b is negative. + + ;if exp(a) < exp(b): + ; return -1 * sign(a) + LOAD FL_E_A + LOAD FL_E_B + CMPU GE + CBRANCH CMPFL_3 ; jump if exp(a) >= exp(b) + ; exp(a) < exp(b), so abs(a) < abs(b) + LOADC -1 +CMPFL_2_1: + ; invert result if signs of a and b are negative + LOAD FL_S_A + CBRANCH.Z CMPFL_XT ; sign is clear, no need to invert + + NOT ; negate result and exit + INC 1 + BRANCH CMPFL_XT +CMPFL_3: + ; exp(a) >= exp(b) + ; check if exp(a) > exp(b) + LOAD FL_E_A + LOAD FL_E_B + CMPU GT + CBRANCH CMPFL_5 ; jump if yes + ; exp(a) = exp(b) + ; exponents are the same, compare fractions now + + ;if frac(a) < frac(b): + ; return -1 * sign(a) + LOAD FL_F_A + LOAD FL_F_B + CMPU GE + CBRANCH CMPFL_4 ; jump if frac(a) >= frac(b) + + ; frac(a) < frac(b) + LOADC -1 + BRANCH CMPFL_2_1 ; check for inversion of result + ;if frac(a) > frac(b): + ; return 1 * neg_result +CMPFL_4: + ; frac(a) >= frac(b) + ; check if frac(a) > frac(b) + LOAD FL_F_A + LOAD FL_F_B + CMPU GT + CBRANCH CMPFL_5 ; jump if frac(a) > frac(b) + ; frac(a) = frac(b) + LOADC 0 + BRANCH CMPFL_XT +CMPFL_5: + ; exp(a) > exp(b): + ; return 1 * sign(a) + LOADC 1 + BRANCH CMPFL_2_1 ; check for inversion of result +CMPFL_XT: + FPADJ CMPFL_FS + RET + +; Negate a float32 number. +; just flip the highest bit, no +; need to unpack. +; if it is zero, do nothing, we +; do not want a -0.0 value +_NEGFLOAT32: + DUP + CBRANCH.Z _NEGFL_XT + LOADCP $80000000 + XOR +_NEGFL_XT: + RET + + .CPOOL + +FLOAT32_ERR_OVR: + .BYTE "floating point overflow",0 +FLOAT32_ERR_TRUNC: + .BYTE "integer overflow",0 +FLOAT32_ERR_DIVZ: + .BYTE "float division by zero",0 diff --git a/lib/rommon.s b/lib/rommon.s new file mode 100644 index 0000000..a967e4b --- /dev/null +++ b/lib/rommon.s @@ -0,0 +1,805 @@ + .EQU CR 13 + .EQU LF 10 + .EQU EOT 4 + .EQU ACK 6 + .EQU NAK 21 + .EQU STX 2 + .EQU UART_REG 2048 + .EQU MON_ADDR 64512 + + BRANCH 2 ; the very first instruction is not + ; executed correctly + LOADCP 65020 ; initialise FP and RP registers + STOREREG FP + LOADCP 65024 + STOREREG RP + + LOADCP MON_ADDR + LOADCP 4096 + STOREI + DROP +CMDLOOP0: + LOADC MESSAGE + LOADC PRINTLINE + CALL + +CMDLOOP: + LOADC NEWLINE + CALL + LOADC PROMPT + CALL +CMDLOOP1: + LOADC CONIN + CALL + LOADC TOUPPER + CALL + + DUP + LOADC CONOUT + CALL + + LOADC 'A' + CMP.S0 EQ + CBRANCH.Z CMD1 + LOADC CMD_A + CALL + BRANCH CMDLOOP2 +CMD1: + LOADC 'X' + CMP.S0 EQ + CBRANCH.Z CMD2 + LOADC CMD_X + CALL + BRANCH CMDLOOP2 +CMD2: + LOADC 'D' + CMP.S0 EQ + CBRANCH.Z CMD3 + LOADC CMD_D + CALL + BRANCH CMDLOOP2 +CMD3: + LOADC 'G' + CMP.S0 EQ + CBRANCH.Z CMD4 + LOADC CMD_G + CALL + BRANCH CMDLOOP2 +CMD4: + LOADC 'L' + CMP.S0 EQ + CBRANCH.Z CMD5 + LOADC CMD_L + CALL + BRANCH CMDLOOP2 +CMD5: + LOADC 'B' + CMP.S0 EQ + CBRANCH.Z CMD6 + LOADC CMD_B + CALL + BRANCH CMDLOOP2 +CMD6: + DROP + BRANCH CMDLOOP0 +CMDLOOP2: + DROP + BRANCH CMDLOOP + +; ---- Command 'A': set current address +CMD_A: + LOADC 32 + LOADC CONOUT + CALL + LOADC READHEX + CALL + CBRANCH.Z CMD_A_INVALID ; 0 if not valid input + LOADCP MON_ADDR + SWAP + STOREI + DROP ; drop STOREI address + RET +CMD_A_INVALID: + DROP + LOADC '.' + LOADC CONOUT + CALL + RET + +; ---- Command 'X': examine current address +CMD_X: + FPADJ -8 ; reserve space for 4 bytes of local variables + LOADCP MON_ADDR + LOADI + STORE 0 ; current memory address + LOADC 4 ; print 8 words + STORE 4 ; Loop counter +CMD_X_LOOP: + LOADC 32 ; print a a space + LOADC CONOUT + CALL + LOAD 0 ; load word via current address + LOADI + LOADC PRINTHEXW ; print it + CALL + LOAD 0 + INC 4 ; increment current address + STORE 0 + LOAD 4 + DEC 1 + DUP + STORE 4 + CBRANCH.NZ CMD_X_LOOP + LOADCP MON_ADDR + LOAD 0 + STOREI + DROP + FPADJ 8 + RET + +; ---- Command 'D': deposit words at current address +CMD_D: + FPADJ -4 + LOADC 4 ; max number of words + STORE 0 +CMD_D_LOOP: + LOADC 32 ; print a space + LOADC CONOUT + CALL + LOADC READHEX + CALL + DUP + CBRANCH.Z CMD_D_EXIT ; check for invalid input + SWAP ; swap return code and value + LOADCP MON_ADDR + LOADI ; get current address + SWAP ; swap address and value for STOREI + STOREI 4 ; store the value with post-increment of address + LOADCP MON_ADDR + SWAP ; swap destination address and value for STOREI + STOREI ; store the new address + DROP + LOADC 2 ; compare return code (swapped above) to 2 + CMP EQ ; check for valid input and return key + CBRANCH CMD_D_EXIT + LOAD 0 + DEC 1 + DUP + STORE 0 + CBRANCH.NZ CMD_D_LOOP +CMD_D_EXIT: + FPADJ 4 + RET + +CMD_G: + DROP ; remove input char + LOADCP NEWLINE + CALL + LOADCP MON_ADDR + LOADI + JUMP + +CMD_L: + LOADCP NEWLINE + CALL + LOADCP RCVBLOCKS + CALL + LOADCP NEWLINE + CALL + RET + +PROMPT: + LOADC '[' + LOADC CONOUT + CALL + LOADCP MON_ADDR + LOADI + LOADC PRINTHEXW + CALL + LOADC PROMPT2 + LOADC PRINTLINE + CALL + RET + +NEWLINE: + LOADC CR + LOADC CONOUT + CALL + LOADC LF + LOADC CONOUT + CALL + RET + +; print string of byte characters +; takes pointer to string on eval stack +PRINTLINE: + DUP ; duplicate address as arg to printchar + LOADC PRINTCHAR + CALL + CBRANCH.Z PRINTLINE_EXIT ; if char is zero, exit + INC 1 ; increment address + BRANCH PRINTLINE +PRINTLINE_EXIT: + DROP ; remove address from stack + RET + +; print a single character +; takes a byte pointer on eval stack +; returns character on eval stack +PRINTCHAR: + LOADI.S1.X2Y ; load word, keep address on stack + BSEL ; select byte of a word via address + DUP ; check for null byte + CBRANCH.Z PRINTCHAR_XT + DUP + LOADC CONOUT + CALL +PRINTCHAR_XT: + RET + +; print a 32-bit hexadecimal number +; takes the value on the stack + +PRINTHEXW: + BROT + DUP + LOADC PRINTHEXB + CALL + BROT + DUP + LOADC PRINTHEXB + CALL + BROT + DUP + LOADC PRINTHEXB + CALL + BROT + LOADC PRINTHEXB + CALL + RET + +PRINTHEXB: + DUP + SHR + SHR + SHR + SHR + LOADC PRINTNIBBLE + CALL + LOADC PRINTNIBBLE + CALL + RET + +PRINTNIBBLE: + LOADC 15 + AND ; isolate nibble + LOADC 10 + CMPU.S0 GE ; nibble >= 10 ? + CBRANCH.NZ PRINTNIBBLE_1 ; then print a-f + LOADC '0' ; else print 0-9 + BRANCH PRINTNIBBLE_2 +PRINTNIBBLE_1: + LOADC 55 ; 55 + 10 == 'A' +PRINTNIBBLE_2: + ADD + LOADC CONOUT + CALL + RET + +; ------ read a 8-digit hexadecimal number from the console +; stores variables on the user stack, so the FP register must be +; inizialized. +; returns two values on the eval stack: +; - return code (topmost) +; 0 - no valid number +; 1 - valid number +; 2 - valid number and enter was pressed +; - result value + +READHEX: + FPADJ -8 + LOADC 0 ; current value + STORE 0 + LOADC 8 ; max number of digits + STORE 4 ; remaining digits counter +READHEX_1: + LOADC CONIN + CALL + LOADC CR ; RETURN pressed? + CMP.S0 EQ + CBRANCH READHEX_RT + DUP + LOADC CONOUT ; echo character + CALL + LOADC CONVHEXDIGIT + CALL + LOADC -1 + CMP.S0 EQ ; invalid character? + CBRANCH.NZ READHEX_XT + LOAD 0 + SHL 2 ; shift previous nibble + SHL 2 + OR ; combine with last digit + STORE 0 + LOAD 4 + DEC 1 + DUP + STORE 4 + CBRANCH.NZ READHEX_1 + BRANCH READHEX_XT1 +READHEX_RT: ; if no digits were entered, set return code + DROP ; drop read character + LOAD 4 ;remaining digits counter + LOADC 8 + CMP NE + CBRANCH READHEX_RT2 + LOADC 0 ; no valid input + BRANCH READHEX_XT3 +READHEX_RT2: + LOADC 2 ; valid input and return pressed + BRANCH READHEX_XT3 +READHEX_XT: + DROP + LOAD 4 + LOADC 8 + CMP EQ ; if no digits were entered + CBRANCH READHEX_XT0 +READHEX_XT1: + LOADC 1 ; valid input flag + BRANCH READHEX_XT3 +READHEX_XT0: + LOADC 0 +READHEX_XT3: + LOAD 0 + SWAP + FPADJ 8 + RET + +; ------ convert character on the eval stack to upper case +TOUPPER: + LOADC 'a' + CMP.S0 LT + CBRANCH TOUPPER_XT + LOADC 'z' + CMP.S0 GT + CBRANCH TOUPPER_XT + LOADC 32 + SUB +TOUPPER_XT: + RET + +; ------ convert hexadecimal digit to integer +; ------ takes an ascii character as parameter on the eval stack +; ------ returns an integer value from 0-15 on the eval stack, +; ------ or -1 if the character was not a valid hexadecimal digit + +CONVHEXDIGIT: + LOADC TOUPPER + CALL + LOADC '0' + CMP.S0 LT ; character < '0'? + CBRANCH.NZ CONVHEXDIGIT_ERR + LOADC '9' + CMP.S0 GT ; character > '9'? + CBRANCH.NZ CONVHEXDIGIT_ISALPHA + LOADC '0' ; character is between '0' and '9', subtract '0' + SUB + BRANCH CONVHEXDIGIT_NBL +CONVHEXDIGIT_ISALPHA: + LOADC 'A' + CMP.S0 LT ; character < 'A'? + CBRANCH.NZ CONVHEXDIGIT_ERR + LOADC 'F' + CMP.S0 GT ; character > 'F'? + CBRANCH.NZ CONVHEXDIGIT_ERR + LOADC 55 ; character is between 'A' and 'F', subtract ('A' - 10) + SUB +CONVHEXDIGIT_NBL: + RET +CONVHEXDIGIT_ERR: + DROP ; remove character from stack + LOADC -1 ; error + RET + +; --------- output a character on serial console +; --------- takes a character (padded to a word) on the eval stack +CONOUT: + LOADC UART_REG ; address of UART register + LOADI ; load status + LOADC 256 ; check bit 8 (tx_busy) + AND + CBRANCH.NZ CONOUT ; loop if bit 8 is not zero + + ; transmitter is idle now, write character + LOADC UART_REG ; address of UART register + SWAP ; swap character and address for STOREI + LOADC 1024 ; TX enable bit + OR ; OR in the character + STOREI + DROP + RET + +; ---- wait until a character is received and return it on eval stack +CONIN: + LOADC WAITFORBYTE + CALL + LOADC -1 ; -1 means timeout + CMP.S0 NE + CBRANCH CONIN_XT ; exit if no timeout + DROP ; remove last result + BRANCH CONIN +CONIN_XT: + RET + + + .EQU L_BLOCKSIZE 32 + .EQU L_WORDSIZE 4 + .EQU CKSUM_PATTERN $AFFECAFE +RCVBLOCKS: + LOADCP MON_ADDR ; pointer to current write position, + LOADI ; kept on stack +RCVBLOCKS_L: + LOADC WAITFORBYTE ; read header byte + CALL + LOADC -1 + CMP.S0 EQ + CBRANCH RCVBLOCKS_XT ; exit on timeout + + ; check for EOT -> end + LOADC EOT + CMP.S0 EQ + CBRANCH RCVBLOCKS_XT + + ; check for STX -> read block + LOADC STX + CMP.S0 EQ + CBRANCH RCVBLOCKS_CONT + + ; anything else -> send NAK + BRANCH RCVBLOCKS_RETRY + +RCVBLOCKS_CONT: + DROP ; remove header byte + DUP ; duplicate pointer + LOADC READBLOCK + CALL + LOADC -1 + CMP.S0 EQ ; check for timeout + CBRANCH RCVBLOCKS_XT ; exit on timeout + + LOADC -2 + CMP.S0 EQ ; check for checksum error + CBRANCH RCVBLOCKS_RETRY + + DROP ; remove return code + LOADC L_BLOCKSIZE ; advance pointer + ADD + + LOADC ACK ; send ACK + LOADC CONOUT + CALL + + ; next block + BRANCH RCVBLOCKS_L + +RCVBLOCKS_RETRY: + DROP ; remove read byte + ; send NAK + LOADC NAK + LOADC CONOUT + CALL + + ; next block + BRANCH RCVBLOCKS_L + +RCVBLOCKS_XT: + DROP ; remove pointer + DROP ; remove read byte + RET + + +; ---- read a sequence of binary words and store into memory +; - arguments: pointer to memory area +READBLOCK: + FPADJ -12 + STORE 0 ; buffer pointer + LOADCP L_BLOCKSIZE + STORE 4 ; remaining bytes + LOADC 0 + STORE 8 ; checksum +READBLOCK_L: + LOADCP READWORD ; read a word + CALL + LOADC -1 ; check for timeout + CMP EQ + CBRANCH.NZ READBLOCK_ERR + + ; DUP ; debug + ; LOADC PRINTHEXW + ; CALL + + + DUP ; duplicate read word + LOAD 8 ; load checksum + ADD ; checksum = ((checksum + data) ^ pattern) << 1 + LOADCP CKSUM_PATTERN + XOR + SHL + STORE 8 ; store new checkcsum + + LOAD 0 ; load buffer pointer + SWAP ; swap value and pointer for STOREI + STOREI 4 ; store word and increment pointer + STORE 0 ; store pointer + + LOAD 4 ; load remaining bytes + DEC L_WORDSIZE ; decrement by word size + DUP + STORE 4 ; store + CBRANCH.NZ READBLOCK_L ; loop if remaining words not zero + + + LOADCP READWORD ; read checksum + CALL + LOADC -1 ; check for timeout + CMP EQ + CBRANCH READBLOCK_ERR + + LOAD 8 ; load checksum + CMP EQ + CBRANCH READBLOCK_OK + LOADC -2 ; return code for checksum error + BRANCH READBLOCK_XT +READBLOCK_OK: + LOADC 0 ; return 0 +READBLOCK_XT: + FPADJ 12 + RET + +READBLOCK_ERR: + DROP ; remove result + LOAD 4 ; return number of missing bytes + FPADJ 8 + RET + +; --- read four bytes (msb to lsb) and return as word +; returns: word, error code (-1 for error, 0 otherwise) + +READWORD: + LOADCP WAITFORBYTE + CALL + DUP + LOADC -1 ; check for error + CMP EQ + CBRANCH.NZ READWORD_ERR + ; first byte is now on stack + BROT ; rotate byte left + + LOADCP WAITFORBYTE + CALL + DUP + LOADC -1 ; check for error + CMP EQ + CBRANCH.NZ READWORD_ERR + ; second byte is now on stack + OR ; OR last byte with this byte + BROT ; rotate bytes left + + LOADCP WAITFORBYTE + CALL + DUP + LOADC -1 ; check for error + CMP EQ + CBRANCH.NZ READWORD_ERR + ; third byte is now on stack + OR ; OR last byte with this byte + BROT + + LOADCP WAITFORBYTE + CALL + DUP + LOADC -1 ; check for error + CMP EQ + CBRANCH.NZ READWORD_ERR + ; fourth byte is now on stack + OR ; OR last byte with this byte + + LOADC 0 ; error code (0: no error) + RET + +READWORD_ERR: + LOADC -1 ; error code + RET + +;---- wait a fixed amount of cycles for a character to be +; received on the UART. +; returns character or -1 on timeout + + .EQU MAX_WAIT 20000000 +WAITFORBYTE: + LOADCP MAX_WAIT ; maximum wait loops +WAITFORBYTE_L: + LOADC UART_REG ; address of UART register + LOADI ; load status + LOADC 512 ; check bit 9 (rx_avail) + AND + CBRANCH WAITFORBYTE_RX ; if bit 9 is one, a character is available + DEC 1 + DUP + CBRANCH.NZ WAITFORBYTE_L + DROP ; remove wait counter from stack + LOADC -1 ; error code + RET +WAITFORBYTE_RX: + DROP ; remove wait counter from stack + LOADC UART_REG + LOADI ; read register again + LOADC 255 ; mask status bits + AND + LOADC UART_REG ; I/O address + LOADC 512 ; set bit 9 (rx_clear) + STOREI ; write register + DROP ; remove address left by STOREI + RET + + .CPOOL + +;---- boot from SD-card + + ; declare buffer addresses used by sdcardlib.s + .EQU CSD_BUF 63984 + .EQU CARD_BUF 64000 +CMD_B: + DROP ; remove input char + LOADCP NEWLINE + CALL + + FPADJ -4 + ; initialize card + LOADC INITSDCARD + CALL + + ; read partition block + LOADC 0 + LOADC CARDREADBLK + CALL + + DUP ; non-zero return code means error + CBRANCH.Z CMD_B_1 +CMD_B_ERR: + LOADC PRINTHEXW ; print error code + CALL + LOADC NEWLINE + CALL + LOADC 0 ; if we return, we need to + ; put a fake input char back on the + ; stack because the main loop will + ; try to remove it + FPADJ 4 + RET + +CMD_B_1: + DROP ; remove error code + ; check boot partition slot (boot flag) + LOADCP CARD_BUF,104 ; offset partition flags second part slot + LOADI + LOADC 2 ; PartFlags [PartBoot] + CMP EQ + CBRANCH CMD_B_C + + ; no boot partition + LOADC $B0 + BRANCH CMD_B_ERR + +CMD_B_C: + ; get start block + LOADCP CARD_BUF,108 ; offset startBlock + LOADI + ; get block count + LOADCP CARD_BUF,124 ; offset bootBlocks + LOADI + + FPADJ -4 ; allocate space for address var + LOADCP MON_ADDR + LOADI + STORE 0 ; initialize dest addr +CMD_B_L: + ; read block + OVER ; duplicate block no + LOADC CARDREADBLK + CALL + + DUP ; check for error + CBRANCH.Z CMD_B_C2 ; continue if zero (no error) + + NIP ; remove start and count, keep error code + NIP + BRANCH CMD_B_ERR +CMD_B_C2: DROP ; remove error code +CMD_B_2: + ; copy to destination + LOAD 0 ; dest addr + LOADC COPY_BLK + CALL + + ; decrement count and loop + LOAD 0 ; increment dest addr + LOADC 512 + ADD + STORE 0 + + SWAP ; swap block no/count, blockno is now ToS + INC 1 + SWAP ; count is now ToS + DEC 1 + DUP + CBRANCH.NZ CMD_B_L ; if not zero, loop + + ; jump to coreloader + DROP + DROP + FPADJ 4 + LOADCP MON_ADDR + LOADI + JUMP + +CMD_B_XT: + FPADJ 4 + RET + +; copy a sdcard block to destination address +; block size is always 512 byte, source +; is always CARD_BUF +; parameters: dest addr +COPY_BLK: + FPADJ -4 + LOADC 128 ; word count + STORE 0 + + LOADCP CARD_BUF ; src addr +COPY_BLK1: + SWAP + ; [ src addr, dest addr ] + OVER ; [ saddr, daddr, saddr ] + LOADI ; [ saddr, daddr, sword ] + STOREI 4 ; [ saddr, daddr + 4 ] + SWAP ; [ daddr + 4, saddr ] + INC 4 ; [ daddr + 4, saddr + 4] + + LOAD 0 ; load and decrement counter + DEC 1 + DUP + STORE 0 ; store it again + CBRANCH.NZ COPY_BLK1 ; if not zero, loop + + DROP ; remove saddr and daddr + DROP + + FPADJ 4 + RET + + .CPOOL + +; wait approx. 1 millisecond +; +; 83.333 MHz Clock, three instructions a 4 cycles +; 83333 / 12 = 6944.4166 +; works only if executed without wait states (i.e. +; from BRAM/SRAM) +WAIT1MSEC: + LOADCP 6944 +WAIT1LOOP: + DEC 1 + DUP + CBRANCH.NZ WAIT1LOOP + DROP + RET + +%include "sdcardboot.s" + .CPOOL +MESSAGE: + .BYTE 13,10,"ROM Monitor v3.0.3", 13, 10, + "Set A)ddress D)eposit eX)amine L)oad G)o B)oot",13,10,0 +PROMPT2: + .BYTE "]> ",0 +END: diff --git a/lib/sdcardboot.s b/lib/sdcardboot.s new file mode 100644 index 0000000..f3b7c9c --- /dev/null +++ b/lib/sdcardboot.s @@ -0,0 +1,613 @@ + .EQU SPIREG $880 + + .EQU SPI_CTRL_WRITE %100000000000000 + .EQU SPI_RX_FILTER_EN %010000000000000 + .EQU SPI_TXRX_EN %001000000000000 + .EQU SPI_CLK_F_EN %000100000000000 + .EQU SPI_CLK_DIV_WR %000010000000000 + .EQU SPI_RX_RD %000001000000000 + .EQU SPI_TX_WR %000000100000000 + + .EQU SPI_C_D %100000000000000 + .EQU SPI_C_CHG %010000000000000 + .EQU SPDI_C_BUSY %001000000000000 + .EQU SPI_TX_RDY %000100000000000 + .EQU SPI_TX_EMPTY %000010000000000 + .EQU SPI_RX_AVAIL %000001000000000 + .EQU SPI_RX_OVR %000000100000000 + + .EQU SPI_TXRX_EN_MASK ~SPI_TXRX_EN + +_WAIT: + LOADC 10 +_WAITL: + LOADC WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ _WAITL + DROP + RET + +INITSDCARD: + LOADC WAIT1MSEC + CALL + + LOADC _SPIINIT1 + CALL + + ;LOADC 'I' + ;LOADCP CONOUT + ;CALL + + LOADC _WAITSPITXRDY + CALL + + ;LOADC 'W' + ;LOADCP CONOUT + ;CALL + + ; send RESET CARD command + LOADC $95 ; send cmd0 with arg 0 and checksum $95 + LOADC $0 + LOADC $0 + LOADC SENDCMD_R1 + CALL + + DROP ; TODO: handle errors + ;LOADCP PRINTHEXW ; print status returned by the card + ;CALL + ;LOADCP NEWLINE + ;CALL + + ;LOADC '9' + ;LOADCP CONOUT + ;CALL + + LOADC _WAITSPITXRDY + CALL + + LOADC _WAIT + CALL + + ;LOADC '1' + ;LOADCP CONOUT + ;CALL + + LOADC $87 + LOADC $01AA + LOADC $8 + LOADC SENDCMD_R7 + CALL + + DROP + + LOADC _WAITSPITXRDY + CALL + + ;LOADC '2' + ;LOADCP CONOUT + ;CALL + + ;LOADCP _WAIT + ;CALL + + ;LOADC '.' + ;LOADCP CONOUT + ;CALL + + LOADC CARDINITV2 + CALL + + ;LOADC '+' + ;LOADCP CONOUT + ;CALL + + + LOADC CARDFASTCLK + CALL + + ;LOADC '3' + ;LOADCP CONOUT + ;CALL + + ; CMD16: set block size to 512 byte + LOADC 0 + LOADC 512 + LOADC 16 + LOADCP SENDCMD_R1 + CALL + + DROP + + ;LOADCP _WAIT + ;CALL + + ;LOADC '4' + ;LOADCP CONOUT + ;CALL + + RET + +; read a 512-byte-block from the card +; args: block number +; returns: 0 on success +CARDREADBLK: + LOADC 128 ; number of words in a block + SWAP ; move block number up the stack + LOADCP CARD_BUF + SWAP + LOADC 0 + SWAP + LOADC 17 ; CMD17: read block + LOADC SENDCMD_PKT + CALL + RET + +; send the card initialization command +; wait until the card responds +CARDINITV2: + LOADC 100 ; try up to 100 times +CARD_LOOP1: + LOADC 50 ; wait 50 msec +CARD_LOOP2: + LOADC WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ CARD_LOOP2 + DROP ; remove loop count value + + LOADC $0 + LOADC $0 + LOADC 58 + LOADC SENDCMD_R7 ; send CMD58 + CALL + DROP ; ignore result (why?) + + LOADC $0 + LOADCP $40000000 + LOADC 41 + LOADC SENDACMD_R1 ; send ACMD41 + CALL + + CBRANCH.Z CARD_OK ; if result is zero, the command succeded + ; and the card initialization is finished + DEC 1 + DUP + CBRANCH.NZ CARD_LOOP1 + DROP ; remove outer loop count value + + RET +CARD_OK: + DROP ; remove outer loop count value + + ; CMD16: set block size to 512 byte + LOADC 0 + LOADC 512 + LOADC 16 + LOADC SENDCMD_R1 + CALL + DROP ; ignore return value + + RET + +; set fast transfer rate +CARDFASTCLK: + LOADC SPIREG + ; set clock divider to ~2,6MHz + LOADC SPI_CLK_DIV_WR+10 + STOREI + DROP + RET + +; perform first phase of card initialization +; which is to enable clock and wait a bit +; leaves the clock running +_SPIINIT1: + LOADC SPIREG + ; set clock divider to ~325KHz + LOADC SPI_CLK_DIV_WR+64 + STOREI + DROP + + ; clear all flags + enable clock + ; /CS and MOSI are default high + LOADC SPIREG + LOADCP SPI_CTRL_WRITE,SPI_CLK_F_EN + STOREI + DROP + + ; we should wait at least for 74 clock cycles now + LOADC 2 ; wait 2 msec, that should be ~300 cycles +_SPIINIT1L: + LOADC WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ _SPIINIT1L + DROP + + LOADC SPIREG + LOADCP SPI_CTRL_WRITE ; disable clock + STOREI + DROP + + LOADCP WAIT1MSEC + CALL + + RET + +; wait for transmission to finish +; (wait for TX_EMPTY bit) +_SPIWAITTX: + LOADC SPIREG + LOADI + LOADCP SPI_TX_EMPTY + AND + CBRANCH.Z _SPIWAITTX + RET + +; finalize a command that has been sent: +; wait until the transmitter is idle +; then disable clock and set MOSI high +_SPIENDCMD: + LOADC $FF + LOADC _SENDBYTE + CALL + LOADC $FF + LOADC _SENDBYTE + CALL + + ;LOADC 'E' + ;LOADCP CONOUT + ;CALL + + LOADC _SPIWAITTX + CALL + + ;LOADC 'w' + ;LOADCP CONOUT + ;CALL + LOADC _WAIT_S ; wait a short time + CALL + + LOADC SPIREG + LOADCP SPI_IDLE_FLAGS ; turn off transceiver + LOADI + STOREI + DROP + + ; wait for a few instructions + LOADC 100 +SPIEND_LP: DEC 1 + DUP + CBRANCH.NZ SPIEND_LP + DROP + + RET + +_WAIT_S: + LOADC 100 +_WAIT_S_L: + DEC 1 + DUP + CBRANCH.NZ _WAIT_S_L + DROP + RET + +; clear RX fifo +CLEAR_RX_FIFO: +CLEAR_RX_L1: + LOADC SPIREG + LOADI + + ;DUP + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + LOADC SPI_RX_AVAIL + AND + CBRANCH.Z CLEAR_RX_X + LOADC SPIREG + LOADC SPI_RX_RD + STOREI + DROP + + ; FIXME: it seems that this + ; does not remove a byte from the fifo, + ; rx_avail stays on, but only after the first + ; byte has been received and read + + ;LOADC 'x' + ;LOADCP CONOUT + ;CALL + + BRANCH CLEAR_RX_L1 +CLEAR_RX_X: + RET + +_WAITSPITXRDY: + LOADC SPIREG + LOADI + LOADCP SPI_TX_RDY + AND + CBRANCH.Z _WAITSPITXRDY + RET + +; send a command and receive a data packet response +; args: packet size in words, buffer pointer +; checksum byte, 32-bit cmd arg, cmd number +; returns: 0 on success +SENDCMD_PKT: + ; first send the command + LOADC SENDCMD_0 + CALL + + LOADC _RCVBYTE ; receive R1 response + CALL + + CBRANCH.NZ SENDCMD_PKT_E ; on success we get 0 + + ; now wait for data token +SENDCMD_PKT_L: + LOADC _RCVBYTE + CALL + LOADC $FF + CMP EQ + CBRANCH SENDCMD_PKT_L + + ; parameters for _RCVWORDS are on the stack now + LOADC _RCVWORDS + CALL + + ; receive 2 crc bytes + LOADC _RCVBYTE + CALL + BROT + LOADC _RCVBYTE + CALL + OR + + ; terminate command + LOADC _SPIENDCMD + CALL + + DROP ; we ignore the checksum for now + + LOADC 0 + RET +SENDCMD_PKT_E: + DROP ; remove remaining args + DROP + LOADC -1 ; return code for error + RET + +; send a command and receive a 1-byte-response (R1) +; args: checksum byte, 32-bit cmd arg, cmd number +; returns: received byte +SENDCMD_R1: + LOADC SENDCMD_0 + CALL + + LOADC _RCVBYTE + CALL + + ;LOADC 'R' + ;LOADCP CONOUT + ;CALL + + ;terminate command (/cs high, disable clock) + LOADC _SPIENDCMD + CALL + + RET + +; send a command +; args: checksum byte, 32-bit cmd arg, cmd number +SENDCMD_0: + ; clear RX FIFO first + LOADC CLEAR_RX_FIFO + CALL + + ;LOADC '>' + ;LOADCP CONOUT + ;CALL + + ; cmd byte is at TOS at this point + LOADC $40 ; or in start of frame bit + OR + LOADC _SENDBYTE + CALL + ; cmd arg is at TOS now + LOADC _SENDWORD + CALL + ; checksum byte is at TOS now + LOADC _SENDBYTE + CALL + + LOADC _XCVR_ENABLE ; enable transceiver last, + CALL ; a complete command should + RET ; fit into the tx fifo + +; send ACMD and receive a 1-byte-response (R1) +; args: checksum byte, 32-bit cmd arg, ACMD number +; returns: received byte or -1 if first response byte +; indicated an error +SENDACMD_R1: + LOADC $0 + LOADC $0 + LOADC 55 ; send CMD55 + LOADC SENDCMD_R1 + CALL + + LOADC 1 ; 1 = idle state, no errors + CMP NE + CBRANCH.NZ SENDACMD_ERR + + ; pass our args to SENDCMD_R1 + LOADC SENDCMD_R1 + CALL + RET + +SENDACMD_ERR: + LOADCP -1 + RET + +; send a command and receive a 4+1-byte-response (R7) +; args: checksum byte, 32-bit cmd arg, cmd number +; returns: received word or -1 if first response byte +; indicated an error + +SENDCMD_R7: + ; send the command + LOADC SENDCMD_0 + CALL + + ;LOADC '7' + ;LOADCP CONOUT + ;CALL + + LOADC _RCVBYTE + CALL + + LOADC _RCVWORD + CALL + + ;terminate command (/cs high, disable clock) + LOADC _SPIENDCMD + CALL + + SWAP ; swap 1st response byte with received word + LOADC %011111110 ; check for any error flags + AND + CBRANCH.Z SENDCMD_R7_NOERR + DROP + LOADC -1 +SENDCMD_R7_NOERR: + RET + +; send a word as 4 bytes, msb first +_SENDWORD: + DUP ; remember original value for later + + BROT ; rotate msb to lsb (byte 0) + LOADC 255 + AND.S0 ; isolate byte, keep previous value + LOADC _SENDBYTE + CALL + + BROT ; byte 1 + LOADC 255 + AND.S0 + LOADC _SENDBYTE + CALL + + BROT ; byte 2 + LOADC 255 + AND + LOADC _SENDBYTE + CALL + + ; byte 3 is already on the stack + LOADC 255 + AND + LOADC _SENDBYTE + CALL + + RET + +; receive multiple 4-byte-words and store into +; memory buffer +; args: number of words, pointer to buffer +_RCVWORDS: + FPADJ -4 + STORE 0 ; store pointer arg into local variable + ; keep counter on stack +_RCVWORDS_LP: + LOAD 0 ; load buf pointer for STOREI + LOADC _RCVWORD + CALL ; receive a word + STOREI 4 ; store to buf with postincrement + STORE 0 ; store pointer variable + + DEC 1 ; decrement word counter + DUP + CBRANCH.NZ _RCVWORDS_LP ; if not null, loop + DROP ; remove counter value + + FPADJ 4 + RET + +; receive 4 bytes, return as word +_RCVWORD: + LOADC _RCVBYTE ; receive first byte + CALL + BROT ; rotate byte to left + + LOADC _RCVBYTE ; receive second byte + CALL + OR ; or first and second byte together + BROT ; rotate 1st + 2nd to left + + LOADC _RCVBYTE ; receive third byte + CALL + OR + BROT + + LOADCP _RCVBYTE ; receive fourth byte + CALL + OR + RET + +_XCVR_ENABLE: + LOADC SPIREG + LOADC SPI_TX_FLAGS + LOADI + STOREI + DROP + RET + +; send a byte +; args: byte to be sent +_SENDBYTE: + LOADC SPIREG + LOADI ; load spi io register + LOADCP SPI_TX_RDY + AND ; check tx_rdy bit + CBRANCH.Z _SENDBYTE ; if not set, loop + + LOADC SPI_TX_WR ; TX_WR bit + OR ; OR in byte to be send + + LOADC SPIREG + SWAP ; swap value and addr for STOREI + STOREI ; store word (flags + data) to io register + DROP ; remove STOREI result + + RET + +; receive a byte. receiver must be enabled. +; returns: received byte +_RCVBYTE: + LOADC SPIREG + LOADI ; load spi io register + LOADC SPI_RX_AVAIL + AND.S0 ; check rx_avail bit, keep original value + CBRANCH.NZ RECVGOTIT + DROP ; rx_avail not set, remove register value and loop + BRANCH _RCVBYTE +RECVGOTIT: + LOADC SPIREG + LOADC SPI_RX_RD ; remove one byte from rx fifo + STOREI + DROP + + LOADC 255 + AND ; keep bits 7-0 + RET + +SPI_TX_FLAGS: .WORD SPI_CTRL_WRITE + SPI_TXRX_EN + SPI_RX_FILTER_EN +SPI_IDLE_FLAGS: .WORD SPI_CTRL_WRITE diff --git a/lib/sdcardlib.s b/lib/sdcardlib.s new file mode 100644 index 0000000..9b45e05 --- /dev/null +++ b/lib/sdcardlib.s @@ -0,0 +1,795 @@ +; Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details + .EQU SPIREG $880 + + .EQU SPI_CTRL_WRITE %100000000000000 + .EQU SPI_RX_FILTER_EN %010000000000000 + .EQU SPI_TXRX_EN %001000000000000 + .EQU SPI_CLK_F_EN %000100000000000 + .EQU SPI_CLK_DIV_WR %000010000000000 + .EQU SPI_RX_RD %000001000000000 + .EQU SPI_TX_WR %000000100000000 + + .EQU SPI_C_D %100000000000000 + .EQU SPI_C_CHG %010000000000000 + .EQU SPDI_C_BUSY %001000000000000 + .EQU SPI_TX_RDY %000100000000000 + .EQU SPI_TX_EMPTY %000010000000000 + .EQU SPI_RX_AVAIL %000001000000000 + .EQU SPI_RX_OVR %000000100000000 + + .EQU SPI_TXRX_EN_MASK ~SPI_TXRX_EN + +_WAIT: + LOADC 10 +_WAITL: + LOADCP WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ _WAITL + DROP + RET + +INITSDCARD: + LOADCP WAIT1MSEC + CALL + + LOADCP _SPIINIT1 + CALL + + ;LOADC 'I' + ;LOADCP CONOUT + ;CALL + + LOADCP _WAITSPITXRDY + CALL + + ;LOADC 'W' + ;LOADCP CONOUT + ;CALL + + ; send RESET CARD command + LOADC $95 ; send cmd0 with arg 0 and checksum $95 + LOADC $0 + LOADC $0 + LOADCP SENDCMD_R1 + CALL + + DROP ; TODO: handle errors + ;LOADCP PRINTHEXW ; print status returned by the card + ;CALL + ;LOADCP NEWLINE + ;CALL + + ;LOADC '9' + ;LOADCP CONOUT + ;CALL + + LOADCP _WAITSPITXRDY + CALL + + LOADCP _WAIT + CALL + + ;LOADC '1' + ;LOADCP CONOUT + ;CALL + + LOADC $87 + LOADC $01AA + LOADC $8 + LOADCP SENDCMD_R7 + CALL + + DROP + + LOADCP _WAITSPITXRDY + CALL + + ;LOADC '2' + ;LOADCP CONOUT + ;CALL + + ;LOADCP _WAIT + ;CALL + + ;LOADC '.' + ;LOADCP CONOUT + ;CALL + + LOADCP CARDINITV2 + CALL + + ;LOADC '+' + ;LOADCP CONOUT + ;CALL + + + LOADCP CARDFASTCLK + CALL + + ;LOADC '3' + ;LOADCP CONOUT + ;CALL + + ; CMD16: set block size to 512 byte + LOADC 0 + LOADC 512 + LOADC 16 + LOADCP SENDCMD_R1 + CALL + + DROP + + ;LOADCP _WAIT + ;CALL + + ;LOADC '4' + ;LOADCP CONOUT + ;CALL + + RET + +; read a 512-byte-block from the card +; args: block number +; returns: 0 on success +CARDREADBLK: + LOADC 128 ; number of words in a block + SWAP ; move block number up the stack + LOADCP CARD_BUF + SWAP + LOADC 0 + SWAP + LOADC 17 ; CMD17: read block + LOADCP SENDCMD_PKT + CALL + RET + +; determine number of blocks +; returns: number of blocks or -1 on error +CARDSIZE: + LOADC 4 + LOADCP CSD_BUF + LOADC 0 + LOADC 0 + LOADC 9 + LOADCP SENDCMD_PKT ; send CMD9 + CALL + + CBRANCH.NZ CARDSIZE_ERR ; if response is zero, an error occurred + + ; take bytes 7, 8 and 9 from CSD data + ; and add 1 to get card size in ksectors + LOADCP CSD_BUF + INC 4 + LOADI + LOADC $3F ; get byte 7 (bits 22-16) + AND + BROT + BROT + + LOADCP CSD_BUF ; get bytes 8 and 9 (bits 15-0) + INC 8 + LOADI + BROT + BROT + LOADCP $FFFF + AND + + OR + + INC 1 + + BROT + SHL 2; multiply by 1024 to get size in sectors + + RET + +CARDSIZE_ERR: + LOADC -1 + RET + +; returns 1 if the card was changed, 0 otherwise +CARDCHANGED: + LOADCP SPIREG + LOADI + LOADCP SPI_C_CHG + AND + LOADC 0 + CMPU NE + RET + +; write a 512-byte-block to the card +; args: block number +; returns: 0 on success +CARDWRITEBLK: + LOADC 128 ; number of words in a block + SWAP ; move block number up the stack + LOADCP CARD_BUF + SWAP + LOADC 0 + SWAP + LOADC 24 ; CMD24: write block + LOADCP SENDCMD_TXPKT + CALL + RET +; send the card initialization command +; wait until the card responds +CARDINITV2: + LOADC 100 ; try up to 100 times +CARD_LOOP1: + LOADC 50 ; wait 50 msec +CARD_LOOP2: + LOADCP WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ CARD_LOOP2 + DROP ; remove loop count value + + LOADC $0 + LOADC $0 + LOADC 58 + LOADCP SENDCMD_R7 ; send CMD58 + CALL + DROP ; ignore result (why?) + + LOADC $0 + LOADCP $40000000 + LOADC 41 + LOADCP SENDACMD_R1 ; send ACMD41 + CALL + + CBRANCH.Z CARD_OK ; if result is zero, the command succeded + ; and the card initialization is finished + DEC 1 + DUP + CBRANCH.NZ CARD_LOOP1 + DROP ; remove outer loop count value + + RET +CARD_OK: + DROP ; remove outer loop count value + + ; CMD16: set block size to 512 byte + LOADC 0 + LOADC 512 + LOADC 16 + LOADCP SENDCMD_R1 + CALL + DROP ; ignore return value + + RET + +; set fast transfer rate +CARDFASTCLK: + LOADC SPIREG + ; set clock divider to ~2,6MHz + LOADCP SPI_CLK_DIV_WR,10 ; using the LOADCP with offset syntax here + STOREI + DROP + RET + +; perform first phase of card initialization +; which is to enable clock and wait a bit +; leaves the clock running +_SPIINIT1: + LOADC SPIREG + ; set clock divider to ~325KHz + LOADCP SPI_CLK_DIV_WR,64 ; LOADCP with offset + STOREI + DROP + + ; clear all flags + enable clock + ; /CS and MOSI are default high + LOADC SPIREG + LOADCP SPI_CTRL_WRITE,SPI_CLK_F_EN + STOREI + DROP + + ; we should wait at least for 74 clock cycles now + LOADC 2 ; wait 2 msec, that should be ~300 cycles +_SPIINIT1L: + LOADCP WAIT1MSEC + CALL + DEC 1 + DUP + CBRANCH.NZ _SPIINIT1L + DROP + + LOADC SPIREG + LOADCP SPI_CTRL_WRITE ; disable clock + STOREI + DROP + + LOADCP WAIT1MSEC + CALL + + RET + +; wait for transmission to finish +; (wait for TX_EMPTY bit) +_SPIWAITTX: + LOADC SPIREG + LOADI + LOADCP SPI_TX_EMPTY + AND + CBRANCH.Z _SPIWAITTX + RET + +; finalize a command that has been sent: +; wait until the transmitter is idle +; then disable clock and set MOSI high +_SPIENDCMD: + LOADCP $FF + LOADCP _SENDBYTE + CALL + LOADCP $FF + LOADCP _SENDBYTE + CALL + + ;LOADC 'E' + ;LOADCP CONOUT + ;CALL + + LOADCP _SPIWAITTX + CALL + + ;LOADC 'w' + ;LOADCP CONOUT + ;CALL + LOADCP _WAIT_S ; wait a short time + CALL + + LOADC SPIREG + LOADCP SPI_IDLE_FLAGS ; turn off transceiver + LOADI + STOREI + DROP + + ; wait for a few instructions + LOADC 100 +SPIEND_LP: DEC 1 + DUP + CBRANCH.NZ SPIEND_LP + DROP + + RET + +_WAIT_S: + LOADC 100 +_WAIT_S_L: + DEC 1 + DUP + CBRANCH.NZ _WAIT_S_L + DROP + RET + +; clear RX fifo +CLEAR_RX_FIFO: +CLEAR_RX_L1: + LOADC SPIREG + LOADI + + ;DUP + ;LOADCP PRINTHEXW + ;CALL + ;LOADCP NEWLINE + ;CALL + + LOADC SPI_RX_AVAIL + AND + CBRANCH.Z CLEAR_RX_X + LOADC SPIREG + LOADC SPI_RX_RD + STOREI + DROP + + ; FIXME: it seems that this + ; does not remove a byte from the fifo, + ; rx_avail stays on, but only after the first + ; byte has been received and read + + ;LOADC 'x' + ;LOADCP CONOUT + ;CALL + + BRANCH CLEAR_RX_L1 +CLEAR_RX_X: + RET + +_WAITSPITXRDY: + LOADC SPIREG + LOADI + LOADCP SPI_TX_RDY + AND + CBRANCH.Z _WAITSPITXRDY + RET + +; send a command and receive a data packet response +; args: packet size in words, buffer pointer +; checksum byte, 32-bit cmd arg, cmd number +; returns: 0 on success +SENDCMD_PKT: + ; first send the command + LOADCP SENDCMD_0 + CALL + + LOADCP _RCVBYTE ; receive R1 response + CALL + + CBRANCH.NZ SENDCMD_PKT_E ; on success we get 0 + + ; now wait for data token +SENDCMD_PKT_L: + LOADCP _RCVBYTE + CALL + LOADC $FF + CMP EQ + CBRANCH SENDCMD_PKT_L + + ; parameters for _RCVWORDS are on the stack now + LOADCP _RCVWORDS + CALL + + ; receive 2 crc bytes + LOADCP _RCVBYTE + CALL + BROT + LOADCP _RCVBYTE + CALL + OR + + ; terminate command + LOADCP _SPIENDCMD + CALL + + DROP ; we ignore the checksum for now + + LOADC 0 + RET +SENDCMD_PKT_E: + DROP ; remove remaining args + DROP + LOADC -1 ; return code for error + RET + +; send a command and send a data packet +; args: packet size in words, buffer pointer +; checksum byte, 32-bit cmd arg, cmd number +; returns: 0 on success +SENDCMD_TXPKT: + ; first send the command + LOADCP SENDCMD_0 + CALL + + ;LOADCP _RCVBYTE + ;CALL + ;DROP ; remove byte received during transmit + + LOADCP _RCVBYTE ; receive R1 response + CALL + + CBRANCH.NZ SENDCMD_TXPKT_E ; on error we get nonzero + + ; send stuff byte + LOADC $FF + LOADCP _SENDBYTE + CALL + + ; now send data token + LOADCP %11111110 + LOADCP _SENDBYTE + CALL + + ; send data block + ; parameters for _SENDWORDS are on the stack now + LOADCP _SENDWORDS + CALL + + ; send 2 dummy crc bytes + LOADC 0 + LOADCP _SENDBYTE + CALL + LOADC 0 + LOADCP _SENDBYTE + CALL + + ;receive data response byte +SENDCMD_TXPKT_LR: + LOADCP _RCVBYTE + CALL + LOADC $FF ; discard $FF bytes + CMP.S0 NE + CBRANCH SENDCMD_TXPKT_CT + DROP + BRANCH SENDCMD_TXPKT_LR + +SENDCMD_TXPKT_CT: + LOADC $1F + AND ; isolate status bits + LOADC $5 ; command accepted bit set? + CMP NE ; if not, exit with error + CBRANCH SENDCMD_TXPKT_E2 + + ; wait until card is busy +SENDCMD_TXPKT_LB: + LOADCP _RCVBYTE ; receive byte + CALL + CBRANCH.NZ SENDCMD_TXPKT_LB ; loop until byte is 0 + ; wait until card is not busy +SENDCMD_TXPKT_L2: + LOADCP _RCVBYTE ;receive byte + CALL + CBRANCH.Z SENDCMD_TXPKT_L2 ; loop if byte is 0 (i.e. MISO is held low) + + LOADC 0 + BRANCH SENDCMD_TXPKT_X + +SENDCMD_TXPKT_E: + DROP ; remove remaining args + DROP +SENDCMD_TXPKT_E2: + LOADC -1 ; return code for error +SENDCMD_TXPKT_X: + ; terminate command + LOADCP _SPIENDCMD + CALL + + RET + +; send a command and receive a 1-byte-response (R1) +; args: checksum byte, 32-bit cmd arg, cmd number +; returns: received byte +SENDCMD_R1: + LOADCP SENDCMD_0 + CALL + + LOADCP _RCVBYTE + CALL + + ;LOADC 'R' + ;LOADCP CONOUT + ;CALL + + ;terminate command (/cs high, disable clock) + LOADCP _SPIENDCMD + CALL + + RET + +; send a command +; args: checksum byte, 32-bit cmd arg, cmd number +SENDCMD_0: + ; clear RX FIFO first + LOADCP CLEAR_RX_FIFO + CALL + + ;LOADC '>' + ;LOADCP CONOUT + ;CALL + + ; cmd byte is at TOS at this point + LOADC $40 ; or in start of frame bit + OR + LOADCP _SENDBYTE + CALL + ; cmd arg is at TOS now + LOADCP _SENDWORD + CALL + ; checksum byte is at TOS now + LOADCP _SENDBYTE + CALL + + LOADCP _XCVR_ENABLE ; enable transceiver last, + CALL ; a complete command should + RET ; fit into the tx fifo + +; send ACMD and receive a 1-byte-response (R1) +; args: checksum byte, 32-bit cmd arg, ACMD number +; returns: received byte or -1 if first response byte +; indicated an error +SENDACMD_R1: + LOADC $0 + LOADC $0 + LOADC 55 ; send CMD55 + LOADCP SENDCMD_R1 + CALL + + LOADC 1 ; 1 = idle state, no errors + CMP NE + CBRANCH.NZ SENDACMD_ERR + + ; pass our args to SENDCMD_R1 + LOADCP SENDCMD_R1 + CALL + RET + +SENDACMD_ERR: + LOADCP -1 + RET + +; send a command and receive a 4+1-byte-response (R7) +; args: checksum byte, 32-bit cmd arg, cmd number +; returns: received word or -1 if first response byte +; indicated an error + +SENDCMD_R7: + ; send the command + LOADCP SENDCMD_0 + CALL + + ;LOADC '7' + ;LOADCP CONOUT + ;CALL + + LOADCP _RCVBYTE + CALL + + LOADCP _RCVWORD + CALL + + ;terminate command (/cs high, disable clock) + LOADCP _SPIENDCMD + CALL + + SWAP ; swap 1st response byte with received word + LOADC %011111110 ; check for any error flags + AND + CBRANCH.Z SENDCMD_R7_NOERR + DROP + LOADC -1 +SENDCMD_R7_NOERR: + RET + +; send a word as 4 bytes, msb first +_SENDWORD: + DUP ; remember original value for later + + BROT ; rotate msb to lsb (byte 0) + LOADC 255 + AND.S0 ; isolate byte, keep previous value + LOADCP _SENDBYTE + CALL + + BROT ; byte 1 + LOADC 255 + AND.S0 + LOADCP _SENDBYTE + CALL + + BROT ; byte 2 + LOADC 255 + AND + LOADCP _SENDBYTE + CALL + + ; byte 3 is already on the stack + LOADC 255 + AND + LOADCP _SENDBYTE + CALL + + RET + +; send multiple 4-byte-words +; args: number of words, pointer to buffer +_SENDWORDS: + FPADJ -4 + STORE 0 ; store pointer arg into local variable + ; keep counter on stack +_SENDWORDS_LP: + LOAD 0 ; load buf pointer + DUP ; duplicate it + INC 4 ; increment pointer + STORE 0 ; and store it back + LOADI ; load from previously duped pointer + LOADCP _SENDWORD + CALL ; send a word + + DEC 1 ; decrement word counter + DUP + CBRANCH.NZ _SENDWORDS_LP ; if not null, loop + DROP ; remove counter value + + FPADJ 4 + RET + +; receive multiple 4-byte-words and store into +; memory buffer +; args: number of words, pointer to buffer +_RCVWORDS: + FPADJ -4 + STORE 0 ; store pointer arg into local variable + ; keep counter on stack +_RCVWORDS_LP: + LOAD 0 ; load buf pointer for STOREI + LOADCP _RCVWORD + CALL ; receive a word + STOREI 4 ; store to buf with postincrement + STORE 0 ; store pointer variable + + DEC 1 ; decrement word counter + DUP + CBRANCH.NZ _RCVWORDS_LP ; if not null, loop + DROP ; remove counter value + + FPADJ 4 + RET + +; receive 4 bytes, return as word +_RCVWORD: + LOADCP _RCVBYTE ; receive first byte + CALL + BROT ; rotate byte to left + + LOADCP _RCVBYTE ; receive second byte + CALL + OR ; or first and second byte together + BROT ; rotate 1st + 2nd to left + + LOADCP _RCVBYTE ; receive third byte + CALL + OR + BROT + + LOADCP _RCVBYTE ; receive fourth byte + CALL + OR + RET + +_XCVR_ENABLE: + LOADC SPIREG + LOADCP SPI_TX_FLAGS + LOADI + STOREI + DROP + RET + +; send a byte +; args: byte to be sent +_SENDBYTE: + LOADC SPIREG + LOADI ; load spi io register + LOADCP SPI_TX_RDY + AND ; check tx_rdy bit + CBRANCH.Z _SENDBYTE ; if not set, loop + + LOADC SPI_TX_WR ; TX_WR bit + OR ; OR in byte to be send + + LOADC SPIREG + SWAP ; swap value and addr for STOREI + STOREI ; store word (flags + data) to io register + DROP ; remove STOREI result + + RET + +; receive a byte. receiver must be enabled. +; returns: received byte +_RCVBYTE: + LOADC SPIREG + LOADI ; load spi io register + LOADC SPI_RX_AVAIL + AND.S0 ; check rx_avail bit, keep original value + CBRANCH.NZ RECV_GOTIT + DROP ; rx_avail not set, remove register value and loop + BRANCH _RCVBYTE +RECV_GOTIT: + LOADC SPIREG + LOADC SPI_RX_RD ; remove one byte from rx fifo + STOREI + DROP + + LOADC 255 + AND ; keep bits 7-0 + RET + +SPI_TX_FLAGS: .WORD SPI_CTRL_WRITE + SPI_TXRX_EN + SPI_RX_FILTER_EN +SPI_IDLE_FLAGS: .WORD SPI_CTRL_WRITE + + .CPOOL + +CSD_BUF: .BLOCK 4 +CARD_BUF: .BLOCK 128 + diff --git a/lib/stdlib.pas b/lib/stdlib.pas index 59ff2a7..c1da7de 100644 --- a/lib/stdlib.pas +++ b/lib/stdlib.pas @@ -2337,7 +2337,7 @@ begin if f.raw then writechannel(f, aChar) else - if (aChar <> #8) and (aChar <> #9) and (aChar <> #4) then + if (aChar <> #8) and (aChar <> #127) and (aChar <> #4) then begin writechannel(f,aChar); if aChar = #13 then diff --git a/pcomp/make.bat b/pcomp/make.bat index ae8df4b..22157a6 100644 --- a/pcomp/make.bat +++ b/pcomp/make.bat @@ -1,11 +1,14 @@ del *.s +del ..\lib\*.lib +del ..\lib\stdlib.s + fpc -Mobjfpc -gl pcomp.pas fpc -gl sasm.pas fpc -gl lsymgen.pas sasm ..\lib\coreloader.s lsymgen ..\lib\coreloader.sym -py pcomp.py -n stdlib.pas +py pcomp.py -n ..\lib\stdlib.pas libgen ..\lib\stdlib.s libgen ..\lib\runtime.s libgen ..\lib\float32.s diff --git a/rtl/arty-a7/Arty-A7-35-Master.xdc b/rtl/arty-a7/Arty-A7-35-Master.xdc new file mode 100644 index 0000000..c618478 --- /dev/null +++ b/rtl/arty-a7/Arty-A7-35-Master.xdc @@ -0,0 +1,218 @@ +## This file is a general .xdc for the Arty A7-35 Rev. D +## To use it in a project: +## - uncomment the lines corresponding to used pins +## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project + +## Clock signal +set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk] +create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk] + +## Switches +set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0] +set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1] +#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2] +#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3] + +## RGB LEDs +#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L18N_T2_35 Sch=led0_b +#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { led0_g }]; #IO_L19N_T3_VREF_35 Sch=led0_g +#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { led0_r }]; #IO_L19P_T3_35 Sch=led0_r +#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { led1_b }]; #IO_L20P_T3_35 Sch=led1_b +#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { led1_g }]; #IO_L21P_T3_DQS_35 Sch=led1_g +#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { led1_r }]; #IO_L20N_T3_35 Sch=led1_r +#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { led2_b }]; #IO_L21N_T3_DQS_35 Sch=led2_b +#set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { led2_g }]; #IO_L22N_T3_35 Sch=led2_g +#set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { led2_r }]; #IO_L22P_T3_35 Sch=led2_r +#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { led3_b }]; #IO_L23P_T3_35 Sch=led3_b +#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { led3_g }]; #IO_L24P_T3_35 Sch=led3_g +#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { led3_r }]; #IO_L23N_T3_35 Sch=led3_r + +## LEDs +set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33} [get_ports led0] +set_property -dict {PACKAGE_PIN J5 IOSTANDARD LVCMOS33} [get_ports led1] +set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2] +set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3] + +## Buttons +set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0] +#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1] +#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2] +#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3] + +## Pmod Header JA +set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports sd_cs_n] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS33} [get_ports sd_mosi] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS33} [get_ports sd_miso] +set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports sd_sck] +#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { sd_dat1 }]; #IO_L6N_T0_VREF_15 Sch=ja[7] +#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { sd_dat2 }]; #IO_L10P_T1_AD11P_15 Sch=ja[8] +set_property -dict {PACKAGE_PIN A18 IOSTANDARD LVCMOS33} [get_ports sd_cd] +#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { sd_nc }]; #IO_25_15 Sch=ja[10] + +###Pmod Header JB +set_property -dict {PACKAGE_PIN E15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[0]}] +set_property -dict {PACKAGE_PIN E16 IOSTANDARD LVCMOS33} [get_ports {VGA_R[1]}] +set_property -dict {PACKAGE_PIN D15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[2]}] +set_property -dict {PACKAGE_PIN C15 IOSTANDARD LVCMOS33} [get_ports {VGA_R[3]}] +set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports {VGA_B[0]}] +set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {VGA_B[1]}] +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS33} [get_ports {VGA_B[2]}] +set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports {VGA_B[3]}] + +###Pmod Header JC +set_property -dict {PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports {VGA_G[0]}] +set_property -dict {PACKAGE_PIN V12 IOSTANDARD LVCMOS33} [get_ports {VGA_G[1]}] +set_property -dict {PACKAGE_PIN V10 IOSTANDARD LVCMOS33} [get_ports {VGA_G[2]}] +set_property -dict {PACKAGE_PIN V11 IOSTANDARD LVCMOS33} [get_ports {VGA_G[3]}] +set_property -dict {PACKAGE_PIN U14 IOSTANDARD LVCMOS33} [get_ports VGA_HS_O] +set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports VGA_VS_O] +#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L23P_T3_A03_D19_14 Sch=jc_p[4] +#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4] + +## Pmod Header JD +#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1] +#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2] +#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3] +#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4] +#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7] +#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8] +#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9] +#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L15N_T2_DQS_35 Sch=jd[10] + +## USB-UART Interface +set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33} [get_ports uart_rxd_out] +set_property -dict {PACKAGE_PIN A9 IOSTANDARD LVCMOS33} [get_ports uart_txd_in] + +## ChipKit Outer Digital Header +#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io0 }]; #IO_L16P_T2_CSI_B_14 Sch=ck_io[0] +#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { ck_io1 }]; #IO_L18P_T2_A12_D28_14 Sch=ck_io[1] +#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { ck_io2 }]; #IO_L8N_T1_D12_14 Sch=ck_io[2] +#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { ck_io3 }]; #IO_L19P_T3_A10_D26_14 Sch=ck_io[3] +#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { ck_io4 }]; #IO_L5P_T0_D06_14 Sch=ck_io[4] +#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { ck_io5 }]; #IO_L14P_T2_SRCC_14 Sch=ck_io[5] +#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { ck_io6 }]; #IO_L14N_T2_SRCC_14 Sch=ck_io[6] +#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { ck_io7 }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=ck_io[7] +#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { ck_io8 }]; #IO_L11P_T1_SRCC_14 Sch=ck_io[8] +#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { ck_io9 }]; #IO_L10P_T1_D14_14 Sch=ck_io[9] +#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { ck_io10 }]; #IO_L18N_T2_A11_D27_14 Sch=ck_io[10] +#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { ck_io11 }]; #IO_L17N_T2_A13_D29_14 Sch=ck_io[11] +#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { ck_io12 }]; #IO_L12N_T1_MRCC_14 Sch=ck_io[12] +#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { ck_io13 }]; #IO_L12P_T1_MRCC_14 Sch=ck_io[13] + +## ChipKit Inner Digital Header +#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { ck_io26 }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=ck_io[26] +#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { ck_io27 }]; #IO_L16N_T2_A15_D31_14 Sch=ck_io[27] +#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { ck_io28 }]; #IO_L6N_T0_D08_VREF_14 Sch=ck_io[28] +#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { ck_io29 }]; #IO_25_14 Sch=ck_io[29] +#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { ck_io30 }]; #IO_0_14 Sch=ck_io[30] +#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { ck_io31 }]; #IO_L5N_T0_D07_14 Sch=ck_io[31] +#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { ck_io32 }]; #IO_L13N_T2_MRCC_14 Sch=ck_io[32] +#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ck_io33 }]; #IO_L13P_T2_MRCC_14 Sch=ck_io[33] +#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { ck_io34 }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=ck_io[34] +#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { ck_io35 }]; #IO_L11N_T1_SRCC_14 Sch=ck_io[35] +#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { ck_io36 }]; #IO_L8P_T1_D11_14 Sch=ck_io[36] +#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { ck_io37 }]; #IO_L17P_T2_A14_D30_14 Sch=ck_io[37] +#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { ck_io38 }]; #IO_L7N_T1_D10_14 Sch=ck_io[38] +#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { ck_io39 }]; #IO_L7P_T1_D09_14 Sch=ck_io[39] +#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { ck_io40 }]; #IO_L9N_T1_DQS_D13_14 Sch=ck_io[40] +#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { ck_io41 }]; #IO_L9P_T1_DQS_14 Sch=ck_io[41] + +## ChipKit Outer Analog Header - as Single-Ended Analog Inputs +## NOTE: These ports can be used as single-ended analog inputs with voltages from 0-3.3V (ChipKit analog pins A0-A5) or as digital I/O. +## WARNING: Do not use both sets of constraints at the same time! +## NOTE: The following constraints should be used with the XADC IP core when using these ports as analog inputs. +#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vaux4_n }]; #IO_L1N_T0_AD4N_35 Sch=ck_an_n[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vaux4_p }]; #IO_L1P_T0_AD4P_35 Sch=ck_an_p[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vaux5_n }]; #IO_L3N_T0_DQS_AD5N_35 Sch=ck_an_n[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vaux5_p }]; #IO_L3P_T0_DQS_AD5P_35 Sch=ck_an_p[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_n }]; #IO_L7N_T1_AD6N_35 Sch=ck_an_n[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { vaux6_p }]; #IO_L7P_T1_AD6P_35 Sch=ck_an_p[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_n }]; #IO_L9N_T1_DQS_AD7N_35 Sch=ck_an_n[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { vaux7_p }]; #IO_L9P_T1_DQS_AD7P_35 Sch=ck_an_p[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { vaux15_n }]; #IO_L10N_T1_AD15N_35 Sch=ck_an_n[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { vaux15_p }]; #IO_L10P_T1_AD15P_35 Sch=ck_an_p[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_n }]; #IO_L1N_T0_AD0N_15 Sch=ck_an_n[5] ChipKit pin=A5 +#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { vaux0_p }]; #IO_L1P_T0_AD0P_15 Sch=ck_an_p[5] ChipKit pin=A5 +## ChipKit Outer Analog Header - as Digital I/O +## NOTE: the following constraints should be used when using these ports as digital I/O. +#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { ck_a0 }]; #IO_0_35 Sch=ck_a[0] ChipKit pin=A0 +#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { ck_a1 }]; #IO_L4P_T0_35 Sch=ck_a[1] ChipKit pin=A1 +#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { ck_a2 }]; #IO_L4N_T0_35 Sch=ck_a[2] ChipKit pin=A2 +#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { ck_a3 }]; #IO_L6P_T0_35 Sch=ck_a[3] ChipKit pin=A3 +#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { ck_a4 }]; #IO_L6N_T0_VREF_35 Sch=ck_a[4] ChipKit pin=A4 +#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { ck_a5 }]; #IO_L11P_T1_SRCC_35 Sch=ck_a[5] ChipKit pin=A5 + +## ChipKit Inner Analog Header - as Differential Analog Inputs +## NOTE: These ports can be used as differential analog inputs with voltages from 0-1.0V (ChipKit Analog pins A6-A11) or as digital I/O. +## WARNING: Do not use both sets of constraints at the same time! +## NOTE: The following constraints should be used with the XADC core when using these ports as analog inputs. +#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vaux12_p }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12] ChipKit pin=A6 +#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vaux12_n }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12] ChipKit pin=A7 +#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { vaux13_p }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13] ChipKit pin=A8 +#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { vaux13_n }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13] ChipKit pin=A9 +#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vaux14_p }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14] ChipKit pin=A10 +#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vaux14_n }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14] ChipKit pin=A11 +## ChipKit Inner Analog Header - as Digital I/O +## NOTE: the following constraints should be used when using the inner analog header ports as digital I/O. +#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { ck_io20 }]; #IO_L2P_T0_AD12P_35 Sch=ad_p[12] ChipKit pin=A6 +#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { ck_io21 }]; #IO_L2N_T0_AD12N_35 Sch=ad_n[12] ChipKit pin=A7 +#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { ck_io22 }]; #IO_L5P_T0_AD13P_35 Sch=ad_p[13] ChipKit pin=A8 +#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { ck_io23 }]; #IO_L5N_T0_AD13N_35 Sch=ad_n[13] ChipKit pin=A9 +#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { ck_io24 }]; #IO_L8P_T1_AD14P_35 Sch=ad_p[14] ChipKit pin=A10 +#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { ck_io25 }]; #IO_L8N_T1_AD14N_35 Sch=ad_n[14] ChipKit pin=A11 + +## ChipKit SPI +#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { ck_miso }]; #IO_L17N_T2_35 Sch=ck_miso +#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { ck_mosi }]; #IO_L17P_T2_35 Sch=ck_mosi +#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { ck_sck }]; #IO_L18P_T2_35 Sch=ck_sck +#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { ck_ss }]; #IO_L16N_T2_35 Sch=ck_ss + +## ChipKit I2C +#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { ck_scl }]; #IO_L4P_T0_D04_14 Sch=ck_scl +#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { ck_sda }]; #IO_L4N_T0_D05_14 Sch=ck_sda +#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports { scl_pup }]; #IO_L9N_T1_DQS_AD3N_15 Sch=scl_pup +#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports { sda_pup }]; #IO_L9P_T1_DQS_AD3P_15 Sch=sda_pup + +## Misc. ChipKit Ports +#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { ck_ioa }]; #IO_L10N_T1_D15_14 Sch=ck_ioa +set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports rst] + +## SMSC Ethernet PHY +#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { eth_col }]; #IO_L16N_T2_A27_15 Sch=eth_col +#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { eth_crs }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=eth_crs +#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L14N_T2_SRCC_15 Sch=eth_mdc +#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L17P_T2_A26_15 Sch=eth_mdio +#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; #IO_L22P_T3_A17_15 Sch=eth_ref_clk +#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L20P_T3_A20_15 Sch=eth_rstn +#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_clk }]; #IO_L14P_T2_SRCC_15 Sch=eth_rx_clk +#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_dv }]; #IO_L13N_T2_MRCC_15 Sch=eth_rx_dv +#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L21N_T3_DQS_A18_15 Sch=eth_rxd[0] +#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L16P_T2_A28_15 Sch=eth_rxd[1] +#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[2] }]; #IO_L21P_T3_DQS_15 Sch=eth_rxd[2] +#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[3] }]; #IO_L18N_T2_A23_15 Sch=eth_rxd[3] +#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L20N_T3_A19_15 Sch=eth_rxerr +#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_clk }]; #IO_L13P_T2_MRCC_15 Sch=eth_tx_clk +#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_en }]; #IO_L19N_T3_A21_VREF_15 Sch=eth_tx_en +#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L15P_T2_DQS_15 Sch=eth_txd[0] +#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L19P_T3_A22_15 Sch=eth_txd[1] +#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[2] }]; #IO_L17N_T2_A25_15 Sch=eth_txd[2] +#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[3] }]; #IO_L18P_T2_A24_15 Sch=eth_txd[3] + +## Quad SPI Flash +#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { qspi_cs }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_cs +#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] +#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] +#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] +#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] + +## Power Measurements +#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_n }]; #IO_L7N_T1_AD2N_15 Sch=ad_n[2] +#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports { vsnsvu_p }]; #IO_L7P_T1_AD2P_15 Sch=ad_p[2] +#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_n }]; #IO_L3N_T0_DQS_AD1N_15 Sch=ad_n[1] +#set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { vsns5v0_p }]; #IO_L3P_T0_DQS_AD1P_15 Sch=ad_p[1] +#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_n }]; #IO_L5N_T0_AD9N_15 Sch=ad_n[9] +#set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { isns5v0_p }]; #IO_L5P_T0_AD9P_15 Sch=ad_p[9] +#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_n }]; #IO_L8N_T1_AD10N_15 Sch=ad_n[10] +#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10] + +set_property BITSTREAM.GENERAL.COMPRESS True [current_design] diff --git a/rtl/arty-a7/Arty_C_mig.ucf b/rtl/arty-a7/Arty_C_mig.ucf new file mode 100644 index 0000000..5a36c18 --- /dev/null +++ b/rtl/arty-a7/Arty_C_mig.ucf @@ -0,0 +1,48 @@ +NET "ddr3_dq[0]" LOC = "K5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[1]" LOC = "L3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[2]" LOC = "K3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[3]" LOC = "L6" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[4]" LOC = "M3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[5]" LOC = "M1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[6]" LOC = "L4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[7]" LOC = "M2" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[8]" LOC = "V4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[9]" LOC = "T5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[10]" LOC = "U4" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[11]" LOC = "V5" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[12]" LOC = "V1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[13]" LOC = "T3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[14]" LOC = "U3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dq[15]" LOC = "R3" | IOSTANDARD = SSTL135 ; +NET "ddr3_dm[0]" LOC = "L1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dm[1]" LOC = "U1" | IOSTANDARD = SSTL135 ; +NET "ddr3_dqs_p[0]" LOC = "N2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_n[0]" LOC = "N1" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_p[1]" LOC = "U2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_dqs_n[1]" LOC = "V2" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_addr[13]" LOC = "T8" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[12]" LOC = "T6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[11]" LOC = "U6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[10]" LOC = "R6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[9]" LOC = "V7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[8]" LOC = "R8" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[7]" LOC = "U7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[6]" LOC = "V6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[5]" LOC = "R7" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[4]" LOC = "N6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[3]" LOC = "T1" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[2]" LOC = "N4" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[1]" LOC = "M6" | IOSTANDARD = SSTL135 ; +NET "ddr3_addr[0]" LOC = "R2" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[2]" LOC = "P2" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[1]" LOC = "P4" | IOSTANDARD = SSTL135 ; +NET "ddr3_ba[0]" LOC = "R1" | IOSTANDARD = SSTL135 ; +NET "ddr3_ck_p[0]" LOC = "U9" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_ck_n[0]" LOC = "V9" | IOSTANDARD = DIFF_SSTL135 ; +NET "ddr3_ras_n" LOC = "P3" | IOSTANDARD = SSTL135 ; +NET "ddr3_cas_n" LOC = "M4" | IOSTANDARD = SSTL135 ; +NET "ddr3_we_n" LOC = "P5" | IOSTANDARD = SSTL135 ; +NET "ddr3_reset_n" LOC = "K6" | IOSTANDARD = SSTL135 ; +NET "ddr3_cke[0]" LOC = "N5" | IOSTANDARD = SSTL135 ; +NET "ddr3_odt[0]" LOC = "R5" | IOSTANDARD = SSTL135 ; +NET "ddr3_cs_n[0]" LOC = "U8" | IOSTANDARD = SSTL135 ; diff --git a/rtl/arty-a7/mig_dram_0/mig_a.prj b/rtl/arty-a7/mig_dram_0/mig_a.prj new file mode 100644 index 0000000..b263a25 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_a.prj @@ -0,0 +1,148 @@ + + + + + + + + mig_dram_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a35ti-csg324/-1L + + 4.2 + + No Buffer + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + DDR3_SDRAM/Components/MT41K128M16XX-15E + 3000 + 1.8V + 4:1 + 83.333 + 0 + 666 + 1.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 14 + 10 + 3 + 1.35V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 5 + Normal + No + Slow Exit + Enable + RZQ/6 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 5 + Enabled + Normal + Dynamic ODT off + NATIVE + + + + diff --git a/rtl/arty-a7/mig_dram_0/mig_b.prj b/rtl/arty-a7/mig_dram_0/mig_b.prj new file mode 100644 index 0000000..b263a25 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_b.prj @@ -0,0 +1,148 @@ + + + + + + + + mig_dram_0 + + 1 + + 1 + + OFF + + 1024 + + ON + + Enabled + + xc7a35ti-csg324/-1L + + 4.2 + + No Buffer + + No Buffer + + ACTIVE LOW + + FALSE + + 1 + + 50 Ohms + + 0 + + + DDR3_SDRAM/Components/MT41K128M16XX-15E + 3000 + 1.8V + 4:1 + 83.333 + 0 + 666 + 1.000 + 1 + 1 + 1 + 1 + 16 + 1 + 1 + Disabled + Strict + 4 + FALSE + + 14 + 10 + 3 + 1.35V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 5 + Normal + No + Slow Exit + Enable + RZQ/6 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 5 + Enabled + Normal + Dynamic ODT off + NATIVE + + + + diff --git a/rtl/arty-a7/mig_dram_0/mig_dram_0.xci b/rtl/arty-a7/mig_dram_0/mig_dram_0.xci new file mode 100644 index 0000000..9027805 --- /dev/null +++ b/rtl/arty-a7/mig_dram_0/mig_dram_0.xci @@ -0,0 +1,1572 @@ +{ + "schema": "xilinx.com:schema:json_instance:1.0", + "ip_inst": { + "xci_name": "mig_dram_0", + "component_reference": "xilinx.com:ip:mig_7series:4.2", + "ip_revision": "1", + "gen_directory": ".", + "parameters": { + "component_parameters": { + "XML_INPUT_FILE": [ { "value": "mig_b.prj", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "RESET_BOARD_INTERFACE": [ { "value": "Custom", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "MIG_DONT_TOUCH_PARAM": [ { "value": "Custom", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "BOARD_MIG_PARAM": [ { "value": "Custom", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "Component_Name": [ { "value": "mig_dram_0", "resolve_type": "user", "usage": "all" } ] + }, + "model_parameters": { + "NoOfControllers": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "COMBINED_INTERFACE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "REFCLK_TYPE": [ { "value": "NOBUF", "resolve_type": "generated", "usage": "all" } ], + "MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "TEMP_MON_CONTROL": [ { "value": "INTERNAL", "resolve_type": "generated", "usage": "all" } ], + "POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "SYSCLK_TYPE": [ { "value": "NOBUF", "resolve_type": "generated", "usage": "all" } ], + "USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DDR3_DQ_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_DQS_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_DM_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_ADDR_WIDTH": [ { "value": "28", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_nCK_PER_CLK": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR3_DATA_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "FREQ_HZ": [ { "value": "83333333", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "MMCM_VCO": [ { "value": "666", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_ID_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_DATA_WIDTH": [ { "value": "128", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_ADDR_WIDTH": [ { "value": "28", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_S_AXI_MEM_SIZE": [ { "value": "268435456", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C0_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C0_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C0_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C0_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C0_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C0_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C0_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C0_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C0_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C1_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C1_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C1_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C1_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C1_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C1_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C1_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C1_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C1_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C1_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C2_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C2_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C2_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C2_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C2_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C2_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C2_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C2_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C2_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C2_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C3_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C3_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C3_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C3_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C3_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C3_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C3_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C3_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C3_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C3_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C4_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C4_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C4_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C4_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C4_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C4_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C4_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C4_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C4_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C4_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C5_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C5_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C5_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C5_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C5_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C5_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C5_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C5_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C5_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C5_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C6_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C6_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C6_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C6_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C6_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C6_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C6_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C6_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C6_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C6_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ], + "C7_MEM_TYPE": [ { "value": "DDR3", "resolve_type": "generated", "usage": "all" } ], + "C7_IS_CLK_SHARED": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_SYSCLK_TYPE": [ { "value": "DIFF", "resolve_type": "generated", "usage": "all" } ], + "C7_USE_AXI": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_ECC": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DDR3_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DDR3_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_ODT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_LPDDR2_DQ_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_DQS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_ROW_WIDTH": [ { "value": "14", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_BANK_WIDTH": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_CKE_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_CS_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_nCS_PER_RANK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_USE_CS_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_USE_DM_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_USE_ODT_PORT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_REG_CTRL": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_LPDDR2_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DQS_CNT_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_DDRX_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDRX_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDRX_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR3_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_DDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_ADDR_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_nCK_PER_CLK": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_LPDDR2_DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_FREQ_HZ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C7_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C7_UI_EXTRA_CLOCKS": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_MMCM_VCO": [ { "value": "1200.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C7_MMCM_CLKOUT0_FREQ": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ], + "C7_MMCM_CLKOUT1_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_MMCM_CLKOUT2_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_MMCM_CLKOUT3_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_MMCM_CLKOUT4_FREQ": [ { "value": "10", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_MMCM_CLKOUT0_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_MMCM_CLKOUT2_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_MMCM_CLKOUT1_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_MMCM_CLKOUT3_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_MMCM_CLKOUT4_EN": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ], + "C7_C_S_AXI_CTRL_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_CTRL_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_CTRL_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_CTRL_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_DATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_ADDR_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_C_S_AXI_MEM_SIZE": [ { "value": "1048576", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_QDRIIP_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_QDRIIP_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_QDRIIP_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_QDRIIP_BW_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_QDRIIP_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_QDRIIP_BURST_LEN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_RLDIII_NUM_DEVICES": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_RLD_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_QK_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_CK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_DK_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_QVLD_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_DEBUG_PORT": [ { "value": "OFF", "resolve_type": "generated", "usage": "all" } ], + "C7_RLDX_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDX_DATA_WIDTH": [ { "value": "18", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDX_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDX_BANK_WIDTH": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDX_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDX_DM_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_CMD_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_ADDR_WIDTH": [ { "value": "29", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_RLDIII_nCK_PER_CLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C7_POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "generated", "usage": "all" } ] + }, + "project_parameters": { + "ARCHITECTURE": [ { "value": "artix7" } ], + "BASE_BOARD_PART": [ { "value": "digilentinc.com:arty-a7-35:part0:1.0" } ], + "BOARD_CONNECTIONS": [ { "value": "" } ], + "DEVICE": [ { "value": "xc7a35ti" } ], + "NEXTGEN_VERSAL": [ { "value": "0" } ], + "PACKAGE": [ { "value": "csg324" } ], + "PREFHDL": [ { "value": "VERILOG" } ], + "SILICON_REVISION": [ { "value": "" } ], + "SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ], + "SPEEDGRADE": [ { "value": "-1L" } ], + "STATIC_POWER": [ { "value": "" } ], + "TEMPERATURE_GRADE": [ { "value": "I" } ] + }, + "runtime_parameters": { + "IPCONTEXT": [ { "value": "IP_Flow" } ], + "IPREVISION": [ { "value": "1" } ], + "MANAGED": [ { "value": "TRUE" } ], + "OUTPUTDIR": [ { "value": "." } ], + "SELECTEDSIMMODEL": [ { "value": "" } ], + "SHAREDDIR": [ { "value": "." } ], + "SWVERSION": [ { "value": "2024.1" } ], + "SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ] + } + }, + "boundary": { + "ports": { + "sys_rst": [ { "direction": "in" } ], + "clk_ref_i": [ { "direction": "in", "display_name": "Clock P", "description": "Clock P" } ], + "ddr3_dq": [ { "direction": "inout", "size_left": "15", "size_right": "0", "display_name": "Data", "description": "Data" } ], + "ddr3_dqs_p": [ { "direction": "inout", "size_left": "1", "size_right": "0", "display_name": "Data Strobe", "description": "Data Strobe" } ], + "ddr3_dqs_n": [ { "direction": "inout", "size_left": "1", "size_right": "0", "display_name": "Data Strobe", "description": "Data Strobe" } ], + "ddr3_addr": [ { "direction": "out", "size_left": "13", "size_right": "0", "display_name": "Address", "description": "Address" } ], + "ddr3_ba": [ { "direction": "out", "size_left": "2", "size_right": "0", "display_name": "Bank Address", "description": "Bank Address" } ], + "ddr3_ras_n": [ { "direction": "out", "display_name": "row address strobe", "description": "row address strobe" } ], + "ddr3_cas_n": [ { "direction": "out", "display_name": "column address strobe", "description": "column address strobe" } ], + "ddr3_we_n": [ { "direction": "out", "display_name": "write enable", "description": "write enable" } ], + "ddr3_reset_n": [ { "direction": "out", "display_name": "reset to memory device", "description": "reset to memory device" } ], + "ddr3_ck_p": [ { "direction": "out", "size_left": "0", "size_right": "0", "display_name": "clock to memory device", "description": "clock to memory device" } ], + "ddr3_ck_n": [ { "direction": "out", "size_left": "0", "size_right": "0", "display_name": "clock to memory device", "description": "clock to memory device" } ], + "ddr3_cke": [ { "direction": "out", "size_left": "0", "size_right": "0", "display_name": "clock enable", "description": "clock enable" } ], + "ddr3_cs_n": [ { "direction": "out", "size_left": "0", "size_right": "0", "display_name": "chip select", "description": "chip select" } ], + "ddr3_dm": [ { "direction": "out", "size_left": "1", "size_right": "0", "display_name": "data mask", "description": "data mask" } ], + "ddr3_odt": [ { "direction": "out", "size_left": "0", "size_right": "0", "display_name": "on die termination", "description": "on die termination" } ], + "app_addr": [ { "direction": "in", "size_left": "7", "size_right": "0" } ], + "app_cmd": [ { "direction": "in", "size_left": "2", "size_right": "0" } ], + "app_en": [ { "direction": "in" } ], + "app_wdf_data": [ { "direction": "in", "size_left": "31", "size_right": "0" } ], + "app_wdf_end": [ { "direction": "in" } ], + "app_wdf_mask": [ { "direction": "in", "size_left": "3", "size_right": "0" } ], + "app_wdf_wren": [ { "direction": "in" } ], + "app_rd_data": [ { "direction": "out", "size_left": "31", "size_right": "0" } ], + "app_rd_data_end": [ { "direction": "out" } ], + "app_rd_data_valid": [ { "direction": "out" } ], + "app_rdy": [ { "direction": "out" } ], + "app_wdf_rdy": [ { "direction": "out" } ], + "app_sr_req": [ { "direction": "in" } ], + "app_sr_active": [ { "direction": "out" } ], + "app_ref_req": [ { "direction": "in" } ], + "app_ref_ack": [ { "direction": "out" } ], + "app_zq_req": [ { "direction": "in" } ], + "app_zq_ack": [ { "direction": "out" } ], + "ui_clk_sync_rst": [ { "direction": "out" } ], + "ui_clk": [ { "direction": "out" } ], + "sys_clk_i": [ { "direction": "in", "display_name": "Clock P", "description": "Clock P" } ], + "init_calib_complete": [ { "direction": "out" } ], + "aresetn": [ { "direction": "in" } ] + }, + "interfaces": { + "SYSTEM_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "resolve_type": "dependent", "usage": "all" } ], + "BOARD.ASSOCIATED_PARAM": [ { "value": "RESET_BOARD_INTERFACE", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "RST": [ { "physical_name": "sys_rst" } ] + } + }, + "CLK_REF_I": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "slave", + "parameters": { + "FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "CLK": [ { "physical_name": "clk_ref_i" } ] + } + }, + "DDR3": { + "vlnv": "xilinx.com:interface:ddrx:1.0", + "abstraction_type": "xilinx.com:interface:ddrx_rtl:1.0", + "mode": "master", + "parameters": { + "CAN_DEBUG": [ { "value": "false", "resolve_type": "generated", "format": "bool", "is_ips_inferred": true, "is_static_object": false } ], + "TIMEPERIOD_PS": [ { "value": "1250", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MEMORY_TYPE": [ { "value": "COMPONENTS", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MEMORY_PART": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "DATA_WIDTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CS_ENABLED": [ { "value": "true", "resolve_type": "generated", "format": "bool", "is_ips_inferred": true, "is_static_object": false } ], + "DATA_MASK_ENABLED": [ { "value": "true", "resolve_type": "generated", "format": "bool", "is_ips_inferred": true, "is_static_object": false } ], + "SLOT": [ { "value": "Single", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "CUSTOM_PARTS": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_ADDR_MAP": [ { "value": "ROW_COLUMN_BANK", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "BURST_LENGTH": [ { "value": "8", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "AXI_ARBITRATION_SCHEME": [ { "value": "TDM", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "CAS_LATENCY": [ { "value": "11", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CAS_WRITE_LATENCY": [ { "value": "11", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "DQ": [ { "physical_name": "ddr3_dq" } ], + "DQS_P": [ { "physical_name": "ddr3_dqs_p" } ], + "DQS_N": [ { "physical_name": "ddr3_dqs_n" } ], + "ADDR": [ { "physical_name": "ddr3_addr" } ], + "BA": [ { "physical_name": "ddr3_ba" } ], + "RAS_N": [ { "physical_name": "ddr3_ras_n" } ], + "CAS_N": [ { "physical_name": "ddr3_cas_n" } ], + "WE_N": [ { "physical_name": "ddr3_we_n" } ], + "RESET_N": [ { "physical_name": "ddr3_reset_n" } ], + "CK_P": [ { "physical_name": "ddr3_ck_p" } ], + "CK_N": [ { "physical_name": "ddr3_ck_n" } ], + "CKE": [ { "physical_name": "ddr3_cke" } ], + "CS_N": [ { "physical_name": "ddr3_cs_n" } ], + "DM": [ { "physical_name": "ddr3_dm" } ], + "ODT": [ { "physical_name": "ddr3_odt" } ] + } + }, + "RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "RST": [ { "physical_name": "ui_clk_sync_rst" } ] + } + }, + "DDR3_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "DDR2_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "LPDDR2_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "QDRIIP_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "RLDII_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "RLDIII_RESET": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "master", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "CLOCK": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "83333333", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_BUSIF": [ { "value": "S_AXI:S_AXI_CTRL", "value_src": "constant", "usage": "all" } ], + "ASSOCIATED_RESET": [ { "value": "aresetn:ui_clk_sync_rst", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "CLK": [ { "physical_name": "ui_clk" } ] + } + }, + "MMCM_CLKOUT0": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "10", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_ASYNC_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "MMCM_CLKOUT1": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "10", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_ASYNC_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "MMCM_CLKOUT2": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "10", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_ASYNC_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "MMCM_CLKOUT3": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "10", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_ASYNC_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "MMCM_CLKOUT4": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "master", + "parameters": { + "FREQ_HZ": [ { "value": "10", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "ASSOCIATED_ASYNC_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ], + "PHASE": [ { "value": "0", "resolve_type": "dependent", "format": "float", "usage": "all" } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "SYS_CLK_I": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "slave", + "parameters": { + "FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "CLK": [ { "physical_name": "sys_clk_i" } ] + } + }, + "ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "ARESETN": [ { "physical_name": "aresetn" } ] + } + }, + "C0_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C1_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C2_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C3_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C4_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C5_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C6_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "C7_ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + } + } + } + } +} \ No newline at end of file diff --git a/rtl/arty-a7/sdspi_testbench_behav.wcfg b/rtl/arty-a7/sdspi_testbench_behav.wcfg new file mode 100644 index 0000000..bb29917 --- /dev/null +++ b/rtl/arty-a7/sdspi_testbench_behav.wcfg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + tx_data[7:0] + tx_data[7:0] + + + rx_data[7:0] + rx_data[7:0] + + + rx_shifter[7:0] + rx_shifter[7:0] + + + tx_shifter[7:0] + tx_shifter[7:0] + + + tx_fifo_out[7:0] + tx_fifo_out[7:0] + + + tx_fifo_rd_en + tx_fifo_rd_en + + + tx_fifo_wr_en + tx_fifo_wr_en + + + rx_fifo_wr_en + rx_fifo_wr_en + + + rx_bit_recvd + rx_bit_recvd + + + tail_x[4:0] + tail_x[4:0] + + + head_x[4:0] + head_x[4:0] + + + tx_ready + tx_ready + + + tx_empty + tx_empty + + + rx_avail + rx_avail + + + tx_write + tx_write + + + rx_read + rx_read + + + ctrl_write + ctrl_write + + + rx_filter_en + rx_filter_en + + + txrx_en + txrx_en + + + spiclk_div_wr + spiclk_div_wr + + + spi_clk_on + spi_clk_on + + + spiclk_f_en + spiclk_f_en + + + spi_clk_f_on + spi_clk_f_on + + + sd_cs_n + sd_cs_n + #DCDCDC + true + + + sd_mosi + sd_mosi + #00FFFF + true + + + sd_miso + sd_miso + + + sd_sck + sd_sck + #FFFF00 + true + + + xcvr_on + xcvr_on + + + hphase_start + hphase_start + #F0E68C + true + + + clk_phase[1:0] + clk_phase[1:0] + #D2691E + true + + + running + running + + + xcvr_bitcount[3:0] + xcvr_bitcount[3:0] + + + spi_clk_count[6:0] + spi_clk_count[6:0] + + + spi_clk_div[6:0] + spi_clk_div[6:0] + + diff --git a/rtl/arty-a7/testbench_behav1.wcfg b/rtl/arty-a7/testbench_behav1.wcfg new file mode 100644 index 0000000..1a2bc03 --- /dev/null +++ b/rtl/arty-a7/testbench_behav1.wcfg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + clk + clk + + + addr[31:0] + addr[31:0] + + + data_in[31:0] + data_in[31:0] + + + data_out[31:0] + data_out[31:0] + + + seq_state[1:0] + seq_state[1:0] + + + PC[31:0] + PC[31:0] + + + nPC[31:0] + nPC[31:0] + + + ins[15:0] + ins[15:0] + BINARYRADIX + + + ins_branch + ins_branch + + + ins_loadrel + ins_loadrel + + + X[31:0] + X[31:0] + + + nX[31:0] + nX[31:0] + + + FP[31:0] + FP[31:0] + + + pc_next_ins[31:0] + pc_next_ins[31:0] + + + mem_wait + mem_wait + + + ins_buf[15:0] + ins_buf[15:0] + + diff --git a/rtl/arty-a7/tridoracpu.tcl b/rtl/arty-a7/tridoracpu.tcl new file mode 100644 index 0000000..46ab1d1 --- /dev/null +++ b/rtl/arty-a7/tridoracpu.tcl @@ -0,0 +1,683 @@ +#***************************************************************************************** +# Vivado (TM) v2020.1 (64-bit) +# +# tridoracpu.tcl: Tcl script for re-creating project 'tridoracpu' +# +# Generated by Vivado on Sat Sep 14 23:58:12 +0200 2024 +# IP Build 2902112 on Wed May 27 22:43:36 MDT 2020 +# +# This file contains the Vivado Tcl commands for re-creating the project to the state* +# when this script was generated. In order to re-create the project, please source this +# file in the Vivado Tcl Shell. +# +# * Note that the runs in the created project will be configured the same way as the +# original project, however they will not be launched automatically. To regenerate the +# run results please launch the synthesis/implementation runs as needed. +# +#***************************************************************************************** + +# uncomment next two statements if you have never initialized the Xilinx Board Store +# this will take quite some time +#xhub::refresh_catalog [xhub::get_xstores xilinx_board_store] +#xhub::install [xhub::get_xitems] + +# Set the reference directory for source file relative paths +set origin_dir "change_this_to_your_rtl_directory" + +set xilinx_board_store_dir [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] +set_param board.repoPaths [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] + +# Use origin directory path location variable, if specified in the tcl shell +if { [info exists ::origin_dir_loc] } { + set origin_dir $::origin_dir_loc +} + +# Set the project name +set _xil_proj_name_ "tridoracpu" + +# Use project name variable, if specified in the tcl shell +if { [info exists ::user_project_name] } { + set _xil_proj_name_ $::user_project_name +} + +variable script_file +set script_file "tridoracpu.tcl" + +# Help information for this script +proc print_help {} { + variable script_file + puts "\nDescription:" + puts "Recreate a Vivado project from this script. The created project will be" + puts "functionally equivalent to the original project for which this script was" + puts "generated. The script contains commands for creating a project, filesets," + puts "runs, adding/importing sources and setting properties on various objects.\n" + puts "Syntax:" + puts "$script_file" + puts "$script_file -tclargs \[--origin_dir \]" + puts "$script_file -tclargs \[--project_name \]" + puts "$script_file -tclargs \[--help\]\n" + puts "Usage:" + puts "Name Description" + puts "-------------------------------------------------------------------------" + puts "\[--origin_dir \] Determine source file paths wrt this path. Default" + puts " origin_dir path value is \".\", otherwise, the value" + puts " that was set with the \"-paths_relative_to\" switch" + puts " when this script was generated.\n" + puts "\[--project_name \] Create project with the specified name. Default" + puts " name is the name of the project from where this" + puts " script was generated.\n" + puts "\[--help\] Print help information for this script" + puts "-------------------------------------------------------------------------\n" + exit 0 +} + +if { $::argc > 0 } { + for {set i 0} {$i < $::argc} {incr i} { + set option [string trim [lindex $::argv $i]] + switch -regexp -- $option { + "--origin_dir" { incr i; set origin_dir [lindex $::argv $i] } + "--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] } + "--help" { print_help } + default { + if { [regexp {^-} $option] } { + puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n" + return 1 + } + } + } + } +} + +# Set the directory path for the original project from where this script was exported +set orig_proj_dir "[file normalize "${origin_dir}/arty-a7"]" + +# Create project +create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xc7a35ticsg324-1L + +# Set the directory path for the new project +set proj_dir [get_property directory [current_project]] + +# Set project properties +set obj [current_project] +#set_property -name "board_part_repo_paths" -value "[file normalize "$xilinx_board_store_dir"]" -objects $obj +set_property -name "board_part" -value "digilentinc.com:arty-a7-35:part0:1.0" -objects $obj +set_property -name "default_lib" -value "xil_defaultlib" -objects $obj +set_property -name "enable_vhdl_2008" -value "1" -objects $obj +set_property -name "ip_cache_permissions" -value "read write" -objects $obj +set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj +set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj +set_property -name "platform.board_id" -value "arty-a7-35" -objects $obj +set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj +set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj +set_property -name "simulator_language" -value "Mixed" -objects $obj +set_property -name "source_mgmt_mode" -value "DisplayOnly" -objects $obj +set_property -name "webtalk.activehdl_export_sim" -value "4" -objects $obj +set_property -name "webtalk.ies_export_sim" -value "4" -objects $obj +set_property -name "webtalk.modelsim_export_sim" -value "4" -objects $obj +set_property -name "webtalk.questa_export_sim" -value "4" -objects $obj +set_property -name "webtalk.riviera_export_sim" -value "4" -objects $obj +set_property -name "webtalk.vcs_export_sim" -value "4" -objects $obj +set_property -name "webtalk.xsim_export_sim" -value "4" -objects $obj +set_property -name "webtalk.xsim_launch_sim" -value "537" -objects $obj + +# Create 'sources_1' fileset (if not found) +if {[string equal [get_filesets -quiet sources_1] ""]} { + create_fileset -srcset sources_1 +} + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +set files [list \ + [file normalize "${origin_dir}/src/uart.v"] \ +] +add_files -norecurse -fileset $obj $files + +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/cpuclk.v" ]\ + [file normalize "${origin_dir}/src/display_clock.v" ]\ + [file normalize "${origin_dir}/src/mem.v" ]\ + [file normalize "${origin_dir}/src/stack.v" ]\ + [file normalize "${origin_dir}/src/stackcpu.v" ]\ + [file normalize "${origin_dir}/src/vgafb.v" ]\ + [file normalize "${origin_dir}/src/top.v" ]\ + [file normalize "${origin_dir}/src/testbench.v" ]\ + [file normalize "${orig_proj_dir}/rom.mem" ]\ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_a.prj" ]\ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_b.prj" ]\ + [file normalize "${origin_dir}/src/dram_bridge.v" ]\ + [file normalize "${origin_dir}/src/sdspi.v" ]\ + [file normalize "${origin_dir}/src/bram_tdp.v" ]\ + [file normalize "${origin_dir}/src/palette.v" ]\ + [file normalize "${origin_dir}/src/irqctrl.v" ]\ + [file normalize "${origin_dir}/src/fifo.v" ]\ + [file normalize "${origin_dir}/src/fifo_testbench.v" ]\ + [file normalize "${origin_dir}/src/sdspi_testbench.v" ]\ +] +set added_files [add_files -fileset sources_1 $files] + +# Set 'sources_1' fileset file properties for remote files +set file "$origin_dir/src/uart.v" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + + +# Set 'sources_1' fileset file properties for local files +set file "src/cpuclk.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/display_clock.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "is_enabled" -value "0" -objects $file_obj + +set file "src/mem.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/stack.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/stackcpu.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/vgafb.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/top.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/testbench.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + +set file "arty-a7/rom.mem" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "file_type" -value "Memory File" -objects $file_obj + +set file "arty-a7/mig_dram_0/mig_a.prj" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "scoped_to_cells" -value "mig_dram_0" -objects $file_obj + +set file "arty-a7/mig_dram_0/mig_b.prj" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "scoped_to_cells" -value "mig_dram_0" -objects $file_obj + +set file "src/dram_bridge.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/palette.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/irqctrl.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + +set file "src/fifo_testbench.v" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + + +# Set 'sources_1' fileset properties +set obj [get_filesets sources_1] +set_property -name "top" -value "top" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj + +# Set 'sources_1' fileset object +set obj [get_filesets sources_1] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${orig_proj_dir}/mig_dram_0/mig_dram_0.xci" ]\ +] +set added_files [add_files -fileset sources_1 $files] + +# Set 'sources_1' fileset file properties for remote files +# None + +# Set 'sources_1' fileset file properties for local files +set file "arty-a7/mig_dram_0/mig_dram_0.xci" +set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]] +set_property -name "generate_files_for_reference" -value "0" -objects $file_obj +set_property -name "registered_with_manager" -value "1" -objects $file_obj +if { ![get_property "is_locked" $file_obj] } { + set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj +} +set_property -name "used_in" -value "synthesis implementation" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj + + +# Create 'constrs_1' fileset (if not found) +if {[string equal [get_filesets -quiet constrs_1] ""]} { + create_fileset -constrset constrs_1 +} + +# Set 'constrs_1' fileset object +set obj [get_filesets constrs_1] + +# Add/Import constrs file and set constrs file properties +set file "[file normalize ${origin_dir}/arty-a7/Arty-A7-35-Master.xdc]" +set file_added [add_files -norecurse -fileset $obj [list $file]] +set file "$origin_dir/arty-a7/Arty-A7-35-Master.xdc" +set file [file normalize $file] +set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]] +set_property -name "file_type" -value "XDC" -objects $file_obj + +# Set 'constrs_1' fileset properties +set obj [get_filesets constrs_1] +set_property -name "target_constrs_file" -value "$orig_proj_dir/Arty-A7-35-Master.xdc" -objects $obj +set_property -name "target_ucf" -value "$orig_proj_dir/Arty-A7-35-Master.xdc" -objects $obj + +# Create 'sim_1' fileset (if not found) +if {[string equal [get_filesets -quiet sim_1] ""]} { + create_fileset -simset sim_1 +} + +# Set 'sim_1' fileset object +set obj [get_filesets sim_1] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/uart_tb.v" ]\ + [file normalize "${orig_proj_dir}/testbench_behav1.wcfg" ]\ +] +set added_files [add_files -fileset sim_1 $files] + +# Set 'sim_1' fileset file properties for remote files +# None + +# Set 'sim_1' fileset file properties for local files +set file [file normalize "${origin_dir}/src/uart_tb.v"] +set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]] +set_property -name "used_in" -value "" -objects $file_obj +set_property -name "used_in_implementation" -value "0" -objects $file_obj +set_property -name "used_in_simulation" -value "0" -objects $file_obj +set_property -name "used_in_synthesis" -value "0" -objects $file_obj + + +# Set 'sim_1' fileset properties +set obj [get_filesets sim_1] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "nl.mode" -value "funcsim" -objects $obj +set_property -name "top" -value "testbench" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj + +# Create 'sim_fifo' fileset (if not found) +if {[string equal [get_filesets -quiet sim_fifo] ""]} { + create_fileset -simset sim_fifo +} + +# Set 'sim_fifo' fileset object +set obj [get_filesets sim_fifo] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${origin_dir}/src/fifo.v" ]\ + [file normalize "${origin_dir}/src/fifo_testbench.v" ]\ +] +set added_files [add_files -fileset sim_fifo $files] + +# Set 'sim_fifo' fileset file properties for remote files +# None + +# Set 'sim_fifo' fileset file properties for local files +# None + +# Set 'sim_fifo' fileset properties +set obj [get_filesets sim_fifo] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "top" -value "fifo_testbench" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj + +# Create 'sim_sdspi' fileset (if not found) +if {[string equal [get_filesets -quiet sim_sdspi] ""]} { + create_fileset -simset sim_sdspi +} + +# Set 'sim_sdspi' fileset object +set obj [get_filesets sim_sdspi] +# Add local files from the original project (-no_copy_sources specified) +set files [list \ + [file normalize "${orig_proj_dir}/sdspi_testbench_behav.wcfg" ]\ +] +set added_files [add_files -fileset sim_sdspi $files] + +# Set 'sim_sdspi' fileset file properties for remote files +# None + +# Set 'sim_sdspi' fileset file properties for local files +# None + +# Set 'sim_sdspi' fileset properties +set obj [get_filesets sim_sdspi] +set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj +set_property -name "sim_mode" -value "post-synthesis" -objects $obj +set_property -name "top" -value "sdspi_testbench" -objects $obj +set_property -name "top_auto_set" -value "0" -objects $obj +set_property -name "top_lib" -value "xil_defaultlib" -objects $obj +set_property -name "xsim.simulate.runtime" -value "10ms" -objects $obj + +# Set 'utils_1' fileset object +set obj [get_filesets utils_1] +# Empty (no sources present) + +# Set 'utils_1' fileset properties +set obj [get_filesets utils_1] + +# Create 'synth_1' run (if not found) +if {[string equal [get_runs -quiet synth_1] ""]} { + create_run -name synth_1 -part xc7a35ticsg324-1L -flow {Vivado Synthesis 2020} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1 +} else { + set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1] + set_property flow "Vivado Synthesis 2020" [get_runs synth_1] +} +set obj [get_runs synth_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Synthesis Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'synth_1_synth_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } { + create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1 +} +set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] +if { $obj != "" } { + +} +set obj [get_runs synth_1] +set_property -name "needs_refresh" -value "1" -objects $obj +set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj + +# set the current synth run +current_run -synthesis [get_runs synth_1] + +# Create 'impl_1' run (if not found) +if {[string equal [get_runs -quiet impl_1] ""]} { + create_run -name impl_1 -part xc7a35ticsg324-1L -flow {Vivado Implementation 2020} -strategy "Performance_RefinePlacement" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1 +} else { + set_property strategy "Performance_RefinePlacement" [get_runs impl_1] + set_property flow "Vivado Implementation 2020" [get_runs impl_1] +} +set obj [get_runs impl_1] +set_property set_report_strategy_name 1 $obj +set_property report_strategy {Vivado Implementation Default Reports} $obj +set_property set_report_strategy_name 0 $obj +# Create 'impl_1_init_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_opt_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } { + create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] +if { $obj != "" } { + +} +# Create 'impl_1_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_place_report_io_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } { + create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] +if { $obj != "" } { + +} +# Create 'impl_1_place_report_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } { + create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] +if { $obj != "" } { + +} +# Create 'impl_1_place_report_control_sets_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } { + create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] +if { $obj != "" } { +set_property -name "options.verbose" -value "1" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj + +} +# Create 'impl_1_place_report_incremental_reuse_1' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } { + create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj + +} +# Create 'impl_1_place_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "is_enabled" -value "0" -objects $obj +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_route_report_drc_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } { + create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_methodology_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } { + create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_power_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } { + create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_route_status_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } { + create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] +if { $obj != "" } { +set_property -name "options.max_paths" -value "10" -objects $obj + +} +# Create 'impl_1_route_report_incremental_reuse_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } { + create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_clock_utilization_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } { + create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] +if { $obj != "" } { + +} +# Create 'impl_1_route_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] +if { $obj != "" } { +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] +if { $obj != "" } { +set_property -name "options.max_paths" -value "10" -objects $obj +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +# Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found) +if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } { + create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1 +} +set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] +if { $obj != "" } { +set_property -name "options.warn_on_violation" -value "1" -objects $obj + +} +set obj [get_runs impl_1] +set_property -name "needs_refresh" -value "1" -objects $obj +set_property -name "strategy" -value "Performance_RefinePlacement" -objects $obj +set_property -name "steps.place_design.args.directive" -value "ExtraPostPlacementOpt" -objects $obj +set_property -name "steps.phys_opt_design.args.directive" -value "Explore" -objects $obj +set_property -name "steps.route_design.args.directive" -value "Explore" -objects $obj +set_property -name "steps.write_bitstream.args.bin_file" -value "1" -objects $obj +set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj +set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj + +# set the current impl run +current_run -implementation [get_runs impl_1] + +puts "INFO: Project created:${_xil_proj_name_}" +# Create 'drc_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "drc_1" ] ] ""]} { +create_dashboard_gadget -name {drc_1} -type drc +} +set obj [get_dashboard_gadgets [ list "drc_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj + +# Create 'methodology_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "methodology_1" ] ] ""]} { +create_dashboard_gadget -name {methodology_1} -type methodology +} +set obj [get_dashboard_gadgets [ list "methodology_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj + +# Create 'power_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "power_1" ] ] ""]} { +create_dashboard_gadget -name {power_1} -type power +} +set obj [get_dashboard_gadgets [ list "power_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj + +# Create 'timing_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "timing_1" ] ] ""]} { +create_dashboard_gadget -name {timing_1} -type timing +} +set obj [get_dashboard_gadgets [ list "timing_1" ] ] +set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj + +# Create 'utilization_1' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "utilization_1" ] ] ""]} { +create_dashboard_gadget -name {utilization_1} -type utilization +} +set obj [get_dashboard_gadgets [ list "utilization_1" ] ] +set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj +set_property -name "run.step" -value "synth_design" -objects $obj +set_property -name "run.type" -value "synthesis" -objects $obj + +# Create 'utilization_2' gadget (if not found) +if {[string equal [get_dashboard_gadgets [ list "utilization_2" ] ] ""]} { +create_dashboard_gadget -name {utilization_2} -type utilization +} +set obj [get_dashboard_gadgets [ list "utilization_2" ] ] +set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj + +move_dashboard_gadget -name {utilization_1} -row 0 -col 0 +move_dashboard_gadget -name {power_1} -row 1 -col 0 +move_dashboard_gadget -name {drc_1} -row 2 -col 0 +move_dashboard_gadget -name {timing_1} -row 0 -col 1 +move_dashboard_gadget -name {utilization_2} -row 1 -col 1 +move_dashboard_gadget -name {methodology_1} -row 2 -col 1 diff --git a/rtl/src/bram_tdp.v b/rtl/src/bram_tdp.v new file mode 100644 index 0000000..9537b9c --- /dev/null +++ b/rtl/src/bram_tdp.v @@ -0,0 +1,46 @@ +`timescale 1ns / 1ps +// taken from https://danstrother.com/2010/09/11/inferring-rams-in-fpgas/ +// modified for one read/write-port and one read-only-port, +/// A parameterized, inferable, true dual-port, dual-clock block RAM in Verilog. + +module bram_tdp #( + parameter DATA = 72, + parameter ADDR = 10 +) ( + // Port A + input wire a_clk, + input wire a_rd, + input wire a_wr, + input wire [ADDR-1:0] a_addr, + input wire [DATA-1:0] a_din, + output reg [DATA-1:0] a_dout, + // Port B + input wire b_clk, + input wire [ADDR-1:0] b_addr, + output reg [DATA-1:0] b_dout, + input wire b_rd +); + +// Shared memory + reg [DATA-1:0] mem [(2**ADDR)-1:0]; + + wire a_en = a_rd || a_wr; + +// Port A +always @(posedge a_clk) begin + if(a_en) + begin + if(a_wr) + mem[a_addr] <= a_din; + else if(a_rd) + a_dout <= mem[a_addr]; + end +end + +// Port B +always @(posedge b_clk) begin + if(b_rd) + b_dout <= mem[b_addr]; +end + +endmodule diff --git a/rtl/src/cpuclk.v b/rtl/src/cpuclk.v new file mode 100644 index 0000000..613d85e --- /dev/null +++ b/rtl/src/cpuclk.v @@ -0,0 +1,83 @@ +`timescale 1ns / 1ps + +module cpu_clkgen( + input wire rst, + input wire clk100, + output wire cpuclk, + output wire dram_refclk, + output wire pixclk, + output wire locked + ); + + wire cpuclk_pre, clk_fb, refclk_pre, pixclk_pre; + + MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW) + .CLKFBOUT_MULT_F(10.0), // Multiply value for all CLKOUT (2.000-64.000). + .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000). + .CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). + // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) + .CLKOUT0_DIVIDE_F(12.0), // Divide amount for CLKOUT0 (1.000-128.000). + .CLKOUT1_DIVIDE(5), + .CLKOUT2_DIVIDE(40), // 40 = 25MHz pixel clock (should be 25.175MHz per spec) for 640x480 + //.CLKOUT2_DIVIDE(25), // 25 = 40MHz pixel clock for 800x600 + //.CLKOUT2_DIVIDE(15), // 15 = 66.66MHz pixel clock (should be 65.0Mhz per spec) for 1024x768 + .CLKOUT3_DIVIDE(1), + .CLKOUT4_DIVIDE(1), + .CLKOUT5_DIVIDE(1), + .CLKOUT6_DIVIDE(1), + // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT6_DUTY_CYCLE(0.5), + // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). + .CLKOUT0_PHASE(0.0), + .CLKOUT1_PHASE(0.0), + .CLKOUT2_PHASE(0.0), + .CLKOUT3_PHASE(0.0), + .CLKOUT4_PHASE(0.0), + .CLKOUT5_PHASE(0.0), + .CLKOUT6_PHASE(0.0), + .CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) + .DIVCLK_DIVIDE(1), // Master division value (1-106) + .REF_JITTER1(0.010), // Reference input jitter in UI (0.000-0.999). + .STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked (FALSE, TRUE) + ) + + MMCME2_BASE_inst ( + /* verilator lint_off PINCONNECTEMPTY */ + // Clock Outputs: 1-bit (each) output: User configurable clock outputs + .CLKOUT0(cpuclk_pre), // 1-bit output: CLKOUT0 + .CLKOUT0B(), // 1-bit output: Inverted CLKOUT0 + .CLKOUT1(refclk_pre), // 1-bit output: CLKOUT1 + .CLKOUT1B(), // 1-bit output: Inverted CLKOUT1 + .CLKOUT2(pixclk_pre), // 1-bit output: CLKOUT2 + .CLKOUT2B(), // 1-bit output: Inverted CLKOUT2 + .CLKOUT3(), // 1-bit output: CLKOUT3 + .CLKOUT3B(), // 1-bit output: Inverted CLKOUT3 + .CLKOUT4(), // 1-bit output: CLKOUT4 + .CLKOUT5(), // 1-bit output: CLKOUT5 + .CLKOUT6(), // 1-bit output: CLKOUT6 + // Feedback Clocks: 1-bit (each) output: Clock feedback ports + .CLKFBOUT(clk_fb), // 1-bit output: Feedback clock + .CLKFBOUTB(), // 1-bit output: Inverted CLKFBOUT + // Status Ports: 1-bit (each) output: MMCM status ports + .LOCKED(locked), // 1-bit output: LOCK + // Clock Inputs: 1-bit (each) input: Clock input + .CLKIN1(clk100), // 1-bit input: Clock + // Control Ports: 1-bit (each) input: MMCM control ports + .PWRDWN(), // 1-bit input: Power-down + /* verilator lint_on PINCONNECTEMPTY */ + .RST(rst), // 1-bit input: Reset + // Feedback Clocks: 1-bit (each) input: Clock feedback ports + .CLKFBIN(clk_fb) // 1-bit input: Feedback clock + ); + + BUFG bufg_cpuclk(.I(cpuclk_pre), .O(cpuclk)); + BUFG bufg_refclk(.I(refclk_pre), .O(dram_refclk)); + BUFG bufg_pixclk(.I(pixclk_pre), .O(pixclk)); +endmodule diff --git a/rtl/src/display_clock.v b/rtl/src/display_clock.v new file mode 100644 index 0000000..898ef7a --- /dev/null +++ b/rtl/src/display_clock.v @@ -0,0 +1,96 @@ +`timescale 1ns / 1ps +`default_nettype none + +// Project F: Display Clocks +// (C)2019 Will Green, Open source hardware released under the MIT License +// Learn more at https://projectf.io + +// Defaults to 25.2 and 126 MHz for 640x480 at 60 Hz + +module display_clock #( + MULT_MASTER=31.5, // master clock multiplier (2.000-64.000) + DIV_MASTER=5, // master clock divider (1-106) + DIV_5X=5.0, // 5x clock divider (1-128) + DIV_1X=25, // 1x clock divider (1-128) + IN_PERIOD=10.0 // period of i_clk in ns (100 MHz = 10.0 ns) + ) + ( + input wire i_clk, // input clock + input wire i_rst, // reset (active high) + output wire o_clk_1x, // pixel clock + output wire o_clk_5x, // 5x clock for 10:1 DDR SerDes + output wire o_locked // clock locked? (active high) + ); + + wire clk_fb; // internal clock feedback + wire clk_1x_pre; + wire clk_5x_pre; + + MMCME2_BASE #( + .BANDWIDTH("OPTIMIZED"), // Jitter programming (OPTIMIZED, HIGH, LOW) + .CLKFBOUT_MULT_F(MULT_MASTER), // Multiply value for all CLKOUT (2.000-64.000). + .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000). + .CLKIN1_PERIOD(IN_PERIOD), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). + // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) + .CLKOUT0_DIVIDE_F(DIV_5X), // Divide amount for CLKOUT0 (1.000-128.000). + .CLKOUT1_DIVIDE(DIV_1X), + .CLKOUT2_DIVIDE(1), + .CLKOUT3_DIVIDE(1), + .CLKOUT4_DIVIDE(1), + .CLKOUT5_DIVIDE(1), + .CLKOUT6_DIVIDE(1), + // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). + .CLKOUT0_DUTY_CYCLE(0.5), + .CLKOUT1_DUTY_CYCLE(0.5), + .CLKOUT2_DUTY_CYCLE(0.5), + .CLKOUT3_DUTY_CYCLE(0.5), + .CLKOUT4_DUTY_CYCLE(0.5), + .CLKOUT5_DUTY_CYCLE(0.5), + .CLKOUT6_DUTY_CYCLE(0.5), + // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). + .CLKOUT0_PHASE(0.0), + .CLKOUT1_PHASE(0.0), + .CLKOUT2_PHASE(0.0), + .CLKOUT3_PHASE(0.0), + .CLKOUT4_PHASE(0.0), + .CLKOUT5_PHASE(0.0), + .CLKOUT6_PHASE(0.0), + .CLKOUT4_CASCADE("FALSE"), // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) + .DIVCLK_DIVIDE(DIV_MASTER), // Master division value (1-106) + .REF_JITTER1(0.010), // Reference input jitter in UI (0.000-0.999). + .STARTUP_WAIT("FALSE") // Delays DONE until MMCM is locked (FALSE, TRUE) + ) + MMCME2_BASE_inst ( + /* verilator lint_off PINCONNECTEMPTY */ + // Clock Outputs: 1-bit (each) output: User configurable clock outputs + .CLKOUT0(clk_5x_pre), // 1-bit output: CLKOUT0 + .CLKOUT0B(), // 1-bit output: Inverted CLKOUT0 + .CLKOUT1(clk_1x_pre), // 1-bit output: CLKOUT1 + .CLKOUT1B(), // 1-bit output: Inverted CLKOUT1 + .CLKOUT2(), // 1-bit output: CLKOUT2 + .CLKOUT2B(), // 1-bit output: Inverted CLKOUT2 + .CLKOUT3(), // 1-bit output: CLKOUT3 + .CLKOUT3B(), // 1-bit output: Inverted CLKOUT3 + .CLKOUT4(), // 1-bit output: CLKOUT4 + .CLKOUT5(), // 1-bit output: CLKOUT5 + .CLKOUT6(), // 1-bit output: CLKOUT6 + // Feedback Clocks: 1-bit (each) output: Clock feedback ports + .CLKFBOUT(clk_fb), // 1-bit output: Feedback clock + .CLKFBOUTB(), // 1-bit output: Inverted CLKFBOUT + // Status Ports: 1-bit (each) output: MMCM status ports + .LOCKED(o_locked), // 1-bit output: LOCK + // Clock Inputs: 1-bit (each) input: Clock input + .CLKIN1(i_clk), // 1-bit input: Clock + // Control Ports: 1-bit (each) input: MMCM control ports + .PWRDWN(), // 1-bit input: Power-down + /* verilator lint_on PINCONNECTEMPTY */ + .RST(i_rst), // 1-bit input: Reset + // Feedback Clocks: 1-bit (each) input: Clock feedback ports + .CLKFBIN(clk_fb) // 1-bit input: Feedback clock + ); + + // explicitly buffer output clocks + BUFG bufg_clk_pix(.I(clk_1x_pre), .O(o_clk_1x)); + BUFG bufg_clk_pix_5x(.I(clk_5x_pre), .O(o_clk_5x)); + +endmodule \ No newline at end of file diff --git a/rtl/src/dram_bridge.v b/rtl/src/dram_bridge.v new file mode 100644 index 0000000..102a8cf --- /dev/null +++ b/rtl/src/dram_bridge.v @@ -0,0 +1,165 @@ +`timescale 1ns / 1ps + +module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32) +( + // local bus + input wire [ADDR_WIDTH-1:0] mem_addr, + output wire [WIDTH-1:0] mem_read_data, + input wire [WIDTH-1:0] mem_write_data, + input wire mem_read_enable, + input wire mem_write_enable, + output wire mem_wait, + + input wire rst_n, + input wire dram_front_clk, + input wire dram_refclk, + + // DDR3 SDRAM + inout wire [15:0] ddr3_dq, + inout wire [1:0] ddr3_dqs_n, + inout wire [1:0] ddr3_dqs_p, + + output wire [13:0] ddr3_addr, + output wire [2:0] ddr3_ba, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire ddr3_reset_n, + output wire [0:0] ddr3_ck_p, + output wire [0:0] ddr3_ck_n, + output wire [0:0] ddr3_cke, + output wire [0:0] ddr3_cs_n, + output wire [1:0] ddr3_dm, + output wire [0:0] ddr3_odt +); + + localparam DRAM_ADDR_WIDTH = 28, DRAM_DATA_WIDTH = 128, DRAM_MASK_WIDTH = 16; + wire [DRAM_ADDR_WIDTH-1:0] app_addr; + wire [2:0] app_cmd; + wire app_en; + wire app_rdy; + wire [DRAM_DATA_WIDTH-1:0] app_rd_data; + wire app_rd_data_end; + wire app_rd_data_valid; + wire [DRAM_DATA_WIDTH-1:0] app_wdf_data; + wire app_wdf_end; + wire [DRAM_MASK_WIDTH-1:0] app_wdf_mask; + wire app_wdf_rdy; + wire app_sr_active; + wire app_ref_ack; + wire app_zq_ack; + wire app_wdf_wren; + wire [11:0] device_temp; + wire ui_clk, ui_rst_sync; + wire init_calib_complete; + + localparam CMD_READ = 3'b1; + localparam CMD_WRITE = 3'b0; + + mig_dram_0 dram0( + // Inouts + .ddr3_dq(ddr3_dq), + .ddr3_dqs_n(ddr3_dqs_n), + .ddr3_dqs_p(ddr3_dqs_p), + // Outputs + .ddr3_addr(ddr3_addr), + .ddr3_ba(ddr3_ba), + .ddr3_ras_n(ddr3_ras_n), + .ddr3_cas_n(ddr3_cas_n), + .ddr3_we_n(ddr3_we_n), + .ddr3_reset_n(ddr3_reset_n), + .ddr3_ck_p(ddr3_ck_p), + .ddr3_ck_n(ddr3_ck_n), + .ddr3_cke(ddr3_cke), + .ddr3_cs_n(ddr3_cs_n), + .ddr3_dm(ddr3_dm), + .ddr3_odt(ddr3_odt), +// Application interface ports + .app_addr (app_addr), + .app_cmd (app_cmd), + .app_en (app_en), + .app_wdf_data (app_wdf_data), + .app_wdf_mask (app_wdf_mask), + .app_wdf_end (app_wdf_end), + .app_wdf_wren (app_wdf_wren), + .app_rd_data (app_rd_data), + .app_rd_data_end (app_rd_data_end), + .app_rd_data_valid (app_rd_data_valid), + .app_rdy (app_rdy), + .app_wdf_rdy (app_wdf_rdy), + .app_sr_req (1'b0), + .app_ref_req (1'b0), + .app_zq_req (1'b0), + .app_sr_active (app_sr_active), + .app_ref_ack (app_ref_ack), + .app_zq_ack (app_zq_ack), + .ui_clk (ui_clk), + .ui_clk_sync_rst (ui_rst_sync), + +// System Clock Ports + .sys_clk_i (dram_front_clk), +// Reference Clock Ports + .clk_ref_i (dram_refclk), + .device_temp (device_temp), + .init_calib_complete (init_calib_complete), + .sys_rst (rst_n) + ); + +// reg [DRAM_DATA_WIDTH-1:0] read_cache; +// reg [ADDR_WIDTH-1:0] cached_addr; +// wire cache_hit = cached_addr == mem_addr; +// wire [DRAM_DATA_WIDTH-1:0] read_data_wrapper = cache_hit ? read_cache : app_rd_data; + + reg [WIDTH-1:0] read_buf; + reg read_inprogress = 0; + + assign app_rd_data_end = 1'b1; + //assign app_wdf_mask = 16'b1111111111111100; + + // addresses on the memory interface are aligned to 16 bytes + // and 28 bits wide (=256MB) + assign app_addr = { mem_addr[DRAM_ADDR_WIDTH:4], 4'b0000 }; + //assign app_addr = { 28'b0 }; + + // select a word from the 128 bits transferred by the dram controller + // according to the lower bits of the address (ignoring bits 1:0) + wire [WIDTH-1:0] read_word; + wire [1:0] word_sel = mem_addr[3:2]; + + assign read_word = word_sel == 3'b11 ? app_rd_data[31:0] : + word_sel == 3'b10 ? app_rd_data[63:32] : + word_sel == 3'b01 ? app_rd_data[95:64] : + app_rd_data[127:96]; + + assign mem_read_data = app_rd_data_valid ? read_word : read_buf; + + // set the write mask according to the lower bits of the address + // (ignoring bit 0) + assign app_wdf_mask = word_sel == 3'b11 ? 16'b1111111111110000 : + word_sel == 3'b10 ? 16'b1111111100001111 : + word_sel == 3'b01 ? 16'b1111000011111111 : + 16'b0000111111111111 ; + + wire write_ready = mem_write_enable & app_wdf_rdy & app_rdy; + assign app_wdf_wren = mem_write_enable & write_ready; + assign app_wdf_end = mem_write_enable & write_ready; + assign app_wdf_data = { {4{mem_write_data}} }; + + assign mem_wait = (mem_read_enable & ~read_inprogress) | + (mem_write_enable & (~app_wdf_rdy | ~app_rdy)) | + (read_inprogress & ~app_rd_data_valid); + + assign app_en = (mem_read_enable & ~read_inprogress) | + (mem_write_enable & write_ready); + assign app_cmd = mem_read_enable ? CMD_READ : CMD_WRITE; + + always @(posedge dram_front_clk) + begin + if(mem_read_enable & ~read_inprogress & app_rdy) + read_inprogress <= 1; + if(read_inprogress & app_rd_data_valid) + read_inprogress <= 0; + if(mem_read_enable & app_rd_data_valid) + read_buf <= mem_read_data; + end +endmodule diff --git a/rtl/src/fifo.v b/rtl/src/fifo.v new file mode 100644 index 0000000..16d9583 --- /dev/null +++ b/rtl/src/fifo.v @@ -0,0 +1,53 @@ +`timescale 1ns / 1ps + +// a simple fifo +module fifo #(parameter DATA_WIDTH = 8, ADDR_WIDTH = 4)( + input wire clk, + input wire reset, + input wire wr_en, + input wire rd_en, + input wire [DATA_WIDTH-1:0] wr_data, + output wire [DATA_WIDTH-1:0] rd_data, + output wire wr_full, + output wire rd_empty + ); + + reg [DATA_WIDTH-1:0] mem [0:2**ADDR_WIDTH-1]; + reg [ADDR_WIDTH:0] head_x = 0; // head and tail have one extra bit + reg [ADDR_WIDTH:0] tail_x = 0; // for detecting overflows + wire [ADDR_WIDTH-1:0] head = head_x[ADDR_WIDTH-1:0]; + wire [ADDR_WIDTH-1:0] tail = tail_x[ADDR_WIDTH-1:0]; + + assign rd_data = mem[tail]; + // the fifo is full when head and tail pointer are the same + // and the extra bits differ (a wraparound occured) + assign wr_full = (head == tail) && (head_x[ADDR_WIDTH] != tail_x[ADDR_WIDTH]); + // the fifo is empty when head and tail pointer are the same + // and the extra bits are the same (no wraparound) + assign rd_empty = (head == tail) && (head_x[ADDR_WIDTH] == tail_x[ADDR_WIDTH]); + + // Writing to FIFO + always @(posedge clk) begin + if (reset) + head_x <= 0; + else if (wr_en) + begin + mem[head] <= wr_data; + // move head, possible wraparound + head_x <= head_x + 1'b1; + end + end + + // Reading from FIFO + always @(posedge clk) + begin + if (reset) + tail_x <= 0; + else if (rd_en) + begin + // rd_data always has current tail data + // move tail, possible wraparound + tail_x <= tail_x + 1'b1; + end + end +endmodule \ No newline at end of file diff --git a/rtl/src/fifo_testbench.v b/rtl/src/fifo_testbench.v new file mode 100644 index 0000000..ccc29ee --- /dev/null +++ b/rtl/src/fifo_testbench.v @@ -0,0 +1,116 @@ +`timescale 1ns / 1ns +`default_nettype none + +module fifo_testbench(); + // Test signals + reg clk = 0; + reg reset = 0; + reg wr_en = 0; + reg rd_en = 0; + reg [7:0] wr_data = 0; + wire [7:0] rd_data; + wire wr_full; + wire rd_empty; + + parameter CLOCK_NS = 10; + + // Unit Under Test + fifo #( + .DATA_WIDTH(8), + .ADDR_WIDTH(4) + ) UUT ( + .clk(clk), + .reset(reset), + .wr_en(wr_en), + .rd_en(rd_en), + .rd_data(rd_data), + .wr_data(wr_data), + .wr_full(wr_full), + .rd_empty(rd_empty) + ); + + // testbench clock + always + #(CLOCK_NS/2) clk <= ~clk; + + initial + begin + // issue reset + reset = 1'b1; + #10 + reset = 1'b0; + #10 + + // Write two bytes + wr_data <= 8'hAB; + wr_en <= 1'b1; + #10; + wr_data <= 8'hCD; + wr_en <= 1'b1; + #10; + wr_en <= 1'b0; + #10 + + // read fifo tail + if (rd_data == 8'hAB) + $display("Pass - Byte 1"); + else + $display("Failed - Byte 2"); + + // read/remove byte from tail + rd_en <= 1'b1; + #10 + // check next byte + if (rd_data == 8'hCD) + $display("Pass - Byte 2"); + else + $display("Failed - Byte 2"); + + // remove 2nd byte + rd_en <= 1'b1; + #10 + + rd_en <= 1'b0; + #10 + + // Write until full + rd_en <= 1'b0; + wr_en <= 1'b0; + + for (integer i = 0; i < 16; i = i + 1) begin + wr_data <= i; + wr_en <= 1'b1; + #10; + end + wr_en <= 1'b0; + + if (wr_full) + $display("Pass - Fifo full"); + else + $display("Failed - Fifo full"); + + + // read until empty + rd_en <= 1'b0; + wr_en <= 1'b0; + + for (integer i = 0; i < 16; i = i + 1) begin + rd_en <= 1'b1; + #10; + end + rd_en <= 1'b0; + + if (rd_empty) + $display("Pass - Fifo empty"); + else + $display("Failed - Fifo empty"); + $finish(); + end + + initial + begin + // Required to dump signals + $dumpfile("fifo_tb_dump.vcd"); + $dumpvars(0); + end +endmodule diff --git a/rtl/src/irqctrl.v b/rtl/src/irqctrl.v new file mode 100644 index 0000000..1a079bf --- /dev/null +++ b/rtl/src/irqctrl.v @@ -0,0 +1,73 @@ +`timescale 1ns / 1ps + +module irqctrl #(IRQ_LINES = 2, IRQ_DELAY_WIDTH = 4) ( + input wire clk, + input wire [IRQ_LINES-1:0] irq_in, + input wire cs, + input wire wr_en, + input wire irq_wr_seten, + output wire [IRQ_LINES-1:0] rd_data, + output wire irq_out + ); + + reg [IRQ_LINES-1:0] irq_status; // a 1 bit here means we have seen an interrupt on that line + reg [IRQ_LINES-1:0] irq_mask; // a bit in irq_status is only set if the corresponding bit in irq_mask is not set + // irq_mask is set from irq_status when an interrupt occurs (ie irq_out is set) + + reg irq_enabled; // globally enable/disable irq_out + reg [IRQ_DELAY_WIDTH-1:0] irq_delay; // counter to delay irq_out for a few cycles + reg irq_delaying; // delay is active + + wire irq_pending = (irq_status != 0); + + assign rd_data = irq_mask; + assign irq_out = irq_enabled && irq_pending && !irq_delaying; + + // irq_status and irq_pending flags + always @(posedge clk) + begin + if(irq_out) // when an interrupt is being signaled to the cpu, + irq_status <= 0; // clear irq status, status will be copied to irq_mask (see below) + else + if(irq_in != 0) + irq_status <= irq_status | (irq_in & ~irq_mask); // add active irq to irq_status + end + + // irq mask + always @(posedge clk) + begin + if (cs && wr_en && irq_wr_seten) // when enabling interrupts, clear mask + irq_mask <= 0; + else + if(irq_out) // when signalling an interrupt, set mask from status + irq_mask <= irq_status; + end + + // manage irq_enabled and irq_delay/irq_delaying + always @(posedge clk) + begin + if(cs && wr_en) // when writing to control register + begin + if(irq_wr_seten) // if wr_seten flag is set, enable interrupts and start delay + begin + irq_enabled <= 1; + irq_delaying <= 1; + irq_delay <= 1; + end + else + irq_enabled <= 0; // else disable interrupts + end + else if(irq_out) irq_enabled <= 0; // after sending interrupt to cpu, disable further interrupts + + if(irq_delaying) // the delay gives the CPU a chance to return from an interrupt handler + begin // if an interrupt is triggered again right after re-enabling interrupts + if(irq_delay==0) + begin + irq_delay <= 1; + irq_delaying <= 0; + end + else + irq_delay <= irq_delay + 1; + end + end + endmodule diff --git a/rtl/src/mem.v b/rtl/src/mem.v new file mode 100644 index 0000000..954443a --- /dev/null +++ b/rtl/src/mem.v @@ -0,0 +1,161 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 05.01.2021 21:53:41 +// Design Name: +// Module Name: mem +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + +// 32 bit wide rom with byte addressing (address bits 1-0 are ignored) +module rom32 #(parameter ADDR_WIDTH = 11, DATA_WIDTH = 32) +( + input wire clk, + input wire [ADDR_WIDTH-1:0] addr, + output reg [DATA_WIDTH-1:0] data_out, + input wire read_enable + ); + + wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 0 + reg [DATA_WIDTH-1:0] rom [0:(2**(ADDR_WIDTH-2))-1]; + + initial begin + $readmemb("C:\\Users\\sebastian\\develop\\fpga\\vdumbcpu\\rom.mem", rom); + end + + always @(posedge clk) data_out <= rom[internal_addr]; + +endmodule + +module ram32 #(parameter ADDR_WIDTH = 16, DATA_WIDTH = 32) + +( + input wire clk, + input wire [ADDR_WIDTH-1:0] addr, + output reg [DATA_WIDTH-1:0] data_out, + input wire read_enable, + input wire [DATA_WIDTH-1:0] data_in, + input wire write_enable + ); + + reg [DATA_WIDTH-1:0] ram [0:(2**(ADDR_WIDTH-2))-1]; // 32bit words with byte addressing + wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 1-0 + + always @(posedge clk) + begin + if(read_enable) + data_out <= ram[internal_addr]; + if(write_enable) + ram[internal_addr] <= data_in; + end +endmodule + +module mem #(parameter ADDR_WIDTH = 32, + parameter DATA_WIDTH = 32) +( + input wire clk, rst_n, + input wire [ADDR_WIDTH-1:0] addr, + output wire [DATA_WIDTH-1:0] data_out, + input wire read_enable, + input wire [DATA_WIDTH-1:0] data_in, + input wire write_enable, + output wire io_enable, + input wire [DATA_WIDTH-1:0] io_rd_data, + output wire mem_wait, + + output wire [ADDR_WIDTH-1:0] dram_addr, + input wire [DATA_WIDTH-1:0] dram_read_data, + output wire [DATA_WIDTH-1:0] dram_write_data, + output wire dram_read_enable, + output wire dram_write_enable, + input wire dram_wait + ); + + wire [DATA_WIDTH-1:0] ram_out, rom_out, dram_out; + + // address map: + // ROM $0000 - $07FF 2K + // IO $0800 - $0FFF 2K + // RAM1 $1000 - $FFFF 60K + // RAM2 $10000 - $FFFFFFFF ~4GB + + wire ram_cs = addr[ADDR_WIDTH-1:12] != { {(ADDR_WIDTH-12){1'b0}}}; + wire ram1_cs = ram_cs && (addr[ADDR_WIDTH-1:16] == { {(ADDR_WIDTH-16){1'b0}}}); + wire ram2_cs = ram_cs && !ram1_cs; + wire rom_cs = !ram_cs && addr[11] == 1'b0; + wire io_cs = !ram_cs && addr[11] == 1'b1; + + assign io_enable = io_cs; + + wire ram_read = ram1_cs && read_enable; + wire ram_write = ram1_cs && write_enable; + wire rom_read = rom_cs && read_enable; + + reg [DATA_WIDTH-1:0] data_buf; + + localparam SEL_RAM1 = 0; + localparam SEL_RAM2 = 1; + localparam SEL_ROM = 2; + localparam SEL_IO = 3; + localparam SEL_ERR = 4; + + reg [1:0] out_sel; + + // test + reg [1:0] wait_state; + + ram32 #(.ADDR_WIDTH(16)) ram0 // 64KB RAM + ( + .clk(clk), + .addr(addr[15:0]), + .data_out(ram_out), + .read_enable(ram_read), + .data_in(data_in), + .write_enable(ram_write) + ); + + rom32 #(.ADDR_WIDTH(11)) rom0 // 2KB ROM + ( + .clk(clk), + .addr(addr[10:0]), + .data_out(rom_out), + .read_enable(rom_read) + ); + + assign dram_out = dram_read_data; + assign dram_addr = addr; + assign dram_write_data = data_in; + assign dram_read_enable = ram2_cs & read_enable; + assign dram_write_enable = ram2_cs & write_enable; + + assign data_out = (out_sel == SEL_RAM1 ) ? ram_out : + (out_sel == SEL_RAM2 ) ? dram_out : + (out_sel == SEL_ROM ) ? rom_out : + (out_sel == SEL_IO ) ? io_rd_data : + data_buf; + + assign mem_wait = ram2_cs && dram_wait; + + always @(posedge clk) + begin + data_buf <= data_out; + if(read_enable) out_sel <= + ram1_cs ? SEL_RAM1 : + ram2_cs ? SEL_RAM2: + rom_cs ? SEL_ROM : + io_cs ? SEL_IO : + SEL_ERR; + end +endmodule diff --git a/rtl/src/palette.v b/rtl/src/palette.v new file mode 100644 index 0000000..d076453 --- /dev/null +++ b/rtl/src/palette.v @@ -0,0 +1,28 @@ +`timescale 1ns / 1ps +// taken from https://danstrother.com/2010/09/11/inferring-rams-in-fpgas/ +// modified for one read/write-port and one read-only-port, +/// A parameterized, inferable, true dual-port, dual-clock block RAM in Verilog. + +module palette #( + parameter SLOTS_WIDTH = 4, COLOR_WIDTH = 12 +) ( + input wire wr_clk, + input wire rd_clk, + input wire wr_en, + input wire [SLOTS_WIDTH-1:0] wr_slot, + input wire [COLOR_WIDTH-1:0] wr_data, + input wire [SLOTS_WIDTH-1:0] rd_slot, + output wire [COLOR_WIDTH-1:0] rd_data +); + +// Shared memory + reg [COLOR_WIDTH-1:0] colors [(2**SLOTS_WIDTH)-1:0]; + + assign rd_data = colors[rd_slot]; + + always @(posedge wr_clk) begin + if(wr_en) colors[wr_slot] <= wr_data; + end + +endmodule + diff --git a/rtl/src/sdspi.v b/rtl/src/sdspi.v new file mode 100644 index 0000000..7141288 --- /dev/null +++ b/rtl/src/sdspi.v @@ -0,0 +1,372 @@ +`timescale 1ns / 1ps + + +// Every spi_clk_div cpu clock cycles the spi clock line is inverted. +// So a spi clock cycle is 2*spi_clk_div cpu clock cycles. +// spi_clk_count counts the cpu cycles from spi_clk_div down to zero. +// The resulting spi clock frequency is: +// (cpu clock freq) / ((sclk_count + 1) * 2) +// So for a 83.33 MHz cpu clock, we get +// spi_clk_div = 10: 83.333 / 22 = 3.788 MHz +// spi_clk_div = 124: 83.333 / 250 = 333.33 KHz + + +module sdspi( + input wire clk, // bus clock + input wire reset, + + input wire[7:0] tx_data, // data to transmit + output wire[7:0] rx_data, // data received + output wire tx_ready, // ready to write a data byte + output wire tx_empty, // transmitter fifo is empty + output wire rx_avail, // a byte has been received + output wire rx_ovr, // receiver overrun + input wire tx_write, // write strobe + input wire rx_read, // read strobe (clears rx_ovr) + + output wire card_detect, // true is card is present + output wire card_changed, // card_detect signal has changed + output wire card_busy, // card is busy (MISO/DO is 0) + + input wire ctrl_write, // set the following flags + input wire rx_filter_en, // set to discard received $FF bytes + input wire txrx_en, // enable transmitter and receiver + input wire spiclk_f_en, // enable spi clock without cs + input wire spiclk_div_wr, // set clock divider via tx_data + + // PMOD connections + output wire sd_cs_n, + output reg sd_mosi, + input wire sd_miso, + output wire sd_sck, + input wire sd_cd + ); + + localparam CLKPHASE_0A = 2'b00; + localparam CLKPHASE_0B = 2'b01; + localparam CLKPHASE_1A = 2'b10; + localparam CLKPHASE_1B = 2'b11; + reg [1:0] clk_phase; + + reg xcvr_on; // if turned off, the rest of the current byte + // will still transmitted, and until then "running" + // will be 1 + (* KEEP *) + reg running; // transmitting/receiving a byte (maybe a dummy byte) + + (* KEEP *) reg [3:0] xcvr_bitcount; // number of bits left of the current byte + + reg [7:0] tx_shifter; + wire tx_fifo_wr_en; + reg tx_fifo_rd_en; + wire tx_fifo_full; + wire tx_fifo_empty; + wire [7:0] tx_fifo_out; + + reg [7:0] rx_shifter; + reg rx_filter; + reg rx_fifo_wr_en; + wire rx_fifo_rd_en; + wire rx_fifo_full; + wire rx_fifo_empty; + wire [7:0] rx_fifo_out; + + reg rx_bit_recvd; // this flag signals a received bit + + reg rx_overrun; // byte received when rx fifo is full + + reg c_changed; + reg c_cs; + + reg spi_clk; // the spi clock signal + reg spi_clk_on; // enable clock, either via init mode or by xcvr_on + reg spi_clk_f_on; // init clock mode, i.e. start clock but no tx/rx + reg [6:0] spi_clk_count; // counting cpu clock ticks + reg [6:0] spi_clk_div; // tick counter for spi clock phases + wire spi_clk_count_z = (spi_clk_count == 7'b0); + reg hphase_start; // start of a spi clock half-phase + + assign tx_ready = !tx_fifo_full; + assign tx_empty = tx_fifo_empty; + assign rx_avail = !rx_fifo_empty; + assign rx_ovr = rx_overrun; + assign rx_data = rx_fifo_out; + + assign card_busy = (sd_miso == 0); + assign card_changed = c_changed; + + assign sd_sck = spi_clk; + assign sd_cs_n = ~c_cs; + + assign card_detect = sd_cd; + + fifo #(.ADDR_WIDTH(4)) tx_fifo(clk, reset, + tx_fifo_wr_en, tx_fifo_rd_en, + tx_data, tx_fifo_out, + tx_fifo_full, + tx_fifo_empty + ); + + fifo #(.ADDR_WIDTH(8)) rx_fifo(clk, reset, + rx_fifo_wr_en, rx_fifo_rd_en, + rx_shifter, rx_fifo_out, + rx_fifo_full, + rx_fifo_empty + ); + + // spi clock + always @(posedge clk) + begin + if(reset) + begin + spi_clk <= 1; // CLK is high when inactive + spi_clk_on <= 0; + spi_clk_count <= 0; + end + else if(spi_clk_on) + begin + + // set spi_clk at start of every half-phase + if(hphase_start) + case(clk_phase) + CLKPHASE_0A: spi_clk <= 1'b0; + CLKPHASE_0B: spi_clk <= 1'b0; + CLKPHASE_1A: spi_clk <= 1'b1; + CLKPHASE_1B: spi_clk <= 1'b1; + endcase + + if(spi_clk_count_z) + begin + spi_clk_count <= spi_clk_div; + clk_phase <= clk_phase + 2'b1; + end + else + spi_clk_count <= spi_clk_count - 7'd1; + end + + // start the clock if needed + if( (spi_clk_on == 0) && (running || spi_clk_f_on)) + begin + spi_clk_on <= 1; + spi_clk_count <= spi_clk_div; + clk_phase <= CLKPHASE_1A; + end + + // turn off the clock if transceiver not running + // and the force-clock-on flag is not set + if( (spi_clk_on == 1) && (!running && !spi_clk_f_on)) + begin + spi_clk_on <= 0; + spi_clk <= 1'b1; + end + end + + // half-phase-start flag trails spi_clk_count_z by one tick + always @(posedge clk) + begin + if(reset) + hphase_start <= 0; + else + hphase_start <= spi_clk_on && spi_clk_count_z; + end + + // handle the force clock enable flag + always @(posedge clk) + begin + if (reset) + spi_clk_f_on <= 0; + else + if (ctrl_write) + spi_clk_f_on <= spiclk_f_en; + end + + // clock divider + always @(posedge clk) + begin + if (spiclk_div_wr) spi_clk_div <= tx_data[6:0]; + end + + // card_changed flag + always @(posedge clk) + begin + if(sd_cd) + c_changed <= 1; + else if(ctrl_write || reset) + c_changed <= 0; + end + + // cs signal + always @(posedge clk) + begin + if(hphase_start && clk_phase == CLKPHASE_0A || !running) + c_cs <= running; + end + + // transmitter + always @(posedge clk) + begin + if(reset) + begin + // ???? we start the bitcount at 1 because we start + // at the second clock phase where the bitcount + // is decremented and the next byte gets loaded + xcvr_bitcount <= 0; + + tx_shifter <= 8'b1; + xcvr_on <= 0; + sd_mosi <= 1; + tx_fifo_rd_en <= 0; + end + else + begin + // handle a control write to disable the transceiver + if(ctrl_write && !txrx_en && xcvr_on) + xcvr_on <= 0; + // a byte might still be in transit, so + // we do not disable the transceiver + // immediately (see "handle running status" below) + else + // handle control write to enable the transceiver + if(ctrl_write && txrx_en && !running) + begin + xcvr_on <= 1; + xcvr_bitcount <= 0; + // next clock phase must be 1B when starting the transceiver, + // so that the first byte is loaded into the shifter then + tx_shifter <= 8'b11111111; + // in case the transceiver is enabled, but no data is in the fifo, + // initialize the shifter with $FF + end + else + // handle clock phases + if (running) + begin + if(hphase_start) + case(clk_phase) + // set mosi signal at start of clock pulse + CLKPHASE_0A: sd_mosi <= tx_shifter[7]; + CLKPHASE_0B: ; + CLKPHASE_1A: begin // shift at rising clock + tx_shifter <= tx_shifter << 1; + xcvr_bitcount <= xcvr_bitcount - 1; + end + CLKPHASE_1B: begin // in the middle of the high clock pulse, + // fetch the next byte if there are no bits + // left in the shift register + if (xcvr_bitcount == 0) + begin + if(!tx_fifo_empty) + begin + tx_shifter <= tx_fifo_out; + tx_fifo_rd_en <= 1; + end + else + tx_shifter <= 8'b11111111; + xcvr_bitcount <= 8; + end + else + tx_fifo_rd_en <= 0; + end + endcase + else + tx_fifo_rd_en <= 0; + end + end + end + + // handle data write + assign tx_fifo_wr_en = tx_write && !tx_fifo_full; + + // Enable fifo read signal if fifo is not empty. + // The data at the fifo tail is always available at + // rx_data, the read signal just moves the tail pointer + // forward. + assign rx_fifo_rd_en = rx_read && !rx_fifo_empty; + + // receiver + always @(posedge clk) + begin + if(reset) + begin + rx_bit_recvd <= 0; + rx_shifter <= 8'b11111111; + rx_fifo_wr_en <= 0; + rx_filter <= 0; + rx_overrun <= 0; + end + else + begin + // handle a control write + if(ctrl_write) + begin + rx_filter <= rx_filter_en; + rx_overrun <= 0; + if(txrx_en && !running) + rx_shifter <= 8'b0; + end + + if (running && hphase_start) + case(clk_phase) + CLKPHASE_0A: ; + CLKPHASE_0B: ; + CLKPHASE_1A: ; + CLKPHASE_1B: begin // in the middle of the high clock pulse, + // sample MISO and put into shift register + // and shift at the same time + rx_shifter <= { rx_shifter[6:0],sd_miso}; + rx_bit_recvd <= 1; + end + endcase + + if (rx_bit_recvd && !sd_cs_n && clk_phase == CLKPHASE_1B) + begin + rx_bit_recvd <= 0; + + // if a complete byte was received, bitcount will be + // 8 because the transmitter has already loaded the next byte + // at this half-phase + if (xcvr_bitcount == 8) + begin + // discard $FF bytes if filter is enabled + if(!rx_filter || rx_shifter != 8'b11111111) + begin + if(rx_fifo_full) // discard received byte if fifo is full + rx_overrun <= 1; // and set overrun flag + else + rx_fifo_wr_en <= 1; // otherwise, enable fifo write strobe, + // fifo will take data from rx_shifter + end + + // turn off filter if a byte != $FF was received + if (rx_filter && rx_shifter != 8'b11111111) + rx_filter <= 0; + end + end + else + rx_fifo_wr_en <= 0; + + end + end + + // handle running status + // (especially keep transmitter running when there are still bits left to be + // transmitted) + always@(posedge clk) + begin + if (reset) + running <= 0; + else + begin + // if we want to turn the transceiver on, set running flag + if (!running && xcvr_on) + running <= 1; + + // when running and a byte has been transmitted, + // check if we should turn the transceiver off + if (running && hphase_start && xcvr_bitcount==0) + if(clk_phase == CLKPHASE_1B) + if (!xcvr_on) + running <= 0; + end + end +endmodule diff --git a/rtl/src/sdspi_testbench.v b/rtl/src/sdspi_testbench.v new file mode 100644 index 0000000..a4113fb --- /dev/null +++ b/rtl/src/sdspi_testbench.v @@ -0,0 +1,199 @@ +`timescale 1ns / 1ns +`default_nettype none + +module sdspi_testbench(); + parameter CLOCK_NS = 10; + integer i,j; + + reg[7:0] rx_testdata[0:3]; + reg[7:0] read_data; + + // Test signals + reg clk = 0; + reg reset = 0; + + reg[7:0] tx_data = 0; + wire[7:0] rx_data; + wire tx_ready; + wire tx_empty; + wire rx_avail; + wire rx_ovr; + reg tx_write = 0; + reg rx_read = 0; + + wire card_detect; + wire card_changed; + wire card_busy; + + reg ctrl_write = 0; + reg rx_filter_en = 0; + reg txrx_en = 0; + reg spiclk_f_en = 0; + reg spiclk_div_wr = 0; + + // PMOD connections + wire sd_cs_n; + wire sd_mosi; + reg sd_miso = 1; + wire sd_sck; + reg sd_cd = 1; + + // Unit Under Test + sdspi UUT ( + .clk(clk), + .reset(reset), + .tx_data(tx_data), + .rx_data(rx_data), + .tx_ready(tx_ready), + .tx_empty(tx_empty), + .rx_avail(rx_avail), + .rx_ovr(rx_ovr), + .tx_write(tx_write), + .rx_read(rx_read), + .card_detect(card_detect), + .card_changed(card_changed), + .card_busy(card_busy), + .ctrl_write(ctrl_write), + .rx_filter_en(rx_filter_en), + .txrx_en(txrx_en), + .spiclk_f_en(spiclk_f_en), + .spiclk_div_wr(spiclk_div_wr), + .sd_cs_n(sd_cs_n), + .sd_mosi(sd_mosi), + .sd_miso(sd_miso), + .sd_sck(sd_sck), + .sd_cd(sd_cd) + ); + + // testbench clock + always + #(CLOCK_NS/2) clk <= ~clk; + + initial + begin + rx_testdata[0] <= 'hFF; + rx_testdata[1] <= 'hFF; + rx_testdata[2] <= 'hCA; + rx_testdata[3] <= 'hFE; + + // issue reset + reset = 1'b1; + #10 + reset = 1'b0; + #10 + + // set clock divider + tx_data <= 3; + spiclk_div_wr <= 1'b1; + #10 + spiclk_div_wr <= 1'b0; + #10 + + // Card initialization phase, + // cycle the clock at least 74 times + // while cs is off and mosi is high . + // we do 32 cycles + spiclk_f_en <= 1'b1; + ctrl_write <= 1'b1; + #10 + spiclk_f_en <= 1'b0; + ctrl_write <= 1'b0; + #10 + for (i=0; i<32*16; i = i + 1) + #10; + spiclk_f_en <= 1'b0; + ctrl_write <= 1'b1; + #10 + ctrl_write <= 1'b0; + #10 + for (i=0; i<32*16; i = i + 1) + #10; + + // Write two bytes + tx_data <= 8'hAB; + tx_write <= 1'b1; + #10; + tx_data <= 8'hCD; + tx_write <= 1'b1; + #10; + tx_write <= 1'b0; + #10 + + // start transceiver, enable rx_filter + txrx_en <= 1'b1; + rx_filter_en <= 1'b1; + ctrl_write <= 1'b1; + #10 + txrx_en <= 1'b0; + rx_filter_en <= 1'b0; + ctrl_write <= 1'b0; + + for (i = 0; i < 2048; i = i + 1) + begin + if (!sd_cs_n && (i % 16)==15) sd_miso <= rx_testdata[(i/(16*8)) % 4][7 - (i/16 % 8)]; + #10; + end + tx_write <= 1'b0; + #10 + + // read from rx fifo + read_data <= rx_data; + #10 + $display("read data 1: %02h", read_data); + + + // strobe rx_read to go to next byte + rx_read <= 1'b1; + #10 // one cycle to transfer the data + rx_read <= 1'b0; + #10 // we need this extra cycle for the fifo tail to move + + read_data <= rx_data; + #10 + $display("read data 2: %02h", read_data); + + // strobe rx_read to go to next byte + rx_read <= 1'b1; + #10 + rx_read <= 1'b0; + #10 // we need this extra cycle for the fifo tail to move + + read_data <= rx_data; + #10 + $display("read data 3: %02h", read_data); + + + // set flag to turn transceiver off + txrx_en <= 1'b0; + ctrl_write <= 1'b1; + #10 + ctrl_write <= 1'b0; + #10; + + // wait for the transceiver to actually turn off + for (i=0; i<32*16; i = i + 1) + #10; + + #10 + // clear rx fifo + for(i=0; i<14; i = i + 1) + begin + $display("clear fifo data %02h", rx_data); + rx_read <= 1'b1; + #10 + rx_read <= 1'b0; + #10 + #10 + #10; // simulate the four cycles of an instruction + end + + $finish(); + end + + initial + begin + // Required to dump signals + $dumpfile("sdspi_tb_dump.vcd"); + $dumpvars(0); + end +endmodule diff --git a/rtl/src/stack.v b/rtl/src/stack.v new file mode 100644 index 0000000..965c070 --- /dev/null +++ b/rtl/src/stack.v @@ -0,0 +1,42 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 17.01.2021 20:59:29 +// Design Name: +// Module Name: stack +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module stack + #(parameter ADDR_WIDTH=4, DATA_WIDTH=16) + ( + input wire clk, + input wire [ADDR_WIDTH-1:0] rd_addr, + input wire [ADDR_WIDTH-1:0] wr_addr, + input wire wr_enable, + output wire [DATA_WIDTH-1:0] rd_data, + input wire [DATA_WIDTH-1:0] wr_data + ); + + reg [DATA_WIDTH-1:0] stack[0:2**ADDR_WIDTH-1]; + + always @(posedge clk) + begin + if(wr_enable) stack[wr_addr] <= wr_data; + end + + assign rd_data = stack[rd_addr]; +endmodule diff --git a/rtl/src/stackcpu.v b/rtl/src/stackcpu.v new file mode 100644 index 0000000..c65ae4e --- /dev/null +++ b/rtl/src/stackcpu.v @@ -0,0 +1,427 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// + +module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32, + WORDSIZE = 4, WORDSIZE_SHIFT = 2) ( + input wire clk, + input wire rst, + + input wire irq, + + output reg [ADDR_WIDTH-1:0] addr, + input wire [WIDTH-1:0] data_in, + output wire read_enable, + output wire [WIDTH-1:0] data_out, + output wire write_enable, + input wire mem_wait, + + output wire led1, + output wire led2, + output wire led3, + + output wire [WIDTH-1:0] debug_out1, + output wire [WIDTH-1:0] debug_out2, + output wire [WIDTH-1:0] debug_out3, + output wire [WIDTH-1:0] debug_out4, + output wire [WIDTH-1:0] debug_out5, + output wire [WIDTH-1:0] debug_out6 + ); + + localparam EVAL_STACK_INDEX_WIDTH = 6; + + wire reset = !rst; + + (* KEEP *) reg [1:0] seq_state; + localparam FETCH = 2'b00; localparam DECODE = 2'b01; localparam EXEC = 2'b10; localparam MEM = 2'b11; + + (* KEEP*) reg [WIDTH-1:0] X, nX; + wire [WIDTH-1:0] Y; + (* KEEP *) reg [WIDTH-1:0] PC, nPC; + reg [WIDTH-1:0] RP, nRP; + reg [WIDTH-1:0] FP, BP; + reg [WIDTH-1:0] IV,IR; + + wire [WIDTH-1:0] pc_next_ins = PC + 2; + + reg [EVAL_STACK_INDEX_WIDTH-1:0] ESP, nESP; + reg stack_write; + + reg irq_pending; + + // eval stack + stack #(.ADDR_WIDTH(EVAL_STACK_INDEX_WIDTH), .DATA_WIDTH(WIDTH)) estack ( + .clk(clk), + .rd_addr(ESP), + .wr_addr(nESP), + .wr_enable(stack_write), + .rd_data(Y), + .wr_data(X) + ); + + reg [15:0] ins; + + wire [WIDTH-1:0] operand; + + // decoded instructions + wire ins_loadrel; + wire ins_load; + wire ins_loadc; + wire ins_store; + wire ins_aluop; + wire ins_ext; + wire ins_xfer; + wire ins_branch; + wire ins_cbranch; + + // decoded extended instructions + wire ins_mem, ins_loadi, ins_storei; + wire ins_fpadj; + wire ins_reg, ins_loadreg, ins_storereg; + wire ins_reg_fp, ins_reg_bp, ins_reg_rp; + wire ins_reg_iv, ins_reg_ir; + wire ins_reg_esp; + wire loadstore_base; + wire cbranch_n; + + wire xfer_x2p, xfer_r2p, xfer_p2r; + wire [1:0] xfer_rs; + + wire [3:0] aluop; + wire [1:0] aluop_sd; + wire aluop_x2y, aluop_ext; + + wire cmp_i, cmp_e, cmp_l; + + wire mem_read; + wire mem_write; + + wire x_is_zero; + // wire [WIDTH-1:0] y_plus_operand = Y + operand; + + wire x_equals_y = X == Y; + wire y_lessthan_x = $signed(Y) < $signed(X); + wire yx_unsigned_less = Y < X; + + reg [WIDTH-1:0] mem_write_data; + + wire mem_read_enable, mem_write_enable; + + assign read_enable = mem_read_enable; + assign data_out = mem_write_data; + assign write_enable = mem_write_enable; + + // debug output ------------------------------------------------------------------------------------ + assign led1 = reset; + assign led2 = ins_loadc; + assign led3 = ins_branch; +// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero, +// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state}; +// assign debug_out2 = data_in; +// assign debug_out3 = nX; +// assign debug_out4 = nPC; +// assign debug_out5 = ins; +// assign debug_out6 = IV; + //-------------------------------------------------------------------------------------------------- + + // instruction decoding + assign ins_branch = (ins[15:13] == 3'b000); + assign ins_aluop = (ins[15:13] == 3'b001); + assign ins_store = (ins[15:13] == 3'b010); + assign ins_xfer = (ins[15:13] == 3'b011); + assign ins_load = (ins[15:13] == 3'b100); + assign ins_cbranch = (ins[15:13] == 3'b101); + assign ins_loadc = (ins[15:13] == 3'b110); + assign ins_ext = (ins[15:13] == 3'b111); + + // sub-decode LOAD/STORE + assign loadstore_base = ins[0]; + + // sub-decode CBRANCH + assign cbranch_n = ins[0]; + + // sub-decode XFER + assign xfer_x2p = ins[0]; + assign xfer_r2p = ins[7]; + assign xfer_p2r = ins[6]; + assign xfer_rs = ins[9:8]; + + // sub-decode OP + assign aluop = ins[12:9]; + assign aluop_x2y = ins[6]; + assign aluop_sd = ins[5:4]; + assign aluop_ext = ins[7]; + + // sub-decode OP.CMP + assign cmp_i = ins[2]; + assign cmp_e = ins[1]; + assign cmp_l = ins[0]; + + assign x_is_zero = X == {WIDTH{1'b0}}; + + // decode extended instructions + assign ins_reg = (ins_ext && ins[12:10] == 3'b000); + assign ins_mem = (ins_ext && ins[12:10] == 3'b001); + assign ins_loadi = (ins_mem && ins[9] == 1'b0); + assign ins_storei = (ins_mem && ins[9] == 1'b1); + assign ins_fpadj = (ins_ext && ins[12:10] == 3'b011); + assign ins_loadrel= (ins_ext && ins[12:10] == 3'b101); + + // sub-decode LOADREG/STOREREG + assign ins_loadreg = (ins_reg && ins[9] == 1'b0); + assign ins_storereg = (ins_reg && ins[9] == 1'b1); + assign ins_reg_fp = (ins_reg && ins[3:0] == 4'b0000); + assign ins_reg_bp = (ins_reg && ins[3:0] == 4'b0001); + assign ins_reg_rp = (ins_reg && ins[3:0] == 4'b0010); + assign ins_reg_iv = (ins_reg && ins[3:0] == 4'b0011); + assign ins_reg_ir = (ins_reg && ins[3:0] == 4'b0100); + assign ins_reg_esp = (ins_reg && ins[3:0] == 4'b0101); + + assign mem_read = ins_loadi || ins_load || ins_loadrel || (ins_xfer && xfer_r2p); + assign mem_write = ins_storei || ins_store || (ins_xfer && xfer_p2r); + + assign mem_read_enable = (seq_state == FETCH) || (seq_state == EXEC && mem_read); + assign mem_write_enable = (seq_state == MEM && mem_write); + + initial + begin + PC <= 0; nPC <= 0; seq_state <= MEM; + ESP <= -1; nESP <= -1; + addr <= 0; + FP <= 0; BP <= 0; RP <= 0; nRP <= 0; + IV <= 0; IR <= 0; + irq_pending <= 0; + end + + // instruction sequencer + always @(posedge clk) + begin + if(reset) + seq_state <= MEM; + else if(mem_wait == 1'b0) + case(seq_state) + FETCH: seq_state <= DECODE; + DECODE: seq_state <= EXEC; + EXEC: seq_state <= MEM; + MEM: seq_state <= FETCH; + default: seq_state <= FETCH; + endcase + end + + // operand register + assign operand = + (ins_load || ins_store || ins_branch || ins_cbranch) ? + { {(WIDTH-13){ins[12]}}, ins[12:1], 1'b0 } + : (ins_loadc) ? { {(WIDTH-13){ins[12]}}, ins[12:0] } // sign extend + : (ins_aluop || ins_mem) ? + { {(WIDTH-4){1'b0}}, ins[3:0] } + : (ins_loadrel) ? { {(WIDTH-10){1'b0}}, ins[9:0] } + : (ins_fpadj) ? { {(WIDTH-10){ins[9]}}, ins[9:0] } // sign extend + : { {WIDTH{1'b0}} }; + + // program counter + always @(posedge clk) + begin + if(reset) nPC <= 0; + else + case(seq_state) + EXEC: + if(ins_xfer && xfer_x2p) nPC <= X; + else if(ins_branch || (ins_cbranch && (x_is_zero != cbranch_n))) nPC <= PC + operand; + else nPC <= pc_next_ins; + MEM: + if(ins_xfer && xfer_r2p) nPC <= data_in; + else if(irq_pending) nPC <= IV; + endcase + end + + // return stack pointer + always @* + begin + if(seq_state == EXEC || seq_state == DECODE || seq_state == MEM) + begin + if (ins_xfer) nRP <= RP + + ({ {(ADDR_WIDTH-3){xfer_rs[1]}},xfer_rs} << WORDSIZE_SHIFT); + // sign extend xfer_rs and multiply by word size + else if (ins_storereg && ins_reg_rp) nRP <= X; + else nRP <= RP; + end + else nRP <= nRP; + end + + // instruction fetch + // depending on bit 1 of the PC, read either the upper or lower half word as an instruction + always @* if(seq_state == DECODE) ins <= PC[1] ? data_in[15:0] : data_in[31:16]; + + // RAM read/write + always @(posedge clk) + begin + if(reset) + begin + addr <= 0; + mem_write_data <= 0; + end + else + case(seq_state) + DECODE: + if(ins_load || ins_store) // read from address in BP/FP + offset + addr <= operand + ( loadstore_base ? BP: FP); + else if (ins_loadi) // read from address in X + addr <= X; + else if (ins_storei) // write to address in Y + addr <= Y; + else if (ins_loadrel) // read from address next to current instruction + addr <= PC + operand; + else if (ins_xfer && xfer_r2p) // read from return stack + addr <= RP; // use the current RP + else if (ins_xfer && xfer_p2r) // write to return stack + addr <= nRP; // use the new RP + EXEC: + begin + if (ins_store) + mem_write_data <= X; + else if (ins_storei) + mem_write_data <= X; + else if (ins_xfer && xfer_p2r) + mem_write_data <= pc_next_ins; + else + mem_write_data <= 0; + end + MEM: + if(!mem_wait) // do not change the address if mem_wait is active + begin + if(ins_xfer && xfer_r2p) addr <= data_in; // on RET take addr for next instruction from the data we just read from mem + else addr <= irq_pending ? IV : nPC; // prepare fetch cycle + end + endcase + end + + // X/ToS-Register + always @(posedge clk) + begin + if(reset) nX <= 0; + else + case(seq_state) + // default: nX <= X; + FETCH, DECODE:; + EXEC: + if(ins_loadc) nX <= operand; + else if(ins_cbranch || ins_store || ins_storereg || (ins_xfer && xfer_x2p)) nX <= Y; + else if(ins_storei) nX <= Y + operand; + else if(ins_loadreg && ins_reg_fp) nX <= FP; + else if(ins_loadreg && ins_reg_bp) nX <= BP; + else if(ins_loadreg && ins_reg_rp) nX <= RP; + else if(ins_loadreg && ins_reg_iv) nX <= IV; + else if(ins_loadreg && ins_reg_ir) nX <= IR; + else if(ins_loadreg && ins_reg_esp) nX <= ESP; + else if(ins_aluop) + begin + case(aluop) + 4'b0000: nX = X + Y; // ADD + 4'b0001: nX = Y - X; // SUB + 4'b0010: nX = ~X; // NOT + 4'b0011: nX = X & Y; // AND + 4'b0100: nX = X | Y; // OR + 4'b0101: nX = X ^ Y; // XOR + 4'b0110: nX = // CMP + cmp_i ^ ((cmp_e && x_equals_y) || (cmp_l && y_lessthan_x)); + 4'b0111: nX = Y; // Y + 4'b1000: nX = aluop_ext ? X >>> 1 : X >> 1; // SHR + 4'b1001: nX = operand[1] ? X << 2 : X << 1; // SHL + 4'b1010: nX = X + operand; // INC + 4'b1011: nX = X - operand; // DEC + 4'b1100: nX = // CMPU + cmp_i ^ ((cmp_e && x_equals_y) || (cmp_l && yx_unsigned_less)); + // 4'b1101: nX = X[7:0] << ((3 - Y[1:0]) << 3); // BPLC + 4'b1101: nX = Y[1:0] == 0 ? { X[7:0], 24'b0 } : + Y[1:0] == 1 ? { 8'b0, X[7:0], 16'b0 } : + Y[1:0] == 2 ? { 16'b0, X[7:0], 8'b0 } : + { 24'b0, X[7:0]}; // BPLC + 4'b1110: nX = { X[23:16], X[15:8], X[7:0], X[31:24] }; // BROT + 4'b1111: nX = { 24'b0, Y[1:0] == 0 ? X[31:24] : Y[1:0] == 1 ? X[23:16] : + Y[1:0] == 2 ? X[15: 8] : X[7:0] }; // BSEL +// 4'b1110: nX = X * Y; // MUL +// 4'b1111: nX = X / Y; // DIV + default: nX = X; + endcase + end + MEM: + if (ins_loadi || ins_load || ins_loadrel) + nX = data_in; + endcase + end + + // estack movement + wire [EVAL_STACK_INDEX_WIDTH-1:0] delta = + ((ins_load || ins_loadc || ins_loadreg || ins_loadrel)) ? 1 + : ((ins_aluop || ins_loadi || ins_storei || ins_xfer)) ? + { {(EVAL_STACK_INDEX_WIDTH-2){aluop_sd[1]}},aluop_sd} // sign extend + : ((ins_store || ins_cbranch || ins_xfer || ins_storereg)) ? -1 + : 0; + + + always @* + begin + if(reset) + nESP <= 0; + else + if(seq_state == EXEC) + begin + nESP = ESP + delta; + end + end + + always @(posedge clk) + begin + // when to write (old) X back to stack (new Y) + // stack write is a reg so it is 1 in the next cycle i.e. MEM state + stack_write <= (seq_state == EXEC && + (ins_load || ins_loadc || ins_loadrel || ins_loadreg + || ((ins_loadi || ins_storei || ins_aluop) && aluop_x2y))); + end + + // FP register + always @(posedge clk) + begin + if(seq_state == EXEC) + begin + if(ins_fpadj) FP <= FP + operand; + else if(ins_storereg && ins_reg_fp) FP <= X; + end + end + + // BP register + always @(posedge clk) if(seq_state == EXEC && ins_storereg && ins_reg_bp) BP <= X; + + // IV register + always @(posedge clk) + begin + if(reset) + IV <= 0; + else if(seq_state == EXEC && ins_storereg && ins_reg_iv) + IV <= X; + end + + // IR register + always @(posedge clk) + begin + if(seq_state == MEM && irq_pending) IR <= nPC; // use nPC as interrupt return addr + end + + // process irq + always @(posedge clk) + begin + if(seq_state == MEM && irq_pending && !(ins_xfer & xfer_r2p)) // in FETCH state, clear irq_pending. + irq_pending <= 0; + else + irq_pending <= irq_pending || irq; // else set irq_pending when irq is high + end + + // advance CPU state + always @ (posedge clk) + begin + if(reset) + { PC, X, ESP, RP } <= { {WIDTH{1'b0}}, {WIDTH{1'b0}}, {WIDTH{1'b0}}, {WIDTH{1'b0}} }; + else if(seq_state == FETCH) + { PC, X, ESP, RP } <= { nPC, nX, nESP, nRP}; + end +endmodule diff --git a/rtl/src/testbench.v b/rtl/src/testbench.v new file mode 100644 index 0000000..8d26bb4 --- /dev/null +++ b/rtl/src/testbench.v @@ -0,0 +1,54 @@ +`timescale 1ns/1ps +`default_nettype none + +module testbench(); + reg clk; + reg rst_n; + wire btn0; + wire sw0; + wire sw1; + wire led0; + wire led1; + wire led2; + wire led3; + wire uart_txd_in; + wire uart_rxd_out; + + wire [15:0] ddr3_dq; + wire [1:0] ddr3_dqs_n; + wire [1:0] ddr3_dqs_p; + wire [13:0] ddr3_addr; + wire [2:0] ddr3_ba; + wire ddr3_ras_n; + wire ddr3_cas_n; + wire ddr3_we_n; + wire ddr3_reset_n; + wire [0:0] ddr3_ck_p; + wire [0:0] ddr3_ck_n; + wire [0:0] ddr3_cke; + wire [0:0] ddr3_cs_n; + wire [1:0] ddr3_dm; + wire [0:0] ddr3_odt; + + integer t; + + top top0(clk, rst_n, btn0, sw0,sw1, led0, led1, led2, led3, uart_txd_in, uart_rxd_out, + ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr, ddr3_ba, ddr3_ras_n, ddr3_cas_n, + ddr3_we_n, ddr3_reset_n, ddr3_ck_p, ddr3_ck_n, ddr3_cke, ddr3_cs_n, ddr3_dm, ddr3_odt); + + initial begin + clk = 1; + t = 0; + rst_n = 0; + end + + always #5.0 clk = ~clk; + + always @(posedge clk) begin + t <= t + 1; + if (t == 2) + rst_n = 1; + if (t == 400) + $finish; + end +endmodule diff --git a/rtl/src/top.v b/rtl/src/top.v new file mode 100644 index 0000000..e79d611 --- /dev/null +++ b/rtl/src/top.v @@ -0,0 +1,288 @@ +`timescale 1ns / 1ps +// either define clock as clk (100MHz on Arty) +// or as clk_1hz for debugging + +`define clock cpuclk +`define clkfreq 83333333 +//`define clock clk +//`define clkfreq 100000000 +//`define clock clk_1hz +`define ENABLE_VGAFB +`define ENABLE_MICROSD + +module top( + input wire clk, + input wire rst, + input wire btn0, + input wire sw0, + input wire sw1, + output wire led0, + output wire led1, + output wire led2, + output wire led3, + input wire uart_txd_in, + output wire uart_rxd_out, + + // DDR3 SDRAM + inout wire [15:0] ddr3_dq, + inout wire [1:0] ddr3_dqs_n, + inout wire [1:0] ddr3_dqs_p, + + output wire [13:0] ddr3_addr, + output wire [2:0] ddr3_ba, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire ddr3_reset_n, + output wire [0:0] ddr3_ck_p, + output wire [0:0] ddr3_ck_n, + output wire [0:0] ddr3_cke, + output wire [0:0] ddr3_cs_n, + output wire [1:0] ddr3_dm, + output wire [0:0] ddr3_odt + +`ifdef ENABLE_VGAFB + , + output wire [3:0] VGA_R, + output wire [3:0] VGA_G, + output wire [3:0] VGA_B, + + output wire VGA_HS_O, + output wire VGA_VS_O +`endif + +`ifdef ENABLE_MICROSD + , + output wire sd_cs_n, + output wire sd_mosi, + input wire sd_miso, + output wire sd_sck, + input wire sd_cd +`endif +); + + reg clk_1hz; + reg [31:0] counter; + + localparam ADDR_WIDTH = 32, WIDTH = 32, + ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4; + + wire [ADDR_WIDTH-1:0] mem_addr; + wire [WIDTH-1:0] mem_read_data; + wire [WIDTH-1:0] mem_write_data; + (* KEEP *) wire mem_wait; + + (* KEEP *) wire mem_read_enable; + (* KEEP *) wire mem_write_enable; + (* KEEP *) wire io_enable; + wire [WIDTH-1:0] io_rd_data; + wire [IOADDR_SEL-1:0] io_slot = mem_addr[IOADDR_WIDTH-1:IOADDR_WIDTH-IOADDR_SEL]; + + wire irq; + + // assign led0 = mem_wait; + + wire [WIDTH-1:0] debug_data1, debug_data2, + debug_data3, debug_data4, + debug_data5, debug_data6; + + assign led0 = debug_data6[0]; + + wire cpuclk, cpuclk_locked; + wire dram_refclk200; + wire pixclk; + cpu_clkgen cpuclk_0(~rst, clk, cpuclk, dram_refclk200, pixclk, cpuclk_locked); + + // DRAM -------------------------------------------------------------------------- + wire [ADDR_WIDTH-1:0] dram_addr; + wire [WIDTH-1:0] dram_read_data, dram_write_data; + wire dram_read_enable, dram_write_enable, dram_wait; + + dram_bridge dram_bridge0 (dram_addr, + dram_read_data, dram_write_data, dram_read_enable, dram_write_enable, dram_wait, + rst, cpuclk, dram_refclk200, + ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr, + ddr3_ba, ddr3_ras_n, ddr3_cas_n, ddr3_we_n, + ddr3_reset_n, ddr3_ck_p, ddr3_ck_n, ddr3_cke, + ddr3_cs_n, ddr3_dm, ddr3_odt); + + mem #(.ADDR_WIDTH(ADDR_WIDTH), .DATA_WIDTH(WIDTH)) mem0( + .clk(`clock), .rst_n(rst), .addr(mem_addr), + .data_out(mem_read_data), .read_enable(mem_read_enable), + .data_in(mem_write_data), .write_enable(mem_write_enable), + .io_enable(io_enable), + .io_rd_data(io_rd_data), + .mem_wait(mem_wait), + .dram_addr(dram_addr), + .dram_read_data(dram_read_data), + .dram_write_data(dram_write_data), + .dram_read_enable(dram_read_enable), + .dram_write_enable(dram_write_enable), + .dram_wait(dram_wait) + ); + +`ifdef ENABLE_VGAFB + localparam FB_ADDR_WIDTH = 14; + wire [FB_ADDR_WIDTH-1:0] fb_rd_addr; + wire [FB_ADDR_WIDTH-1:0] fb_wr_addr; + wire [WIDTH-1:0] fb_rd_data; + wire [WIDTH-1:0] fb_wr_data; + wire fb_rd_en, fb_wr_en; + + wire fb_cs_en = io_enable && (io_slot == 2); + + assign fb_rd_en = fb_cs_en && mem_read_enable; + assign fb_wr_en = fb_cs_en && mem_write_enable; + assign fb_wr_data = mem_write_data; + + vgafb vgafb0(`clock, pixclk, rst, + mem_addr[3:0], fb_rd_data, fb_wr_data, + fb_rd_en, fb_wr_en, + VGA_HS_O, VGA_VS_O, VGA_R, VGA_G, VGA_B); +`endif + + // SPI SD card controller ------------------------------------------------------------------- +`ifdef ENABLE_MICROSD + wire [7:0] spi_tx_data; + (*KEEP*) wire [7:0] spi_rx_data; + wire spi_tx_ready; // ready to transmit new data + wire spi_tx_empty; // tx fifo is empty + wire spi_rx_avail; // a byte has been received + wire spi_rx_ovr; // receiver overrun + wire spi_tx_write; // write strobe + wire spi_rx_read; // read strobe (clears rx_avail) + + wire spi_card_detect; // true is card is present + wire spi_card_changed; // card_detect signal has changed + wire spi_card_busy; // card is busy (MISO/DO is 0) + + wire spi_ctrl_write; // set the following flags + wire spi_rx_filter_en; // set to wait for start bit (1-to-0) when receiving + wire spi_txrx_en; // enable transmitter and receiver + wire spi_sclk_f_en; // enable spi clock without transceiver + wire spi_sclk_div_wr; // set clock divider from tx_data + + wire spi_cs; // cs signal for spi controller + wire [WIDTH-1:0] spi_rd_data; + + assign spi_cs = io_enable && (io_slot == 1); + + // spi read data: [ 0,...,0,cd,cc,cb,tr,te,ra,ro,d,d,d,d,d,d,d,d ] + // cd = card detect, cc = card changed, cb = card busy, + // tr = transmitter ready, te = tx fifo empty, + // ra = received byte available, ro = receive overrun, d = received byte + assign spi_rd_data = + { {WIDTH-15{1'b0}}, spi_card_detect, spi_card_changed, spi_card_busy, + spi_tx_ready, spi_tx_empty, + spi_rx_avail, spi_rx_ovr, spi_rx_data }; + + // spi write data: [ 0,...,0,CW,CF,Cx,Cc,Cd,DR,DW,d,d,d,d,d,d,d,d ] + // CW = control write, CF = enable receive filter, Cx = enable transceiver, + // Cc = force spi clock on, Cd = write clock divider, + // DR = read acknowledge, DW = data write, d = byte to be sent + assign spi_ctrl_write = spi_cs && mem_write_enable && mem_write_data[14]; + assign spi_rx_filter_en = mem_write_data[13]; + assign spi_txrx_en = mem_write_data[12]; + assign spi_sclk_f_en = mem_write_data[11]; + assign spi_sclk_div_wr = spi_cs && mem_write_enable && mem_write_data[10]; + assign spi_rx_read = mem_write_data[9]; + assign spi_tx_write = spi_cs && mem_write_enable && mem_write_data[8]; + assign spi_tx_data = mem_write_data[7:0]; + + sdspi sdspi0(.clk(`clock), .reset(~rst), + .tx_data(spi_tx_data), .rx_data(spi_rx_data), + .tx_ready(spi_tx_ready), .tx_empty(spi_tx_empty), + .rx_avail(spi_rx_avail), .rx_ovr(spi_rx_ovr), + .tx_write(spi_tx_write), .rx_read(spi_rx_read), + .card_detect(spi_card_detect), .card_changed(spi_card_changed), .card_busy(spi_card_busy), + // ctrl_write is used with rx_filter_en, txrx_en and spiclk_f_en + .ctrl_write(spi_ctrl_write), + .rx_filter_en(spi_rx_filter_en), .txrx_en(spi_txrx_en), .spiclk_f_en(spi_sclk_f_en), + // + .spiclk_div_wr(spi_sclk_div_wr), + .sd_cs_n(sd_cs_n), + .sd_mosi(sd_mosi), .sd_miso(sd_miso), .sd_sck(sd_sck), .sd_cd(sd_cd)); +`endif + + // UART ----------------------------------------------------------------------- + + // uart write data: [ 0, 0, 0, 0, 0, T, C, 0, c, c, c, c, c, c, c, c ] + // T = transmit enable, C = receiver clear, c = 8-bit-character + // uart read data: [ 0, 0, 0, 0, 0, 0, A, B, c, c, c, c, c, c, c, c ] + // A = char available, B = tx busy, c = 8-bit-character + wire uart_cs = io_enable && (io_slot == 0); + wire uart_tx_en = uart_cs && mem_write_enable && mem_write_data[10]; + wire uart_rx_clear = uart_cs && mem_write_enable && mem_write_data[9]; + wire uart_rx_avail; + wire uart_rx_busy, uart_tx_busy; + wire uart_err; + wire [7:0] uart_rx_data; + wire [7:0] uart_tx_data; + wire [31:0] uart_baud = 32'd115200; + wire [WIDTH-1:0] uart_rd_data; + + assign uart_tx_data = mem_write_data[7:0]; + assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data }; + + reg timer_tick; + reg[23:0] tick_count; + wire [1:0] irq_in = { timer_tick, uart_rx_avail }; + wire [1:0] irqc_rd_data0; + wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 }; + wire irqc_seten = mem_write_data[7]; + wire irqc_cs = io_enable && (io_slot == 3); + + assign io_rd_data = (io_slot == 0) ? uart_rd_data : + `ifdef ENABLE_MICROSD + (io_slot == 1) ? spi_rd_data : + `endif + `ifdef ENABLE_VGAFB + (io_slot == 2) ? fb_rd_data : + `endif + (io_slot == 3) ? irqc_rd_data: + + -1; + + buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst, + uart_baud, + uart_txd_in, uart_rxd_out, + uart_rx_clear, uart_tx_en, + uart_rx_avail, uart_tx_busy, + uart_tx_data, uart_rx_data); + + // CPU ----------------------------------------------------------------- + stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq), + .addr(mem_addr), + .data_in(mem_read_data), .read_enable(mem_read_enable), + .data_out(mem_write_data), .write_enable(mem_write_enable), + .mem_wait(mem_wait), + .led1(led1), .led2(led2), .led3(led3), + .debug_out1(debug_data1), + .debug_out2(debug_data2), + .debug_out3(debug_data3), + .debug_out4(debug_data4), + .debug_out5(debug_data5), + .debug_out6(debug_data6)); + + // Interrupt Controller + irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable, + irqc_seten, irqc_rd_data0, + irq); + + // count clock ticks + // generate interrupt every 20nth of a second + always @ (posedge `clock) + begin + counter <= counter + 1; + if (counter >= (`clkfreq/20)) + begin + counter <= 0; + timer_tick <= 1; + tick_count <= tick_count + 1'b1; + end + else + begin + timer_tick <= 0; + end + end +endmodule diff --git a/rtl/src/uart.v b/rtl/src/uart.v new file mode 100644 index 0000000..fec26a3 --- /dev/null +++ b/rtl/src/uart.v @@ -0,0 +1,262 @@ +/* +Copyright (c) 2010-2020, James Bowman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of swapforth nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +`default_nettype none +//`define def_clkfreq 100000000 +`define def_clkfreq 83333333 + +module baudgen( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire restart, + output wire ser_clk); + parameter CLKFREQ = `def_clkfreq; + + wire [38:0] aclkfreq = CLKFREQ; + reg [38:0] d; + wire [38:0] dInc = d[38] ? ({4'd0, baud}) : (({4'd0, baud}) - aclkfreq); + wire [38:0] dN = restart ? 0 : (d + dInc); + wire fastclk = ~d[38]; + assign ser_clk = fastclk; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + d <= 0; + end else begin + d <= dN; + end + end +endmodule + +/* + +-----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + | | | | | | | | | | | | + |start| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |stop1|stop2| + | | | | | | | | | | | ? | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + + +*/ + +module uart( + input wire clk, // System clock + input wire resetq, + + // Outputs + output wire uart_busy, // High means UART is transmitting + output reg uart_tx, // UART transmit wire + // Inputs + input wire [31:0] baud, + input wire uart_wr_i, // Raise to transmit byte + input wire [7:0] uart_dat_i // 8-bit data +); + parameter CLKFREQ = `def_clkfreq; + + reg [3:0] bitcount; + reg [8:0] shifter; + + assign uart_busy = |bitcount; + wire sending = |bitcount; + + wire ser_clk; + + wire starting = uart_wr_i & ~uart_busy; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .resetq(resetq), + .baud(baud), + .restart(1'b0), + .ser_clk(ser_clk)); + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + uart_tx <= 1; + bitcount <= 0; + shifter <= 0; + end else begin + if (starting) begin + shifter <= { uart_dat_i[7:0], 1'b0 }; + bitcount <= 1 + 8 + 1; + end + + if (sending & ser_clk) begin + { shifter, uart_tx } <= { 1'b1, shifter }; + bitcount <= bitcount - 4'd1; + end + end + end + +endmodule + +module rxuart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire uart_rx, // UART recv wire + input wire rd, // read strobe + output wire valid, // has data + output wire [7:0] data); // data + parameter CLKFREQ = `def_clkfreq; + + reg [4:0] bitcount; + reg [7:0] shifter; + + // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter + + wire idle = &bitcount; + wire sample; + reg [2:0] hh = 3'b111; + wire [2:0] hhN = {hh[1:0], uart_rx}; + wire startbit = idle & (hhN[2:1] == 2'b10); + wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter; + + wire ser_clk; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .baud({baud[30:0], 1'b0}), + .resetq(resetq), + .restart(startbit), + .ser_clk(ser_clk)); + + assign valid = (bitcount == 18); + reg [4:0] bitcountN; + always @* + if (startbit) + bitcountN = 0; + else if (!idle & !valid & ser_clk) + bitcountN = bitcount + 5'd1; + else if (valid & rd) + bitcountN = 5'b11111; + else + bitcountN = bitcount; + + // 3,5,7,9,11,13,15,17 + assign sample = (bitcount > 2) & bitcount[0] & !valid & ser_clk; + assign data = shifter; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + hh <= 3'b111; + bitcount <= 5'b11111; + shifter <= 0; + end else begin + hh <= hhN; + bitcount <= bitcountN; + shifter <= shifterN; + end + end +endmodule + +module fifo_rxuart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire uart_rx, // UART recv wire + input wire rd, // read strobe + output wire valid, // has data + output wire [7:0] data); // data + parameter CLKFREQ = `def_clkfreq; + + localparam ADDR_WIDTH = 6; + localparam DATA_WIDTH = 8; + + reg fifo_wr_en; + (*KEEP*) wire fifo_rd_en, fifo_full, fifo_empty; + wire [DATA_WIDTH-1:0] fifo_wr_data, fifo_rd_data; + (*KEEP*) wire rx_avail; + + assign valid = !fifo_empty; + assign data = fifo_rd_data; + assign fifo_rd_en = rd; + + fifo #(.ADDR_WIDTH(ADDR_WIDTH)) rx_fifo(clk, ~resetq, + fifo_wr_en, fifo_rd_en, + fifo_wr_data, fifo_rd_data, + fifo_full, + fifo_empty + ); + + rxuart #(.CLKFREQ(CLKFREQ)) _rx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_rx(uart_rx), + .rd(fifo_wr_en), // strobe read signal on fifo write + .valid(rx_avail), + .data(fifo_wr_data)); + + always @(posedge clk) + begin + if (!resetq) + fifo_wr_en <= 0; + else if(!fifo_wr_en && rx_avail) // ILA shows fifo_wr_en stays 0 ?? + fifo_wr_en <= 1; // pulse fifo_wr_en for one clock + else // rx_avail goes zero one clock later + fifo_wr_en <= 0; + end +endmodule + +module buart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire rx, // recv wire + output wire tx, // xmit wire + input wire rd, // read strobe + input wire wr, // write strobe + output wire valid, // has recv data + output wire busy, // is transmitting + input wire [7:0] tx_data, + output wire [7:0] rx_data // data +); + parameter CLKFREQ = `def_clkfreq; + + fifo_rxuart #(.CLKFREQ(CLKFREQ)) _rx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_rx(rx), + .rd(rd), + .valid(valid), + .data(rx_data)); + uart #(.CLKFREQ(CLKFREQ)) _tx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_busy(busy), + .uart_tx(tx), + .uart_wr_i(wr), + .uart_dat_i(tx_data)); +endmodule diff --git a/rtl/src/uart_tb.v b/rtl/src/uart_tb.v new file mode 100644 index 0000000..7f794a2 --- /dev/null +++ b/rtl/src/uart_tb.v @@ -0,0 +1,100 @@ +////////////////////////////////////////////////////////////////////// +// File Downloaded from http://www.nandland.com +////////////////////////////////////////////////////////////////////// + +// This testbench will exercise both the UART Tx and Rx. +// It sends out byte 0xAB over the transmitter +// It then exercises the receive by receiving byte 0x3F +`timescale 1ns/10ps + +module uart_tb (); + + // Testbench uses a 10 MHz clock + // Want to interface to 115200 baud UART + // 10000000 / 115200 = 87 Clocks Per Bit. + parameter c_CLOCK_PERIOD_NS = 100; + parameter c_CLKS_PER_BIT = 87; + parameter c_BIT_PERIOD = 8600; + + reg r_Clock = 0; + reg r_Tx_DV = 0; + wire w_Tx_Done; + reg [7:0] r_Tx_Byte = 0; + reg r_Rx_Serial = 1; + wire [7:0] w_Rx_Byte; + + + // Takes in input byte and serializes it + task UART_WRITE_BYTE; + input [7:0] i_Data; + integer ii; + begin + + // Send Start Bit + r_Rx_Serial <= 1'b0; + #(c_BIT_PERIOD); + #1000; + + + // Send Data Byte + for (ii=0; ii<8; ii=ii+1) + begin + r_Rx_Serial <= i_Data[ii]; + #(c_BIT_PERIOD); + end + + // Send Stop Bit + r_Rx_Serial <= 1'b1; + #(c_BIT_PERIOD); + end + endtask // UART_WRITE_BYTE + + + uart_rx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) UART_RX_INST + (.i_Clock(r_Clock), + .i_Rx_Serial(r_Rx_Serial), + .o_Rx_DV(), + .o_Rx_Byte(w_Rx_Byte) + ); + + uart_tx #(.CLKS_PER_BIT(c_CLKS_PER_BIT)) UART_TX_INST + (.i_Clock(r_Clock), + .i_Tx_DV(r_Tx_DV), + .i_Tx_Byte(r_Tx_Byte), + .o_Tx_Active(), + .o_Tx_Serial(), + .o_Tx_Done(w_Tx_Done) + ); + + + always + #(c_CLOCK_PERIOD_NS/2) r_Clock <= !r_Clock; + + + // Main Testing: + initial + begin + + // Tell UART to send a command (exercise Tx) + @(posedge r_Clock); + @(posedge r_Clock); + r_Tx_DV <= 1'b1; + r_Tx_Byte <= 8'hAB; + @(posedge r_Clock); + r_Tx_DV <= 1'b0; + @(posedge w_Tx_Done); + + // Send a command to the UART (exercise Rx) + @(posedge r_Clock); + UART_WRITE_BYTE(8'h3F); + @(posedge r_Clock); + + // Check that the correct command was received + if (w_Rx_Byte == 8'h3F) + $display("Test Passed - Correct Byte Received"); + else + $display("Test Failed - Incorrect Byte Received"); + + end + +endmodule \ No newline at end of file diff --git a/rtl/src/vgafb.v b/rtl/src/vgafb.v new file mode 100644 index 0000000..4e8d668 --- /dev/null +++ b/rtl/src/vgafb.v @@ -0,0 +1,292 @@ +`timescale 1ns / 1ps +`default_nettype none + +// Project F: Display Timings +// (C)2019 Will Green, Open Source Hardware released under the MIT License +// Learn more at https://projectf.io + +//128K video memory is not enough for 640x480x4 +`define RES_640_400 +//`define RES_1024_768 + +module display_timings #( + H_RES=640, // horizontal resolution (pixels) + V_RES=480, // vertical resolution (lines) + H_FP=16, // horizontal front porch + H_SYNC=96, // horizontal sync + H_BP=48, // horizontal back porch + V_FP=10, // vertical front porch + V_SYNC=2, // vertical sync + V_BP=33, // vertical back porch + H_POL=0, // horizontal sync polarity (0:neg, 1:pos) + V_POL=0 // vertical sync polarity (0:neg, 1:pos) + ) + ( + input wire i_pix_clk, // pixel clock + input wire i_rst, // reset: restarts frame (active high) + output wire o_hs, // horizontal sync + output wire o_vs, // vertical sync + output wire o_de, // display enable: high during active video + output wire o_frame, // high for one tick at the start of each frame + output wire o_scanline, // high for one tick at the start of each scanline + output reg o_vblank, // high during vertical blank phase + output reg signed [15:0] o_sx, // horizontal beam position (including blanking) + output reg signed [15:0] o_sy // vertical beam position (including blanking) + ); + + // Horizontal: sync, active, and pixels + localparam signed H_STA = 0 - H_FP - H_SYNC - H_BP; // horizontal start + localparam signed HS_STA = H_STA + H_FP; // sync start + localparam signed HS_END = HS_STA + H_SYNC; // sync end + localparam signed HA_STA = 0; // active start + localparam signed HA_END = H_RES - 1; // active end + + // Vertical: sync, active, and pixels + localparam signed V_STA = 0 - V_FP - V_SYNC - V_BP; // vertical start + localparam signed VS_STA = V_STA + V_FP; // sync start + localparam signed VS_END = VS_STA + V_SYNC; // sync end + localparam signed VA_STA = 0; // active start + localparam signed VA_END = V_RES - 1; // active end + + // generate sync signals with correct polarity + assign o_hs = H_POL ? (o_sx > HS_STA && o_sx <= HS_END) + : ~(o_sx > HS_STA && o_sx <= HS_END); + assign o_vs = V_POL ? (o_sy > VS_STA && o_sy <= VS_END) + : ~(o_sy > VS_STA && o_sy <= VS_END); + + // display enable: high during active period + assign o_de = (o_sx >= 0 && o_sy >= 0); + + // o_frame: high for one tick at the start of each frame + assign o_frame = (o_sy == V_STA && o_sx == H_STA); + // o_scanline: high for one tick at the start of each visible scanline + assign o_scanline = (o_sy >= VA_STA) && (o_sy <= VA_END) && (o_sx == H_STA); + + always @(posedge i_pix_clk) + begin + if(o_frame) o_vblank <= 1; + else if (o_de) o_vblank <= 0; + end + + always @ (posedge i_pix_clk) + begin + if (i_rst) // reset to start of frame + begin + o_sx <= H_STA; + o_sy <= V_STA; + end + else + begin + if (o_sx == HA_END) // end of line + begin + o_sx <= H_STA; + if (o_sy == VA_END) // end of frame + o_sy <= V_STA; + else + o_sy <= o_sy + 16'sh1; + end + else + o_sx <= o_sx + 16'sh1; + end + end +endmodule + +// Project F: Display Controller VGA Demo +// (C)2020 Will Green, Open source hardware released under the MIT License +// Learn more at https://projectf.io + +// This demo requires the following Verilog modules: +// * display_clocks +// * display_timings +// * test_card_simple or another test card + +module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) ( + input wire cpu_clk, // cpu clock + input wire CLK, // pixel clock + input wire RST_BTN, // reset button + input wire[3:0] reg_sel, // register select/address + output wire [VMEM_DATA_WIDTH-1:0] rd_data, + input wire [VMEM_DATA_WIDTH-1:0] wr_data, + input wire rd_en, + input wire wr_en, + + output wire VGA_HS, // horizontal sync output + output wire VGA_VS, // vertical sync output + output wire [3:0] VGA_R, // 4-bit VGA red output + output wire [3:0] VGA_G, // 4-bit VGA green output + output wire [3:0] VGA_B // 4-bit VGA blue output + ); + + localparam BITS_PER_PIXEL = 4; localparam MAX_SHIFT_COUNT = 7; + localparam REG_RD_ADDR = 0; localparam REG_WR_ADDR = 1; localparam REG_VMEM = 2; + localparam REG_PAL_SLOT = 3; localparam REG_PAL_DATA = 4; + localparam REG_CTL = 5; + + localparam COLOR_WIDTH = 12; + localparam PALETTE_WIDTH = 4; + + // Display Clocks + wire pix_clk = CLK; // pixel clock + wire clk_lock = 1; // clock locked? + + wire vmem_rd_en; + wire vmem_wr_en; + wire [VMEM_DATA_WIDTH-1:0] vmem_rd_data; + reg [VMEM_ADDR_WIDTH-1:0] cpu_rd_addr; + reg [VMEM_ADDR_WIDTH-1:0] cpu_wr_addr; + reg [VMEM_ADDR_WIDTH-1:0] pix_addr; + wire [VMEM_DATA_WIDTH-1:0] pix_data; + wire pix_rd; + wire [VMEM_DATA_WIDTH-1:0] status; + + assign vmem_rd_en = rd_en; + assign vmem_wr_en = (reg_sel == REG_VMEM) && wr_en; + assign rd_data = (reg_sel == REG_VMEM) ? vmem_rd_data : + (reg_sel == REG_RD_ADDR) ? cpu_rd_addr : + (reg_sel == REG_WR_ADDR) ? cpu_wr_addr : + (reg_sel == REG_CTL) ? status : + 32'hFFFFFFFF; + + wire [VMEM_ADDR_WIDTH-1:0] cpu_addr = vmem_wr_en ? cpu_wr_addr : cpu_rd_addr; + + bram_tdp #(.DATA(VMEM_DATA_WIDTH),.ADDR(VMEM_ADDR_WIDTH)) vram0 ( + .a_rd(vmem_rd_en), .a_clk(cpu_clk), + .a_wr(vmem_wr_en), .a_addr(cpu_addr), .a_din(wr_data), + .a_dout(vmem_rd_data), + .b_clk(pix_clk), .b_addr(pix_addr), .b_dout(pix_data), + .b_rd(pix_rd) + ); + + wire palette_wr_en = (reg_sel == REG_PAL_DATA) && wr_en; + reg [PALETTE_WIDTH-1:0] palette_wr_slot; + wire [COLOR_WIDTH-1:0] color_data; + + palette palette0(.wr_clk(cpu_clk), .rd_clk(pix_clk), .wr_en(palette_wr_en), + .wr_slot(palette_wr_slot), .wr_data(wr_data[COLOR_WIDTH-1:0]), + .rd_slot(pixel[3:0]), .rd_data(color_data)); + + // Display Timings + wire signed [15:0] sx; // horizontal screen position (signed) + wire signed [15:0] sy; // vertical screen position (signed) + wire h_sync; // horizontal sync + wire v_sync; // vertical sync + wire de; // display enable + wire frame; // frame start + wire scanline; // scanline start + wire vblank; // vertical blank + reg vblank_buf; // vertical blank in cpu clock domain + + display_timings #( // 640x480 800x600 1280x720 1920x1080 +`ifdef RES_1024_768 + .H_RES(1024), // 640 800 1280 1920 + .V_RES(768), // 480 600 720 1080 + .H_FP(24), // 16 40 110 88 + .H_SYNC(136), // 96 128 40 44 + .H_BP(160), // 48 88 220 148 + .V_FP(3), // 10 1 5 4 + .V_SYNC(6), // 2 4 5 5 + .V_BP(29), // 33 23 20 36 + .H_POL(0), // 0 1 1 1 + .V_POL(0) // 0 1 1 1 + `endif + `ifdef RES_640_400 + .H_RES(640), + .V_RES(400), + .H_FP(16), + .H_SYNC(96), + .H_BP(48), + .V_FP(12), + .V_SYNC(2), + .V_BP(35), + .H_POL(0), + .V_POL(1) + `endif + ) + display_timings_inst ( + .i_pix_clk(CLK), + .i_rst(!RST_BTN), + .o_hs(h_sync), + .o_vs(v_sync), + .o_de(de), + .o_frame(frame), + .o_scanline(scanline), + .o_vblank(vblank), + .o_sx(sx), + .o_sy(sy) + ); + + wire [7:0] red; + wire [7:0] green; + wire [7:0] blue; + + reg [VMEM_DATA_WIDTH-1:0] shifter; + reg [4:0] shift_count; + + // delayed frame signal for pix_rd + reg frame_d; + + assign pix_rd = frame_d || scanline || (shift_count == 2); + + assign status = { 4'b0001, {(VMEM_DATA_WIDTH-5){1'b0}}, vblank_buf}; + + wire [BITS_PER_PIXEL-1:0] pixel = shifter[VMEM_DATA_WIDTH-1:VMEM_DATA_WIDTH-BITS_PER_PIXEL]; + + always @(posedge pix_clk) frame_d <= frame; + + always @(posedge cpu_clk) vblank_buf <= vblank; + + always @(posedge cpu_clk) + begin + if(wr_en) + begin + case(reg_sel) + REG_RD_ADDR: cpu_rd_addr <= wr_data; + REG_WR_ADDR: cpu_wr_addr <= wr_data; + REG_VMEM: cpu_wr_addr <= cpu_wr_addr + 1; // auto-increment write addr on write + REG_PAL_SLOT: palette_wr_slot <= wr_data[3:0]; + endcase + end + else + if(rd_en && reg_sel == REG_VMEM) cpu_rd_addr <= cpu_rd_addr + 1; // auto-increment read addr on read + end + + always @(posedge pix_clk) + begin + if(scanline || shift_count == MAX_SHIFT_COUNT) // before start of a line + begin // or at the end of a word, reset shifter with pixel data + shift_count <= 0; + shifter <= pix_data; + end + else if(de) + begin + shift_count <= shift_count + 1; + shifter <= shifter << BITS_PER_PIXEL; + end + + if(frame) // at start of frame, reset pixel pointer + pix_addr <= 0; + else if(shift_count == 1) // after the first pixel, increment address + pix_addr <= pix_addr + 1; + end + +// Hard-Coded RGBI palette +// // Pixel = { red, green, blue, intensity } +// assign red = pixel[3] ? pixel[0] ? 255 : 127: 0; +// assign green = pixel[2] ? pixel[0] ? 255 : 127: 0; +// assign blue = pixel[1] ? pixel[0] ? 255 : 127: 0; + +// // VGA Output +// // VGA Pmod is 12-bit so we take the upper nibble of each colour +// assign VGA_HS = h_sync; +// assign VGA_VS = v_sync; +// assign VGA_R = de ? red[7:4] : 4'b0; +// assign VGA_G = de ? green[7:4] : 4'b0; +// assign VGA_B = de ? blue[7:4] : 4'b0; + + // 12 bit RGB palette + assign VGA_HS = h_sync; + assign VGA_VS = v_sync; + assign VGA_R = de ? color_data[11:8] : 4'b0; + assign VGA_G = de ? color_data[7:4] : 4'b0; + assign VGA_B = de ? color_data[3:0] : 4'b0; +endmodule diff --git a/tridoraemu/README.md b/tridoraemu/README.md index f7ac81c..0ec332b 100644 --- a/tridoraemu/README.md +++ b/tridoraemu/README.md @@ -23,7 +23,7 @@ On the first run, this may take a while as the go build system fetches some exte Start the *tridoraemu* binary in the same directory as the SD-Card image file (*sdcard.img*) and the ROM file (*rommon.prog*). It needs to be started on the command line as it uses the terminal window for the serial console. On startup, the emulator opens the VGA framebuffer window which is only used for graphics output. -The Tridora software (esp. the editor) requires a decent vt100-compatible (plus colors) terminal emulator. It has been successfully tested with (new) Windows Terminal, WezTerm and xterm. +The Tridora software (esp. the editor) requires a decent vt100-compatible (plus colors) terminal emulator. It has been successfully tested with (new) Windows Terminal, Alacritty, WezTerm and xterm. The color scheme in the editor is meant for a dark terminal background. diff --git a/tridoraemu/framebuffer.go b/tridoraemu/framebuffer.go index a3a92ab..4586287 100644 --- a/tridoraemu/framebuffer.go +++ b/tridoraemu/framebuffer.go @@ -75,16 +75,17 @@ func (f *Framebuffer) write(value word, byteaddr word) (error) { } func (f *Framebuffer) readVmem() word { - result := f.vmem[f.readAddr] + result := f.vmem[f.readAddr & (VmemWords - 1)] f.readAddr += 1 return result } func (f *Framebuffer) writeVmem(value word) { - f.vmem[f.writeAddr] = value + vaddr := f.writeAddr & (VmemWords - 1) + f.vmem[vaddr] = value - y := f.writeAddr / WordsPerLine - x := f.writeAddr % WordsPerLine * PixelPerWord + y := vaddr / WordsPerLine + x := vaddr % WordsPerLine * PixelPerWord for i := 0; i < PixelPerWord; i++ { pixel := (value & PixelMask) >> (VmemWidth - BitsPerPixel)