diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4ae7f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +db +greybox_tmp +incremental_db +output_files +simulation +hc_output +scaler +hps_isw_handoff +vip +*_sim +.qsys_edit +PLLJ_PLLSPE_INFO.txt +*.bak +*.orig +*.rej +*.qdf +*.rpt +*.smsg +*.summary +*.done +*.jdi +*.pin +*.sof +*.qws +*.ppf +*.ddb +build_id.v +c5_pin_model_dump.txt +*.sopcinfo +*.csv +*.f +*.cmp +*.sip +*.spd +*.bsf +*~ +*.xml +*_netlist +*.cdf +**/.DS_Store \ No newline at end of file diff --git a/BubSys.qpf b/BubSys.qpf new file mode 100644 index 0000000..acade07 --- /dev/null +++ b/BubSys.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 17.0.0 Build 595 04/25/2017 SJ Lite Edition +# Date created = 10:52:30 August 17, 2024 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "17.0" +DATE = "10:52:30 August 17, 2024" + +# Revisions + +PROJECT_REVISION = "BubSys" diff --git a/BubSys.qsf b/BubSys.qsf new file mode 100644 index 0000000..08f601a --- /dev/null +++ b/BubSys.qsf @@ -0,0 +1,102 @@ +# -------------------------------------------------------------------------- +# +# MiSTer project +# +# WARNING WARNING WARNING: +# Do not add files to project in Quartus IDE! It will mess this file! +# Add the files manually to files.qip file. +# +# -------------------------------------------------------------------------- + +set_global_assignment -name TOP_LEVEL_ENTITY sys_top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.0 Lite Edition" + +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT" +set_global_assignment -name ALLOW_POWER_UP_DONT_CARE ON +set_global_assignment -name QII_AUTO_PACKED_REGISTERS NORMAL +set_global_assignment -name ROUTER_LCELL_INSERTION_AND_LOGIC_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_RETIMING ON +set_global_assignment -name OPTIMIZATION_TECHNIQUE SPEED +set_global_assignment -name MUX_RESTRUCTURE ON +set_global_assignment -name REMOVE_REDUNDANT_LOGIC_CELLS ON +set_global_assignment -name AUTO_DELAY_CHAINS_FOR_HIGH_FANOUT_INPUT_PINS ON +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON +set_global_assignment -name ADV_NETLIST_OPT_SYNTH_WYSIWYG_REMAP ON +set_global_assignment -name SYNTH_GATED_CLOCK_CONVERSION ON +set_global_assignment -name PRE_MAPPING_RESYNTHESIS ON +set_global_assignment -name ROUTER_CLOCKING_TOPOLOGY_ANALYSIS ON +set_global_assignment -name ECO_OPTIMIZE_TIMING ON +set_global_assignment -name PERIPHERY_TO_CORE_PLACEMENT_AND_ROUTING_OPTIMIZATION ON +set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON +set_global_assignment -name ALM_REGISTER_PACKING_EFFORT MEDIUM +set_global_assignment -name SEED 1 + +set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" + +#enable it only if 8bit indexed mode is used in core +#set_global_assignment -name VERILOG_MACRO "MISTER_FB_PALETTE=1" + +#do not enable DEBUG_NOHDMI in release! +#set_global_assignment -name VERILOG_MACRO "MISTER_DEBUG_NOHDMI=1" + +# disable bilinear filtering when downscaling +#set_global_assignment -name VERILOG_MACRO "MISTER_DOWNSCALE_NN=1" + +# disable adaptive scanline filtering +#set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_ADAPTIVE=1" + +#use only 1MB per frame for scaler to free ~21MB DDR3 RAM +#set_global_assignment -name VERILOG_MACRO "MISTER_SMALL_VBUF=1" + +# Disable YC / Composite output to save some resources +#set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_YC=1" + +# Disable ALSA audio output to save some resources +#set_global_assignment -name VERILOG_MACRO "MISTER_DISABLE_ALSA=1" + +source sys/sys.tcl +source sys/sys_analog.tcl +source files.qip +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE stp1.stp +set_global_assignment -name SDC_FILE BubSys.sdc +set_global_assignment -name SYSTEMVERILOG_FILE BubSys.sv +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name VERILOG_FILE rtl/BubSys_emu.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_top.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_cpu.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_sound.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_bbd8/BubSys_bbd8.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_components/BubSys_PROM.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_components/BubSys_SRAM.v +set_global_assignment -name VERILOG_FILE rtl/ipcores/k5289.v +set_global_assignment -name VERILOG_FILE rtl/ipcores/K005297/K005297.v +set_global_assignment -name QIP_FILE rtl/GX400_video/GX400_video.qip +set_global_assignment -name QIP_FILE rtl/ipcores/fx68k/fx68k.qip +set_global_assignment -name QIP_FILE rtl/ipcores/t80/T80.qip +set_global_assignment -name QIP_FILE rtl/ipcores/jtframe_sdram/jtframe_sdram64.qip +set_global_assignment -name QIP_FILE rtl/ipcores/jt49/jt49.qip +set_global_assignment -name QIP_FILE rtl/ipcores/vlm5030_gl/vlm5030_gl.qip +set_global_assignment -name CDF_FILE jtag.cdf +set_global_assignment -name QIP_FILE sys/sys.qip +set_global_assignment -name SIGNALTAP_FILE stp1.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/BubSys.sdc b/BubSys.sdc new file mode 100644 index 0000000..2344cca --- /dev/null +++ b/BubSys.sdc @@ -0,0 +1,4 @@ +derive_pll_clocks +derive_clock_uncertainty + +# core specific constraints diff --git a/BubSys.srf b/BubSys.srf new file mode 100644 index 0000000..505e355 --- /dev/null +++ b/BubSys.srf @@ -0,0 +1,29 @@ +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Synthesized away node \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|outclk_wire\[2\]\"" { } { } 0 14320 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(129): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(134): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Found combinational loop of 47 nodes" { } { } 0 332125 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(209): object \"vip_newcfg\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at sys_top.v(594): object \"VSET\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(17): vip\|output_inst\|vid_clk could not be matched with a net" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored create_generated_clock at sys_top.sdc(16): Argument is an empty collection" { } { } 0 332049 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored filter at sys_top.sdc(37): VID_CLK could not be matched with a clock" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_audio:pll_audio\|pll_audio_0002:pll_audio_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 276027 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_cyclonev_pll.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_pll_reconfig_core.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "cyclonev_pll" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} diff --git a/BubSys.sv b/BubSys.sv new file mode 100644 index 0000000..32c797d --- /dev/null +++ b/BubSys.sv @@ -0,0 +1,468 @@ +//============================================================================ +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module emu +( + //Master input clock + input CLK_50M, + + //Async reset from top-level module. + //Can be used as initial reset. + input RESET, + + //Must be passed to hps_io module + inout [48:0] HPS_BUS, + + //Base video clock. Usually equals to CLK_SYS. + output CLK_VIDEO, + + //Multiple resolutions are supported using different CE_PIXEL rates. + //Must be based on CLK_VIDEO + output CE_PIXEL, + + //Video aspect ratio for HDMI. Most retro systems have ratio 4:3. + //if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio. + output [12:0] VIDEO_ARX, + output [12:0] VIDEO_ARY, + + output [7:0] VGA_R, + output [7:0] VGA_G, + output [7:0] VGA_B, + output VGA_HS, + output VGA_VS, + output VGA_DE, // = ~(VBlank | HBlank) + output VGA_F1, + output [1:0] VGA_SL, + output VGA_SCALER, // Force VGA scaler + output VGA_DISABLE, // analog out is off + + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + output HDMI_FREEZE, + output HDMI_BLACKOUT, + +`ifdef MISTER_FB + // Use framebuffer in DDRAM + // FB_FORMAT: + // [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + // [3] : 0=16bits 565 1=16bits 1555 + // [4] : 0=RGB 1=BGR (for 16/24/32 modes) + // + // FB_STRIDE either 0 (rounded to 256 bytes) or multiple of pixel size (in bytes) + output FB_EN, + output [4:0] FB_FORMAT, + output [11:0] FB_WIDTH, + output [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + output [13:0] FB_STRIDE, + input FB_VBL, + input FB_LL, + output FB_FORCE_BLANK, + +`ifdef MISTER_FB_PALETTE + // Palette control for 8bit modes. + // Ignored for other video modes. + output FB_PAL_CLK, + output [7:0] FB_PAL_ADDR, + output [23:0] FB_PAL_DOUT, + input [23:0] FB_PAL_DIN, + output FB_PAL_WR, +`endif +`endif + + output LED_USER, // 1 - ON, 0 - OFF. + + // b[1]: 0 - LED status is system status OR'd with b[0] + // 1 - LED status is controled solely by b[0] + // hint: supply 2'b00 to let the system control the LED. + output [1:0] LED_POWER, + output [1:0] LED_DISK, + + // I/O board button press simulation (active high) + // b[1]: user button + // b[0]: osd button + output [1:0] BUTTONS, + + input CLK_AUDIO, // 24.576 MHz + output [15:0] AUDIO_L, + output [15:0] AUDIO_R, + output AUDIO_S, // 1 - signed audio samples, 0 - unsigned + output [1:0] AUDIO_MIX, // 0 - no mix, 1 - 25%, 2 - 50%, 3 - 100% (mono) + + //ADC + inout [3:0] ADC_BUS, + + //SD-SPI + output SD_SCK, + output SD_MOSI, + input SD_MISO, + output SD_CS, + input SD_CD, + + //High latency DDR3 RAM interface + //Use for non-critical time purposes + output DDRAM_CLK, + input DDRAM_BUSY, + output [7:0] DDRAM_BURSTCNT, + output [28:0] DDRAM_ADDR, + input [63:0] DDRAM_DOUT, + input DDRAM_DOUT_READY, + output DDRAM_RD, + output [63:0] DDRAM_DIN, + output [7:0] DDRAM_BE, + output DDRAM_WE, + + //SDRAM interface with lower latency + output SDRAM_CLK, + output SDRAM_CKE, + output [12:0] SDRAM_A, + output [1:0] SDRAM_BA, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nCS, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nWE, + +`ifdef MISTER_DUAL_SDRAM + //Secondary SDRAM + //Set all output SDRAM_* signals to Z ASAP if SDRAM2_EN is 0 + input SDRAM2_EN, + output SDRAM2_CLK, + output [12:0] SDRAM2_A, + output [1:0] SDRAM2_BA, + inout [15:0] SDRAM2_DQ, + output SDRAM2_nCS, + output SDRAM2_nCAS, + output SDRAM2_nRAS, + output SDRAM2_nWE, +`endif + + input UART_CTS, + output UART_RTS, + input UART_RXD, + output UART_TXD, + output UART_DTR, + input UART_DSR, + + // Open-drain User port. + // 0 - D+/RX + // 1 - D-/TX + // 2..6 - USR2..USR6 + // Set USER_OUT to 1 to read from USER_IN. + input [6:0] USER_IN, + output [6:0] USER_OUT, + + input OSD_STATUS +); + +///////// Default values for ports not used in this core ///////// + +assign ADC_BUS = 'Z; +assign USER_OUT = '1; +assign {UART_RTS, UART_TXD, UART_DTR} = 0; +assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; +assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = 'Z; + +assign LED_DISK = 0; +assign LED_POWER = 0; +assign BUTTONS = 0; + + + +/////////////////////////////////////////////////////////// +////// PLL +//// + +wire CLK72M, CLK57M, CLK48M; +wire pll_locked; + +pll pll( + .refclk (CLK_50M ), + .rst (RESET ), + .outclk_0 (CLK72M ), + .outclk_1 (SDRAM_CLK ), + .outclk_2 (CLK57M ), + .outclk_3 (CLK48M ), + .locked (pll_locked ) +); + + + +/////////////////////////////////////////////////////////// +////// HPS_IO +//// + +// Status Bit Map: +// Upper Lower +// 0 1 2 3 4 5 6 +// 01234567890123456789012345678901 23456789012345678901234567890123 +// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV +// X XXXXXXX X XXXXXXXXXXXXXXXXX + +wire [127:0] status; //status bits + +`include "build_id.v" +localparam CONF_STR = { + "BubSysROM;", + "-;", + "P1,Scaler Settings;", + "P1-;", + "P1O23,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", + "h0P1O4,Orientation,Horizontal,Vertical;", + "P1O5,VGA Scaler,off,on;", + "P1O68,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", + "-;", + "P2,Game Settings;", + "P2-;", + "P2OA,Gamma,original,user;", + "P2OS,Swap IRQ,default,IRQ2<=>IRQ1;", + "P2OCF,K5289 volume,0,+1,+2,+3,+4,+5,+6,+7,-8,-7,-6,-5,-4,-3,-2,-1;", + "P2OGJ,VLM volume,0,+1,+2,+3,+4,+5,+6,+7,-8,-7,-6,-5,-4,-3,-2,-1;", + "P2OKN,PSG1 volume,0,+1,+2,+3,+4,+5,+6,+7,-8,-7,-6,-5,-4,-3,-2,-1;", + "P2OOR,PSG2 volume,0,+1,+2,+3,+4,+5,+6,+7,-8,-7,-6,-5,-4,-3,-2,-1;", + "-;", + "DIP;", + "-;", + "R0,Reset and close OSD;", + "J1,Button 1,Button 2,Button 3,Coin,Start,Service;", + "jn,A,B,X,R,Start,Select;", + + "V,v",`BUILD_DATE +}; + + +//ioctl +wire [15:0] ioctl_index; +wire ioctl_download; +wire [26:0] ioctl_addr; +wire [7:0] ioctl_data; +wire ioctl_wr; +wire ioctl_wait; + +wire [1:0] buttons; //hardware button +wire [15:0] joystick_0; +wire [15:0] joystick_1; + +wire forced_scandoubler; //? +wire [21:0] gamma_bus; + +wire direct_video; + +wire video_rotation; //output from the core + +hps_io #(.CONF_STR(CONF_STR)) hps_io +( + .clk_sys (CLK72M ), + .HPS_BUS (HPS_BUS ), + .EXT_BUS ( ), + + .buttons (buttons ), + .status (status ), + .status_in (128'h0 ), + + .status_menumask ({15'd0, video_rotation} ), + .direct_video (direct_video ), + .new_vmode (1'b0 ), + + .forced_scandoubler (forced_scandoubler ), + .gamma_bus (gamma_bus ), + + .ioctl_download (ioctl_download ), + .ioctl_upload ( ), + .ioctl_upload_req (1'b0 ), + .ioctl_wr (ioctl_wr ), + .ioctl_addr (ioctl_addr ), + .ioctl_dout (ioctl_data ), + .ioctl_din ( ), + .ioctl_index (ioctl_index ), + .ioctl_wait (ioctl_wait ), + + .joystick_0 (joystick_0 ), + .joystick_1 (joystick_1 ) +); + + + +/////////////////////////////////////////////////////////// +////// CORE +//// + +wire hsync, vsync; +wire hblank, vblank; +wire [4:0] video_r_5bpp, video_g_5bpp, video_b_5bpp; //need to use color conversion LUT +wire vcen; + +reg [3:0] por_delay; +reg soft_reset; +always @(posedge CLK72M) begin + if(RESET | status[0] | buttons[1]) begin + por_delay <= 4'd0; + soft_reset <= 1'b1; + end + else begin + por_delay <= por_delay == 4'd15 ? 4'd15 : por_delay + 4'd1; + soft_reset <= soft_reset != 4'd15; + end +end + +assign AUDIO_S = 1'b1; +assign AUDIO_MIX = 2'd0; + +BubSys_emu gameboard_top ( + .i_EMU_CLK72M (CLK72M ), + .i_EMU_CLK57M (CLK57M ), + .i_EMU_CLK48M (CLK48M ), + .i_EMU_INITRST (RESET ), + .i_EMU_SOFTRST (RESET | status[0] | buttons[1] ), + + .o_HBLANK (hblank ), + .o_VBLANK (vblank ), + .o_HSYNC (hsync ), + .o_VSYNC (vsync ), + .o_VIDEO_CEN (vcen ), + .o_VIDEO_DEN ( ), + .o_VIDEO_ROT (video_rotation ), + + .o_VIDEO_R (video_r_5bpp ), + .o_VIDEO_G (video_g_5bpp ), + .o_VIDEO_B (video_b_5bpp ), + + .i_VOL (status[27:12] ), + .o_SND_L (AUDIO_L ), + .o_SND_R (AUDIO_R ), + + .i_MAINCPU_SWAPIRQ (status[28] ), + .o_BMC_ACC (LED_USER ), + + .i_JOYSTICK0 (joystick_0 ), + .i_JOYSTICK1 (joystick_1 ), + + .ioctl_index (ioctl_index ), + .ioctl_download (ioctl_download ), + .ioctl_addr (ioctl_addr ), + .ioctl_data (ioctl_data ), + .ioctl_wr (ioctl_wr ), + .ioctl_wait (ioctl_wait ), + + .sdram_dq (SDRAM_DQ ), + .sdram_a (SDRAM_A ), + .sdram_dqml (SDRAM_DQML ), + .sdram_dqmh (SDRAM_DQMH ), + .sdram_ba (SDRAM_BA ), + .sdram_nwe (SDRAM_nWE ), + .sdram_ncas (SDRAM_nCAS ), + .sdram_nras (SDRAM_nRAS ), + .sdram_ncs (SDRAM_nCS ), + .sdram_cke (SDRAM_CKE ), + + .debug ( ) +); + +//Bubble System resistor network gamma LUT, caculated by MAME's resnet.cpp +function [7:0] bubsys_gamma (input [4:0] bubsys_5bpp); begin +case(bubsys_5bpp) + 5'd0 : bubsys_gamma = 8'h00; + 5'd1 : bubsys_gamma = 8'h01; + 5'd2 : bubsys_gamma = 8'h02; + 5'd3 : bubsys_gamma = 8'h04; + 5'd4 : bubsys_gamma = 8'h05; + 5'd5 : bubsys_gamma = 8'h06; + 5'd6 : bubsys_gamma = 8'h08; + 5'd7 : bubsys_gamma = 8'h09; + 5'd8 : bubsys_gamma = 8'h0B; + 5'd9 : bubsys_gamma = 8'h0D; + 5'd10: bubsys_gamma = 8'h0F; + 5'd11: bubsys_gamma = 8'h12; + 5'd12: bubsys_gamma = 8'h14; + 5'd13: bubsys_gamma = 8'h16; + 5'd14: bubsys_gamma = 8'h19; + 5'd15: bubsys_gamma = 8'h1C; + 5'd16: bubsys_gamma = 8'h21; + 5'd17: bubsys_gamma = 8'h24; + 5'd18: bubsys_gamma = 8'h29; + 5'd19: bubsys_gamma = 8'h2E; + 5'd20: bubsys_gamma = 8'h33; + 5'd21: bubsys_gamma = 8'h39; + 5'd22: bubsys_gamma = 8'h40; + 5'd23: bubsys_gamma = 8'h49; + 5'd24: bubsys_gamma = 8'h50; + 5'd25: bubsys_gamma = 8'h5B; + 5'd26: bubsys_gamma = 8'h68; + 5'd27: bubsys_gamma = 8'h78; + 5'd28: bubsys_gamma = 8'h8E; + 5'd29: bubsys_gamma = 8'hA8; + 5'd30: bubsys_gamma = 8'hCC; + 5'd31: bubsys_gamma = 8'hFF; +endcase +end endfunction + +wire [7:0] video_r_8bpp = status[10] ? {video_r_5bpp, 3'd0} : bubsys_gamma(video_r_5bpp); +wire [7:0] video_g_8bpp = status[10] ? {video_g_5bpp, 3'd0} : bubsys_gamma(video_g_5bpp); +wire [7:0] video_b_8bpp = status[10] ? {video_b_5bpp, 3'd0} : bubsys_gamma(video_b_5bpp); + + + +/////////////////////////////////////////////////////////// +////// SCALER +//// + +assign VGA_F1 = 0; +assign VGA_SCALER = status[5]; +assign VGA_DISABLE = 0; +assign HDMI_FREEZE = 0; +assign HDMI_BLACKOUT = 0; + +wire [1:0] ar = status[3:2]; +wire no_rotate = direct_video | ~status[4]; +assign VIDEO_ARX = (!ar) ? no_rotate ? 12'd4 : 12'd3 : (ar - 1'd1); +assign VIDEO_ARY = (!ar) ? no_rotate ? 12'd3 : 12'd4 : 12'd0; + +arcade_video #(256,24) arcade_video ( + .clk_video (CLK72M ), + .ce_pix (vcen ), + + .RGB_in ({video_r_8bpp, video_g_8bpp, video_b_8bpp}), + .HBlank (hblank ), + .VBlank (vblank ), + .HSync (hsync ), + .VSync (vsync ), + + .CLK_VIDEO (CLK_VIDEO ), + .CE_PIXEL (CE_PIXEL ), + .VGA_R (VGA_R ), + .VGA_G (VGA_G ), + .VGA_B (VGA_B ), + .VGA_HS (VGA_HS ), + .VGA_VS (VGA_VS ), + .VGA_DE (VGA_DE ), + .VGA_SL (VGA_SL ), + + .fx (status[8:6] ), //3bit + .forced_scandoubler (forced_scandoubler ), + .gamma_bus (gamma_bus ) //22bit +); + +reg flip = 1'b0; +reg rotate_ccw = 1'b0; +wire video_rotated; +screen_rotate screen_rotate ( .* ); + + +endmodule diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md index 7a43432..4e1b562 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# ikacore_Bubsys \ No newline at end of file +Known issue: Vic Viper temporarily disappears at the intruder stage, when you fire laser and missiles simultaneously with quadrupled firepower. +Current status: Fixable, custom chip known as K005295 will be decapped. \ No newline at end of file diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..1e6a801 --- /dev/null +++ b/clean.bat @@ -0,0 +1,36 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +for /d %%i in (sys\*_sim) do rmdir /s /q "%%i" +for /d %%i in (rtl\*_sim) do rmdir /s /q "%%i" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del *.cdf +del *.rpt +del /s new_rtl_netlist +del /s old_rtl_netlist +pause diff --git a/cr_ie_info.json b/cr_ie_info.json new file mode 100644 index 0000000..b0bc898 --- /dev/null +++ b/cr_ie_info.json @@ -0,0 +1,22 @@ +{ + "system" : { + "platform" : "windows64", + "os_name" : "Windows 10", + "os_version" : "10.0" + }, + "error" : { + "executable" : "quartus", + "comment" : "not_applicable", + "error_message" : "Access Violation at 0X000001F8ED249940", + "source_file" : "unknown", + "line" : "0", + "stack_trace" : "\t0x1f8ed24993f:\n\t 0x69e5126b: QtGui4 + 0x36126b (?text@QStandardItem@@QEBA?AVQString@@XZ + 0x2b)\n\t0x7ffa051331bb: resr_flowg + 0x31bb (?add_pr_revisions@FLOWG_REVISIONS_LIST@@IEAAXPEAVQStandardItem@@W4ACF_VARIABLE_TYPE_ENUM@@W4ACF_ENUM_VALUE_ENUM@@@Z + 0x9b)\n\t0x7ffa0513709d: resr_flowg + 0x709d (?load_revisions@FLOWG_REVISIONS_LIST@@QEAAXXZ + 0x48d)\n\t 0x6991f9f7: QtCore4 + 0x11f9f7 (?event@QObject@@UEAA_NPEAVQEvent@@@Z + 0xe7)\n\t 0x69b51402: QtGui4 + 0x61402 (?event@QWidget@@MEAA_NPEAVQEvent@@@Z + 0xd42)\n\t 0x69e72676: QtGui4 + 0x382676 (?event@QFrame@@MEAA_NPEAVQEvent@@@Z + 0x36)\n\t 0x69ee3587: QtGui4 + 0x3f3587 (?event@QAbstractScrollArea@@MEAA_NPEAVQEvent@@@Z + 0x257)\n\t 0x69b12e95: QtGui4 + 0x22e95 (?notify_helper@QApplicationPrivate@@QEAA_NPEAVQObject@@PEAVQEvent@@@Z + 0xf5)\n\t 0x69b12b2f: QtGui4 + 0x22b2f (?notify@QApplication@@UEAA_NPEAVQObject@@PEAVQEvent@@@Z + 0x17bf)\n\t 0x6990d92b: QtCore4 + 0x10d92b (?notifyInternal@QCoreApplication@@AEAA_NPEAVQObject@@PEAVQEvent@@@Z + 0x7b)\n\t 0x6990f502: QtCore4 + 0x10f502 (?sendPostedEvents@QCoreApplicationPrivate@@SAXPEAVQObject@@HPEAVQThreadData@@@Z + 0x2b2)\n\t 0x69932fb8: QtCore4 + 0x132fb8 (?processEvents@QEventDispatcherWin32@@UEAA_NV?$QFlags@W4ProcessEventsFlag@QEventLoop@@@@@Z + 0xb98)\n\t0x7ffaab9782e0: USER32 + 0x182e0 (DispatchMessageW + 0x740)\n\t0x7ffaab977da0: USER32 + 0x17da0 (DispatchMessageW + 0x200)\n\t 0x69932802: QtCore4 + 0x132802 (?processEvents@QEventDispatcherWin32@@UEAA_NV?$QFlags@W4ProcessEventsFlag@QEventLoop@@@@@Z + 0x3e2)\n\t 0x69b70eb4: QtGui4 + 0x80eb4 (?openPopup@QApplicationPrivate@@QEAAXPEAVQWidget@@@Z + 0x204)\n\t 0x6990a88b: QtCore4 + 0x10a88b (?exec@QEventLoop@@QEAAHV?$QFlags@W4ProcessEventsFlag@QEventLoop@@@@@Z + 0x22b)\n\t 0x6990ce6f: QtCore4 + 0x10ce6f (?exec@QCoreApplication@@SAHXZ + 0xdf)\n\t0x7ff618f5197b: quartus + 0x197b (?qgq_main@@YAHHPEAPEBD@Z + 0x7b)\n\t0x7ffa84fb2d68: CCL_MSG + 0x12d68 (?msg_main_thread@@YAPEAXPEAX@Z + 0x18)\n\t0x7ffa84fb454e: CCL_MSG + 0x1454e (?msg_thread_wrapper@@YAPEAXP6APEAXPEAX@Z0@Z + 0x6e)\n\t0x7ffa850d5b00: ccl_mem + 0x15b00 (?mem_thread_wrapper@@YAPEAXP6APEAXPEAX@Z0@Z + 0x70)\n\t0x7ffa84fb2631: CCL_MSG + 0x12631 (?msg_exe_main@@YAHHPEAPEBDP6AHH0@Z@Z + 0xa1)\n\t0x7ff618f524e7: quartus + 0x24e7 (WinMain + 0x127)\n\t0x7ff618f51e58: quartus + 0x1e58 (__tmainCRTStartup + 0x148)\n\t0x7ffaab82257c: KERNEL32 + 0x1257c (BaseThreadInitThunk + 0x1c)\n\t0x7ffaac78af27: ntdll + 0x5af27 (RtlUserThreadStart + 0x27)\n", + "subsystem" : "unknown" + }, + "quartus" : { + "quartus_bits" : "64", + "version" : "17.0.0", + "build" : "595", + "edition" : "Lite Edition" + } +} \ No newline at end of file diff --git a/files.qip b/files.qip new file mode 100644 index 0000000..a0cb11e --- /dev/null +++ b/files.qip @@ -0,0 +1,21 @@ +set_global_assignment -name SDC_FILE BubSys.sdc +set_global_assignment -name SYSTEMVERILOG_FILE BubSys.sv + +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name VERILOG_FILE rtl/BubSys_emu.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_top.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_cpu.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_sound.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_bbd8/BubSys_bbd8.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_components/BubSys_PROM.v +set_global_assignment -name VERILOG_FILE rtl/BubSys_components/BubSys_SRAM.v +set_global_assignment -name VERILOG_FILE rtl/ipcores/k5289.v +set_global_assignment -name VERILOG_FILE rtl/ipcores/K005297/K005297.v +set_global_assignment -name QIP_FILE rtl/GX400_video/GX400_video.qip +set_global_assignment -name QIP_FILE rtl/ipcores/fx68k/fx68k.qip +set_global_assignment -name QIP_FILE rtl/ipcores/t80/T80.qip +set_global_assignment -name QIP_FILE rtl/ipcores/jtframe_sdram/jtframe_sdram64.qip +set_global_assignment -name QIP_FILE rtl/ipcores/jt49/jt49.qip +set_global_assignment -name QIP_FILE rtl/ipcores/vlm5030_gl/vlm5030_gl.qip + + diff --git a/resources/BubbleSystem_schematics.pdf b/resources/BubbleSystem_schematics.pdf new file mode 100644 index 0000000..1c9caaf Binary files /dev/null and b/resources/BubbleSystem_schematics.pdf differ diff --git a/rtl/BubSys_bbd8/BubSys_bbd8.v b/rtl/BubSys_bbd8/BubSys_bbd8.v new file mode 100644 index 0000000..6f0834c --- /dev/null +++ b/rtl/BubSys_bbd8/BubSys_bbd8.v @@ -0,0 +1,1406 @@ +module BubSys_bbd8 ( + //48MHz input clock + input wire i_EMUCLK, + + //module enable + input wire i_RST, + + //4bit width mode + input wire i_4BEN, + + //BOUT timing select + input wire i_BDO_TSEL, + + //4MHz output clock + output reg o_BMCCLK_PCEN, + + //Bubble control signal inputs + input wire i_BOOTEN_n, + input wire i_BSS_n, + input wire i_BSEN_n, + input wire i_REPEN_n, + input wire i_SWAPEN_n, + + output wire [3:0] o_BDO_n, + output wire o_ACC, + + //Data request + output wire o_BUBROM_BOOT_CS, o_BUBROM_PAGE_CS, + output wire [17:0] o_BUBROM_ADDR, + input wire [15:0] i_BUBROM_DATA, + output wire o_BUBROM_RD, + input wire i_BUBROM_DATA_RDY +); + +/* + + ////////////////////////////////////////////////////// + //// INTERNAL ORGANIZATION OF FBM54DB + // + + + -1 + ----O---- DETECTOR 1 + \ |0 / <------------ bubble output signal latched here(magnetic field -Y) by MB3908 sense amplifier; stretcher patterns exist here + --O-- DETECTOR 0 + | ← ← ← ← ← propagation direction + |1 2 95 96 97 98 99 100 101 680 681 + O-----O ... O-----O-----O-----O-----O-----O-----O-- --O-----O + ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ + __^__ __^__ __^__ __^__ __^__ __^__ __^__ __^__ <-- "block" replicators; replicators for two bootloops + ↓ | | | | | | | | | | | | | | | | can be operated independantly from page replicators + | | | | | | | | | | | | | | | | + ↓ | L | | L | | L | | L | | L | | L | | L | | L | + | O | | O | | O | | O | | O | | O | | O | | O | + ← ↓ | O | | O | | O | | O | | O | | O | ..... | O | | O | <-- each loop can hold 2053 magnetic bubbles + ↙ | P | | P | | P | | P | | P | | P | | P | | P | + ↓ ↑ EXTERNAL ↓ |B 0| |B 1| | 0| | 1| | 2| | 3| |582| |583| + | MAGNETIC | | | | | | | | | | | | | | | | + FIELD ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~O N~ + | | | | | | | | | | | | | | |L E| + | | | | | | | | | | | | | | |D W| + ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ <-- swap gate swaps an old bubble with a new bubble at the same time: -Y + / \ / \ / \ / \ / \ / \ / \ / \ 2 1 + O-- .... ---O---/-O-\-/-O-\-/-O-\-/-O-\-/-O-\-/-O-\- /-O-\-/-O-\---O-----O ... O-----O + | 626 625 624 623 622 621 42 41 40 39 | + ↓ discarded ↑ __________^_0________ + -Y position | G E N E R A T O R | <-- generates a bubble at +Y + + SEE JAPANESE PATENT: + JPA 1992074376-000000 / 特許出願公開 平4-74376 ;contains replicator/swap gate diagram + JPA 1989220199-000000 / 特許出願公開 平1-220199 ;explains bubble write procedure + + !!!! IMPORTANT NOTE !!!! + Note that FBM54DB is organized with EVEN HALF and ODD HALF. The EVEN HALF + has 1 even bootloop + 292 even minor loops and the ODD HALF has the same + but they are odd numbered loops. Due to the physical width of minor loop, + there is one position between a position and a position on read/write + track. That is, there is one bubble for every two positions, like a diagram + below: + + P P P P P P P P + ODD O---*---O---*---O---*---O---* + bubble bubble bubble bubble + + P P P P P P P P + EVEN *---O---*---O---*---O---*---O + bubble bubble bubble bubble + + Bubble moves one position every 10us, so in this case, 1 bit of data is + transferred every 20us. Developers wanted to speed things up. So, they + made another half that can be "interleaved". FBM54DB has two detectors + and two MB3908 sense amplifiers. Each SA launches data 50kbps anyway + but its open collector(negative logic) outputs are interleaved outside, + therefore the user can get 100kbps data. The BMC inverts negative logic + data internally. + + I merged the EVEN HALF and the ODD HALF in the diagaram above, for my + convenience. Therefore the diagram that represents the real organization + will be like this: + + ODD HALF : + + -1 + ----O---- DETECTOR 1 + \ |0 / + --O-- DETECTOR 0 + | ← ← ← ← ← propagation direction + |1 2 95 96 97 98 99 100 101 680 681 + O-----O ... O-----O-----O-----O-----O-----O-----O-- --O-----O + ↑ ↑ ↑ ↑ + __^__ __^__ __^__ __^__ + | | | | | | | | + | | | | | | | | + | L | | L | | L | | L | + | O | | O | | O | | O | + ← | O | | O | | O | ..... | O | + ↙ | P | | P | | P | | P | + ↓ ↑ EXTERNAL |B 1| | 1| | 3| |583| + | MAGNETIC | | | | | | | | + FIELD ~ ~ ~ ~ ~ ~ ~O N~ + | | | | | | |L E| + | | | | | | |D W| + ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ + / \ / \ / \ / \ 2 1 + O-- .... ---O-----O---/-O-\---O---/-O-\---O---/-O-\- --O---/-O-\---O-----O ... O-----O + | 626 625 624 623 622 621 42 41 40 39 | + ↓ discarded ↑ __________^_0________ + -Y position | G E N E R A T O R | + + EVEN HALF : + + -1 + ----O---- DETECTOR 1 + \ |0 / + --O-- DETECTOR 0 + | ← ← ← ← ← propagation direction + |1 2 95 96 97 98 99 100 101 680 681 + O-----O ... O-----O-----O-----O-----O-----O-----O-- --O-----O + ↑ ↑ ↑ ↑ + __^__ __^__ __^__ __^__ + | | | | | | | | + | | | | | | | | + | L | | L | | L | | L | + | O | | O | | O | | O | + ← | O | | O | | O | ..... | O | + ↙ | P | | P | | P | | P | + ↓ ↑ EXTERNAL |B 0| | 0| | 2| |582| + | MAGNETIC | | | | | | | | + FIELD ~ ~ ~ ~ ~ ~ ~ ~ + | | | | | | | | + | | | | | | | | + ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ ¯↓^↑¯ + / \ / \ / \ / \ 2 1 + O-- .... ---O---/-O-\---O---/-O-\---O---/-O-\---O--- --/-O-\---O-----O-----O ... O-----O + | 626 625 624 623 622 621 42 41 40 39 | + ↓ discarded ↑ __________^_0________ + -Y position | G E N E R A T O R | + + + ////////////////////////////////////////////////////// + //// EXACT MINOR LOOP POSITION OF FBM54DB + + A good minor loop in FBM54DB can hold 2053 magnetic bubbles. This means + that the total count of positions is 2053. Early bubble memories had put + a bubble every two positions to prevent bubble-bubble interaction, but + FBM54DB doesn't require such action. In the diagram, it appears to be + the swap gate and the replicator exist in symmetrical positions, + but actually, it's not. + + 1 0 2052 + ____ __O___O___O__ + | | | | + | | | O 2051 + | | | | + | | | O 2050 + | | | | + | | | O 2049 + | | | | + | ¯¯¯¯ O 2048 + same loops ~~ partially ~~~ + continue ~~ magnified ~~~ + | ____ O 1541 + | | | | + 912+0 O | O O 1540 + | | | LOOP | + +1 O | O #584 O 1539 + | | | | + +2 O | O O 1538 + | | | +624 | + ¯¯¯¯ ¯¯O¯↓¯O¯↑¯O¯¯ + +623 / \ +625 + 42 / 41 \ 40 39 + --O----↓----O----↑----O---------O + bubble bubble + goes OUT goes IN + on this on this + position position + at -Y at -Y + + To increase loop capacity and density of each half, Fujitsu lengthened + minor loops about twice. I assume they are shaped like "H". + + Replicator is on absolute position 0 + Swap gate is on absolute position 1536 +*/ + +/* + An MB3908 has two DFF with /Q OC output, and triggered on every positive + edge of BOUTCLK from MB14506 timing generator. For example, the waveform + below is showing a transfer of "6C 36 B1" + + 0us 0 0 0 0 0 0 0 0 0 0 0 + BOUTCLK |¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____ + D1 ¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + D0 ________|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______ + bootloop ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + +7~8us + user page ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + +0~1us + + Konami's BMC has different sampling timings for bootloop and user page, + respectively. I don't know how the unknown MCU inside the BMC + samples(or latches) data. I assume that MCU gets data from memory-mapped + register once per bit, but there are several possibilities that the MCU + gets several times, triggers flip-flops to sample data, or enables a kind + of transparent latch for quite a long time. + + My friend Maki sent me a Bubble System PCB which has a deteriorated LS244. + Total three LS244 are used as bubble memory control signal buffers, and + its propagation delay is often prolonged due to aging or the output + goes weak. Finally, it often became insufficient to drive a fairly long + transmission line. + + Anyway, to prevent this missampling, bubble data should be launched 0-1us + earlier when reading the bootloop, and 5-6us earlier when reading user + pages. +*/ + + + +/////////////////////////////////////////////////////////// +////// CLOCK DIVIDER +//// + +reg [3:0] clk_div12; +always @(posedge i_EMUCLK) begin + if(i_RST) clk_div12 <= 4'd0; + else clk_div12 <= clk_div12 == 4'd11 ? 4'd0 : clk_div12 + 4'd1; + + o_BMCCLK_PCEN <= clk_div12 == 4'd4; +end + + + +/////////////////////////////////////////////////////////// +////// MODULES +//// + +//TimingGenerator +wire [2:0] ACCTYPE; +wire [12:0] BOUTCYCLENUM; +wire [11:0] RELPAGE; +wire nBINCLKEN; +wire nBOUTCLKEN; + +//SPILoader -> BubbleInterface +wire nOUTBUFWRCLKEN; +wire [14:0] OUTBUFWRADDR; +wire OUTBUFWRDATA; + +assign o_ACC = ~i_BSEN_n; + + +BubSys_bbd8_TimingGenerator TimingGenerator_0 ( + .MCLK (i_EMUCLK ), + + .nEN (i_RST ), + .TIMINGSEL (1'b0 ), + + .CLKOUT ( ), + .nBSS (i_BSS_n ), + .nBSEN (i_BSEN_n ), + .nREPEN (i_REPEN_n ), + .nBOOTEN (i_BOOTEN_n ), + .nSWAPEN (i_SWAPEN_n ), + + .ACCTYPE (ACCTYPE ), + .BOUTCYCLENUM (BOUTCYCLENUM ), + .nBINCLKEN (nBINCLKEN ), + .nBOUTCLKEN (nBOUTCLKEN ), + + .RELPAGE (RELPAGE ) +); + + +BubSys_bbd8_BubbleBuffer BubbleBuffer_0 ( + .MCLK (i_EMUCLK ), + + .BITWIDTH4 (1'b0 ), + + .ACCTYPE (ACCTYPE ), + .BOUTCYCLENUM (BOUTCYCLENUM ), + .nBINCLKEN (nBINCLKEN ), + .nBOUTCLKEN (nBOUTCLKEN ), + + .nOUTBUFWRCLKEN (nOUTBUFWRCLKEN ), + .OUTBUFWRADDR (OUTBUFWRADDR ), + .OUTBUFWRDATA (OUTBUFWRDATA ), + + .DOUT0 (o_BDO_n[0] ), + .DOUT1 (o_BDO_n[1] ), + .DOUT2 (o_BDO_n[2] ), + .DOUT3 (o_BDO_n[3] ) +); + + +/* + Block RAM Buffer Address [DOUT1/DOUT0] + 1bit 0 + 13bit address + 1bit CS + 0000-1327 : bootloader data 1328*2 bits + 1328-1911 : 584*2 bad loop table + 1912-1926 : 14*2 or 15*2 bits of CRC(??) data, at least 28 bits + 1927-4038 : 11 = filler + 4039-4103 : X0 = 65 of ZEROs on EVEN channel (or possibly 64?) + 4104 : X1 = 1 of ONE on EVEN channel + 4105 : XX = DON'T CARE + 4106-7167 : 00 = empty space + 7168-7170 : 00 = 3 position shifted page data + 7171-7751 : 581bits remaining page data + + 8191 : 00 = empty bubble propagation line +*/ + +reg [3:0] state = 4'd0; +reg [7:0] copy_data_length = 8'h00; //bootloader = 0xA6, page = 0x40 +reg [5:0] timeout; +reg [4:0] data_select = 5'd0; //MSB is the buffer write strobe +reg [15:0] data_received; +reg [13:0] buffer_address = 14'd16383; +wire buffer_wr = data_select[4]; +wire buffer_data = data_received[~data_select[3:0]]; +reg [17:0] rom_addr = 18'd0; +reg rom_rd = 1'b0; +reg rom_boot_cs = 1'b0; +reg rom_page_cs = 1'b0; + +assign o_BUBROM_BOOT_CS = rom_boot_cs; +assign o_BUBROM_PAGE_CS = rom_page_cs; +assign o_BUBROM_ADDR = rom_addr; +assign o_BUBROM_RD = rom_rd; + +assign nOUTBUFWRCLKEN = ~buffer_wr; +assign OUTBUFWRADDR = buffer_address; +assign OUTBUFWRDATA = buffer_data; + +always @(posedge i_EMUCLK) begin + if(i_RST) state <= 4'd0; + else begin + if(state == 4'd0) begin + buffer_address = 14'd16383; + rom_boot_cs <= 1'b0; + rom_page_cs <= 1'b0; + if(ACCTYPE == 3'b110 || ACCTYPE == 3'b111) state <= 4'd1; + end + else if(state == 4'd1) begin + if(ACCTYPE == 3'b110) begin + copy_data_length <= 8'hA6; + buffer_address <= 14'd0; + rom_boot_cs <= 1'b1; + rom_addr <= 18'd0; + end + else if(ACCTYPE == 3'b111) begin + copy_data_length <= 8'h40; + buffer_address <= 14'd14342; + rom_page_cs <= 1'b1; + rom_addr <= {6'h0, RELPAGE} << 6; + end + + rom_rd <= 1'b0; + state <= 4'd2; + end + else if(state == 4'd2) begin rom_rd <= 1'b1; state <= 4'd3; end + else if(state == 4'd3) begin timeout <= 5'd0; state <= 4'd4; end + else if(state == 4'd4) begin + timeout <= timeout == 5'd31 ? 5'd31 : timeout + 5'd1; + if(i_BUBROM_DATA_RDY || timeout == 5'd31) state <= 4'd5; + end + else if(state == 4'd5) begin + rom_rd <= 1'b0; + data_received <= i_BUBROM_DATA; + data_select <= 5'd16; + state <= 4'd6; + end + else if(state == 4'd6) begin + data_select <= data_select == 5'd0 ? 5'd0 : data_select + 5'd1; + buffer_address <= buffer_address + 14'd1; + if(data_select == 5'd31) begin + copy_data_length <= copy_data_length - 8'h1; + rom_addr <= rom_addr + 18'd1; + state <= 4'd7; + end + end + else if(state == 4'd7) begin + if(copy_data_length != 8'h00) state <= 4'd2; + else begin + if(ACCTYPE == 3'b000) state <= 4'd0; + end + end + end +end + + + + + +endmodule + +module BubSys_bbd8_TimingGenerator +/* + BubbleDrive8_emucore > modules > TimingGenerator.v + + Copyright (C) 2020-2021, Raki + + TimingGenerator provides all timing signals related to + the bubble memory side. This module uses 48MHz as master clock, + x4 of the original function timing generator(FTG) MB14506. + Thereby BubbleDrive8 can manage all bubble logic without using + a PLL block. + + + * more details of signals below can be found on bubsys85.net * + + CLKOUT: + 4MHz clock for the bubble memory controller: maybe an MCU uses this + nBSS: Bubble Shift Start + a pulse to notify a start of access cycle + nBSEN: Bubble Shift ENable + magnetic field rotates when this signal goes low + nREPEN: REPlicator ENable + FTG use this signal to replicate a bubble + nBOOTEN: BOOTloop ENable + controller can access two bootloops by driving this signal low + nSWAPEN: SWAP gate ENable + FTG use this signal to write a page to a bubble memory + + nEN: module enable signal + ACCTYPE: bubble access mode type + BOUTCYCLENUM: bubble output cycle number: counts serial bits + nBINCLKEN: emulator samples bubble data for page write when this goes low + nBOUTCLKEN: emulator launches bubble data when this goes low + nNOBUBBLE: emulator launches 1(no bubble) + + ABSPAGE: bubble memory's absolute position number + + + * For my convenience, many comments are written in Korean * +*/ + +( + //48MHz input clock + input wire MCLK, + + //4MHz output clock + output reg CLKOUT = 1'b1, + + //Input control + input wire nEN, + input wire TIMINGSEL, + + //Bubble control signal inputs + input wire nBSS, + input wire nBSEN, + input wire nREPEN, + input wire nBOOTEN, + input wire nSWAPEN, + + //Emulator signal outputs + output wire [2:0] ACCTYPE, + output reg [12:0] BOUTCYCLENUM, + output reg nBINCLKEN = 1'b1, + output reg nBOUTCLKEN = 1'b0, + + output wire [11:0] RELPAGE +); + +localparam INITIAL_ABS_PAGE = 12'd1968; //0-2052 +reg __REF_nBOUTCLKEN_ORIG = 1'b0; +reg __REF_CLK12M = 1'b0; + + +/* + GLOBAL NET/REGS +*/ +reg nBSS_intl; +reg nBSEN_intl; +reg nREPEN_intl; +reg nBOOTEN_intl; +reg nSWAPEN_intl; + + + +/* + CLOCK DIVIDER +*/ + +/* + 1 1 1 1 1 1 1 1 1 1 2 2 2 2 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 0 1 2 3 4 ... + 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 0 + 48MHz ¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_| + 12MHz _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + 4MHz ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| + + BMC signals ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________________________________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + |---------> sampled + + + synchronization |---| |---| + determine current access state |---| |---| + MCLK counting |---------------|-----------------> + + This block generates 12MHz ref clk, and 4MHz BMC clock. BMC always launches + its signal at a "falling edge" of 4MHz. I don't know if it's synchronized + to 4MHz or if they added a simple buffer delay. Anyway, all control signals + arrives at a negative edge of the departing 4MHz. + MB14506 starts to rotate magnetic field 23*12Mclk(about 83.33ns*23) later + just after nBSEN is sampled. +*/ + +reg [4:0] counter12 = 4'd0; + + +always @(posedge MCLK) +begin + if(counter12 == 4'd1) + begin + __REF_CLK12M <= 1'b1; + counter12 <= counter12 + 4'd1; + end + else if(counter12 == 4'd3) + begin + __REF_CLK12M <= 1'b0; + counter12 <= counter12 + 4'd1; + end + else if(counter12 == 4'd5) + begin + __REF_CLK12M <= 1'b1; + CLKOUT <= 1'b1; + counter12 <= counter12 + 4'd1; + end + else if(counter12 == 4'd7) + begin + __REF_CLK12M <= 1'b0; + counter12 <= counter12 + 4'd1; + end + else if(counter12 == 4'd9) + begin + __REF_CLK12M <= 1'b1; + counter12 <= counter12 + 4'd1; + end + else if(counter12 == 4'd11) + begin + __REF_CLK12M <= 1'b0; + CLKOUT <= 1'b0; + counter12 <= 4'd0; + end + else + begin + counter12 <= counter12 + 4'd1; + end +end + + + +/* + BUFFER CHAIN +*/ +reg [4:0] step1 = 5'b11110; +reg [4:0] step2 = 5'b11110; +reg [4:0] step3 = 5'b11110; + +always @(negedge MCLK) +begin + step1[4] <= nEN | nSWAPEN; + step1[3] <= nEN | nBSS; + step1[2] <= nEN | nBSEN; + step1[1] <= nEN | (nREPEN | ~nBOOTEN); + step1[0] <= ~nEN & nBOOTEN; + + step2 <= step1; + step3 <= step2; +end + + + +/* + SYNCHRONIZER +*/ +always @(posedge MCLK) +begin + if(counter12 == 4'd3 || counter12 == 4'd7 || counter12 == 4'd11) + begin + nSWAPEN_intl <= step3[4]; + nBSS_intl <= step3[3]; + nBSEN_intl <= step3[2]; + nREPEN_intl <= step3[1]; + nBOOTEN_intl <= step3[0]; + end +end + + +/* + ACCESS TYPE STATE MACHINE +*/ + +/* + nREPEN ¯¯¯¯¯¯¯¯¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + nBSS_intl ¯¯¯¯¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + nBOOTEN_intl ______________________________________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + nBSEN_intl ¯¯¯¯¯¯¯¯|____________________________________|¯¯¯¯¯¯¯¯¯|__________________________|¯¯¯¯¯¯|__________________________|¯¯¯ + nREPEN_intl ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + nSWAPEN_intl ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_|¯¯¯¯¯¯¯¯ + |----(bootloader load out enable)----| |(page load out enable)| |(swap)| + ----->TIME A |B |C |A |B |E |D(HOLD) |A |B |E |F |A +*/ + +//[magnetic field activation/data transfer/mode] +localparam RST = 3'b000; //A +localparam STBY = 3'b001; //B +localparam BOOT = 3'b110; //C +localparam USER = 3'b111; //D +localparam IDLE = 3'b100; //E +localparam SWAP = 3'b101; //F + +reg [2:0] access_type = RST; +assign ACCTYPE = access_type; + +always @(posedge MCLK) if(nEN) access_type = RST; else +begin + case ({nBSS_intl, nBOOTEN_intl, nBSEN_intl, nREPEN_intl, nSWAPEN_intl}) + 5'b10111: //최초 시작 후의 리셋 상태, 또는 부트로더 액세스가 끝난 후 아주 잠깐 발생 + begin + if(access_type == STBY) + begin + access_type <= STBY; + end + else + begin + access_type <= RST; + end + end + + 5'b00111: //부트로더 스탠바이 + begin + if(access_type == RST) + begin + access_type <= STBY; + end + else + begin + access_type <= access_type; + end + end + + 5'b10011: //부트로더 액세스 중 + begin + if(access_type == STBY || access_type == BOOT || access_type == RST) + begin + access_type <= BOOT; + end + else + begin + access_type <= access_type; + end + end + + 5'b11111: //유저 영역 리셋 상태 + begin + if(access_type == STBY) + begin + access_type <= STBY; + end + else + begin + access_type <= RST; + end + end + + 5'b01111: //페이지 스탠바이 + begin + if(access_type == RST) + begin + access_type <= STBY; + end + else + begin + access_type <= access_type; + end + end + + 5'b11011: //페이지 seek중, 또는 페이지 로딩 중(로딩 중에는 리플리케이션을 유지) + begin + if(access_type == STBY || access_type == RST) + begin + access_type <= IDLE; + end + else + begin + access_type <= access_type; + end + end + + 5'b11001: //리플리케이션 펄스가 들어왔을 때 + begin + if(access_type == IDLE) + begin + access_type <= USER; + end + else + begin + access_type <= access_type; + end + end + + 5'b11010: //스왑 펄스가 들어왔을 때 + begin + if(access_type == IDLE) + begin + access_type <= SWAP; + end + else + begin + access_type <= access_type; + end + end + + default: + begin + access_type <= access_type; + end + endcase +end + + + +/* + BUBBLE CYCLE STATE MACHINE +*/ + +/* + +Y 568 +-X 208 +X 448 + -Y 328 +*/ + +//12MHz 1 bubble cycle = 120clks +//48MHz 1 bubble cycle = 480clks +//12MHz 1.5클럭이 씹힌 후에 계산, 만약 BMC신호가 38ns 이상 지연되면 1클럭 추가로 씹힘 +//1.5클럭 씹힌 후 22클럭이 지난 직후 -X자기장 생성 시작 + +reg [9:0] MCLK_counter = 10'd0; //마스터 카운터는 세기 쉽게 1부터 시작 0아님!! + +//master clock counters +always @(posedge MCLK) if(nEN) MCLK_counter = 10'd0; else +begin + //시작 + if(MCLK_counter == 10'd0) + begin + if(access_type[2] == 1'b0) + begin + MCLK_counter <= 10'd0; + end + else + begin + MCLK_counter <= MCLK_counter + 10'd1; + end + end + + //53번째 pos엣지에서 half disk -X방향 위치 + else if(MCLK_counter == 10'd208) + begin + if(access_type[2] == 1'b0) //-X방향에서 자기장회전이 끝났다면 + begin + MCLK_counter <= 10'd0; //그대로 정지 + end + else + begin + MCLK_counter <= MCLK_counter + 10'd1; + end + end + + //143번째 pos엣지에서 half disk +Y방향 위치 + else if(MCLK_counter == 10'd568) + begin + MCLK_counter <= 10'd89; + end + + else + begin + MCLK_counter <= MCLK_counter + 10'd1; + end +end + + +/* + ABSOLUTE POSITION COUNTER +*/ + +reg [11:0] absolute_page_number = INITIAL_ABS_PAGE; +reg [11:0] relative_page_number = 12'd1127; +assign RELPAGE = relative_page_number; + +always @(posedge MCLK) begin + if(nEN) begin + absolute_page_number <= INITIAL_ABS_PAGE; + relative_page_number <= 12'd1127; + end + else begin + //143번째 pos엣지에서 half disk +Y방향 위치 + if(MCLK_counter == 10'd568) begin + if(absolute_page_number < 12'd2052) absolute_page_number <= absolute_page_number + 12'd1; + else absolute_page_number <= 12'd0; + relative_page_number <= relative_page_number >= 12'd1531 ? relative_page_number - 12'd1531 : relative_page_number + 12'd522; + end + end +end + + + +/* + TIMING CONSTANTS +*/ + +/* + +Y 568 +-X 208 +X 448 + -Y 328 +*/ + +/* + An MB3908 has two DFF with /Q OC output, and triggered on every positive + edge of BOUTCLK from MB14506 timing generator. For example, the waveform + below is showing a transfer of "6C 36 B1" + + 0us 0 0 0 0 0 0 0 0 0 0 0 + BOUTCLK |¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____|¯|_____ + D1 ¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + D0 ________|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______ + bootloop ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + +7~8us + user page ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + +0~1us + + Konami's BMC has different sampling timings for bootloop and user page, + respectively. I don't know how the unknown MCU inside the BMC + samples(or latches) data. I assume that MCU gets data from memory-mapped + register once per bit, but there are several possibilities that the MCU + gets several times, triggers flip-flops to sample data, or enables a kind + of transparent latch for quite a long time. + + My friend Maki sent me a Bubble System PCB which has a deteriorated LS244. + Total three LS244 are used as bubble memory control signal buffers, and + its propagation delay is often prolonged due to aging or the output + goes weak. Finally, it often became insufficient to drive a fairly long + transmission line. + + Anyway, to prevent this missampling, bubble data should be launched 0-1us + earlier when reading the bootloop, and 5-6us earlier when reading user + pages. +*/ + +reg [9:0] OUTBUFFER_CLKEN_TIMING = 10'd0; +reg [9:0] CYCLECOUNTER_TIMING = 10'd568; + +always @(posedge MCLK) +begin + if(nEN == 1'b1) + begin + OUTBUFFER_CLKEN_TIMING <= 10'd0; + CYCLECOUNTER_TIMING <= 10'd568; + end + else + begin + if(TIMINGSEL == 1'b0) + begin + OUTBUFFER_CLKEN_TIMING <= 10'd328 - 10'd2; //오리지널 타이밍 - 20ns + CYCLECOUNTER_TIMING <= 10'd568; //오리지널 타이밍 + end + else + begin + if(access_type == BOOT) + begin + OUTBUFFER_CLKEN_TIMING <= 10'd328 - 10'd2; //오리지널 타이밍 - 20ns + CYCLECOUNTER_TIMING <= 10'd568; //오리지널 타이밍 + end + else if(access_type == USER) + begin + OUTBUFFER_CLKEN_TIMING <= 10'd568 - 10'd48; //오리지널 타이밍 - 6us + CYCLECOUNTER_TIMING <= 10'd568 - 10'd60; //오리지널보다 카운터를 2.5us 빨리 증가시킴 + end + else + begin + OUTBUFFER_CLKEN_TIMING <= 10'd328 - 10'd2; //오리지널 타이밍 - 20ns + CYCLECOUNTER_TIMING <= 10'd568; //오리지널 타이밍 + end + end + end +end + + + +/* + CYCLE COUNTER +*/ + +reg [6:0] bout_propagation_delay_counter = 7'd127; //98 +reg [9:0] bout_page_cycle_counter = 10'd1023; //584 +reg [12:0] bout_bootloop_cycle_counter = {1'b0, INITIAL_ABS_PAGE}; //4106 + +//assign BOUTCYCLENUM = bout_page_cycle_counter[14:2]; + +always @(posedge MCLK) if(nEN) begin + BOUTCYCLENUM <= 13'd8191; + bout_propagation_delay_counter <= 7'd127; + bout_page_cycle_counter = 10'd1023; + bout_bootloop_cycle_counter = {1'b0, INITIAL_ABS_PAGE}; +end else +begin + //리셋상태 + if(MCLK_counter == 10'd0) + begin + if(access_type == RST) //리셋 시 + begin + BOUTCYCLENUM <= 13'd8191; + + bout_propagation_delay_counter <= 7'd127; + + bout_page_cycle_counter <= 10'd1023; + + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter; + end + else //그냥 다른 때는 그대로 유지 + begin + BOUTCYCLENUM <= BOUTCYCLENUM; + + bout_propagation_delay_counter <= bout_propagation_delay_counter; + + bout_page_cycle_counter <= bout_page_cycle_counter; + + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter; + end + end + + //+Y에서 한번씩 체크 + else if(MCLK_counter == CYCLECOUNTER_TIMING) //magnetic field rotation activated + begin + if(access_type[1] == 1'b0) //IDLE 또는 SWAP: 실제로 데이터가 나가지 않음 + begin + //empty propagation line + BOUTCYCLENUM <= 13'd8191; + + //reset state + bout_propagation_delay_counter <= 7'd127; + + //reset state + bout_page_cycle_counter <= 10'd1023; + + //count up + if(bout_bootloop_cycle_counter < 13'd4105) + begin + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter + 13'd1; //bootloop cycle counter는 계속 세기 + end + else + begin + bout_bootloop_cycle_counter <= 13'd0; + end + end + + else //BOOT 또는 USER + begin + if(bout_propagation_delay_counter == 7'd127 || bout_propagation_delay_counter < 7'd97) //부트로더(초반 2비트가 씹힘)와 페이지 공히 첫 98싸이클 무효 + begin + //empty propagation line + BOUTCYCLENUM <= 13'd8191; + + //count up + if(bout_propagation_delay_counter < 7'd127) + begin + bout_propagation_delay_counter <= bout_propagation_delay_counter + 7'd1; + end + else + begin + bout_propagation_delay_counter <= 7'd0; + end + + //reset state + bout_page_cycle_counter <= 10'd1023; + + //count up + if(bout_bootloop_cycle_counter < 13'd4105) + begin + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter + 13'd1; //bootloop cycle counter는 계속 세기 + end + else + begin + bout_bootloop_cycle_counter <= 13'd0; + end + end + + else //98사이클 지난 후부터 + begin + if(access_type[0] == 1'b0) //BOOT 액세스, + begin + //hold + bout_propagation_delay_counter <= bout_propagation_delay_counter; + + //reset state + bout_page_cycle_counter <= 10'd1023; + + //count up + if(bout_bootloop_cycle_counter < 13'd4105) + begin + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter + 13'd1; //bootloop cycle counter는 계속 세기 + BOUTCYCLENUM <= bout_bootloop_cycle_counter + 13'd1; + end + else + begin + bout_bootloop_cycle_counter <= 13'd0; + BOUTCYCLENUM <= 13'd0; + end + end + else //USER 액세스 + begin + if(bout_page_cycle_counter == 10'd1023 || bout_page_cycle_counter < 10'd583) //페이지는 584-1 카운트 + begin + //hold + bout_propagation_delay_counter <= bout_propagation_delay_counter; + + //count up + if(bout_page_cycle_counter < 10'd583) + begin + bout_page_cycle_counter <= bout_page_cycle_counter + 10'd1; + BOUTCYCLENUM <= {3'b000, (bout_page_cycle_counter + 10'd1)}; + end + else + begin + bout_page_cycle_counter <= 10'd0; + BOUTCYCLENUM <= 13'd0; + end + + //count up + if(bout_bootloop_cycle_counter < 13'd4105) + begin + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter + 13'd1; //bootloop cycle counter는 계속 세기 + end + else + begin + bout_bootloop_cycle_counter <= 13'd0; + end + end + else + begin + //hold + bout_propagation_delay_counter <= bout_propagation_delay_counter; + + //hold + bout_page_cycle_counter <= bout_page_cycle_counter; + + //count up + if(bout_bootloop_cycle_counter < 13'd4105) + begin + bout_bootloop_cycle_counter <= bout_bootloop_cycle_counter + 13'd1; //bootloop cycle counter는 계속 세기 + end + else + begin + bout_bootloop_cycle_counter <= 13'd0; + end + end + end + end + end + end +end + +//bubble output clock enable generator +always @(posedge MCLK) +begin + //리셋상태 + if(MCLK_counter == 10'd0) + begin + nBOUTCLKEN <= 1'b0; + end + //버블 -Y에서 체크 + else if(MCLK_counter == OUTBUFFER_CLKEN_TIMING) //propagation delay보상을 위해 신호를 15ns정도 일찍 보내기; 오래된 기판의 경우 LS244가 느려짐 + begin + nBOUTCLKEN <= 1'b0; + end + else + begin + nBOUTCLKEN <= 1'b1; + end +end + +//bubble input enable generator +always @(posedge MCLK) +begin + //리셋상태 + if(MCLK_counter == 10'd0) + begin + nBINCLKEN <= 1'b1; + end + //버블 시작, +Y에서 한번씩 체크 + else if(MCLK_counter == 10'd88 || MCLK_counter == 10'd568) + begin + nBINCLKEN <= 1'b0; + end + else + begin + nBINCLKEN <= 1'b1; + end +end + +endmodule + + +module BubSys_bbd8_BubbleBuffer +/* + BubbleDrive8_emucore > modules > BubbleBuffer.v + + Copyright (C) 2020-2022, Raki + + BubbleInterface acts as a buffer. This buffer has 8k*1bit space per + one bubble memory. So, a 2Mbit module can take two of them, and a 4Mb, + unreleased, undeveloped, never-seen one takes four. + This buffer can hold both bootloader(2053*2) and user pages(584). SPI + Loader writes the bootloader and a requested page on here. One important + thing is that this buffer also has the synchronization pattern and empty + propagation line. + 64 of LOGIC LOW + 1 of LOGIC HIGH + extra 1 of DON'T CARE synchronization + pattern bits are loaded on the D0 buffer during the FPGA configuration + session. BUBBLE VALID CYCLE COUNTER automatically sweeps the address bus + of the buffer, so entire bootloop read can be accomplished without + unnatural behavior or exceptional asynchronous code that forces to make + the pattern. + Timing Generator makes Clock Enable pulses(active low) to launch a bubble + bit. + + * For my convenience, many comments are written in Korean * +*/ + +( + //48MHz input clock + input wire MCLK, + + //4bit width mode + input wire BITWIDTH4, + + //Emulator signal outputs + input wire [2:0] ACCTYPE, //access type + input wire [12:0] BOUTCYCLENUM, //bubble output cycle number + input wire nBINCLKEN, + input wire nBOUTCLKEN, //bubble output asynchronous control ticks + + //Bubble out buffer interface + input wire nOUTBUFWRCLKEN, //bubble outbuffer write clk + input wire [14:0] OUTBUFWRADDR, //bubble outbuffer write address + input wire OUTBUFWRDATA, //bubble outbuffer write data + + //Bubble data out + output wire DOUT0, + output wire DOUT1, + output wire DOUT2, + output wire DOUT3 +); + + + +/* + OUTBUFFER READ ADDRESS DECODER +*/ + +/* + Block RAM Buffer Address [DOUT1/DOUT0] + 1bit 0 + 13bit address + 1bit CS + 0000-1327 : bootloader data 1328*2 bits + 1328-1911 : 584*2 bad loop table + 1912-1926 : 14*2 or 15*2 bits of CRC(??) data, at least 28 bits + 1927-4038 : 11 = filler + 4039-4103 : X0 = 65 of ZEROs on EVEN channel (or possibly 64?) + 4104 : X1 = 1 of ONE on EVEN channel + 4105 : XX = DON'T CARE + 4106-7167 : 00 = empty space + 7168-7170 : 00 = 3 position shifted page data + 7171-7751 : 581bits remaining page data + + 8191 : 00 = empty bubble propagation line +*/ + +localparam BOOT = 3'b110; //C +localparam USER = 3'b111; //D + +reg [12:0] outbuffer_read_address = 13'b1_1111_1111_1111; + +always @(*) +begin + case (ACCTYPE) + BOOT: + begin + outbuffer_read_address <= BOUTCYCLENUM; + end + USER: + begin + outbuffer_read_address <= {3'b111, BOUTCYCLENUM[9:0]}; + end + default: + begin + outbuffer_read_address <= 13'b1_1111_1111_1111; + end + endcase +end + + + +/* + OUTBUFFER WRITE ADDRESS DECODER +*/ + +wire [3:0] outbuffer_write_enable; +reg [3:0] outbuffer_we_decoder = 4'b1111; //D3 D2 DOUT1 DOUT0 +assign outbuffer_write_enable = outbuffer_we_decoder; +reg [12:0] outbuffer_write_address; + +always @(*) +begin + case(BITWIDTH4) + 1'b0: //2BITMODE + begin + case(OUTBUFWRADDR[0]) + 1'b0: + begin + outbuffer_write_address <= OUTBUFWRADDR[13:1]; + outbuffer_we_decoder <= 4'b1101; + end + 1'b1: + begin + outbuffer_write_address <= OUTBUFWRADDR[13:1]; + outbuffer_we_decoder <= 4'b1110; + end + endcase + end + 1'b1: //4BITMODE: no game released + begin + case(OUTBUFWRADDR[1:0]) + 2'b00: + begin + outbuffer_write_address <= OUTBUFWRADDR[14:2]; + outbuffer_we_decoder <= 4'b0111; + end + 2'b01: + begin + outbuffer_write_address <= OUTBUFWRADDR[14:2]; + outbuffer_we_decoder <= 4'b1011; + end + 2'b10: + begin + outbuffer_write_address <= OUTBUFWRADDR[14:2]; + outbuffer_we_decoder <= 4'b1101; + end + 2'b11: + begin + outbuffer_write_address <= OUTBUFWRADDR[14:2]; + outbuffer_we_decoder <= 4'b1110; + end + endcase + end + endcase +end + + + +/* + OUTBUFFER +*/ + +//DOUT0 +reg D0_outbuffer[8191:0]; +reg D0_outbuffer_read_data; +assign DOUT0 = ~D0_outbuffer_read_data; + +always @(posedge MCLK) +begin + if(nOUTBUFWRCLKEN == 1'b0) + begin + if (outbuffer_write_enable[0] == 1'b0) + begin + D0_outbuffer[outbuffer_write_address] <= OUTBUFWRDATA; + end + end +end + +always @(posedge MCLK) //read +begin + if(nBOUTCLKEN == 1'b0) + begin + D0_outbuffer_read_data <= D0_outbuffer[outbuffer_read_address]; + end +end + +initial +begin + $readmemb("./rtl/BubSys_bbd8/D0_outbuffer.txt", D0_outbuffer); +end + + +//DOUT1 +reg D1_outbuffer[8191:0]; +reg D1_outbuffer_read_data; +assign DOUT1 = ~D1_outbuffer_read_data; + +always @(posedge MCLK) +begin + if(nOUTBUFWRCLKEN == 1'b0) + begin + if (outbuffer_write_enable[1] == 1'b0) + begin + D1_outbuffer[outbuffer_write_address] <= OUTBUFWRDATA; + end + end +end + +always @(posedge MCLK) //read +begin + if(nBOUTCLKEN == 1'b0) + begin + D1_outbuffer_read_data <= D1_outbuffer[outbuffer_read_address]; + end +end + +initial +begin + $readmemb("./rtl/BubSys_bbd8/D1_outbuffer.txt", D1_outbuffer); +end + + +//DOUT2 +reg D2_outbuffer[8191:0]; +reg D2_outbuffer_read_data; +assign DOUT2 = (BITWIDTH4 == 1'b0) ? ~1'b1 : ~D2_outbuffer_read_data; + +always @(posedge MCLK) +begin + if(nOUTBUFWRCLKEN == 1'b0) + begin + if (outbuffer_write_enable[2] == 1'b0) + begin + D2_outbuffer[outbuffer_write_address] <= OUTBUFWRDATA; + end + end +end + +always @(posedge MCLK) //read +begin + if(nBOUTCLKEN == 1'b0) + begin + D2_outbuffer_read_data <= D2_outbuffer[outbuffer_read_address]; + end +end + +initial +begin + $readmemb("./rtl/BubSys_bbd8/D2_outbuffer.txt", D2_outbuffer); +end + + +//DOUT3 +reg D3_outbuffer[8191:0]; +reg D3_outbuffer_read_data; +assign DOUT3 = (BITWIDTH4 == 1'b0) ? ~1'b1 : ~D3_outbuffer_read_data; + +always @(posedge MCLK) +begin + if(nOUTBUFWRCLKEN == 1'b0) + begin + if (outbuffer_write_enable[3] == 1'b0) + begin + D3_outbuffer[outbuffer_write_address] <= OUTBUFWRDATA; + end + end +end + +always @(posedge MCLK) //read +begin + if(nBOUTCLKEN == 1'b0) + begin + D3_outbuffer_read_data <= D3_outbuffer[outbuffer_read_address]; + end +end + +initial +begin + $readmemb("./rtl/BubSys_bbd8/D3_outbuffer.txt", D3_outbuffer); +end + +endmodule \ No newline at end of file diff --git a/rtl/BubSys_bbd8/D0_outbuffer.txt b/rtl/BubSys_bbd8/D0_outbuffer.txt new file mode 100644 index 0000000..87a8957 --- /dev/null +++ b/rtl/BubSys_bbd8/D0_outbuffer.txt @@ -0,0 +1,25 @@ +@0000 //0000-1926: bootloop data + error map + CRC(??) code 1927*2 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +@0787 //1927-4038: filler 2112 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@0FC7 //4039-4103: synchronizing pattern 0s +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1008 //4104: synchronizing pattern 1 +1 + +@1009 //4105: don't care +0 + +@100A //4106-7167: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1C00 //7168-7751: page data +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1E48 //7752-8190: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1FFF //8191: empty propagation line +0 \ No newline at end of file diff --git a/rtl/BubSys_bbd8/D1_outbuffer.txt b/rtl/BubSys_bbd8/D1_outbuffer.txt new file mode 100644 index 0000000..1d8e674 --- /dev/null +++ b/rtl/BubSys_bbd8/D1_outbuffer.txt @@ -0,0 +1,25 @@ +@0000 //0000-1926: bootloop data + error map + CRC(??) code 1927*2 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +@0787 //1927-4038: filler 2112 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@0FC7 //4039-4103: synchronizing pattern 0s +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1008 //4104: synchronizing pattern 1(0 on D1) +0 + +@1009 //4105: don't care +0 + +@100A //4106-7167: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1C00 //7168-7751: page data +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1E48 //7752-8190: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1FFF //8191: empty propagation line +0 \ No newline at end of file diff --git a/rtl/BubSys_bbd8/D2_outbuffer.txt b/rtl/BubSys_bbd8/D2_outbuffer.txt new file mode 100644 index 0000000..d65fe18 --- /dev/null +++ b/rtl/BubSys_bbd8/D2_outbuffer.txt @@ -0,0 +1,26 @@ +@0000 //0000-1926: bootloop data + error map + CRC(??) code 1927*2 bits +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@0787 //1927-4038: filler 2112 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@0FC7 //4039-4103: synchronizing pattern 0s +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1008 //4104: synchronizing pattern 1(0 on D1) +0 + +@1009 //4105: don't care +0 + +@100A //4106-7167: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1C00 //7168-7751: page data +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1E48 //7752-8190: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1FFF //8191: empty propagation line +0 \ No newline at end of file diff --git a/rtl/BubSys_bbd8/D3_outbuffer.txt b/rtl/BubSys_bbd8/D3_outbuffer.txt new file mode 100644 index 0000000..d65fe18 --- /dev/null +++ b/rtl/BubSys_bbd8/D3_outbuffer.txt @@ -0,0 +1,26 @@ +@0000 //0000-1926: bootloop data + error map + CRC(??) code 1927*2 bits +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@0787 //1927-4038: filler 2112 bits +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@0FC7 //4039-4103: synchronizing pattern 0s +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1008 //4104: synchronizing pattern 1(0 on D1) +0 + +@1009 //4105: don't care +0 + +@100A //4106-7167: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1C00 //7168-7751: page data +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +@1E48 //7752-8190: unused space +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + +@1FFF //8191: empty propagation line +0 \ No newline at end of file diff --git a/rtl/BubSys_components/BubSys_PROM.v b/rtl/BubSys_components/BubSys_PROM.v new file mode 100644 index 0000000..a78d3b7 --- /dev/null +++ b/rtl/BubSys_components/BubSys_PROM.v @@ -0,0 +1,61 @@ +module BubSys_PROM #(parameter AW=10, parameter DW=8, parameter simhexfile="") ( + input wire i_MCLK, + + input wire [AW-1:0] i_PROG_ADDR, + input wire [DW-1:0] i_PROG_DIN, + input wire i_PROG_CS, + input wire i_PROG_WR, + + input wire [AW-1:0] i_ADDR, + output reg [DW-1:0] o_DOUT, + input wire i_RD +); + +reg [DW-1:0] ROM [0:(2**AW)-1]; +always @(posedge i_MCLK) begin + if(i_PROG_CS & i_PROG_WR) ROM[i_PROG_ADDR] <= i_PROG_DIN; + else begin + if(i_RD) o_DOUT <= ROM[i_ADDR]; + end +end + +initial +begin + if( simhexfile != "" ) begin + $readmemh(simhexfile, ROM); + end +end + +endmodule + + +module BubSys_PROM_DC #(parameter AW=10, parameter DW=8, parameter simhexfile="") ( + input wire i_PROG_CLK, + input wire [AW-1:0] i_PROG_ADDR, + input wire [DW-1:0] i_PROG_DIN, + input wire i_PROG_CS, + input wire i_PROG_WR, + + input wire i_MCLK, + input wire [AW-1:0] i_ADDR, + output reg [DW-1:0] o_DOUT, + input wire i_RD +); + +reg [DW-1:0] ROM [0:(2**AW)-1]; +always @(posedge i_PROG_CLK) begin + if(i_PROG_CS && i_PROG_WR) ROM[i_PROG_ADDR] <= i_PROG_DIN; +end + +always @(posedge i_MCLK) begin + if(i_RD) o_DOUT <= ROM[i_ADDR]; +end + +initial +begin + if( simhexfile != "" ) begin + $readmemh(simhexfile, ROM); + end +end + +endmodule \ No newline at end of file diff --git a/rtl/BubSys_components/BubSys_SRAM.v b/rtl/BubSys_components/BubSys_SRAM.v new file mode 100644 index 0000000..8f5bc2d --- /dev/null +++ b/rtl/BubSys_components/BubSys_SRAM.v @@ -0,0 +1,26 @@ +module BubSys_SRAM #(parameter AW=10, parameter DW=8, parameter simhexfile="") ( + input wire i_MCLK, + + input wire [AW-1:0] i_ADDR, + input wire [DW-1:0] i_DIN, + output reg [DW-1:0] o_DOUT, + input wire i_RD, + input wire i_WR +); + +reg [DW-1:0] RAM [0:(2**AW)-1]; +always @(posedge i_MCLK) begin + if(i_WR) RAM[i_ADDR] <= i_DIN; + else begin + if(i_RD) o_DOUT <= RAM[i_ADDR]; + end +end + +integer i; +initial begin + if( simhexfile != "" ) begin + $readmemh(simhexfile, RAM); + end +end + +endmodule \ No newline at end of file diff --git a/rtl/BubSys_cpu.v b/rtl/BubSys_cpu.v new file mode 100644 index 0000000..85e42a3 --- /dev/null +++ b/rtl/BubSys_cpu.v @@ -0,0 +1,746 @@ +`timescale 10ns/10ns +module BubSys_cpu ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK9M_PCEN, + input wire i_EMU_CLK9M_NCEN, + input wire i_EMU_CLK6M_PCEN, + input wire i_EMU_CLK6M_NCEN, + + input wire i_EMU_INITRST_n, + input wire i_EMU_SOFTRST_n, + + //reset control by the sound CPU + input wire i_MAINCPU_RSTCTRL, + output wire o_MAINCPU_RSTSTAT, + input wire i_MAINCPU_SWAPIRQ, + + //bubble memory subsystem + input wire i_BMC_MCLK, //48MHz + input wire i_BMC_TEMPLO_n, + output wire o_BMC_ACC, + + output wire [14:0] o_GFX_ADDR, + input wire [15:0] i_GFX_DO, + output wire [15:0] o_GFX_DI, + output wire o_GFX_RnW, + output wire o_GFX_UDS_n, + output wire o_GFX_LDS_n, + + output reg o_VZCS_n, + output reg o_VCS1_n, + output reg o_VCS2_n, + output reg o_CHACS_n, + output reg o_OBJRAM_n, + + output wire o_HFLIP, + output wire o_VFLIP, + + input wire i_ABS_1H_n, + input wire i_ABS_2H, + input wire i_ABS_32H, + + input wire i_VBLANK_n, + input wire i_FRAMEPARITY, + + input wire i_BLK, + + input wire [10:0] i_CD, + + //sound interrupts/DMA + output wire o_SND_NMI, + output wire o_SND_INT, + output wire [7:0] o_SND_CODE, + output wire o_SND_DMA_BR, + input wire i_SND_DMA_BG_n, + output wire [14:1] o_SND_DMA_ADDR, + output wire [7:0] o_SND_DMA_DO, + input wire [7:0] i_SND_DMA_DI, + output wire o_SND_DMA_RnW, + output wire o_SND_DMA_LDS_n, + output reg o_SND_DMA_SNDRAM_CS, + + input wire i_TIMER_IRQ, + + input wire [7:0] i_IN0, i_IN1, i_IN2, i_DIPSW1, i_DIPSW2, i_DIPSW3, + + output wire [4:0] o_VIDEO_R, + output wire [4:0] o_VIDEO_G, + output wire [4:0] o_VIDEO_B, + + output wire o_BUBROM_BOOT_CS, o_BUBROM_PAGE_CS, + output wire [17:0] o_BUBROM_ADDR, + input wire [15:0] i_BUBROM_DATA, + output wire o_BUBROM_RD, + input wire i_BUBROM_DATA_RDY +); + + + +/////////////////////////////////////////////////////////// +////// CLOCK AND RESET +//// + +//BMC region +wire bmc_rst = ~i_EMU_INITRST_n | ~i_EMU_SOFTRST_n; +wire bmc_maincpu_rstctrl_n; +wire bclk = i_BMC_MCLK; +wire clk4m_pcen; + +//Main CPU region +wire maincpu_pwrup = ~i_EMU_INITRST_n; +wire maincpu_rst = ~i_EMU_INITRST_n | ~i_EMU_SOFTRST_n | i_MAINCPU_RSTCTRL | ~bmc_maincpu_rstctrl_n; +wire mclk = i_EMU_MCLK; +wire clk9m_pcen = i_EMU_CLK9M_PCEN; +wire clk9m_ncen = i_EMU_CLK9M_NCEN; +wire clk6m_pcen = i_EMU_CLK6M_PCEN; +wire clk6m_ncen = i_EMU_CLK6M_NCEN; + + + +assign o_MAINCPU_RSTSTAT = maincpu_rst; //watchdog + + +/////////////////////////////////////////////////////////// +////// SYSTEM BUS +//// + +//dma synchronizer(72MHz/48MHz CDC) +wire dma_br_n, dma_bg_n, dma_bgack_n; +reg [1:0] dma_br_n_sync, dma_bg_n_sync, dma_bgack_n_sync; +wire dma_act = ~dma_bgack_n_sync[1]; +always @(posedge mclk) begin //48MHz -> 72MHz + dma_br_n_sync[0] <= dma_br_n; + dma_br_n_sync[1] <= dma_br_n_sync[0]; + dma_bgack_n_sync[0] <= dma_bgack_n; + dma_bgack_n_sync[1] <= dma_bgack_n_sync[0]; +end +always @(posedge bclk) begin //72MHz -> 48MHz + dma_bg_n_sync[0] <= dma_bg_n; + dma_bg_n_sync[1] <= dma_bg_n_sync[0]; +end + +//Main 68k bus/control +wire [15:0] maincpu_do; +wire [23:1] maincpu_addr; +wire maincpu_as_n, maincpu_r_nw, maincpu_lds_n, maincpu_uds_n; +wire [2:0] maincpu_fc; + +//Bubble memory controller bus/control +wire [15:0] bmc_di, bmc_do; +wire bmc_ale; //address latch enable(48MHz) +reg [15:0] bmc_al; //address latch LS272*2 +reg [2:0] bmc_ale_sync; +always @(posedge mclk) begin + bmc_ale_sync[0] <= bmc_ale; + bmc_ale_sync[2:1] <= bmc_ale_sync[1:0]; + if(bmc_ale_sync[2:1] == 2'b01) bmc_al <= bmc_do; +end +wire [7:1] bmc_addr; +wire bmc_as_n, bmc_r_nw, bmc_lds_n, bmc_uds_n; +reg [1:0] bmc_as_n_sync, bmc_r_nw_sync; +reg [3:0] bmc_lds_n_sync, bmc_uds_n_sync; +reg bmc_lds_n_negedge, bmc_uds_n_negedge; +always @(posedge mclk) begin + bmc_as_n_sync[0] <= bmc_as_n; + bmc_r_nw_sync[0] <= bmc_r_nw; + bmc_as_n_sync[1] <= bmc_as_n_sync[0]; + bmc_r_nw_sync[1] <= bmc_r_nw_sync[0]; + + bmc_lds_n_sync[0] <= bmc_lds_n; + bmc_uds_n_sync[0] <= bmc_uds_n; + bmc_lds_n_sync[3:1] <= bmc_lds_n_sync[2:0]; + bmc_uds_n_sync[3:1] <= bmc_uds_n_sync[2:0]; + + bmc_lds_n_negedge <= bmc_lds_n_sync[3] && !bmc_lds_n_sync[1]; + bmc_uds_n_negedge <= bmc_uds_n_sync[3] && !bmc_uds_n_sync[1]; +end +wire [2:0] bmc_fc; + +//Main bus/control, CPU+BMC multiplexed +reg [15:0] mainbus_di; +wire [15:0] mainbus_do = dma_act ? bmc_do : maincpu_do; //no need to synchronize +wire [23:1] mainbus_addr = dma_act ? {bmc_al, bmc_addr} : maincpu_addr; //no need to synchronize +wire mainbus_as_n = dma_act ? bmc_as_n_sync[1] : maincpu_as_n; +wire mainbus_r_nw = dma_act ? bmc_r_nw_sync[1] : maincpu_r_nw; +wire mainbus_lds_n = dma_act ? ~bmc_lds_n_negedge : maincpu_lds_n; +wire mainbus_uds_n = dma_act ? ~bmc_uds_n_negedge : maincpu_uds_n; +wire [2:0] mainbus_fc = dma_act ? bmc_fc : maincpu_fc; + +assign bmc_di = dma_act ? mainbus_di : mainbus_do; + +wire [23:0] debug_mainbus_addr = {mainbus_addr, mainbus_uds_n}; + +//send signals to the GFX board +assign o_GFX_ADDR = mainbus_addr[15:1]; +assign o_GFX_DI = mainbus_do; +assign o_GFX_RnW = mainbus_r_nw; +assign o_GFX_UDS_n = mainbus_uds_n; +assign o_GFX_LDS_n = mainbus_lds_n; + + + +/////////////////////////////////////////////////////////// +////// MAIN CPU +//// + +reg maincpu_vpa_n; +reg maincpu_dtack_n; +reg [2:0] maincpu_ipl; +fx68k u_maincpu ( + .clk (mclk ), + .HALTn (1'b1 ), + .extReset (maincpu_rst ), + .pwrUp (maincpu_pwrup ), + .enPhi1 (clk9m_pcen ), + .enPhi2 (clk9m_ncen ), + + .eRWn (maincpu_r_nw ), + .ASn (maincpu_as_n ), + .LDSn (maincpu_lds_n ), + .UDSn (maincpu_uds_n ), + .E ( ), + .VMAn ( ), + + .iEdb (mainbus_di ), //data bus in + .oEdb (maincpu_do ), //data bus out + .eab (maincpu_addr ), //23 downto 1 + + .FC0 (maincpu_fc[0] ), + .FC1 (maincpu_fc[1] ), + .FC2 (maincpu_fc[2] ), + + .BGn (dma_bg_n ), + .oRESETn ( ), + .oHALTEDn ( ), + + .DTACKn (maincpu_dtack_n ), + .VPAn (maincpu_vpa_n ), + + .BERRn (1'b1 ), + + .BRn (dma_br_n_sync[1] ), + .BGACKn (dma_bgack_n_sync[1] ), + + .IPL0n (maincpu_ipl[0] ), + .IPL1n (maincpu_ipl[1] ), + .IPL2n (maincpu_ipl[2] ) +); + + + + +/////////////////////////////////////////////////////////// +////// BUBBLE MEMORY +//// + +reg bmc_cs; +wire bmcclk_pcen; //generated by bubble memory emulator +wire booten_n, bss_n, bsen_n, repen_n, swapen_n; +wire [3:0] bdo_n; + +BubSys_bbd8 u_bbd8 ( + .i_EMUCLK (bclk ), + .i_RST (bmc_rst ), + + .i_4BEN (1'b0 ), + .i_BDO_TSEL (1'b0 ), + + .o_BMCCLK_PCEN (bmcclk_pcen ), + + .i_BOOTEN_n (booten_n ), + .i_BSS_n (bss_n ), + .i_BSEN_n (bsen_n ), + .i_REPEN_n (repen_n ), + .i_SWAPEN_n (swapen_n ), + + .o_BDO_n (bdo_n ), + .o_ACC (o_BMC_ACC ), + + .o_BUBROM_BOOT_CS (o_BUBROM_BOOT_CS ), + .o_BUBROM_PAGE_CS (o_BUBROM_PAGE_CS ), + .o_BUBROM_ADDR (o_BUBROM_ADDR ), + .i_BUBROM_DATA (i_BUBROM_DATA ), + .o_BUBROM_RD (o_BUBROM_RD ), + .i_BUBROM_DATA_RDY (i_BUBROM_DATA_RDY ) +); + + + +/////////////////////////////////////////////////////////// +////// BUBBLE MEMORY CONTROLLER +//// + +wire bmc_irq_n; + +K005297 u_K005297 ( + .i_MCLK (bclk ), + + .i_CLK4M_PCEN_n (~bmcclk_pcen ), + + .i_MRST_n (~bmc_rst ), + + .i_REGCS_n (~bmc_cs ), + .i_DIN (bmc_di ), //write to BMC/BMC DMA read + .i_AIN (mainbus_addr[3:1] ), //write to BMC + .i_R_nW (mainbus_r_nw ), + .i_UDS_n (mainbus_uds_n ), + .i_LDS_n (mainbus_lds_n ), + .i_AS_n (mainbus_as_n ), + + .o_DOUT (bmc_do ), + .o_AOUT (bmc_addr ), + .o_R_nW (bmc_r_nw ), + .o_UDS_n (bmc_uds_n ), + .o_LDS_n (bmc_lds_n ), + .o_AS_n (bmc_as_n ), + .o_ALE (bmc_ale ), + + .o_BR_n (dma_br_n ), + .i_BG_n (dma_bg_n_sync[1] ), + .o_BGACK_n (dma_bgack_n ), + + .o_CPURST_n (bmc_maincpu_rstctrl_n ), + .o_IRQ_n (bmc_irq_n ), + + .o_FCOUT (bmc_fc ), + .i_FCIN (mainbus_fc ), + + .o_BDOUT_n ( ), + .i_BDIN_n ({bdo_n[1:0], 2'b11} ), + .o_BOOTEN_n (booten_n ), + .o_BSS_n (bss_n ), + .o_BSEN_n (bsen_n ), + .o_REPEN_n (repen_n ), + .o_SWAPEN_n (swapen_n ), + .i_TEMPLO_n (1'b1 ), + .o_HEATEN_n ( ), + .i_4BEN_n (1'b1 ), + + .o_INT1_ACK_n ( ), + .i_TST1 (1'b1 ), + .i_TST2 (1'b0 ), + .i_TST3 (1'b1 ), + .i_TST4 (1'b0 ), + .i_TST5 (1'b1 ), + + .o_CTRL_DMAIO_OE_n ( ), + .o_CTRL_DATA_OE_n ( ) +); + + + +/////////////////////////////////////////////////////////// +////// ADDRESS DECODER +//// + +reg sharedram_cs, gamerom_rd, workram_cs, extram_cs; +reg dmastat_cs, sndlatch_cs; +reg palram_cs; +reg syscfg_cs, dip_cs, btn_cs; +always @(*) begin + sharedram_cs= 1'b0; //shared RAM between BMC/CPU + gamerom_rd = 1'b0; + workram_cs = 1'b0; + bmc_cs = 1'b0; + extram_cs = 1'b0; + + dmastat_cs = 1'b0; + sndlatch_cs = 1'b0; + o_SND_DMA_SNDRAM_CS = 1'b0; + + syscfg_cs = 1'b0; + dip_cs = 1'b0; + btn_cs = 1'b0; + + palram_cs = 1'b0; + o_VZCS_n = 1'b1; + o_VCS1_n = 1'b1; + o_VCS2_n = 1'b1; + o_CHACS_n = 1'b1; + o_OBJRAM_n = 1'b1; + + maincpu_vpa_n = 1'b1; + + if(!mainbus_as_n && mainbus_addr[23:19] == 5'b00000) begin + //1st LS138 + sharedram_cs= mainbus_addr[18:16] == 3'b000; //0x000000-0x000FFF, 6116*2 + workram_cs = mainbus_addr[18:16] == 3'b001; //0x010000-0x01FFFF, 62256*2 + o_SND_DMA_SNDRAM_CS = mainbus_addr[18:16] == 3'b010; //0x020000-0x027FFF, sound RAM address space + o_CHACS_n = ~(mainbus_addr[18:16] == 3'b011); //0x030000-0x03FFFF, 4416*8 + bmc_cs = mainbus_addr[18:16] == 3'b100; //0x040000-0x04FFFF, bubble memory controller + extram_cs = mainbus_addr[18:16] == 3'b111; //0x070000-0x07FFFF, 6264*2(expansion RAM) + + //2nd LS138 + if(mainbus_addr[18:16] == 3'b101) begin + o_VZCS_n = ~(mainbus_addr[15:13] == 3'b000); //0x190000-0x190FFF, 16k*1, byte only + o_VCS1_n = ~(mainbus_addr[15:13] == 3'b001); //0x100000-0x101FFF, 32k*2, Toshiba 32kbit TC5533 + o_VCS2_n = ~(mainbus_addr[15:13] == 3'b010); //0x102000-0x103FFF, 32k*1, byte only + o_OBJRAM_n = ~(mainbus_addr[15:13] == 3'b011); //0x180000-0x180FFF, 16k*1, byte only + palram_cs = mainbus_addr[15:13] == 3'b101; //0x090000-0x091FFF, 16k*2, byte only + syscfg_cs = mainbus_addr[15:13] == 3'b111; + end + + //3rd LS138 + if(mainbus_addr[18:13] == 6'b101_110 && !mainbus_lds_n) begin + sndlatch_cs = mainbus_addr[12:10] == 3'b000; + dip_cs = mainbus_addr[12:10] == 3'b001; + btn_cs = mainbus_addr[12:10] == 3'b011; + dmastat_cs = mainbus_addr[12:10] == 3'b100; + end + end + + maincpu_vpa_n = mainbus_as_n | ~mainbus_addr[23]; +end + + + +/////////////////////////////////////////////////////////// +////// MAIN CPU DTACK +//// + +//work ram timings +reg abs_32h_z; +wire abs_32h_pe = i_ABS_32H & ~abs_32h_z; +always @(posedge mclk) if(clk6m_pcen) abs_32h_z <= i_ABS_32H; + +reg [2:0] workram_rfsh_stat = 3'd0; //0 = idle, 1, 2, 3 = refresh, 4 = refresh pending +always @(posedge mclk) if(clk6m_pcen) begin + if(workram_rfsh_stat == 3'd0) begin + if(workram_cs) begin + if(abs_32h_pe) workram_rfsh_stat <= 3'd4; + end + else begin + if(abs_32h_pe) workram_rfsh_stat <= workram_rfsh_stat + 2'd1; + end + end + else if(workram_rfsh_stat == 3'd4) begin + if(!workram_cs) workram_rfsh_stat <= 3'd1; + end + else begin + if(workram_rfsh_stat == 3'd3) workram_rfsh_stat <= 3'd0; + else workram_rfsh_stat <= workram_rfsh_stat + 3'd1; + end +end + +//dtack generator +wire dtack0_n = 1'b0; +reg dtack1_n, dtack2_pre_n, dtack2_n; +wire dtack3_n = ~((workram_rfsh_stat == 3'd0 | workram_rfsh_stat == 3'd4) & workram_cs); +always @(posedge mclk) begin + if(maincpu_uds_n & maincpu_lds_n) begin + dtack1_n <= 1'b1; + dtack2_pre_n <= 1'b1; + dtack2_n <= 1'b1; + end + else begin + if(clk6m_pcen) begin + if(!i_ABS_1H_n) dtack1_n <= 1'b0; + dtack2_pre_n <= 1'b0; + end + + if(clk6m_ncen) begin + if({i_ABS_2H, ~i_ABS_1H_n} == 2'b00) dtack2_n <= dtack2_pre_n; + end + end +end + +//DTACK selector +wire [1:0] dtack_sel; +assign dtack_sel[1] = workram_cs | bmc_cs | o_SND_DMA_SNDRAM_CS | ~o_CHACS_n | ~o_VCS1_n | ~o_VCS2_n; // | exdtack <- not used, never used +assign dtack_sel[0] = workram_cs | ~o_VZCS_n | ~o_OBJRAM_n; +always @(*) begin + case(dtack_sel) + 2'd0: maincpu_dtack_n = dtack0_n; //bootloader ROM, program ROM(2Mbit), IO spaces + 2'd1: maincpu_dtack_n = dtack1_n; //scrollram, objram + 2'd2: maincpu_dtack_n = dtack2_n; //soundram, charram, vram1, vram2 + 2'd3: maincpu_dtack_n = dtack3_n; //workram + endcase +end + + + +/////////////////////////////////////////////////////////// +////// MAIN CPU IRQ +//// + +wire iack_vblank_n, iack_fparity_n, iack_timer_n; +reg vblank_z, vblank_zz, fparity_z, fparity_zz, timer_z, timer_zz, bmc_irq_n_z, bmc_irq_n_zz; +reg irq_vblank_n, irq_fparity_n, irq_timer_n; + +always @(posedge mclk) begin + vblank_z <= ~i_VBLANK_n; + vblank_zz <= vblank_z; + fparity_z <= i_FRAMEPARITY; + fparity_zz <= fparity_z; + timer_z <= i_TIMER_IRQ; + timer_zz <= timer_z; + bmc_irq_n_z <= bmc_irq_n; + bmc_irq_n_zz <= bmc_irq_n_z; + + if(maincpu_rst) begin + irq_vblank_n <= 1'b1; + irq_fparity_n <= 1'b1; + irq_timer_n <= 1'b1; + end + else begin + if(!iack_vblank_n) irq_vblank_n <= 1'b1; + else begin + if({vblank_zz, vblank_z} == 2'b01) irq_vblank_n <= 1'b0; + end + if(!iack_fparity_n) irq_fparity_n <= 1'b1; + else begin + if({fparity_zz, fparity_z} == 2'b01) irq_fparity_n <= 1'b0; + end + if(!iack_timer_n) irq_timer_n <= 1'b1; + else begin + if({timer_zz, timer_z} == 2'b01) irq_timer_n <= 1'b0; + end + end +end + +//Bubble System uses LS147 only, not make a delayed signal +always @(*) begin + if(!bmc_irq_n_zz) maincpu_ipl = 3'b010; + else begin + if(!irq_timer_n) maincpu_ipl = 3'b011; + else begin + if(i_MAINCPU_SWAPIRQ ? !irq_fparity_n : !irq_vblank_n) maincpu_ipl = 3'b101; + else begin + if(i_MAINCPU_SWAPIRQ ? !irq_vblank_n : !irq_fparity_n) maincpu_ipl = 3'b110; + else maincpu_ipl = 3'b111; + end + end + end +end + + + +/////////////////////////////////////////////////////////// +////// OUTLATCH(SYSTEM CONFIGURATION) +//// + +reg [5:0] syscfg[0:1]; +always @(posedge mclk) begin + if(maincpu_rst) begin + syscfg[0] <= 6'h00; + syscfg[1] <= 6'h00; + end + else begin if(syscfg_cs) begin + if(!mainbus_uds_n && !mainbus_r_nw) begin + case(mainbus_addr[3:1]) + //3'd0: syscfg[0][0] <= maincpu_do[8]; //coin counter 1 + //3'd1: syscfg[0][1] <= maincpu_do[8]; + 3'd2: syscfg[0][2] <= mainbus_do[8]; //sound interrupt tick + 3'd3: syscfg[0][3] <= mainbus_do[8]; //dma_busrq + 3'd4: syscfg[0][4] <= mainbus_do[8]; //sound NMI + 3'd7: syscfg[0][5] <= mainbus_do[8]; //timerirq_ack_n + default: ; + endcase + end + if(!mainbus_lds_n && !mainbus_r_nw) begin + case(mainbus_addr[3:1]) + 3'd0: syscfg[1][0] <= mainbus_do[0]; //vblankirq_ack_n + 3'd1: syscfg[1][1] <= mainbus_do[0]; //frameirq_ack_n + 3'd2: syscfg[1][2] <= mainbus_do[0]; //gfx_hflip + 3'd3: syscfg[1][3] <= mainbus_do[0]; //gfx_vflip + //3'd4: syscfg[1][4] <= maincpu_do[0]; //gfx_h288 + //3'd5: syscfg[1][5] <= maincpu_do[0]; //gfx_interlaced + default: ; + endcase + end + end end +end + +assign iack_vblank_n = syscfg[1][0]; +assign iack_fparity_n = syscfg[1][1]; +assign iack_timer_n = syscfg[0][5]; +assign o_HFLIP = syscfg[1][2]; +assign o_VFLIP = syscfg[1][3]; +assign o_SND_INT = syscfg[0][2]; +assign o_SND_NMI = syscfg[0][4]; + + + +/////////////////////////////////////////////////////////// +////// WORK RAM +//// + +wire [15:0] sharedram_q; +BubSys_SRAM #(.AW(11), .DW(8), .simhexfile()) u_sharedram_hi ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[11:1] ), + .i_DIN (mainbus_do[15:8] ), + .o_DOUT (sharedram_q[15:8] ), + .i_WR (sharedram_cs & ~mainbus_r_nw & ~mainbus_uds_n & mainbus_fc[2]), + .i_RD (sharedram_cs & mainbus_r_nw & ~mainbus_uds_n & mainbus_fc[2]) +); +BubSys_SRAM #(.AW(11), .DW(8), .simhexfile()) u_sharedram_lo ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[11:1] ), + .i_DIN (mainbus_do[7:0] ), + .o_DOUT (sharedram_q[7:0] ), + .i_WR (sharedram_cs & ~mainbus_r_nw & ~mainbus_lds_n & mainbus_fc[2]), + .i_RD (sharedram_cs & mainbus_r_nw & ~mainbus_lds_n & mainbus_fc[2]) +); + +wire [15:0] workram_q; +BubSys_SRAM #(.AW(15), .DW(8), .simhexfile()) u_workram_hi ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[15:1] ), + .i_DIN (mainbus_do[15:8] ), + .o_DOUT (workram_q[15:8] ), + .i_WR (workram_cs & ~mainbus_r_nw & ~mainbus_uds_n), + .i_RD (workram_cs & mainbus_r_nw & ~mainbus_uds_n) +); +BubSys_SRAM #(.AW(15), .DW(8), .simhexfile()) u_workram_lo ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[15:1] ), + .i_DIN (mainbus_do[7:0] ), + .o_DOUT (workram_q[7:0] ), + .i_WR (workram_cs & ~mainbus_r_nw & ~mainbus_lds_n), + .i_RD (workram_cs & mainbus_r_nw & ~mainbus_lds_n) +); + +//6264*2, gradius uses this +wire [15:0] extram_q; +BubSys_SRAM #(.AW(13), .DW(8), .simhexfile()) u_extram_hi ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[13:1] ), + .i_DIN (mainbus_do[15:8] ), + .o_DOUT (extram_q[15:8] ), + .i_WR (extram_cs & ~mainbus_r_nw & ~mainbus_uds_n), + .i_RD (extram_cs & mainbus_r_nw & ~mainbus_uds_n) +); +BubSys_SRAM #(.AW(13), .DW(8), .simhexfile()) u_extram_lo ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (mainbus_addr[13:1] ), + .i_DIN (mainbus_do[7:0] ), + .o_DOUT (extram_q[7:0] ), + .i_WR (extram_cs & ~mainbus_r_nw & ~mainbus_lds_n), + .i_RD (extram_cs & mainbus_r_nw & ~mainbus_lds_n) +); + + + + +/////////////////////////////////////////////////////////// +////// Palette RAM +//// + +//make palram wr signal +wire palram_hi_cs = &{palram_cs, ~mainbus_uds_n}; +wire palram_lo_cs = &{palram_cs, ~mainbus_lds_n}; + +//make colorram address +wire [10:0] palram_addr = palram_cs ? mainbus_addr[11:1] : i_CD; + +//declare COLORRAM +wire [7:0] palram_lo_q, palram_hi_q; +wire [15:0] palram_q = {palram_hi_q, palram_lo_q}; + +BubSys_SRAM #(.AW(11), .DW(8), .simhexfile()) u_palram_hi ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (palram_addr ), + .i_DIN (mainbus_do[15:8] ), + .o_DOUT (palram_hi_q ), + .i_WR (palram_hi_cs & ~mainbus_r_nw), + .i_RD (1'b1 ) +); + +BubSys_SRAM #(.AW(11), .DW(8), .simhexfile()) u_palram_lo ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (palram_addr ), + .i_DIN (mainbus_do[7:0] ), + .o_DOUT (palram_lo_q ), + .i_WR (palram_lo_cs & ~mainbus_r_nw), + .i_RD (1'b1 ) +); + +//rgb driver latch +reg [14:0] rgblatch; +always @(posedge mclk) if(clk6m_pcen) begin + rgblatch <= {palram_hi_q[6:0], palram_lo_q}; +end + +assign o_VIDEO_B = i_BLK ? rgblatch[14:10] : 5'd0; +assign o_VIDEO_G = i_BLK ? rgblatch[9:5] : 5'd0; +assign o_VIDEO_R = i_BLK ? rgblatch[4:0] : 5'd0; + + + +/////////////////////////////////////////////////////////// +////// SOUNDLATCH +//// + +reg [7:0] soundlatch = 8'h00; +assign o_SND_CODE = soundlatch; +always @(posedge mclk) begin + if(sndlatch_cs && !mainbus_r_nw && !mainbus_lds_n) soundlatch <= mainbus_do[7:0]; +end + + + +/////////////////////////////////////////////////////////// +////// DMA +//// + +assign o_SND_DMA_BR = syscfg[0][3]; //sound cpu bus request +assign o_SND_DMA_ADDR = mainbus_addr[14:1]; +assign o_SND_DMA_DO = mainbus_do[7:0]; +assign o_SND_DMA_RnW = mainbus_r_nw; +assign o_SND_DMA_LDS_n = mainbus_lds_n; + + + + +/////////////////////////////////////////////////////////// +////// READ BUS MUX +//// + +//assign o_BMC_ACC = mainbus_fc == 3'b110 && mainbus_addr == 23'h8000 /* synthesis keep */; + +wire gfx_cs = ~&{o_VZCS_n, o_VCS1_n, o_VCS2_n, o_CHACS_n, o_OBJRAM_n}; + +//CDC synchronizer +reg [7:0] snd_dma_di_sync[0:1]; +reg [1:0] snd_dma_bg_n_sync; +always @(posedge mclk) begin + snd_dma_di_sync[0] <= i_SND_DMA_DI; + snd_dma_di_sync[1] <= snd_dma_di_sync[0]; + + snd_dma_bg_n_sync[0] <= i_SND_DMA_BG_n; + snd_dma_bg_n_sync[1] <= snd_dma_bg_n_sync[0]; +end + + +always @(*) begin + mainbus_di = 16'hFFFF; + + if(bmc_cs) mainbus_di = bmc_do; + else if(sharedram_cs) mainbus_di = sharedram_q; + else if(workram_cs) mainbus_di = workram_q; + else if(extram_cs) mainbus_di = extram_q; + else if(palram_cs) mainbus_di = palram_q; + else if(gfx_cs) mainbus_di = i_GFX_DO; + else if(btn_cs) begin + case(mainbus_addr[2:1]) + 2'd0: mainbus_di = {8'hFF, i_IN0}; + 2'd1: mainbus_di = {8'hFF, i_IN1}; + 2'd2: mainbus_di = {8'hFF, i_IN2}; + 2'd3: mainbus_di = {16'hFFFF}; + endcase + end + else if(dip_cs) begin + case(mainbus_addr[2:1]) + 2'd0: mainbus_di = {16'hFFFF}; + 2'd1: mainbus_di = {8'hFF, i_DIPSW1}; + 2'd2: mainbus_di = {8'hFF, i_DIPSW2}; + 2'd3: mainbus_di = {8'hFF, i_DIPSW3}; + endcase + end + else if(o_SND_DMA_SNDRAM_CS) mainbus_di = {8'hFF, snd_dma_di_sync[1]}; + else if(dmastat_cs) mainbus_di = {{15{1'b1}}, snd_dma_bg_n_sync[1]}; +end + + +endmodule diff --git a/rtl/BubSys_emu.v b/rtl/BubSys_emu.v new file mode 100644 index 0000000..0e369e8 --- /dev/null +++ b/rtl/BubSys_emu.v @@ -0,0 +1,476 @@ +module BubSys_emu ( + input wire i_EMU_CLK72M, + input wire i_EMU_CLK57M, + input wire i_EMU_CLK48M, + input wire i_EMU_INITRST, + input wire i_EMU_SOFTRST, + + //video syncs + output wire o_HBLANK, + output wire o_VBLANK, + output wire o_HSYNC, + output wire o_VSYNC, + output wire o_VIDEO_CEN, //video clock enable + output wire o_VIDEO_DEN, //video data enable + output wire o_VIDEO_ROT, //only for twinbee + + output wire [4:0] o_VIDEO_R, + output wire [4:0] o_VIDEO_G, + output wire [4:0] o_VIDEO_B, + + input wire [15:0] i_VOL, + output wire signed [15:0] o_SND_L, + output wire signed [15:0] o_SND_R, + + input wire i_MAINCPU_SWAPIRQ, + output wire o_BMC_ACC, + + input wire [15:0] i_JOYSTICK0, + input wire [15:0] i_JOYSTICK1, + + //mister ioctl + input wire [15:0] ioctl_index, + input wire ioctl_download, + input wire [26:0] ioctl_addr, + input wire [7:0] ioctl_data, + input wire ioctl_wr, + output wire ioctl_wait, + + //mister sdram + inout wire [15:0] sdram_dq, + output wire [12:0] sdram_a, + output wire sdram_dqml, + output wire sdram_dqmh, + output wire [1:0] sdram_ba, + output wire sdram_nwe, + output wire sdram_ncas, + output wire sdram_nras, + output wire sdram_ncs, + output wire sdram_cke, + + output wire debug +); + + + +/////////////////////////////////////////////////////////// +////// ROM DISTRIBUTOR +//// + +//start addr length comp num mame rom parts num location description +//0x0000_0000 0x0004_0FFF FBM54DB BANK0 bubble memory user page +//0x0004_1000 0x0000_2000 5l 400-a~e03 27C64 BRAM sound program(bootloader/base) +//0x0004_3000 0x0000_0200 FBM54DB BRAM bubble memory bootloader +//0x0004_3200 0x0000_0100 2a 400-a01 82S129 BRAM wavetable +//0x0004_3300 0x0000_0100 1a 400-a02 82S129 BRAM wavetable +//0x0004_3400 <-----------------ROM END-----------------> + +//dipsw bank +reg [7:0] DIPSW1 = 8'hFF; +reg [7:0] DIPSW2 = 8'h42; +reg [7:0] DIPSW3 = 8'hFF; +reg [7:0] CORECONFIG = 8'h00; + +assign o_VIDEO_ROT = CORECONFIG[1:0] == 2'd0; + + + +/////////////////////////////////////////////////////////// +////// SDRAM/BRAM DOWNLOADER INTERFACE +//// + +//download complete +reg rom_download_done = 1'b0; + +//enables +reg prog_sdram_en = 1'b0; +reg prog_bram_en = 1'b0; + +//sdram control +wire sdram_init; +reg prog_sdram_wr_busy = 1'b0; +wire prog_sdram_ack; +assign ioctl_wait = sdram_init | prog_sdram_wr_busy; +//assign ioctl_wait = 1'b0; + +reg [1:0] prog_sdram_bank_sel; +reg [21:0] prog_sdram_addr; +reg [1:0] prog_sdram_mask; +reg [15:0] prog_sdram_din_buf; + +//bram control +reg [13:0] prog_bram_addr; +reg [7:0] prog_bram_din_buf; +reg prog_bram_wr; +reg [3:0] prog_bram_csreg; + +wire prog_bram_wave2_cs = prog_bram_csreg[3]; +wire prog_bram_wave1_cs = prog_bram_csreg[2]; +wire prog_bram_bootrom_cs = prog_bram_csreg[1]; +wire prog_bram_sndrom_cs = prog_bram_csreg[0]; +assign debug = rom_download_done; + +//state machine +always @(posedge i_EMU_CLK72M) begin + if((i_EMU_INITRST | rom_download_done) == 1'b1) begin + if(i_EMU_INITRST) rom_download_done <= 1'b0; + + //enables + prog_sdram_en <= 1'b0; + prog_bram_en <= 1'b0; + + //sdram + prog_sdram_addr <= 22'h3F_FFFF; + prog_sdram_wr_busy <= 1'b0; + prog_sdram_bank_sel <= 2'd0; + prog_sdram_mask <= 2'b00; + prog_sdram_din_buf <= 16'hFFFF; + + //bram + prog_bram_din_buf <= 8'hFF; + prog_bram_addr <= 14'h3FFF; + prog_bram_wr <= 1'b0; + prog_bram_csreg <= 4'b0000; + + if(ioctl_index == 16'd254) begin //DIP SWITCH + if(ioctl_wr == 1'b1) begin + if(ioctl_addr[2:0] == 3'd0) DIPSW1 <= ioctl_data; + else if(ioctl_addr[2:0] == 3'd1) DIPSW2 <= ioctl_data; + else if(ioctl_addr[2:0] == 3'd2) DIPSW3 <= ioctl_data; + else if(ioctl_addr[2:0] == 3'd3) CORECONFIG <= ioctl_data; + end + end + end + else begin + // ROM DATA UPLOAD + if(ioctl_index == 16'd0) begin //ROM DATA + // BLOCK RAM REGION + if(ioctl_addr[19:12] > 8'h4_0 ) begin + prog_sdram_en <= 1'b0; + prog_bram_en <= 1'b1; + + if(ioctl_wr == 1'b1) begin + prog_bram_din_buf <= ioctl_data; + prog_bram_addr <= ioctl_addr[13:0] - 14'h1000; + prog_bram_wr <= 1'b1; + + if(ioctl_addr[13:12] == 2'd1 || ioctl_addr[13:12] == 2'd2) prog_bram_csreg <= 4'b0001; //sound rom + else begin + if(ioctl_addr[9:8] == 2'd0 || ioctl_addr[9:8] == 2'd1) prog_bram_csreg <= 4'b0010; + else if(ioctl_addr[9:8] == 2'd2) prog_bram_csreg <= 4'b0100; //wavetable 1(400-A 01) + else if(ioctl_addr[9:8] == 2'd3) prog_bram_csreg <= 4'b1000; + end + end + else begin + prog_bram_wr <= 1'b0; + end + end + + // SDRAM REGION + else begin + prog_sdram_en <= 1'b1; + prog_bram_en <= 1'b0; + + if(prog_sdram_wr_busy == 1'b0) begin + if(ioctl_wr == 1'b1) begin + prog_sdram_wr_busy <= 1'b1; + prog_sdram_bank_sel <= 2'd0; + prog_sdram_addr <= {4'b00_00, ioctl_addr[18:1]}; + prog_sdram_din_buf <= {ioctl_data, ioctl_data}; + prog_sdram_mask <= ioctl_addr[0] ? 2'b10 : 2'b01; //lo : hi(68k big endian) + end + end + else begin + if(prog_sdram_ack == 1'b1) begin + prog_sdram_wr_busy <= 1'b0; + end + end + end + end + + else if(ioctl_index == 16'd254) begin //DIP SWITCH + prog_sdram_en <= 1'b0; + prog_bram_en <= 1'b0; + rom_download_done <= 1'b1; + end + end +end + + + +/////////////////////////////////////////////////////////// +////// BUBBLE MEMORY(BOOTLOADER) +//// + +wire [17:0] bubrom_addr; +wire bubrom_boot_cs; +wire [15:0] bubrom_boot_q; +reg [7:0] prog_bram_din_hi; +always @(posedge i_EMU_CLK72M) if(prog_bram_wr & ~prog_bram_addr[0]) prog_bram_din_hi <= prog_bram_din_buf; + +BubSys_PROM_DC #(.AW(8), .DW(16), .simhexfile()) u_bootrom_lo ( + .i_PROG_CLK (i_EMU_CLK72M ), + .i_PROG_ADDR (prog_bram_addr[8:1] ), + .i_PROG_DIN ({prog_bram_din_hi, prog_bram_din_buf}), + .i_PROG_CS (prog_bram_bootrom_cs ), + .i_PROG_WR (prog_bram_wr & prog_bram_addr[0]), + + .i_MCLK (i_EMU_CLK48M ), + .i_ADDR (bubrom_addr[7:0] ), + .o_DOUT (bubrom_boot_q ), + .i_RD (bubrom_boot_cs ) +); + + + +/////////////////////////////////////////////////////////// +////// SDRAM CONTROLLER +//// + +wire [21:0] ba0_addr; +wire [21:0] ba1_addr; +wire [21:0] ba2_addr; +wire [3:0] rd; +wire [3:0] ack; +wire [3:0] dst; +wire [3:0] rdy; +wire [15:0] data_read; + +reg [8:0] rfsh_cntr; +wire rfsh = rfsh_cntr == 9'd384; +always @(posedge i_EMU_CLK72M) begin + if(i_EMU_INITRST) begin + rfsh_cntr <= 9'd0; + end + else begin if(o_VIDEO_CEN) begin + if(rfsh_cntr < 9'd384) rfsh_cntr <= rfsh_cntr + 9'd1; + else rfsh_cntr <= 9'd0; + end end +end + +jtframe_sdram64 #(.HF(0)) sdram_controller ( + .rst (i_EMU_INITRST ), + .clk (i_EMU_CLK72M ), + .init (sdram_init ), + + .ba0_addr (ba0_addr ), + .ba1_addr (ba1_addr ), + .ba2_addr (22'h00_0000 ), + .ba3_addr (22'h00_0000 ), + .rd ({3'b000, rd[0]} ), + .wr (4'b0000 ), + .din (prog_sdram_din_buf ), + .din_m (2'b00 ), + + .prog_en (prog_sdram_en ), + .prog_addr (prog_sdram_addr ), + .prog_rd (1'b0 ), + .prog_wr (prog_sdram_wr_busy ), + .prog_din (prog_sdram_din_buf ), + .prog_din_m (prog_sdram_mask ), + .prog_ba (prog_sdram_bank_sel ), + .prog_dst ( ), + .prog_dok ( ), + .prog_rdy ( ), + .prog_ack (prog_sdram_ack ), + + .rfsh (rfsh ), + + .ack (ack ), + .dst (dst ), + .dok ( ), + .rdy (rdy ), + .dout (data_read ), + + .sdram_dq (sdram_dq ), + .sdram_a (sdram_a ), + .sdram_dqml (sdram_dqml ), + .sdram_dqmh (sdram_dqmh ), + .sdram_ba (sdram_ba ), + .sdram_nwe (sdram_nwe ), + .sdram_ncas (sdram_ncas ), + .sdram_nras (sdram_nras ), + .sdram_ncs (sdram_ncs ), + .sdram_cke (sdram_cke ) +); + + + +/////////////////////////////////////////////////////////// +////// ROM SLOTS +//// + +wire bubrom_rd; +wire bubrom_page_cs; +wire [15:0] bubrom_page_q; + +reg slot0_rdrq_z, slot0_rdrq_zz; //48MHz -> 72MHz +always @(posedge i_EMU_CLK72M) slot0_rdrq_z <= bubrom_rd & bubrom_page_cs; +always @(posedge i_EMU_CLK72M) slot0_rdrq_zz <= slot0_rdrq_z; + +wire slot0_ok; +reg [3:0] slot0_ok_dly; +always @(posedge i_EMU_CLK72M) begin + slot0_ok_dly[0] <= slot0_ok; + slot0_ok_dly[3:1] <= slot0_ok_dly[2:0]; +end +reg slot0_ok_z, slot0_ok_zz; //72MHz -> 48MHz +always @(posedge i_EMU_CLK48M) slot0_ok_z <= |{slot0_ok_dly[3:0]}; +always @(posedge i_EMU_CLK48M) slot0_ok_zz <= slot0_ok_z; + +jtframe_rom_2slots #( + // Slot 0: Bubble Memory user pages + .SLOT0_AW (18 ), + .SLOT0_DW (16 ), + .SLOT0_OFFSET (22'h00_0000 ), + + // Slot 1: No ROM + .SLOT1_AW (4 ), + .SLOT1_DW (16 ), + .SLOT1_OFFSET (22'h02_0800 ) +) bank0 ( + .rst (~rom_download_done ), + .clk (i_EMU_CLK72M ), + + .slot0_cs (slot0_rdrq_zz ), + .slot1_cs (1'b0 ), + + .slot0_ok (slot0_ok ), + .slot1_ok ( ), + + .slot0_addr (bubrom_addr ), + .slot1_addr (4'b0000 ), + + .slot0_dout (bubrom_page_q ), + .slot1_dout ( ), + + .sdram_addr (ba0_addr ), + .sdram_req (rd[0] ), + .sdram_ack (ack[0] ), + .data_dst (dst[0] ), + .data_rdy (rdy[0] ), + .data_read (data_read ) +); + + + +/////////////////////////////////////////////////////////// +////// INPUT MAPPER +//// + +/* + MiSTer joystick(SNES) + bit + 0 right + 1 left + 2 down + 3 up + 4 service(SELECT) + 5 coin(R) + 6 start(START) + 7 btn1(A) + 8 btn2(B) + 9 btn3(X) +*/ + +wire [7:0] IN0, IN1, IN2; + +//System control +assign IN0[0] = ~i_JOYSTICK0[5]; //p1 coin +assign IN0[1] = ~i_JOYSTICK1[5]; //p2 coin +assign IN0[2] = ~i_JOYSTICK0[4]; //service +assign IN0[3] = ~i_JOYSTICK0[6]; //p1 start +assign IN0[4] = ~i_JOYSTICK1[6]; //p2 start +assign IN0[5] = 1'b1; +assign IN0[6] = 1'b1; +assign IN0[7] = 1'b1; + +//Player 1 control +assign IN1[0] = ~i_JOYSTICK0[1]; +assign IN1[1] = ~i_JOYSTICK0[0]; +assign IN1[2] = ~i_JOYSTICK0[3]; +assign IN1[3] = ~i_JOYSTICK0[2]; +assign IN1[4] = ~i_JOYSTICK0[7]; +assign IN1[5] = ~i_JOYSTICK0[8]; +assign IN1[6] = ~i_JOYSTICK0[9]; +assign IN1[7] = 1'b1; + +//Player 2 control +assign IN2[0] = ~i_JOYSTICK1[1]; +assign IN2[1] = ~i_JOYSTICK1[0]; +assign IN2[2] = ~i_JOYSTICK1[3]; +assign IN2[3] = ~i_JOYSTICK1[2]; +assign IN2[4] = ~i_JOYSTICK1[7]; //btn 1 +assign IN2[5] = ~i_JOYSTICK1[8]; //btn 2 +assign IN2[6] = ~i_JOYSTICK1[9]; +assign IN2[7] = 1'b1; + + + +/////////////////////////////////////////////////////////// +////// GAME BOARD +//// + +reg [15:0] bubrom_data; +reg bubrom_data_rdy; + +always @(*) begin + bubrom_data = 16'h0000; + if(bubrom_boot_cs) bubrom_data = bubrom_boot_q; + else if(bubrom_page_cs) bubrom_data = bubrom_page_q; + + bubrom_data_rdy = 1'b0; + if(bubrom_boot_cs) bubrom_data_rdy = 1'b1; + else if(bubrom_page_cs) bubrom_data_rdy = slot0_ok_zz; +end + +BubSys_top gameboard_top ( + .i_EMU_CLK72M (i_EMU_CLK72M ), + .i_EMU_CLK57M (i_EMU_CLK57M ), + .i_EMU_CLK48M (i_EMU_CLK48M ), + .i_EMU_INITRST_n (~i_EMU_INITRST ), + .i_EMU_SOFTRST_n (~i_EMU_SOFTRST & rom_download_done), + + .o_HBLANK (o_HBLANK ), + .o_VBLANK (o_VBLANK ), + .o_HSYNC (o_HSYNC ), + .o_VSYNC (o_VSYNC ), + .o_VIDEO_CEN (o_VIDEO_CEN ), + .o_VIDEO_DEN (o_VIDEO_DEN ), + + .o_VIDEO_R (o_VIDEO_R ), + .o_VIDEO_G (o_VIDEO_G ), + .o_VIDEO_B (o_VIDEO_B ), + + .i_VOL (i_VOL ), + .o_SND_L (o_SND_L ), + .o_SND_R (o_SND_R ), + + .i_MAINCPU_SWAPIRQ (i_MAINCPU_SWAPIRQ ), + .o_BMC_ACC (o_BMC_ACC ), + + .i_IN0 (IN0 ), + .i_IN1 (IN1 ), + .i_IN2 (IN2 ), + .i_DIPSW1 (DIPSW1 ), + .i_DIPSW2 (DIPSW2 ), + .i_DIPSW3 (DIPSW3 ), + + //DRAM request, 48MHz + .o_BUBROM_BOOT_CS (bubrom_boot_cs ), + .o_BUBROM_PAGE_CS (bubrom_page_cs ), + .o_BUBROM_ADDR (bubrom_addr ), + .i_BUBROM_DATA (bubrom_data ), + .o_BUBROM_RD (bubrom_rd ), + .i_BUBROM_DATA_RDY (bubrom_data_rdy ), + + //PROM programming + .i_EMU_PROM_ADDR (prog_bram_addr ), + .i_EMU_PROM_DATA (prog_bram_din_buf ), + .i_EMU_PROM_WR (prog_bram_wr ), + .i_EMU_PROM_WAVE1_CS (prog_bram_wave1_cs ), + .i_EMU_PROM_WAVE2_CS (prog_bram_wave2_cs ), + .i_EMU_PROM_SNDROM_CS (prog_bram_sndrom_cs ) +); + +endmodule \ No newline at end of file diff --git a/rtl/BubSys_sound.v b/rtl/BubSys_sound.v new file mode 100644 index 0000000..2577fda --- /dev/null +++ b/rtl/BubSys_sound.v @@ -0,0 +1,511 @@ +module BubSys_sound ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK3M58_PCEN, + input wire i_EMU_CLK3M58_NCEN, + input wire i_EMU_CLK1M79_PCEN, + input wire i_EMU_CLK1M79_NCEN, + + input wire i_EMU_INITRST_n, + input wire i_EMU_SOFTRST_n, + + //reset control by the sound CPU + output wire o_MAINCPU_RSTCTRL, + input wire i_MAINCPU_RSTSTAT, + + input wire i_SND_NMI, + input wire i_SND_INT, + input wire [7:0] i_SND_CODE, + input wire i_SND_DMA_BR, + output wire o_SND_DMA_BG_n, + input wire [14:1] i_SND_DMA_ADDR, + input wire [7:0] i_SND_DMA_DO, + output wire [7:0] o_SND_DMA_DI, + input wire i_SND_DMA_RnW, + input wire i_SND_DMA_LDS_n, + input wire i_SND_DMA_SNDRAM_CS, + + output wire o_TIMER_IRQ, + + input wire [15:0] i_VOL, + output wire signed [15:0] o_SND_R, o_SND_L, + + input wire i_EMU_PROM_CLK, + input wire [13:0] i_EMU_PROM_ADDR, + input wire [7:0] i_EMU_PROM_DATA, + input wire i_EMU_PROM_WR, + + input wire i_EMU_PROM_WAVE1_CS, + input wire i_EMU_PROM_WAVE2_CS, + input wire i_EMU_PROM_SNDROM_CS +); + + + +/////////////////////////////////////////////////////////// +////// CLOCK AND RESET +//// + +wire sndcpu_rst = ~i_EMU_INITRST_n | ~i_EMU_SOFTRST_n; +wire mclk = i_EMU_MCLK; +wire clk3m58_pcen = i_EMU_CLK3M58_PCEN; +wire clk3m58_ncen = i_EMU_CLK3M58_NCEN; +wire clk1m79_pcen = i_EMU_CLK1M79_PCEN; +wire clk1m79_ncen = i_EMU_CLK1M79_NCEN; + + + + +/////////////////////////////////////////////////////////// +////// SOUND CPU +//// + +wire [15:0] sndcpu_addr; +reg [7:0] sndbus_di; +wire [7:0] sndcpu_do; +wire sndcpu_wr_n, sndcpu_rd_n; + +wire sndcpu_mreq_n; +wire sndcpu_iorq_n; +wire sndcpu_rfsh_n; +reg sndcpu_int_n; +wire sndcpu_nmi_n; +wire sndcpu_br_n; + +T80pa u_sndcpu ( + .RESET_n (~sndcpu_rst ), + .CLK (mclk ), + .CEN_p (clk1m79_pcen ), + .CEN_n (clk1m79_ncen ), + .WAIT_n (1'b1 ), + .INT_n (sndcpu_int_n ), + .NMI_n (sndcpu_nmi_n ), + .RD_n (sndcpu_rd_n ), + .WR_n (sndcpu_wr_n ), + .A (sndcpu_addr ), + .DI (sndbus_di ), + .DO (sndcpu_do ), + .IORQ_n (sndcpu_iorq_n ), + .M1_n ( ), + .MREQ_n (sndcpu_mreq_n ), + .BUSRQ_n (sndcpu_br_n ), + .BUSAK_n (o_SND_DMA_BG_n ), + .RFSH_n (sndcpu_rfsh_n ), + .out0 (1'b0 ), //????? + .HALT_n ( ) +); + + + +/////////////////////////////////////////////////////////// +////// DMA +//// + +reg [1:0] snd_dma_br_sync; +assign sndcpu_br_n = ~snd_dma_br_sync[1]; +always @(posedge mclk) begin + snd_dma_br_sync[0] <= i_SND_DMA_BR; + snd_dma_br_sync[1] <= snd_dma_br_sync[0]; +end + +//68k bus control synchronizer/negedge detector <- CDC!! +reg [3:0] snd_dma_wr_n_sync, snd_dma_rd_n_sync; +reg snd_dma_wrrq_n, snd_dma_rdrq_n; +always @(posedge mclk) begin + //synchronize read/write strobe only, the address/data is guaranteed to be stable before the strobe is asserted + snd_dma_wr_n_sync[0] <= i_SND_DMA_RnW | i_SND_DMA_LDS_n; + snd_dma_wr_n_sync[3:1] <= snd_dma_wr_n_sync[2:0]; + + snd_dma_rd_n_sync[0] <= ~i_SND_DMA_RnW | i_SND_DMA_LDS_n; + snd_dma_rd_n_sync[3:1] <= snd_dma_rd_n_sync[2:0]; + + snd_dma_wrrq_n <= ~(snd_dma_wr_n_sync[3] && !snd_dma_wr_n_sync[2]); + snd_dma_rdrq_n <= ~(snd_dma_rd_n_sync[3] && !snd_dma_rd_n_sync[2]); +end + +wire is_dma_acc = ~o_SND_DMA_BG_n; +wire [15:0] sndbus_addr = is_dma_acc ? {2'b01, i_SND_DMA_ADDR} : sndcpu_addr; +wire [7:0] sndbus_do = is_dma_acc ? i_SND_DMA_DO : sndcpu_do; +wire sndbus_wr_n = is_dma_acc ? snd_dma_wrrq_n : sndcpu_wr_n; +wire sndbus_rd_n = is_dma_acc ? snd_dma_rdrq_n : sndcpu_rd_n; +wire sndbus_mreq_n = is_dma_acc ? ~i_SND_DMA_SNDRAM_CS : sndcpu_mreq_n; +wire sndbus_rfsh_n = is_dma_acc ? 1'b1 : sndcpu_rfsh_n; +assign o_SND_DMA_DI = sndbus_di; + + +/////////////////////////////////////////////////////////// +////// SOUND IRQ +//// + +reg [3:0] snd_int_sync; //CDC!!! +reg [1:0] snd_nmi_sync; +assign sndcpu_nmi_n = ~snd_nmi_sync[1]; +always @(posedge mclk) begin + snd_int_sync[0] <= i_SND_INT; + snd_int_sync[3:1] <= snd_int_sync[2:0]; + + if(sndcpu_rst | ~sndcpu_iorq_n) sndcpu_int_n <= 1'b1; + else begin + if(snd_int_sync[3:2] == 2'b01) sndcpu_int_n <= 1'b0; + end + + snd_nmi_sync[0] <= i_SND_NMI; + snd_nmi_sync[1] <= snd_nmi_sync[0]; +end + + + +/////////////////////////////////////////////////////////// +////// ADDRESS DECODER +//// + +reg sndrom_rd, sndram_cs, voiceram_cs, wave1_wr, wave2_wr; +reg vlmctrl_wr, sndcode_rd, wave1_tg, wave2_tg, psg1_cs, psg2_cs, fltctrl_wr; + +always @(*) begin + sndrom_rd = 1'b0; + sndram_cs = 1'b0; + voiceram_cs = 1'b0; + wave1_wr = 1'b0; + wave2_wr = 1'b0; + + vlmctrl_wr = 1'b0; + sndcode_rd = 1'b0; + wave1_tg = 1'b0; + wave2_tg = 1'b0; + psg1_cs = 1'b0; + psg2_cs = 1'b0; + fltctrl_wr = 1'b0; + + //1st LS138 + if(!sndbus_mreq_n && sndbus_rfsh_n) begin + case(sndbus_addr[15:13]) + 3'd0: sndrom_rd = 1'b1; + 3'd2: sndram_cs = 1'b1; + 3'd3: sndram_cs = 1'b1; + 3'd4: voiceram_cs = 1'b1; + 3'd5: wave1_wr = 1'b1; + 3'd6: wave2_wr = 1'b1; + default: ; + endcase + end + + //2nd LS138 + if(!sndbus_mreq_n && sndbus_rfsh_n && sndbus_addr[15:13] == 3'd7) begin + case(sndbus_addr[2:0]) + 3'd0: vlmctrl_wr = 1'b1; + 3'd1: sndcode_rd = 1'b1; + 3'd3: wave1_tg = 1'b1; + 3'd4: wave2_tg = 1'b1; + 3'd5: psg2_cs = 1'b1; + 3'd6: psg1_cs = 1'b1; + 3'd7: fltctrl_wr = 1'b1; + default: ; + endcase + end +end + + + +/////////////////////////////////////////////////////////// +////// SOUND PROGRAM SPACE +//// + +wire [7:0] sndrom_q; +BubSys_PROM_DC #(.AW(13), .DW(8), .simhexfile()) u_sndrom ( + .i_PROG_CLK (i_EMU_PROM_CLK ), + .i_PROG_ADDR (i_EMU_PROM_ADDR[12:0] ), + .i_PROG_DIN (i_EMU_PROM_DATA ), + .i_PROG_CS (i_EMU_PROM_SNDROM_CS ), + .i_PROG_WR (i_EMU_PROM_WR ), + + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (sndbus_addr[12:0] ), + .o_DOUT (sndrom_q ), + .i_RD (sndrom_rd ) +); + +wire [7:0] sndram_q; +BubSys_SRAM #(.AW(14), .DW(8), .simhexfile()) u_sndram ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (sndbus_addr[13:0] ), + .i_DIN (sndbus_do ), + .o_DOUT (sndram_q ), + .i_WR (sndram_cs && !sndbus_wr_n ), + .i_RD (sndram_cs && !sndbus_rd_n ) +); + + + +/////////////////////////////////////////////////////////// +////// SOUND TIMER +//// + +//14.31818MHz clocked four LS393 half blocks, take [13:0] MSBs +reg [12:0] snd_timer; +always @(posedge mclk) begin + //if(sndcpu_rst) snd_timer <= 13'd0; //doesn't have reset originally + //else begin + if(clk1m79_ncen) snd_timer <= snd_timer == 13'd8191 ? 13'd0 : snd_timer + 13'd1; + //end end +end + +assign o_TIMER_IRQ = snd_timer[12]; + + + +/////////////////////////////////////////////////////////// +////// VLM5030 +//// + +//VLM5030 control latches +reg [7:0] vlm_param_latch; //LS373 transparent latch +reg [3:0] vlm_ctrl_latch = 4'b0010; //{vlm_rst, vlm_start, /vlm_param_latch_oe, vlm_param_latch_en} + +always @(posedge mclk) begin + if(vlmctrl_wr && !sndbus_wr_n) vlm_ctrl_latch <= sndbus_addr[6:3]; + + if(vlm_ctrl_latch[0]) vlm_param_latch <= sndbus_do; +end + +//VLM5030 side wires +wire vlm_rst = vlm_ctrl_latch[3]; +wire vlm_st = vlm_ctrl_latch[2]; +wire vlm_busy; + +wire [15:0] vlm_addr; +wire vlm_me_n; //Memory Enable +wire signed [9:0] vlm_sound; + +//VLM5030 command rom +wire [10:0] voiceram_addr = voiceram_cs ? sndbus_addr[10:0] : vlm_addr[10:0]; +wire [7:0] voiceram_q; +BubSys_SRAM #(.AW(11), .DW(8), .simhexfile()) u_voiceram ( + .i_MCLK (i_EMU_MCLK ), + .i_ADDR (voiceram_addr ), + .i_DIN (vlm_param_latch ), + .o_DOUT (voiceram_q ), + .i_WR (voiceram_cs && !sndbus_wr_n), + .i_RD (1'b1 ) +); + + +//VLM5030 bus +wire [7:0] vlm_di = vlm_me_n ? vlm_param_latch : voiceram_q; //negative logic + +//main chip +vlm5030_gl u_vlm ( + .i_clk (i_EMU_MCLK ), + .i_oscen (clk3m58_pcen ), + .i_rst (vlm_rst ), + .i_start (vlm_st ), + .i_vcu (1'b0 ), + .i_tst1 (1'b0 ), + .i_d (vlm_di ), + .o_a (vlm_addr ), + .o_me_l (vlm_me_n ), + .o_bsy (vlm_busy ), + .o_audio (vlm_sound ) +); + + + +/////////////////////////////////////////////////////////// +////// AY-3-8910 +//// + +wire [7:0] psg1_q, psg2_q; +wire [7:0] psg1_iob_out, psg2_ioa_out, psg2_iob_out; +wire [9:0] psg1_sound, psg2_sound; +assign o_MAINCPU_RSTCTRL = ~psg1_iob_out[7]; + +//MAME PSG1(4F on the board) +jt49_bus u_psg1 ( + .rst_n (~sndcpu_rst ), + .clk (mclk ), + .clk_en (clk1m79_pcen ), + .bdir (psg1_cs & (~sndcpu_rd_n | ~sndcpu_wr_n) & ~sndbus_addr[7]), + .bc1 (psg1_cs & (~sndcpu_rd_n | ~sndcpu_wr_n) & ~sndbus_addr[8]), + .din (sndbus_do ), + + .sel (1'b1 ), + .dout (psg1_q ), + .sound (psg1_sound ), + .A ( ), + .B ( ), + .C ( ), + .sample ( ), + + .IOA_in ({~i_MAINCPU_RSTSTAT, 1'b1, vlm_busy, 1'b1, snd_timer[12:9]}), + .IOA_out ( ), + .IOA_oe ( ), + + .IOB_in ( ), + .IOB_out (psg1_iob_out ), + .IOB_oe ( ) +); + +//MAME PSG2(4H on the board) +jt49_bus u_psg2 ( + .rst_n (~sndcpu_rst ), + .clk (mclk ), + .clk_en (clk1m79_pcen ), + .bdir (psg2_cs & (~sndcpu_rd_n | ~sndcpu_wr_n) & ~sndbus_addr[9]), + .bc1 (psg2_cs & (~sndcpu_rd_n | ~sndcpu_wr_n) & ~sndbus_addr[10]), + .din (sndbus_do ), + + .sel (1'b1 ), + .dout (psg2_q ), + .sound (psg2_sound ), + .A ( ), + .B ( ), + .C ( ), + .sample ( ), + + .IOA_in ( ), + .IOA_out (psg2_ioa_out ), + .IOA_oe ( ), + + .IOB_in ( ), + .IOB_out (psg2_iob_out ), + .IOB_oe ( ) +); + + + +/////////////////////////////////////////////////////////// +////// K005289 WAVETABLE +//// + +wire [4:0] prom1_addr, prom2_addr; +wire [3:0] prom1_q, prom2_q; +wire [7:0] wave1_sound, wave2_sound; + +//wavetable address generator +K005289 u_K005289( + .i_RST_n (~sndcpu_rst ), + .i_CLK (mclk ), + .i_CEN (clk3m58_pcen ), + + .i_LD1 (wave1_wr ), + .i_TG1 (wave1_tg ), + + .i_LD2 (wave2_wr ), + .i_TG2 (wave2_tg ), + + .i_COUNTER (sndbus_addr[11:0] ), + + .o_Q1 (prom1_addr ), + .o_Q2 (prom2_addr ) +); + +//wavetable ROMs +BubSys_PROM_DC #(.AW(8), .DW(4), .simhexfile()) u_waverom1 ( + .i_PROG_CLK (i_EMU_PROM_CLK ), + .i_PROG_ADDR (i_EMU_PROM_ADDR[7:0] ), + .i_PROG_DIN (i_EMU_PROM_DATA[3:0] ), + .i_PROG_CS (i_EMU_PROM_WAVE1_CS ), + .i_PROG_WR (i_EMU_PROM_WR ), + + .i_MCLK (i_EMU_MCLK ), + .i_ADDR ({psg2_ioa_out[7:5], prom1_addr}), + .o_DOUT (prom1_q ), + .i_RD (1'b1 ) +); + +BubSys_PROM_DC #(.AW(8), .DW(4), .simhexfile()) u_waverom2 ( + .i_PROG_CLK (i_EMU_PROM_CLK ), + .i_PROG_ADDR (i_EMU_PROM_ADDR[7:0] ), + .i_PROG_DIN (i_EMU_PROM_DATA[3:0] ), + .i_PROG_CS (i_EMU_PROM_WAVE2_CS ), + .i_PROG_WR (i_EMU_PROM_WR ), + + .i_MCLK (i_EMU_MCLK ), + .i_ADDR ({psg2_iob_out[7:5], prom2_addr}), + .o_DOUT (prom2_q ), + .i_RD (1'b1 ) +); + +//volume LUT, replaces 4066 switches +BubSys_PROM #(.AW(8), .DW(8), .simhexfile("./rtl/ipcores/vollut.txt")) u_vollut1 ( + .i_MCLK (i_EMU_MCLK ), + + .i_PROG_ADDR ( ), + .i_PROG_DIN ( ), + .i_PROG_CS (1'b1 ), + .i_PROG_WR ( ), + + .i_ADDR ({psg2_ioa_out[3:0], prom1_q}), + .o_DOUT (wave1_sound ), + .i_RD (1'b1 ) +); + +BubSys_PROM #(.AW(8), .DW(8), .simhexfile("./rtl/ipcores/vollut.txt")) u_vollut2 ( + .i_MCLK (i_EMU_MCLK ), + + .i_PROG_ADDR ( ), + .i_PROG_DIN ( ), + .i_PROG_CS (1'b1 ), + .i_PROG_WR ( ), + + .i_ADDR ({psg2_iob_out[3:0], prom2_q}), + .o_DOUT (wave2_sound ), + .i_RD (1'b1 ) +); + + + +/////////////////////////////////////////////////////////// +////// SOUND MIXER +//// + +/* + psg_sound = 10-bit unsigned + vlm_sound = 10-bit signed + wavex_sound = 8-bit(normally 7-bit) unsigned +*/ + +wire signed [9:0] psg1_sound_ac, psg2_sound_ac; +jt49_dcrm2 #(.sw(10)) psg1_accap (.clk(mclk), .cen(clk3m58_pcen), .rst(sndcpu_rst), .din(psg1_sound), .dout(psg1_sound_ac)); +jt49_dcrm2 #(.sw(10)) psg2_accap (.clk(mclk), .cen(clk3m58_pcen), .rst(sndcpu_rst), .din(psg2_sound), .dout(psg2_sound_ac)); + +wire signed [7:0] wave1_sound_ac, wave2_sound_ac; +jt49_dcrm2 #(.sw(8)) wave1_accap (.clk(mclk), .cen(clk3m58_pcen), .rst(sndcpu_rst), .din(wave1_sound), .dout(wave1_sound_ac)); +jt49_dcrm2 #(.sw(8)) wave2_accap (.clk(mclk), .cen(clk3m58_pcen), .rst(sndcpu_rst), .din(wave2_sound), .dout(wave2_sound_ac)); + +reg signed [13:0] psg1_sound_vol, psg2_sound_vol; +reg signed [13:0] vlm_sound_vol; +reg signed [13:0] wave1_sound_vol, wave2_sound_vol; +reg signed [15:0] final_sound; +assign o_SND_L = final_sound; +assign o_SND_R = final_sound; + +always @(posedge mclk) begin + psg1_sound_vol <= psg1_sound_ac * (6'sd8 + $signed(i_VOL[11:8])); + psg2_sound_vol <= psg2_sound_ac * (6'sd12 + $signed(i_VOL[15:12])); + vlm_sound_vol <= vlm_sound * (6'sd10 + $signed(i_VOL[7:4])); + wave1_sound_vol <= wave1_sound_ac * (6'sd8 + $signed(i_VOL[3:0])); + wave2_sound_vol <= wave2_sound_ac * (6'sd8 + $signed(i_VOL[3:0])); + final_sound <= (psg1_sound_vol + psg2_sound_vol + vlm_sound_vol + wave1_sound_vol + wave2_sound_vol) * 3'sd2; +end + + + +/////////////////////////////////////////////////////////// +////// BUS MUX +//// + +always @(*) begin + sndbus_di = 8'hFF; + + if(sndrom_rd) begin + sndbus_di = sndrom_q; + end + else if(sndram_cs) sndbus_di = sndram_q; + else if(sndcode_rd) sndbus_di = i_SND_CODE; + else if(psg1_cs) sndbus_di = psg1_q; + else if(psg2_cs) sndbus_di = psg2_q; +end + + + +endmodule \ No newline at end of file diff --git a/rtl/BubSys_top.v b/rtl/BubSys_top.v new file mode 100644 index 0000000..ba33b05 --- /dev/null +++ b/rtl/BubSys_top.v @@ -0,0 +1,351 @@ +module BubSys_top ( + input wire i_EMU_CLK72M, + input wire i_EMU_CLK57M, + input wire i_EMU_CLK48M, + input wire i_EMU_INITRST_n, + input wire i_EMU_SOFTRST_n, + + //video syncs + output reg o_HBLANK, //NOT the original blanking signal + output wire o_VBLANK, + output wire o_HSYNC, + output wire o_VSYNC, + output wire o_VIDEO_CEN, //video clock enable + output wire o_VIDEO_DEN, //video data enable + + output wire [4:0] o_VIDEO_R, + output wire [4:0] o_VIDEO_G, + output wire [4:0] o_VIDEO_B, + + //sound + input wire [15:0] i_VOL, + output wire signed [15:0] o_SND_L, + output wire signed [15:0] o_SND_R, + + //configuration + input wire i_MAINCPU_SWAPIRQ, + output wire o_BMC_ACC, + + //user inputs + input wire [7:0] i_IN0, i_IN1, i_IN2, i_DIPSW1, i_DIPSW2, i_DIPSW3, + + //SDRAM requests + output wire o_BUBROM_BOOT_CS, o_BUBROM_PAGE_CS, + output wire [17:0] o_BUBROM_ADDR, + input wire [15:0] i_BUBROM_DATA, + output wire o_BUBROM_RD, + input wire i_BUBROM_DATA_RDY, + + //PROM programming + input wire [13:0] i_EMU_PROM_ADDR, + input wire [7:0] i_EMU_PROM_DATA, + input wire i_EMU_PROM_WR, + input wire i_EMU_PROM_WAVE1_CS, + input wire i_EMU_PROM_WAVE2_CS, + input wire i_EMU_PROM_SNDROM_CS +); + + +/////////////////////////////////////////////////////////// +////// CLOCK DIVIDER +//// + +/* + 0 4 8 12 16 20 + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| +*/ + +reg [3:0] clk18m_cen_sr = 4'd1; +reg [7:0] clk9m_cen_sr = 8'd1; +reg [11:0] clk6m_cen_sr = 12'd1; +always @(posedge i_EMU_CLK72M) begin + if(!i_EMU_INITRST_n) begin + clk18m_cen_sr <= 4'd1; + clk9m_cen_sr <= 8'd1; + clk6m_cen_sr <= 12'd1; + end + else begin + clk18m_cen_sr[3:1] <= clk18m_cen_sr[2:0]; + clk18m_cen_sr[0] <= clk18m_cen_sr[3]; + clk9m_cen_sr[7:1] <= clk9m_cen_sr[6:0]; + clk9m_cen_sr[0] <= clk9m_cen_sr[7]; + clk6m_cen_sr[11:1] <= clk6m_cen_sr[10:0]; + clk6m_cen_sr[0] <= clk6m_cen_sr[11]; + end +end + +//clock enables, generated by shift register(for better performance); +wire clk18m_ncen = clk18m_cen_sr[3]; +wire clk9m_ncen = clk9m_cen_sr[3]; +wire clk9m_pcen = clk9m_cen_sr[7]; +wire clk6m_ncen = clk6m_cen_sr[7]; +wire clk6m_pcen = clk6m_cen_sr[11]; + +//sound clock +reg [4:0] snd_cen_cntr = 5'd0; +reg clk3m58_ncen, clk3m58_pcen; +reg clk1m79_ncen, clk1m79_pcen; +always @(posedge i_EMU_CLK57M) begin + if(!i_EMU_INITRST_n) snd_cen_cntr <= 5'd0; + else snd_cen_cntr <= snd_cen_cntr == 5'd31 ? 5'd0 : snd_cen_cntr + 5'd1; + + if(!i_EMU_INITRST_n) begin + clk3m58_pcen <= 1'b0; + clk3m58_ncen <= 1'b0; + clk1m79_pcen <= 1'b0; + clk1m79_ncen <= 1'b0; + end + else begin + clk3m58_pcen <= snd_cen_cntr[3:0] == 4'd6; + clk3m58_ncen <= snd_cen_cntr[3:0] == 4'd14; + clk1m79_pcen <= snd_cen_cntr == 5'd14; + clk1m79_ncen <= snd_cen_cntr == 5'd30; + end +end + +reg debug_clk9m, debug_clk6m; +always @(posedge i_EMU_CLK72M) begin + if(clk9m_ncen) debug_clk9m <= 1'b0; + else if(clk9m_pcen) debug_clk9m <= 1'b1; + + if(clk6m_ncen) debug_clk6m <= 1'b0; + else if(clk6m_pcen) debug_clk6m <= 1'b1; +end + +reg debug_clk3m58, debug_clk1m79; +always @(posedge i_EMU_CLK57M) begin + if(clk3m58_ncen) debug_clk3m58 <= 1'b0; + else if(clk3m58_pcen) debug_clk3m58 <= 1'b1; + + if(clk1m79_ncen) debug_clk1m79 <= 1'b0; + else if(clk1m79_pcen) debug_clk1m79 <= 1'b1; +end + + + + +/////////////////////////////////////////////////////////// +////// BOARD INTERCONNECTION +//// + +wire maincpu_rstctrl, maincpu_rststat; +wire gfx_scrollram_cs, gfx_videoram_cs, gfx_colorram_cs, gfx_charram_cs, gfx_objram_cs; +wire [14:0] gfx_addr; +wire [15:0] gfx_do, gfx_di; +wire gfx_r_nw, gfx_uds_n, gfx_lds_n; +wire abs_1h_n, abs_2h, abs_32h, gfx_frameparity; +wire gfx_hflip, gfx_vflip; +wire gfx_blk; +wire [10:0] gfx_cd; +wire gfx_hblank_n, gfx_vblank_n, gfx_vsync_n, gfx_hsync_n; +wire [7:0] snd_code; +wire snd_nmi, snd_int; +wire snd_dma_br, snd_dma_bg_n; +wire [14:1] snd_dma_addr; +wire [7:0] snd_dma_do, snd_dma_di; +wire snd_dma_r_nw, snd_dma_lds_n; +wire snd_dma_sndram_cs; +wire timer_irq; + +assign o_VBLANK = ~gfx_vblank_n; +assign o_HSYNC = ~gfx_hsync_n; +assign o_VSYNC = ~gfx_vsync_n; +assign o_VIDEO_CEN = clk6m_pcen; +assign o_VIDEO_DEN = gfx_blk; + +wire [15:0] debug_video = {1'b0, o_VIDEO_B, o_VIDEO_G, o_VIDEO_R}; +wire [8:0] hcounter; +wire [8:0] vcounter; + + +/////////////////////////////////////////////////////////// +////// CPU BOARD +//// + +BubSys_cpu u_cpuboard ( + .i_EMU_MCLK (i_EMU_CLK72M ), + .i_EMU_CLK9M_PCEN (clk9m_pcen ), + .i_EMU_CLK9M_NCEN (clk9m_ncen ), + .i_EMU_CLK6M_PCEN (clk6m_pcen ), + .i_EMU_CLK6M_NCEN (clk6m_ncen ), + + .i_EMU_INITRST_n (i_EMU_INITRST_n ), + .i_EMU_SOFTRST_n (i_EMU_SOFTRST_n ), + + .i_MAINCPU_RSTCTRL (maincpu_rstctrl ), + .o_MAINCPU_RSTSTAT (maincpu_rststat ), + .i_MAINCPU_SWAPIRQ (i_MAINCPU_SWAPIRQ ), + + .i_BMC_MCLK (i_EMU_CLK48M ), + .i_BMC_TEMPLO_n (1'b1 ), + .o_BMC_ACC (o_BMC_ACC ), + + .o_GFX_ADDR (gfx_addr ), + .i_GFX_DO (gfx_do ), + .o_GFX_DI (gfx_di ), + .o_GFX_RnW (gfx_r_nw ), + .o_GFX_UDS_n (gfx_uds_n ), + .o_GFX_LDS_n (gfx_lds_n ), + + .o_VZCS_n (gfx_scrollram_cs ), + .o_VCS1_n (gfx_videoram_cs ), + .o_VCS2_n (gfx_colorram_cs ), + .o_CHACS_n (gfx_charram_cs ), + .o_OBJRAM_n (gfx_objram_cs ), + + .o_HFLIP (gfx_hflip ), + .o_VFLIP (gfx_vflip ), + + .i_ABS_1H_n (abs_1h_n ), + .i_ABS_2H (abs_2h ), + .i_ABS_32H (abs_32h ), + + .i_VBLANK_n (gfx_vblank_n ), //470pF+LS244 10ns? delay + .i_FRAMEPARITY (gfx_frameparity ), //same as above + + .i_BLK (gfx_blk ), + + .i_CD (gfx_cd ), + + .o_SND_INT (snd_int ), + .o_SND_NMI (snd_nmi ), + .o_SND_CODE (snd_code ), + .o_SND_DMA_BR (snd_dma_br ), + .i_SND_DMA_BG_n (snd_dma_bg_n ), + .o_SND_DMA_ADDR (snd_dma_addr ), + .o_SND_DMA_DO (snd_dma_do ), + .i_SND_DMA_DI (snd_dma_di ), + .o_SND_DMA_RnW (snd_dma_r_nw ), + .o_SND_DMA_LDS_n (snd_dma_lds_n ), + .o_SND_DMA_SNDRAM_CS (snd_dma_sndram_cs ), + + .i_TIMER_IRQ (timer_irq ), + + .i_IN0 (i_IN0 ), + .i_IN1 (i_IN1 ), + .i_IN2 (i_IN2 ), + .i_DIPSW1 (i_DIPSW1 ), + .i_DIPSW2 (i_DIPSW2 ), + .i_DIPSW3 (i_DIPSW3 ), + + .o_VIDEO_R (o_VIDEO_R ), + .o_VIDEO_G (o_VIDEO_G ), + .o_VIDEO_B (o_VIDEO_B ), + + .o_BUBROM_BOOT_CS (o_BUBROM_BOOT_CS ), + .o_BUBROM_PAGE_CS (o_BUBROM_PAGE_CS ), + .o_BUBROM_ADDR (o_BUBROM_ADDR ), + .i_BUBROM_DATA (i_BUBROM_DATA ), + .o_BUBROM_RD (o_BUBROM_RD ), + .i_BUBROM_DATA_RDY (i_BUBROM_DATA_RDY ) +); + + + +/////////////////////////////////////////////////////////// +////// VIDEO BOARD +//// + +GX400_video u_gx400_video ( + .i_EMU_MCLK (i_EMU_CLK72M ), + + .i_EMU_CLK18M_NCEN (clk18m_ncen ), + .i_EMU_CLK6M_PCEN (clk6m_pcen ), + .i_EMU_CLK6M_NCEN (clk6m_ncen ), + + .i_MRST_n (i_EMU_INITRST_n ), + + .i_GFX_ADDR (gfx_addr ), + .o_GFX_DO (gfx_do ), + .i_GFX_DI (gfx_di ), + .i_GFX_RnW (gfx_r_nw ), + .i_GFX_UDS_n (gfx_uds_n ), + .i_GFX_LDS_n (gfx_lds_n ), + + .i_VZCS_n (gfx_scrollram_cs ), + .i_VCS1_n (gfx_videoram_cs ), + .i_VCS2_n (gfx_colorram_cs ), + .i_CHACS_n (gfx_charram_cs ), + .i_OBJRAM_n (gfx_objram_cs ), + + .i_HFLIP (gfx_hflip ), + .i_VFLIP (gfx_vflip ), + + .o_HBLANK_n (gfx_hblank_n ), + .o_VBLANK_n (gfx_vblank_n ), + .o_HSYNC_n (gfx_hsync_n ), + .o_VSYNC_n (gfx_vsync_n ), + + .o_ABS_1H_n (abs_1h_n ), + .o_ABS_2H (abs_2h ), + .o_ABS_32H (abs_32h ), + .o_FRAMEPARITY (gfx_frameparity ), + + .o_BLK (gfx_blk ), + + .o_CD (gfx_cd ), + + .o_DEBUG_HCNTR (hcounter ), + .o_DEBUG_VCNTR (vcounter ) +); + +always @(posedge i_EMU_CLK72M) begin + if(!i_EMU_INITRST_n) begin + o_HBLANK <= 1'b0; + end + else begin if(clk6m_pcen) begin + if(hcounter == 9'd149) o_HBLANK <= 1'b1; + else if(hcounter == 9'd277) o_HBLANK <= 1'b0; + end end +end + + + +/////////////////////////////////////////////////////////// +////// SOUND SECTION +//// + +BubSys_sound u_sound ( + .i_EMU_MCLK (i_EMU_CLK57M ), + .i_EMU_CLK3M58_PCEN (clk3m58_pcen ), + .i_EMU_CLK3M58_NCEN (clk3m58_ncen ), + .i_EMU_CLK1M79_PCEN (clk1m79_pcen ), + .i_EMU_CLK1M79_NCEN (clk1m79_ncen ), + + .i_EMU_INITRST_n (i_EMU_INITRST_n ), + .i_EMU_SOFTRST_n (i_EMU_SOFTRST_n ), + + .o_MAINCPU_RSTCTRL (maincpu_rstctrl ), + .i_MAINCPU_RSTSTAT (maincpu_rststat ), + + .i_SND_INT (snd_int ), + .i_SND_NMI (snd_nmi ), + .i_SND_CODE (snd_code ), + .i_SND_DMA_BR (snd_dma_br ), + .o_SND_DMA_BG_n (snd_dma_bg_n ), + .i_SND_DMA_ADDR (snd_dma_addr ), + .i_SND_DMA_DO (snd_dma_do ), + .o_SND_DMA_DI (snd_dma_di ), + .i_SND_DMA_RnW (snd_dma_r_nw ), + .i_SND_DMA_LDS_n (snd_dma_lds_n ), + .i_SND_DMA_SNDRAM_CS (snd_dma_sndram_cs ), + + .o_TIMER_IRQ (timer_irq ), + + .i_VOL (i_VOL ), + .o_SND_L (o_SND_L ), + .o_SND_R (o_SND_R ), + + .i_EMU_PROM_CLK (i_EMU_CLK72M ), + .i_EMU_PROM_ADDR (i_EMU_PROM_ADDR ), + .i_EMU_PROM_DATA (i_EMU_PROM_DATA ), + .i_EMU_PROM_WR (i_EMU_PROM_WR ), + + .i_EMU_PROM_WAVE1_CS (i_EMU_PROM_WAVE1_CS ), + .i_EMU_PROM_WAVE2_CS (i_EMU_PROM_WAVE2_CS ), + .i_EMU_PROM_SNDROM_CS (i_EMU_PROM_SNDROM_CS ) +); + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/GX400_video.qip b/rtl/GX400_video/GX400_video.qip new file mode 100644 index 0000000..a5df73e --- /dev/null +++ b/rtl/GX400_video/GX400_video.qip @@ -0,0 +1,9 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) GX400_video.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) GX400_video_sram.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) GX400_video_dram.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005290.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005291.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005292.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005293.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005294.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) K005295.v ] diff --git a/rtl/GX400_video/GX400_video.v b/rtl/GX400_video/GX400_video.v new file mode 100644 index 0000000..39160fc --- /dev/null +++ b/rtl/GX400_video/GX400_video.v @@ -0,0 +1,1082 @@ +module GX400_video ( + input wire i_EMU_MCLK, + + input wire i_EMU_CLK18M_NCEN, + input wire i_EMU_CLK6M_PCEN, //REF_CLK6M + input wire i_EMU_CLK6M_NCEN, + + input wire i_MRST_n, + + input wire [14:0] i_GFX_ADDR, + output reg [15:0] o_GFX_DO, + input wire [15:0] i_GFX_DI, + input wire i_GFX_RnW, + input wire i_GFX_UDS_n, + input wire i_GFX_LDS_n, + + input wire i_VZCS_n, + input wire i_VCS1_n, + input wire i_VCS2_n, + input wire i_CHACS_n, + input wire i_OBJRAM_n, + + input wire i_HFLIP, + input wire i_VFLIP, + + output wire o_HBLANK_n, + output wire o_VBLANK_n, + output wire o_HSYNC_n, + output wire o_VSYNC_n, + + output wire o_ABS_1H_n, + output wire o_ABS_2H, + output wire o_ABS_32H, + output wire o_FRAMEPARITY, + + output wire o_BLK, + + output wire [10:0] o_CD, + + output wire [8:0] o_DEBUG_HCNTR, //for pixel capture purpose + output wire [8:0] o_DEBUG_VCNTR +); + + + +/////////////////////////////////////////////////////////// +////// CLOCK AND RESET +//// + +wire mclk = i_EMU_MCLK; +wire clk18m_ncen = i_EMU_CLK18M_NCEN; +wire clk6m_pcen = i_EMU_CLK6M_PCEN; +wire clk6m_ncen = i_EMU_CLK6M_NCEN; + + + +/////////////////////////////////////////////////////////// +////// timinggen +//// + +wire HBLANK_n; +wire VBLANK_n; +assign o_VBLANK_n = VBLANK_n; +assign o_HBLANK_n = HBLANK_n; +wire VBLANKH_n; +wire VCLK; +wire CSYNC_n; + +//hcounter +wire ABS_256H, + ABS_128H, ABS_64H, ABS_32H, ABS_16H, + ABS_8H, ABS_4H, ABS_2H, ABS_1H; + +wire FLIP_128H, FLIP_64H, FLIP_32H, FLIP_16H, + FLIP_8H, FLIP_4H, FLIP_2H, FLIP_1H; + +//vcounter +wire ABS_128V, ABS_64V, ABS_32V, ABS_16V, + ABS_8V, ABS_4V, ABS_2V, ABS_1V; + +wire FLIP_128V, FLIP_64V, FLIP_32V, FLIP_16V, + FLIP_8V, FLIP_4V, FLIP_2V, FLIP_1V; + +//misc +wire ABS_n256H = ~ABS_256H; +wire ABS_n1H = ~ABS_1H; +wire ABS_128HA = (ABS_256H & ABS_128H) | (ABS_n256H & ABS_32H); + +wire FLIP_n256H = ABS_n256H ^ i_HFLIP; + +wire DMA_n = ~&{ABS_128V, ABS_64V, ABS_32V, ~ABS_16V}; //vcounter 480-495 + +//to CPU +assign o_ABS_1H_n = ABS_n1H; +assign o_ABS_2H = ABS_2H; +assign o_ABS_32H = ABS_32H; + + +K005292 u_dut ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_MRST_n (i_MRST_n ), + + .i_HFLIP (i_HFLIP ), + .i_VFLIP (i_VFLIP ), + .i_H288 (1'b0 ), + .i_INTER (1'b0 ), + + .o_HBLANK_n (HBLANK_n ), + .o_VBLANK_n (VBLANK_n ), + .o_VBLANKH_n (VBLANKH_n ), //VBLANK** + + .o_ABS_H ({ABS_256H, + ABS_128H, ABS_64H, ABS_32H, ABS_16H, + ABS_8H, ABS_4H, ABS_2H, ABS_1H}), + .o_ABS_V ({ABS_128V, ABS_64V, ABS_32V, ABS_16V, + ABS_8V, ABS_4V, ABS_2V, ABS_1V}), + .o_FLIP_H ({FLIP_128H, FLIP_64H, FLIP_32H, FLIP_16H, + FLIP_8H, FLIP_4H, FLIP_2H, FLIP_1H}), + .o_FLIP_V ({FLIP_128V, FLIP_64V, FLIP_32V, FLIP_16V, + FLIP_8V, FLIP_4V, FLIP_2V, FLIP_1V}), + + .o_VCLK (VCLK ), + + .o_FRAMEPARITY (o_FRAMEPARITY ), + + .o_VSYNC_n (o_VSYNC_n ), + .o_HSYNC_n (o_HSYNC_n ), + .o_CSYNC_n ( ), + + .i_TEST (5'b10010 ), + + .o_DEBUG_HCNTR (o_DEBUG_HCNTR ), + .o_DEBUG_VCNTR (o_DEBUG_VCNTR ) +); + +wire ORINC; +reg [7:0] OBJ; +wire objcntr_tick = ORINC | (&{OBJ[7:4]}); + +always @(posedge mclk) begin + if(clk6m_pcen) begin + if(ABS_1H == 1'b0) begin //posedge of 1H + if(DMA_n == 1'b0) begin + OBJ <= 8'd0; + end + else begin + if(objcntr_tick == 1'b0) begin + OBJ <= OBJ + 8'd1; + end + end + end + end +end + + + + +// +// MEMORY TIMING GENERATOR SECTION +// + +/* + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| + ---(511)---|----(0)----|----(1)----|----(2)----| + + TIME1 ___________________|¯¯¯|___________________|¯¯¯| + TIME2 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___| + CHAMPX ¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯ + VRTIME ¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯ + OBJCLRWE¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯ + + BUFWE ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯ + BUFRAS ___________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|____ + dl-ras ____________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|___ +*/ + +//timing singals + +wire TIME1; //SCROLLRAM/OBJRAM read latch enable(active high) +wire TIME2; //SCROLLRAM/OBJRAM data write enable(active low) +wire VRTIME; //Video Read TIME +wire CHAMPX; //CHAracter MultiPleXer +wire OBJCLRWE; //OBJect CLeaR Write Enable + +reg CLK6M; +always @(posedge mclk) begin + if(clk6m_ncen) CLK6M <= 1'b0; + else if(clk6m_pcen) CLK6M <= 1'b1; +end + +reg TIMING_F; //1HF +always @(posedge mclk) begin + if(clk6m_pcen) begin + TIMING_F <= ABS_1H; + end +end + +reg [3:0] TIMING_SR; +always @(posedge mclk) begin + if(clk18m_ncen) begin + TIMING_SR[3] <= TIMING_F; + TIMING_SR[2:0] <= TIMING_SR[3:1]; + end +end + +assign TIME1 = ~(~TIMING_F | CLK6M); +assign TIME2 = ~(TIMING_F & TIMING_SR[2]); +assign VRTIME = ~(TIMING_F & ~TIMING_SR[3]); +assign CHAMPX = TIMING_SR[2] | TIMING_SR[1]; +wire CHAMPX1 = CHAMPX; +assign OBJCLRWE = TIMING_SR[2] | ~TIMING_SR[1]; + +//DRAM delay +reg CHAMPX2; +always @(posedge mclk) begin + if(clk18m_ncen) begin + CHAMPX2 <= CHAMPX; + end +end + + +// +// VIDEO TIMING GENERATOR SECTION +// + +//timing singals +wire OBJWR; //switches mux between active display+buffer clear/sprite engine write +wire OBJCLR; //fix mux output to 0 while clearing the buffer by writing 0s + +reg TIMING_A; +always @(posedge mclk) begin + if(clk6m_pcen) begin + if({ABS_8H, ABS_4H, ABS_2H, ABS_1H} == 4'd15) begin //posedge of 16H + TIMING_A <= ~(HBLANK_n & VBLANKH_n); + end + end +end + +reg TIMING_B; +always @(posedge mclk) begin + if(clk6m_pcen) begin //negedge cen + if(ABS_1H == 1'b1) begin //every ODD pixel + TIMING_B <= TIMING_A; + end + end +end + +reg TIMING_C; +always @(posedge mclk) begin + if(clk6m_pcen) begin + if({ABS_2H, ABS_1H} == 2'd3) begin //posedge of 4H + TIMING_C <= TIMING_A; + end + end +end + +reg TIMING_D; +always @(posedge mclk) begin + if(clk6m_pcen) begin + TIMING_D <= TIMING_C; + end +end + +reg TIMING_E; +always @(posedge mclk) begin + if(clk6m_pcen) begin + TIMING_E <= ~TIMING_D & VBLANK_n; + end +end + +assign OBJWR = TIMING_B; +assign OBJCLR = ~TIMING_B; +assign o_BLK = TIMING_E; + + + + + + + + +/////////////////////////////////////////////////////////// +////// tilemapgen +//// + +// +// scrollram section +// + +/* + FETCHES HSCROLL(1 PIXEL ROW) VALUE WHEN VCLK = 1 + + MCLK 0 1 2 3 4 5 0 1 2 3 4 5 + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|___|¯¯¯|___| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| + ----(7)----|----(0)----|----(1)----|----(2)----|----(3)----| + >SRAM DOUT >SRAM DOUT >SRAM DOUT >SRAM DOUT access speed >150ns + + TIME1 ___________________|¯¯¯|___________________|¯¯¯|____________ + TIME2 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯ + VCLK ___________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + ADDR |-------(TM-A LO)-------|-------(TM-A HI)-------| + DEVICE |---(CPU)---|---(GFX)---|---(CPU)---|---(GFX)---| + | TM-A LO | | TM-A HI | + + + FETCHES VSCROLL(8 PIXEL COLUMN) VALUE WHEN VCLK = 0 + (TM-A for 4H = 0, TM-B for 4H = 1) + + 1 1 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| + ----(7)----|----(0)----|----(1)----|----(2)----|----(3)----|----(4)----|----(5)----|----(6)----|----(7)----| + + TIME1 ___________________|¯¯¯|___________________|¯¯¯|___________________|¯¯¯|___________________|¯¯¯|____________ + TIME2 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯ + VCLK ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + SCRLATCH¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___| + SCRADDR --(TM-A)---|--------------------(TM-B)---------------------|--------------------(TM-A)---------------------| + DEVICE ---(GFX)---|---(CPU)---|---(GFX)---|---(CPU)---|---(GFX)---|---(CPU)---|---(GFX)---|---(CPU)---|---(GFX)---| + + VRAMADDR--(TM-B)---|--------------------(TM-A)---------------------|--------------------(TM-B)---------------------| + t0 t1 t2 + + 0. HSCROLL values for TM-A and TM-B are latched when VCLK = 1 + + t0 + 1. MUX provides TM-A VSCROLL address when 4H = 0 & VCLK = 0 + 2. tilemap generator latches TM-A VSCROLL value at posedge of ~(1H & 2H) + 3. Then TM-A VSCROLL value will be valid during next 4px-cycle + 4. In this next 4px-cycle, tilemap generator provides previously latched(at VCLK = 0) TM-A HSCROLL value + + t1 + 1. Again, tilemap generator latches TM-A VSCROLL value at posedge of ~(1H & 2H) since MUX provided TM-B VSCROLL address + 2. Then TM-B VSCROLL value will be valid during next 4px-cycle + 3. In this next 4px-cycle, tilemap generator provides previously latched(at VCLK = 0) TM-B HSCROLL value +*/ + +//make scrollram address +wire [10:0] scrollval_addr; +assign scrollval_addr = (~VCLK == 1'b0) ? + {1'b0, ABS_4H, ABS_2H, FLIP_128V, FLIP_64V, FLIP_32V, FLIP_16V, FLIP_8V, FLIP_4V, FLIP_2V, FLIP_1V} : //HORIZONTAL SCROLL + {1'b1, 1'b1, 1'b1, 1'b1, ABS_4H,FLIP_n256H, FLIP_128H, FLIP_64H, FLIP_32H, FLIP_16H, FLIP_8H}; //VERTICAL SCROLL + +wire [10:0] scrollram_addr; +assign scrollram_addr = (~ABS_1H == 1'b0) ? + scrollval_addr : + i_GFX_ADDR[10:0]; + +//make scrollram wr signal +wire scrollram_wr = (i_VZCS_n | i_GFX_RnW | i_GFX_LDS_n | TIME2); + +//declare SCROLLRAM +wire [7:0] scrollram_dout; +GX400_video_sram #(.aw( 11 ), .dw( 8 ), .simhexfile()) u_scrollram_lo ( + .i_MCLK (mclk ), + .i_ADDR (scrollram_addr ), + .i_DIN (i_GFX_DI[7:0] ), + .o_DOUT (scrollram_dout ), + .i_WR_n (scrollram_wr ), + .i_RD_n (1'b0 ) +); + +//declare CPU side latch +wire [7:0] scrollram_readlatch_q; +GX400_video_asynclatch u_scrollram_cpulatch ( + .i_MCLK (mclk ), + .i_D (scrollram_dout ), + .o_Q (scrollram_readlatch_q ), + .i_LE (TIME1 ) +); + + + +wire [11:0] vram_addr; +wire [2:0] line_addr; + +wire SHIFTA1; +wire SHIFTA2; +wire SHIFTB; + +//declare tilemapgen core: requires clock +K005291 u_K005291 ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_HFLIP (i_HFLIP ), + .i_VFLIP (i_VFLIP ), + + .i_ABS_n256H (ABS_n256H ), + .i_ABS_128HA (ABS_128HA ), + .i_ABS_64H (ABS_64H ), + .i_ABS_32H (ABS_32H ), + .i_ABS_16H (ABS_16H ), + .i_ABS_8H (ABS_8H ), + .i_ABS_4H (ABS_4H ), + .i_ABS_2H (ABS_2H ), + .i_ABS_1H (ABS_1H ), + + .i_ABS_128V (ABS_128V ), + .i_ABS_64V (ABS_64V ), + .i_ABS_32V (ABS_32V ), + .i_ABS_16V (ABS_16V ), + .i_ABS_8V (ABS_8V ), + .i_ABS_4V (ABS_4V ), + .i_ABS_2V (ABS_2V ), + .i_ABS_1V (ABS_1V ), + + .i_VCLK (VCLK ), + + .i_CPU_ADDR (i_GFX_ADDR[11:0] ), + .i_GFXDATA (scrollram_dout ), + + .o_TILELINEADDR (line_addr ), + + .o_VRAMADDR (vram_addr ), + + .o_SHIFTA1 (SHIFTA1 ), + .o_SHIFTA2 (SHIFTA2 ), + .o_SHIFTB (SHIFTB ) +); + + + +// +// VRAM1+2 section +// + +/* + MCLK + 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| + PIXEL ----(7)----|----(0)----|----(1)----|----(2)----|----(3)----|----(4)----|----(5)----|----(6)----|----(7)----| + /DTACK ¯S0¯¯S1¯¯S2¯¯S3¯¯S4¯|_w___w__S5__S6|¯S7¯¯¯¯¯¯¯¯¯¯S0¯¯S1¯¯S2¯¯S3¯¯S4¯|_w___w__S5__S6|¯S7¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + >SRAM CPU DIN >SRAM GFX DOUT >SRAM CPU DOUT >SRAM GFX DOUT 100ns access speed + VRTIME ¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ enable + DEVICE |---------(CPU)---------|---------(GFX)---------|---------(CPU)---------|---------(GFX)---------| + |(RD VALID)-| |(RD VALID)-| ext. gates allow RD during pixel 0 and 1 cycles + |WRVAL| |WRVAL| ext. gates allow WR during pixel 0 cycle + | VRAM ADDR TM-A | VRAM ADDR TM-B | + + >VRAM ADDR TM-A latched at /2H + >CHARRAM TM-A line data latched +*/ + +//make vram wr signal +wire vram1h_wr = (i_VCS1_n | i_GFX_RnW | i_GFX_UDS_n | ABS_1H | ABS_2H); //pixel 0 and 4 +wire vram1l_wr = (i_VCS1_n | i_GFX_RnW | i_GFX_LDS_n | ABS_1H | ABS_2H); +wire vram2l_wr = (i_VCS2_n | i_GFX_RnW | i_GFX_LDS_n | ABS_1H | ABS_2H); + +//declare vram1 +wire [15:0] vram1_dout; +GX400_video_sram #(.aw( 12 ), .dw( 8 ), .simhexfile()) u_vram1_hi ( + .i_MCLK (mclk ), + .i_ADDR (vram_addr ), + .i_DIN (i_GFX_DI[15:8] ), + .o_DOUT (vram1_dout[15:8] ), + .i_WR_n (vram1h_wr ), + .i_RD_n (VRTIME ) +); + +GX400_video_sram #(.aw( 12 ), .dw( 8 ), .simhexfile()) u_vram1_lo ( + .i_MCLK (mclk ), + .i_ADDR (vram_addr ), + .i_DIN (i_GFX_DI[7:0] ), + .o_DOUT (vram1_dout[7:0] ), + .i_WR_n (vram1l_wr ), + .i_RD_n (VRTIME ) +); + +//declare vram2 +wire [7:0] vram2_dout; +GX400_video_sram #(.aw( 12 ), .dw( 8 ), .simhexfile()) u_vram2_lo ( + .i_MCLK (mclk ), + .i_ADDR (vram_addr ), + .i_DIN (i_GFX_DI[7:0] ), + .o_DOUT (vram2_dout ), + .i_WR_n (vram2l_wr ), + .i_RD_n (VRTIME ) +); + + +// +// VRAM1 tile code DFF +// + +reg [10:0] tile_code; +reg VVFF; +always @(posedge mclk) begin + if(clk6m_pcen) begin + if({ABS_4H, ABS_2H, ABS_1H} == 3'd3 || {ABS_4H, ABS_2H, ABS_1H} == 3'd7) begin //posedge of /2H + tile_code <= vram1_dout[10:0]; + VVFF <= vram1_dout[11]; + end + end +end + + +// +// VRAM1+2 properties +// + +wire VHFF = vram2_dout[7]; +wire [6:0] VC = vram2_dout[6:0]; +wire [3:0] PR = vram1_dout[15:12]; + + +// +// tile address +// + +wire [7:0] VCA; +wire [13:0] __REF_VCA_ORIGINAL = {tile_code, line_addr ^ {3{VVFF}}}; +assign VCA = (CHAMPX2 == 1'b0) ? + {tile_code[4:0], line_addr[2:0] ^ {3{VVFF}}} : {1'b1, tile_code[10:5], 1'b1}; //RAS : CAS + + + + + + +/////////////////////////////////////////////////////////// +////// objengine +//// + +// +// OBJRAM SECTION +// + +//make objram address +wire [10:0] objram_addr; +assign objram_addr = (~ABS_n1H == 1'b0) ? + i_GFX_ADDR[10:0] : + {ABS_8V, ABS_4V, ABS_2V, ABS_1V, ABS_128H, ABS_64H, ABS_32H, ABS_16H, ABS_8H, ABS_4H, ABS_2H}; + +//make objram wr signal +wire objram_wr = |{i_OBJRAM_n, i_GFX_RnW, i_GFX_LDS_n, TIME2}; //LS32*4 + +//declare OBJRAM +wire [7:0] objram_dout; +GX400_video_sram #(.aw( 11 ), .dw( 8 ), .simhexfile()) u_objram_lo ( + .i_MCLK (mclk ), + .i_ADDR (objram_addr ), + .i_DIN (i_GFX_DI[7:0] ), + .o_DOUT (objram_dout ), + .i_WR_n (objram_wr ), + .i_RD_n (1'b0 ) +); + +//declare CPU side latch +wire [7:0] objram_readlatch_q; +GX400_video_asynclatch u_objram_cpulatch ( + .i_MCLK (mclk ), + .i_D (objram_dout ), + .o_Q (objram_readlatch_q ), + .i_LE (TIME1 ) +); + + +// +// SPRITE DMA SECTION +// + +reg [7:0] obj_priority; +always @(posedge mclk) begin + if(clk6m_pcen) begin + if({ABS_8H, ABS_4H, ABS_2H, ABS_1H} == 4'd1) begin //posedge of /px1 of every 16 pixels + obj_priority <= objram_dout; + end + end +end + +reg [7:0] obj_attr; +always @(posedge mclk) begin + if(clk6m_pcen) begin + if(ABS_1H == 1'b1) begin //posedge of /px1 + obj_attr <= objram_dout; + end + end +end + +//make objtable address +wire [2:0] ORA; +wire [10:0] objtable_addr; +assign objtable_addr = (DMA_n == 1'b0) ? + {obj_priority, ABS_8H, ABS_4H, ABS_2H} : + {OBJ, ORA}; + + +//make objtable_wr +wire objtable_wr = ~(ABS_1H & ~DMA_n); + +//declare objtable ram +wire [7:0] objtable_dout; +GX400_video_sram #(.aw( 11 ), .dw( 8 )) u_objtable ( + .i_MCLK (mclk ), + .i_ADDR (objtable_addr ), + .i_DIN (obj_attr ), + .o_DOUT (objtable_dout ), + .i_WR_n (objtable_wr ), + .i_RD_n (1'b0 ) +); + + +wire [7:0] OCA; +wire CHAOV; +reg OBJHL; + +wire [7:0] FA, FB; +wire XA7, XB7; +wire OBJBUF_CAS; + +wire WRTIME2; +wire COLORLATCH_n; +wire XPOS_D0; +wire PIXELLATCH_WAIT_n; +wire LATCH_A_D2; +wire [2:0] PIXELSEL; + + +//declare objengine core +K005295 #(.ENABLE_DOUBLE_HEIGHT_MODE(0)) u_K005295 ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_DMA_n (DMA_n ), + .i_VBLANKH_n (VBLANKH_n ), + .i_VBLANK_n (VBLANK_n ), + .i_HBLANK_n (HBLANK_n ), + .i_ABS_4H (ABS_4H ), + .i_ABS_2H (ABS_2H ), + .i_ABS_1H (ABS_1H ), + .i_CHAMPX (CHAMPX2 ), + .i_OBJWR (OBJWR ), + + .i_FLIP (i_HFLIP ), + + .i_OBJDATA (objtable_dout ), + .o_ORA (ORA ), + + .o_CAS (OBJBUF_CAS ), + + .o_FA (FA ), + .o_FB (FB ), + + .o_XA7 (XA7 ), + .o_XB7 (XB7 ), + + .i_OBJHL (OBJHL ), + .o_CHAOV (CHAOV ), + .o_ORINC (ORINC ), + + .o_WRTIME2 (WRTIME2 ), + .o_COLORLATCH_n (COLORLATCH_n ), + .o_XPOS_D0 (XPOS_D0 ), + .o_PIXELLATCH_WAIT_n (PIXELLATCH_WAIT_n ), + .o_LATCH_A_D2 (LATCH_A_D2 ), + .o_PIXELSEL (PIXELSEL ), + + .o_OCA (OCA ) +); + + + +/////////////////////////////////////////////////////////// +////// CHARRAM +//// + +/* + MCLK 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 + CLK18M _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + CLK9M ¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯| + CLK6M ¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___|¯¯¯¯¯¯¯|___| + PIXEL ----(3)----|----(4)----|----(5)----|----(6)----|----(7)----|----(0)----|----(1)----|----(2)----|----(3)----| + /DTACK ¯S0¯¯S1¯¯S2¯¯S3¯¯S4¯|_w___w__S5__S6|¯S7¯¯¯¯¯¯¯¯¯¯S0¯¯S1¯¯S2¯¯S3¯¯S4¯|_w___w__S5__S6|¯S7¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + >row >column >row >column + CHAMPX2 ¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + /RAS ___________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|________________ 15ns delayed + /CAS ________________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯|___________ 85ns delayed + + >DRAM CPU/REFRESH >DRAM GFX DOUT >DRAM CPU/REFRESH >DRAM GFX DOU DRAM async access speed 150ns + Automatically refreshes ROW ADDRESS during CPU/HV counter access cycle + DEVICE |---------(CPU)---------|---------(GFX)---------|---------(CPU)---------|---------(GFX)---------| + LATCHED CPU WR ¯¯¯¯¯¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + |(WR VALID)-| |(WR VALID)-| + |(RD VALID)-| |(RD VALID)-| + | CHARRAM ADDR TM-A | CHARRAM ADDR TM-B | + + >CHARRAM TM-A data latched by tilemapsr + >CHARRAM data TM-B latched by tilemapsr +*/ + +//LS153*4 MUX +wire [7:0] refresh_addr = {ABS_16V, ABS_8V, ABS_4V, ABS_2V, ABS_1V, ABS_128H, ABS_64H, ABS_32H}; +wire [7:0] cpu_addr; +assign cpu_addr = (i_CHACS_n == 1'b1) ? + refresh_addr : + (CHAMPX2 == 1'b0) ? + i_GFX_ADDR[8:1] : {1'b1, i_GFX_ADDR[14:9], 1'b1}; //RAS(A9-A2) : CAS(1, A15-A10, 1) + +//LS157*2 11A/B MUX +wire [7:0] gfx_addr; +assign gfx_addr = (CHAOV == 1'b0) ? OCA : VCA; + +//LS157*2 10A/B MUX +wire [7:0] charram_addr; +assign charram_addr = (~ABS_2H == 1'b0) ? gfx_addr : cpu_addr; + + +// +// DRAM modules +// + +//RAS/CAS +wire charram_ras_n = ~CHAMPX; +reg charram_cas_n = 1'b1; //54.25ns delayed RAS, same as CHAMPX2 +always @(posedge mclk) if(clk18m_ncen) begin + charram_cas_n <= charram_ras_n; +end + +//WR/RD +reg charramu_en; //upper +reg charraml_en; //upper +always @(posedge mclk) if(clk6m_ncen) begin //negedge of 6M, every even pixel + if(ABS_1H == 1'b0) begin //posedge of every even pixel + charramu_en <= i_GFX_UDS_n | i_CHACS_n; + charraml_en <= i_GFX_LDS_n | i_CHACS_n; + end +end + +wire charcs1_n = i_CHACS_n | ABS_2H | i_GFX_ADDR[0]; +wire charcs2_n = i_CHACS_n | ABS_2H | ~i_GFX_ADDR[0]; +wire charram1_rw = charcs1_n | i_GFX_RnW; //R=1 W=0 +wire charram2_rw = charcs2_n | i_GFX_RnW; + +wire charram1_rd = ~charram1_rw; //disables output when reading +wire charram2_rd = ~charram2_rw; //disables output when reading +wire charram1u_wr = charramu_en | charram1_rw; +wire charram1l_wr = charraml_en | charram1_rw; +wire charram2u_wr = charramu_en | charram2_rw; +wire charram2l_wr = charraml_en | charram2_rw; + + +//declare charram +wire [15:0] charram1_dout; //A1=0 +wire [15:0] charram2_dout; //A1=1 + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px0 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[15:12] ), + .o_DOUT (charram1_dout[15:12] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram1u_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px1 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[11:8] ), + .o_DOUT (charram1_dout[11:8] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram1u_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px2 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[7:4] ), + .o_DOUT (charram1_dout[7:4] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram1l_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px3 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[3:0] ), + .o_DOUT (charram1_dout[3:0] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram1l_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px4 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[15:12] ), + .o_DOUT (charram2_dout[15:12] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram2u_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px5 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[11:8] ), + .o_DOUT (charram2_dout[11:8] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram2u_wr ), + .i_RD_n (1'b0 ) +); +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px6 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[7:4] ), + .o_DOUT (charram2_dout[7:4] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram2l_wr ), + .i_RD_n (1'b0 ) +); + +GX400_video_dram #(.dw( 4 ), .aw( 8 ), .rw( 8 ), .cw( 6 ), .ctop( 6 ), .cbot( 1 ), .simhexfile(), .init(0)) u_chrram_px7 ( + .i_MCLK (mclk ), + .i_ADDR (charram_addr ), + .i_DIN (i_GFX_DI[3:0] ), + .o_DOUT (charram2_dout[3:0] ), + .i_RAS_n (charram_ras_n ), + .i_CAS_n (charram_cas_n ), + .i_WR_n (charram2l_wr ), + .i_RD_n (1'b0 ) +); + + + +/////////////////////////////////////////////////////////// +////// tilemapsr +//// + +// +// timing signal generation +// + +wire A_FLIP; +wire B_FLIP; + +wire AFF = i_HFLIP ^ A_FLIP; +wire BFF = i_HFLIP ^ B_FLIP; + +wire [1:0] A_MODE = {(~SHIFTA1 | ~AFF), (~SHIFTA1 | AFF)}; +wire [1:0] B_MODE = {(~SHIFTB | ~BFF), (~SHIFTB | BFF)}; + + +wire [3:0] A_PIXEL; +wire [3:0] B_PIXEL; +wire A_TRN_n; +wire B_TRN_n; + +K005290 u_K005290 ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_GFXDATA ({charram1_dout, charram2_dout}), + + .i_ABS_n4H (~ABS_4H ), + .i_ABS_2H (ABS_2H ), + + .i_AFF (AFF ), + .i_BFF (BFF ), + + .i_A_MODE (A_MODE ), + .i_B_MODE (B_MODE ), + + .o_A_PIXEL (A_PIXEL ), + .o_B_PIXEL (B_PIXEL ), + + .o_A_TRN_n (A_TRN_n ), + .o_B_TRN_n (B_TRN_n ) +); + + + + + + + +/////////////////////////////////////////////////////////// +////// objlinelatch +//// + +wire TILELINELATCH_n = ~(ABS_1H & ABS_2H); +wire [7:0] DA; +wire [7:0] DB; + + +K005294 u_K005294 ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_GFXDATA ({charram1_dout, charram2_dout}), + .i_OC (objtable_dout[4:1] ), + + .i_TILELINELATCH_n (TILELINELATCH_n ), + + .o_DA (DA ), + .o_DB (DB ), + + .i_WRTIME2 (WRTIME2 ), + .i_COLORLATCH_n (COLORLATCH_n ), + .i_XPOS_D0 (XPOS_D0 ), + .i_PIXELLATCH_WAIT_n (PIXELLATCH_WAIT_n ), + .i_LATCH_A_D2 (LATCH_A_D2 ), + .i_PIXELSEL (PIXELSEL ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// FRAME BUFFER +//// + + +reg FBTIMING_A; +always @(posedge mclk) if(clk6m_pcen) begin + FBTIMING_A <= WRTIME2; +end + +reg FBTIMING_B; +always @(posedge mclk) if(clk6m_ncen) begin //negative edge of CLK6M + FBTIMING_B <= FBTIMING_A; +end + +wire wrtime2_buf_ras_n = FBTIMING_A & ~FBTIMING_B; +wire objbuf_ras_n = (OBJWR == 1'b0) ? ~CHAMPX : wrtime2_buf_ras_n; + + + +reg FBTIMING_C; +always @(posedge mclk) if(clk6m_pcen) begin //positive edge of CLK6M + FBTIMING_C <= FBTIMING_A; +end + +wire wrtime2_buf_we_n = CLK6M | ~FBTIMING_C; +wire objbuf_we_n = (OBJWR == 1'b0) ? OBJCLRWE : wrtime2_buf_we_n; + + + +reg objbuf_ras_dly_n; +always @(posedge mclk) if(clk18m_ncen) begin + OBJHL <= ~objbuf_ras_n; + objbuf_ras_dly_n <= objbuf_ras_n; +end + + +wire evenbuf_overwrite_disable = ~(~XA7 & |{DA[3:0]}); +wire [7:0] evenbuf_dout; +wire [7:0] evenbuf_din = (OBJCLR == 1'b1) ? 8'h00 : + (evenbuf_overwrite_disable == 1'b0) ? DA : evenbuf_dout; + +wire oddbuf_overwrite_disable = ~(~XB7 & |{DB[3:0]}); +wire [7:0] oddbuf_dout; +wire [7:0] oddbuf_din = (OBJCLR == 1'b1) ? 8'h00 : + (oddbuf_overwrite_disable == 1'b0) ? DB : oddbuf_dout; + + +//EVEN +GX400_video_dram #(.dw( 8 ), .aw( 8 ), .init( 1 )) u_evenbuf ( + .i_MCLK (i_EMU_MCLK), .i_ADDR (FA), + .i_DIN (evenbuf_din), .o_DOUT (evenbuf_dout), + .i_RAS_n (objbuf_ras_n), .i_CAS_n (~OBJBUF_CAS), .i_WR_n (objbuf_we_n), .i_RD_n (1'b0) +); + + +//ODD +GX400_video_dram #(.dw( 8 ), .aw( 8 ), .init( 1 )) u_oddbuf ( + .i_MCLK (i_EMU_MCLK), .i_ADDR (FB), + .i_DIN (oddbuf_din), .o_DOUT (oddbuf_dout), + .i_RAS_n (objbuf_ras_n), .i_CAS_n (~OBJBUF_CAS), .i_WR_n (objbuf_we_n), .i_RD_n (1'b0) +); + + + +/////////////////////////////////////////////////////////// +////// prihandler +//// + +wire SHIFTA1_CLKD = SHIFTA1; +wire SHIFTA2_CLKD = SHIFTA2; +wire SHIFTB_CLKD = SHIFTB; + +wire ABS_n6n7H = ~(ABS_4H & ABS_2H); +wire ABS_n2n3H = ~(~ABS_4H & ABS_2H); + +K005293 u_K005293 ( + .i_EMU_MCLK (mclk ), + .i_EMU_CLK6MPCEN_n (~clk6m_pcen ), + + .i_HFLIP (i_HFLIP ), + + .i_SHIFTA1 (SHIFTA1_CLKD ), + .i_SHIFTA2 (SHIFTA2_CLKD ), + .i_SHIFTB (SHIFTB_CLKD ), + + .i_ABS_n1H (ABS_n1H ), + .i_ABS_n6n7H (ABS_n6n7H ), + .i_ABS_n2n3H (ABS_n2n3H ), + + .i_A_PIXEL (A_PIXEL ), + .i_B_PIXEL (B_PIXEL ), + .i_OBJBUF_DATA ({oddbuf_dout, evenbuf_dout}), + + .i_A_TRN_n (A_TRN_n ), + .i_B_TRN_n (B_TRN_n ), + + .i_VHFF (VHFF ), + .i_VC (VC ), + .i_PR (PR ), + + .o_A_FLIP (A_FLIP ), + .o_B_FLIP (B_FLIP ), + + .o_CD (o_CD ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DATA OUTPUT MUX +//// + +always @(*) begin + case({i_VZCS_n, i_VCS1_n, i_VCS2_n, charcs1_n, charcs2_n, i_OBJRAM_n}) + 6'b011111: o_GFX_DO <= {8'hFF, scrollram_readlatch_q}; + 6'b101111: o_GFX_DO <= vram1_dout; + 6'b110111: o_GFX_DO <= {8'hFF, vram2_dout}; + 6'b111011: o_GFX_DO <= charram1_dout; + 6'b111101: o_GFX_DO <= charram2_dout; + 6'b111110: o_GFX_DO <= {8'hFF, objram_readlatch_q}; + default: o_GFX_DO <= 16'hFFFF; //pull up + endcase +end + +endmodule + + + +module GX400_video_asynclatch ( + input wire i_MCLK, + input wire [7:0] i_D, + output wire [7:0] o_Q, + input wire i_LE +); + +reg [7:0] REGISTER; +always @(posedge i_MCLK) begin + if(i_LE) REGISTER <= i_D; +end + +assign o_Q = i_LE ? i_D : REGISTER; + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/GX400_video_dram.v b/rtl/GX400_video/GX400_video_dram.v new file mode 100644 index 0000000..6120940 --- /dev/null +++ b/rtl/GX400_video/GX400_video_dram.v @@ -0,0 +1,69 @@ +/* + DRAM +*/ + +module GX400_video_dram #( parameter + dw=8, // data width + aw=8, // address bus width (number of pins) + rw=aw, // row width (usually address but width) + cw=aw, // column width (address but width or shorter) + ctop=cw-1, // index in address where MSB of col is + cbot=0, // index in address where LSB of col is + simhexfile="", + init=0 +) +( + input wire i_MCLK, + input wire [aw-1:0] i_ADDR, + input wire [dw-1:0] i_DIN, + output reg [dw-1:0] o_DOUT, + input wire i_RAS_n, + input wire i_CAS_n, + input wire i_WR_n, + input wire i_RD_n +); + +reg [dw-1:0] RAM [0:(2**(rw+cw))-1]; +reg prev_ras; +reg prev_cas; +reg [rw-1:0] ROW_ADDR; +reg [cw-1:0] COL_ADDR; +wire [rw+cw-1:0] ADDR = {COL_ADDR, ROW_ADDR}; + +wire valid_n = prev_cas | i_RAS_n; + +always @(posedge i_MCLK) +begin + prev_ras <= i_RAS_n; + prev_cas <= i_CAS_n; + + if(i_RAS_n == 1'b0 && prev_ras == 1'b1) + begin + ROW_ADDR <= i_ADDR; + end + + if(i_CAS_n == 1'b0 && prev_cas == 1'b1) + begin + COL_ADDR <= i_ADDR[ctop:cbot]; + end +end + + +always @(posedge i_MCLK) begin + if(!valid_n) begin + if(!i_WR_n) RAM[ADDR] <= i_DIN; + else o_DOUT <= RAM[ADDR]; + end +end + +integer i; + +initial +begin + if( simhexfile != "" ) + begin + $readmemh(simhexfile, RAM); + end +end + +endmodule diff --git a/rtl/GX400_video/GX400_video_sim.v b/rtl/GX400_video/GX400_video_sim.v new file mode 100644 index 0000000..5fd6390 --- /dev/null +++ b/rtl/GX400_video/GX400_video_sim.v @@ -0,0 +1,72 @@ +module GX400_video_sim +( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + input wire [8:0] i_HCOUNTER, + input wire [8:0] i_VCOUNTER, + input wire [15:0] i_VIDEODATA +); + + +/* + VCNTR + 272 - HCNTR 278~511 + 128~149; 150 end of line + ~ + 495 - HCNTR 278~511 + 128~149; 150 end of frame +*/ + +reg [7:0] RESNET_CONSTANT[31:0]; +reg [7:0] BITMAP_HEADER[63:0]; +integer BITMAP_LINE_ADDRESS = 32'h29D36; +wire [4:0] B = i_VIDEODATA[14:10]; +wire [4:0] G = i_VIDEODATA[9:5]; +wire [4:0] R = i_VIDEODATA[4:0]; + +integer fd; +integer i; +reg [15:0] frame = 16'd0; + +initial begin + $readmemh("./GX400_video/debug_resnet_level.txt", RESNET_CONSTANT); + $readmemh("./GX400_video/debug_bitmap_header.txt", BITMAP_HEADER); +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_VCOUNTER > 9'd271 && i_VCOUNTER < 9'd496) begin + if (i_VCOUNTER == 9'd272 && i_HCOUNTER == 9'd276) begin + BITMAP_LINE_ADDRESS = 20'h29D36; //reset line + + fd = $fopen($sformatf("./vsim/gx400_frame%0d.bmp", frame), "wb"); //generate new file + + for(i = 0; i < 54; i = i + 1) begin //write bitmap header + $fwrite(fd, "%c", BITMAP_HEADER[i]); + end + + $display("Start of frame %d", frame); //debug message + + end + else if(i_HCOUNTER == 9'd277) begin + $fseek(fd, BITMAP_LINE_ADDRESS, 0); //set current line address + end + else if(i_HCOUNTER > 9'd277 || i_HCOUNTER < 9'd150) begin + $fwrite(fd, "%c%c%c", RESNET_CONSTANT[B], RESNET_CONSTANT[G], RESNET_CONSTANT[R]); //B G R + end + else if(i_HCOUNTER == 9'd150) begin + BITMAP_LINE_ADDRESS = BITMAP_LINE_ADDRESS - 32'h300; //decrease line + end + else if(i_VCOUNTER == 9'd495 && i_HCOUNTER == 9'd151) begin + $fclose(fd); //close this frame + $display("Frame %d saved", frame); //debug message + + frame = frame + 16'd1; + end + else begin + + end + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/GX400_video_sram.v b/rtl/GX400_video/GX400_video_sram.v new file mode 100644 index 0000000..e92b00f --- /dev/null +++ b/rtl/GX400_video/GX400_video_sram.v @@ -0,0 +1,44 @@ +/* + SRAM +*/ + +module GX400_video_sram #(parameter + dw=8, + aw=10, + simhexfile="" +) +( + input wire i_MCLK, + input wire [aw-1:0] i_ADDR, + input wire [dw-1:0] i_DIN, + output reg [dw-1:0] o_DOUT, + input wire i_WR_n, + input wire i_RD_n +); + +reg [dw-1:0] RAM [0:(2**aw)-1]; + +always @(posedge i_MCLK) +begin + if(i_WR_n == 1'b0) + begin + RAM[i_ADDR] <= i_DIN; + end +end + +always @(posedge i_MCLK) //read +begin + if(i_RD_n == 1'b0) + begin + o_DOUT <= RAM[i_ADDR]; + end +end + +initial +begin + if( simhexfile != "" ) begin + $readmemh(simhexfile, RAM); + end +end + +endmodule diff --git a/rtl/GX400_video/K005290.v b/rtl/GX400_video/K005290.v new file mode 100644 index 0000000..0ae61a2 --- /dev/null +++ b/rtl/GX400_video/K005290.v @@ -0,0 +1,228 @@ +/* + tilemapsr TILEMAP SHIFT REGISTER ARRAY +*/ + +module K005290 ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + //pixel data + input wire [31:0] i_GFXDATA, + + //hcounter + input wire i_ABS_n4H, + input wire i_ABS_2H, + + //flips + input wire i_AFF, + input wire i_BFF, + + //sr mode + input wire [1:0] i_A_MODE, + input wire [1:0] i_B_MODE, + + //pixel output + output reg [3:0] o_A_PIXEL, + output reg [3:0] o_B_PIXEL, + + //pixel transparent flag + output wire o_A_TRN_n, + output wire o_B_TRN_n +); + + +/////////////////////////////////////////////////////////// +////// TILELINE LATCH +//// + +/* + pixel 0 1 2 3 4 5 6 7 + 1H _|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯|_|¯| + 2H ___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯|___|¯¯¯| + /4H ¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + 4H _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______| +*/ + +reg ABS_2H_dl; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + ABS_2H_dl <= i_ABS_2H; + end +end + +wire pixel3_n = ~(i_ABS_2H & ABS_2H_dl & i_ABS_n4H); +wire pixel7_n = ~(i_ABS_2H & ABS_2H_dl & ~i_ABS_n4H); + + +// +// tileline latches +// + +reg [31:0] A_TILELINELATCH; +reg [31:0] B_TILELINELATCH; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!pixel7_n) begin //posedge of px7 + A_TILELINELATCH <= i_GFXDATA; + end + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!pixel3_n) begin //posedge of px3 + B_TILELINELATCH <= i_GFXDATA; + end + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// PIXEL SHIFT REGISTER +//// + +// +// TM-A shift register +// + +reg [3:0] A_PIXEL0 = 4'h0; +reg [3:0] A_PIXEL1 = 4'h0; +reg [3:0] A_PIXEL2 = 4'h0; +reg [3:0] A_PIXEL3 = 4'h0; +reg [3:0] A_PIXEL4 = 4'h0; +reg [3:0] A_PIXEL5 = 4'h0; +reg [3:0] A_PIXEL6 = 4'h0; +reg [3:0] A_PIXEL7 = 4'h0; + +reg [3:0] A_PIXEL_DELAY1; +reg [3:0] A_PIXEL_DELAY2; +reg [3:0] A_PIXEL_DELAY3; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + case(i_A_MODE) + 2'b00: begin end + 2'b01: begin //shift reversed direction(right) + A_PIXEL0 <= 4'h0; + A_PIXEL1 <= A_PIXEL0; + A_PIXEL2 <= A_PIXEL1; + A_PIXEL3 <= A_PIXEL2; + A_PIXEL4 <= A_PIXEL3; + A_PIXEL5 <= A_PIXEL4; + A_PIXEL6 <= A_PIXEL5; + A_PIXEL7 <= A_PIXEL6; + end + 2'b10: begin + A_PIXEL0 <= A_PIXEL1; + A_PIXEL1 <= A_PIXEL2; + A_PIXEL2 <= A_PIXEL3; + A_PIXEL3 <= A_PIXEL4; + A_PIXEL4 <= A_PIXEL5; + A_PIXEL5 <= A_PIXEL6; + A_PIXEL6 <= A_PIXEL7; + A_PIXEL7 <= 4'h0; + end + 2'b11: begin + A_PIXEL0 <= A_TILELINELATCH[31:28]; + A_PIXEL1 <= A_TILELINELATCH[27:24]; + A_PIXEL2 <= A_TILELINELATCH[23:20]; + A_PIXEL3 <= A_TILELINELATCH[19:16]; + A_PIXEL4 <= A_TILELINELATCH[15:12]; + A_PIXEL5 <= A_TILELINELATCH[11:8]; + A_PIXEL6 <= A_TILELINELATCH[7:4]; + A_PIXEL7 <= A_TILELINELATCH[3:0]; + end + endcase + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_AFF == 1'b0) begin + A_PIXEL_DELAY1 <= A_PIXEL0; //shift normally + end + else begin + A_PIXEL_DELAY1 <= A_PIXEL7; //shift reversed direction(right) + end + + A_PIXEL_DELAY2 <= A_PIXEL_DELAY1; + A_PIXEL_DELAY3 <= A_PIXEL_DELAY2; + + o_A_PIXEL <= A_PIXEL_DELAY3; + end +end + +assign o_A_TRN_n = |{o_A_PIXEL}; + + +// +// TM-B shift register +// + +reg [3:0] B_PIXEL0 = 4'h0; +reg [3:0] B_PIXEL1 = 4'h0; +reg [3:0] B_PIXEL2 = 4'h0; +reg [3:0] B_PIXEL3 = 4'h0; +reg [3:0] B_PIXEL4 = 4'h0; +reg [3:0] B_PIXEL5 = 4'h0; +reg [3:0] B_PIXEL6 = 4'h0; +reg [3:0] B_PIXEL7 = 4'h0; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + case(i_B_MODE) + 2'b00: begin end + 2'b01: begin + B_PIXEL0 <= 4'h0; + B_PIXEL1 <= B_PIXEL0; + B_PIXEL2 <= B_PIXEL1; + B_PIXEL3 <= B_PIXEL2; + B_PIXEL4 <= B_PIXEL3; + B_PIXEL5 <= B_PIXEL4; + B_PIXEL6 <= B_PIXEL5; + B_PIXEL7 <= B_PIXEL6; + end + 2'b10: begin + B_PIXEL0 <= B_PIXEL1; + B_PIXEL1 <= B_PIXEL2; + B_PIXEL2 <= B_PIXEL3; + B_PIXEL3 <= B_PIXEL4; + B_PIXEL4 <= B_PIXEL5; + B_PIXEL5 <= B_PIXEL6; + B_PIXEL6 <= B_PIXEL7; + B_PIXEL7 <= 4'h0; + end + 2'b11: begin + B_PIXEL0 <= B_TILELINELATCH[31:28]; + B_PIXEL1 <= B_TILELINELATCH[27:24]; + B_PIXEL2 <= B_TILELINELATCH[23:20]; + B_PIXEL3 <= B_TILELINELATCH[19:16]; + B_PIXEL4 <= B_TILELINELATCH[15:12]; + B_PIXEL5 <= B_TILELINELATCH[11:8]; + B_PIXEL6 <= B_TILELINELATCH[7:4]; + B_PIXEL7 <= B_TILELINELATCH[3:0]; + end + endcase + end +end + +always @(*) begin + if(i_BFF == 1'b0) begin + o_B_PIXEL <= B_PIXEL0; //shift normally + end + else begin + o_B_PIXEL <= B_PIXEL7; //shift reversed direction(right) + end +end + +assign o_B_TRN_n = |{o_B_PIXEL}; + + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/K005291.v b/rtl/GX400_video/K005291.v new file mode 100644 index 0000000..a27869e --- /dev/null +++ b/rtl/GX400_video/K005291.v @@ -0,0 +1,150 @@ +/* + tilemapgen TILEMAP GENERATOR +*/ + +module K005291 ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + //CPU flip + input wire i_HFLIP, + input wire i_VFLIP, + + //HV counters + input wire i_ABS_n256H, + input wire i_ABS_128HA, + input wire i_ABS_64H, + input wire i_ABS_32H, + input wire i_ABS_16H, + input wire i_ABS_8H, + input wire i_ABS_4H, + input wire i_ABS_2H, + input wire i_ABS_1H, + + input wire i_ABS_128V, + input wire i_ABS_64V, + input wire i_ABS_32V, + input wire i_ABS_16V, + input wire i_ABS_8V, + input wire i_ABS_4V, + input wire i_ABS_2V, + input wire i_ABS_1V, + + input wire i_VCLK, + + //CPU address/GFX data bus + input wire [11:0] i_CPU_ADDR, + input wire [7:0] i_GFXDATA, + + //to CHARRAM + output reg [2:0] o_TILELINEADDR, + + //to VRAM1+2 + output wire [11:0] o_VRAMADDR, + + output wire o_SHIFTA1, + output wire o_SHIFTA2, + output wire o_SHIFTB +); + + +wire ABS_4H = i_ABS_4H; +wire ABS_2H = i_ABS_2H; +wire ABS_1H = i_ABS_1H; + +wire FLIP_n256H = i_ABS_n256H ^ i_HFLIP; +wire FLIP_128HA = i_ABS_128HA ^ i_HFLIP; +wire FLIP_64H = i_ABS_64H ^ i_HFLIP; +wire FLIP_32H = i_ABS_32H ^ i_HFLIP; +wire FLIP_16H = i_ABS_16H ^ i_HFLIP; +wire FLIP_8H = i_ABS_8H ^ i_HFLIP; +wire FLIP_4H = i_ABS_4H ^ i_HFLIP; +wire FLIP_2H = i_ABS_2H ^ i_HFLIP; +wire FLIP_1H = i_ABS_1H ^ i_HFLIP; + +wire FLIP_128V = i_ABS_128V ^ i_VFLIP; +wire FLIP_64V = i_ABS_64V ^ i_VFLIP; +wire FLIP_32V = i_ABS_32V ^ i_VFLIP; +wire FLIP_16V = i_ABS_16V ^ i_VFLIP; +wire FLIP_8V = i_ABS_8V ^ i_VFLIP; +wire FLIP_4V = i_ABS_4V ^ i_VFLIP; +wire FLIP_2V = i_ABS_2V ^ i_VFLIP; +wire FLIP_1V = i_ABS_1V ^ i_VFLIP; + + + +/////////////////////////////////////////////////////////// +////// TILEMAP SCROLL +//// + +// +// HSCROLL +// + +reg [8:0] TMA_HSCROLL_VALUE = 9'h1F; +reg [8:0] TMB_HSCROLL_VALUE = 9'h1F; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_VCLK) begin + case({ABS_4H, ABS_2H, ABS_1H}) + 3'd1: begin TMA_HSCROLL_VALUE[7:0] <= i_GFXDATA; end //latch TM-A lower bits at px1 + 3'd3: begin TMA_HSCROLL_VALUE[8] <= i_GFXDATA[0]; end //latch TM-B high bit at px3 + 3'd5: begin TMB_HSCROLL_VALUE[7:0] <= i_GFXDATA; end //latch TM-A lower bits at px5 + 3'd7: begin TMB_HSCROLL_VALUE[8] <= i_GFXDATA[0]; end //latch TM-B high bit at px7 + default: begin end + endcase + end + end +end + +//vram address +wire [5:0] horizontal_tile_addr; //6 bit: 64 horizontal tiles(512 horizontal pixels) +assign horizontal_tile_addr = (ABS_4H == 1'b0) ? + TMA_HSCROLL_VALUE[8:3] + {FLIP_n256H, FLIP_128HA, FLIP_64H, FLIP_32H, FLIP_16H, FLIP_8H} : + TMB_HSCROLL_VALUE[8:3] + {FLIP_n256H, FLIP_128HA, FLIP_64H, FLIP_32H, FLIP_16H, FLIP_8H}; + +//shift +assign o_SHIFTA1 = (TMA_HSCROLL_VALUE[2:0] + {FLIP_4H, FLIP_2H, FLIP_1H} == 3'd7) ? 1'b0 : 1'b1; +assign o_SHIFTA2 = (TMA_HSCROLL_VALUE[2:0] + {FLIP_4H, FLIP_2H, FLIP_1H} == 3'd3) ? 1'b0 : 1'b1; +assign o_SHIFTB = (TMB_HSCROLL_VALUE[2:0] + {FLIP_4H, FLIP_2H, FLIP_1H} == 3'd3) ? 1'b0 : 1'b1; + + + +// +// VSCROLL +// + +reg [7:0] TMAB_VSCROLL_VALUE = 8'hF; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + case({ABS_4H, ABS_2H, ABS_1H}) + 3'd3: begin TMAB_VSCROLL_VALUE <= i_GFXDATA; //latch TM-B second at px3 + o_TILELINEADDR <= TMAB_VSCROLL_VALUE[2:0] + {FLIP_4V, FLIP_2V, FLIP_1V}; end + 3'd7: begin TMAB_VSCROLL_VALUE <= i_GFXDATA; //latch TM-A first at px7 + o_TILELINEADDR <= TMAB_VSCROLL_VALUE[2:0] + {FLIP_4V, FLIP_2V, FLIP_1V}; end + default: begin end + endcase + end +end + +//pixel 3: get TM-B vscroll value +//pixel 7: get TM-A vscroll value/update TM-B line address +//pixel 3: get TM-B vscroll value/update TM-A line address + +//vram address +wire [7:0] vertical_tile_addr; //[7:3] 5 bit: 32 vertical tiles(512 horizontal pixels) +assign vertical_tile_addr = TMAB_VSCROLL_VALUE + {FLIP_128V, FLIP_64V, FLIP_32V, FLIP_16V, FLIP_8V, FLIP_4V, FLIP_2V, FLIP_1V}; + + + +/////////////////////////////////////////////////////////// +////// VRAM TILE ADDRESS +//// + +assign o_VRAMADDR = (ABS_2H == 1'b0) ? + i_CPU_ADDR : + {ABS_4H, vertical_tile_addr[7:3], horizontal_tile_addr}; + + + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/K005292.v b/rtl/GX400_video/K005292.v new file mode 100644 index 0000000..3f92079 --- /dev/null +++ b/rtl/GX400_video/K005292.v @@ -0,0 +1,301 @@ +module K005292 ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + input wire i_MRST_n, + + input wire i_HFLIP, + input wire i_VFLIP, + input wire i_H288, //set horizontal pixel as 288 + input wire i_INTER, //interlaced + + output reg o_HBLANK_n, + output wire o_VBLANK_n, + output wire o_VBLANKH_n, + + output wire [8:0] o_ABS_H, + output wire [7:0] o_ABS_V, + output wire [7:0] o_FLIP_H, + output wire [7:0] o_FLIP_V, + + output reg o_VCLK, + + output wire o_FRAMEPARITY, + + output reg o_HSYNC_n, + output wire o_VSYNC_n, + output reg o_CSYNC_n, + + input wire [4:0] i_TEST, //PIN24 23 22 21 20 + + output wire [8:0] o_DEBUG_HCNTR, + output wire [8:0] o_DEBUG_VCNTR +); + + + +/////////////////////////////////////////////////////////// +////// CLOCK AND RESET +//// + +wire mrst = ~i_MRST_n; +wire mclk = i_EMU_MCLK; +wire clk6m_pcen = ~i_EMU_CLK6MPCEN_n; + + + +/////////////////////////////////////////////////////////// +////// GLOBAL SIGNALS +//// + +reg [8:0] hcntr, vcntr; +reg vclk_pcen; + +assign o_ABS_H = hcntr; +assign o_FLIP_H = i_HFLIP ? ~hcntr[7:0] : hcntr[7:0]; +assign o_ABS_V = vcntr[7:0]; +assign o_FLIP_V = i_VFLIP ? ~vcntr[7:0] : vcntr[7:0]; +assign o_DEBUG_HCNTR = hcntr; +assign o_DEBUG_VCNTR = vcntr; + + +/////////////////////////////////////////////////////////// +////// HORIZONTAL COUNTER +//// + +always @(posedge mclk) begin + if(mrst) hcntr <= 9'd0; + else begin if(clk6m_pcen) begin + hcntr <= hcntr == 9'd511 ? 9'd128 : hcntr + 9'd1; + end end +end + + + +/////////////////////////////////////////////////////////// +////// VIDEO TIMINGS +//// + +//VERTICAL VIDEO TIMINGS +reg dff_D8, dff_D19, dff_C28; +wire dff_D19_pcen = vclk_pcen & (vcntr[4:0] == 5'd15) & ~(vcntr[7:5] == 3'b111) & (dff_D19 == 1'b0); +wire dff_C28_pcen = vclk_pcen & (vcntr[4:0] == 5'd15) & (dff_D19 == 1'b0 && vcntr[7:5] != 3'b111) & (dff_C28 == 1'b0); +always @(posedge mclk) begin + //D8 + if(mrst) dff_D8 <= 1'b0; + else begin if(vclk_pcen) begin + if(vcntr[0] == 1'b0) dff_D8 <= ~vcntr[8]; + end end + + //D19 + if(mrst) dff_D19 <= 1'b0; + else begin if(vclk_pcen) begin + if(vcntr[4:0] == 5'd15) dff_D19 <= ~(vcntr[7:5] == 3'b111); + end end + + if(mrst) dff_C28 <= 1'b0; + else begin if(vclk_pcen) begin + if(vcntr[4:0] == 5'd15) if(dff_D19 == 1'b1 && vcntr[7:5] == 3'b111) dff_C28 <= ~dff_C28; + end end +end + +assign o_VBLANK_n = dff_D19; +assign o_VSYNC_n = vcntr[8]; +assign o_VBLANKH_n = (~vcntr[8] & ~dff_D8) | dff_D19; +assign o_FRAMEPARITY = dff_C28; //256V + + +//MODE0 VCLK/SYNC +reg vclk_mode0; +wire vclk_mode0_pcen = (hcntr[8] == 1'b0 && hcntr[6:0] == 7'd47) & clk6m_pcen; +always @(posedge mclk) begin + if(mrst) begin + vclk_mode0 <= 1'b1; + end + else begin if(clk6m_pcen) begin + if(hcntr == 9'd255 || hcntr[8]) vclk_mode0 <= 1'b0; + else begin + if(hcntr[3:0] == 4'd15) begin + vclk_mode0 <= ~hcntr[6] & hcntr[5]; + end + end + end end +end + +wire sync_mode0_n = ~vclk_mode0 & (vcntr[8] | ~i_TEST[4]); + + +//MODE2/3 VCLK/SYNC +reg vclk_mode23; +wire vclk_mode23_pcen = (hcntr[4:0] == 5'd31 && vclk_mode0) & clk6m_pcen; +always @(posedge mclk) begin + if(mrst) begin + vclk_mode23 <= 1'b0; + end + else begin if(clk6m_pcen) begin + if(hcntr[4:0] == 5'd31) vclk_mode23 <= vclk_mode0; + end end +end + +reg dff_D41; +wire hblank_mode23_n = dff_D41 | hcntr[8]; +always @(posedge mclk) begin + if(mrst) begin + dff_D41 <= 1'b0; + end + else begin if(clk6m_pcen) begin + if(hcntr[5:0] == 6'd31) dff_D41 <= hcntr[8]; + end end +end + +wire sync_mode23_n = ~vclk_mode23 & (vcntr[8] | ~i_TEST[4]); + + +//MODE1 VCLK/SYNC +reg dff_C2, dff_A44, dff_B43, dff_C14, dff_C8, dff_C8_censel; +wire dff_B43_ncen = (hcntr[5:0] == 6'd47 && (hcntr[8:6] == 3'b101 || hcntr[8:6] == 3'b010)) & clk6m_pcen; +wire debug_dff_C8_clk = ~dff_C14 && vcntr[7:0] == 8'b11110111 && i_TEST[4] && vclk_mode0; +wire debug_dff_C8_clk_pcen = ~dff_C14 && vcntr[7:0] == 8'b11110111 && i_TEST[4] && vclk_mode0_pcen; +wire debug_something_long = (hcntr[8:6] == 3'b101 || hcntr[8:6] == 3'b010); +always @(posedge mclk) begin + //B43 + if(clk6m_pcen) begin + if(hcntr[5:0] == 6'd63 || ~hcntr[5]) dff_B43 <= 1'b1; + else begin + if(hcntr[4:0] == 5'd15) dff_B43 <= ~(hcntr[8:6] == 3'b101 || hcntr[8:6] == 3'b010); + end + end + + //C14 + if(mrst) dff_C14 <= 1'b1; + else begin + if(clk6m_pcen) begin + if(dff_D19_pcen || dff_D19) dff_C14 <= 1'b0; + else begin if(vclk_pcen) begin + if(vcntr[3:0] == 4'd7) dff_C14 <= ~dff_C14; + end end + end + end + + //C8 + if(mrst) dff_C8 <= 1'b0; + else begin + if(clk6m_pcen) begin + if(dff_C28_pcen || dff_C28) dff_C8 <= 1'b1; + else begin + if(vcntr[7:0] == 8'd247 && !dff_C14 && i_TEST[4] && vclk_mode0_pcen) dff_C8 <= ~dff_C8; + end + end + end + + //C8_pre: NOT an original signal + if(mrst) dff_C8_censel <= 1'b0; + else begin if(clk6m_pcen) begin + if(hcntr == 9'd511 && vcntr == 9'd502) dff_C8_censel <= 1'b0; + else if(hcntr == 9'd511 && vcntr == 9'd271) dff_C8_censel <= 1'b1; + end end + + //C2 + if(mrst) dff_C2 <= 1'b0; + else begin + if(clk6m_pcen) begin + if(dff_D19_pcen || dff_D19) dff_C2 <= 1'b1; + else begin if(vclk_pcen) begin + if(vcntr[2:0] == 3'd7) dff_C2 <= ~dff_C2; + end end + end + end + + //A44 + if(clk6m_pcen) begin + if(!((hcntr == 9'd191 || hcntr[8:6] == 3'b010 || hcntr == 9'd383 || hcntr[8:6] == 3'b101) && !i_TEST[2])) dff_A44 <= 1'b0; + else begin + if(hcntr[4:0] == 5'd15) dff_A44 <= ~dff_A44; + end + end +end + +reg vclk_mode1, vclk_mode1_pcen; +always @(*) begin + case(i_TEST[3:2]) + 2'b00: vclk_mode1 = dff_C8 ? vclk_mode0 : (~dff_B43 & hcntr[8]); + 2'b01: vclk_mode1 = (~dff_B43 & hcntr[8]); + 2'b10: vclk_mode1 = (vclk_mode0 & dff_C8); + 2'b11: vclk_mode1 = 1'b0; + endcase + + case(i_TEST[3:2]) + 2'b00: vclk_mode1_pcen = dff_C8_censel ? vclk_mode0_pcen : (dff_B43_ncen & hcntr[8]); + 2'b01: vclk_mode1_pcen = (dff_B43_ncen & hcntr[8]); + 2'b10: vclk_mode1_pcen = (vclk_mode0_pcen & dff_C8_censel); + 2'b11: vclk_mode1_pcen = 1'b0; + endcase +end + +wire gate_A12 = (~i_TEST[0] & dff_C2) | (i_TEST[3] | dff_B43) | (~i_TEST[0] & ~dff_C14); +wire gate_A29 = dff_A44 | (vcntr[8] | ~i_TEST[4]); +wire gate_B21 = dff_C14 | (~vclk_mode0 | i_TEST[3]); +wire sync_mode1_n = gate_A12 & gate_A29 & gate_B21; + + + +/////////////////////////////////////////////////////////// +////// TIMING MUX +//// + +always @(*) begin + case({i_H288, i_INTER}) + 2'b00: o_VCLK = vclk_mode0; + 2'b01: o_VCLK = vclk_mode1; + 2'b10: o_VCLK = vclk_mode23; + 2'b11: o_VCLK = vclk_mode23; + endcase + + case({i_H288, i_INTER}) + 2'b00: vclk_pcen = vclk_mode0_pcen; + 2'b01: vclk_pcen = vclk_mode1_pcen; + 2'b10: vclk_pcen = vclk_mode23_pcen; + 2'b11: vclk_pcen = vclk_mode23_pcen; + endcase + + o_HBLANK_n = i_H288 ? hblank_mode23_n : hcntr[8]; + + case({i_H288, i_INTER}) + 2'b00: o_CSYNC_n = sync_mode0_n; + 2'b01: o_CSYNC_n = sync_mode1_n; + 2'b10: o_CSYNC_n = sync_mode23_n; + 2'b11: o_CSYNC_n = sync_mode23_n; + endcase + + //for emulation + case({i_H288, i_INTER}) + 2'b00: o_HSYNC_n = ~vclk_mode0; + 2'b01: o_HSYNC_n = gate_B21 & gate_A12 & ~(dff_A44 & ~vcntr[8]); + 2'b10: o_HSYNC_n = ~vclk_mode23; + 2'b11: o_HSYNC_n = ~vclk_mode23; + endcase +end + + + +/////////////////////////////////////////////////////////// +////// VERTICAL COUNTER +//// + +//async +//always @(posedge (vclk & i_TEST[1]) or posedge mrst) begin +// if(mrst) vcntr <= 9'd0; +// else begin +// vcntr <= vcntr == 9'd511 ? 9'd248 : vcntr + 9'd1; +// end +//end + +//sync +always @(posedge mclk) begin + if(mrst) vcntr <= 9'd0; + else begin if(vclk_pcen) begin + vcntr <= vcntr == 9'd511 ? 9'd248 : vcntr + 9'd1; + end end +end + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/K005293.v b/rtl/GX400_video/K005293.v new file mode 100644 index 0000000..112ba50 --- /dev/null +++ b/rtl/GX400_video/K005293.v @@ -0,0 +1,545 @@ +/* + prihandler PRIORITY HANDLER +*/ + +module K005293 ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + //flip + input wire i_HFLIP, + + //clocked shift + input wire i_SHIFTA1, + input wire i_SHIFTA2, + input wire i_SHIFTB, + + //timings + input wire i_ABS_n1H, + input wire i_ABS_n6n7H, + input wire i_ABS_n2n3H, + + //pixel input + input wire [3:0] i_A_PIXEL, + input wire [3:0] i_B_PIXEL, + //sprite pixels + input wire [15:0] i_OBJBUF_DATA, + + //pixel transparent flag + input wire i_A_TRN_n, + input wire i_B_TRN_n, + + //tile properties + input wire i_VHFF, + input wire [6:0] i_VC, + input wire [3:0] i_PR, + + //delayed flips + output wire o_A_FLIP, + output wire o_B_FLIP, + + //palette code + output reg [10:0] o_CD +); + + + +/////////////////////////////////////////////////////////// +////// PROPERTY DATA SHIFTER +//// + +/* + if SCROLL = 0 + + i_ABS_n2n3H i_ABS_n6n7H i_ABS_n2n3H i_ABS_n6n7H + i_SHIFTA1 i_SHIFTA2 + i_SHIFTB + TM-A DELAY1 -> DELAY2 -> DELAY3 -> DELAY4 + TM-B DELAY1 -> DELAY2 -> DELAY3 +*/ + +// +// TM-A +// + +//PR4, PR3, PR2, PR1, VHFF, VC6 ... VC0 + +reg [11:0] A_PROPERTY_DELAY1; +reg [11:0] A_PROPERTY_DELAY2; +reg [11:0] A_PROPERTY_DELAY3; +reg [11:0] A_PROPERTY_DELAY4; + +wire [3:0] a_pr = A_PROPERTY_DELAY4[11:8]; +wire [6:0] a_palette = A_PROPERTY_DELAY4[6:0]; +assign o_A_FLIP = A_PROPERTY_DELAY3[7]; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n)begin + if((i_ABS_n2n3H || i_ABS_n1H) == 1'b0) A_PROPERTY_DELAY1 <= {i_PR, i_VHFF, i_VC}; //posedge of pixel 3 + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if((i_ABS_n6n7H || i_ABS_n1H) == 1'b0) A_PROPERTY_DELAY2 <= A_PROPERTY_DELAY1; //posedge of pixel 7 + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_SHIFTA1 == 1'b0) A_PROPERTY_DELAY3 <= A_PROPERTY_DELAY2; //posedge of SHIFT-A1 + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_SHIFTA2 == 1'b0) A_PROPERTY_DELAY4 <= A_PROPERTY_DELAY3; //posedge of SHIFT-A2 + end +end + + +// +// TM-B +// + +reg [9:0] B_PROPERTY_DELAY1; +reg [9:0] B_PROPERTY_DELAY2; +reg [9:0] B_PROPERTY_DELAY3; + +wire [1:0] b_pr = B_PROPERTY_DELAY3[9:8]; +wire [6:0] b_palette = B_PROPERTY_DELAY3[6:0]; +assign o_B_FLIP = B_PROPERTY_DELAY3[7]; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if((i_ABS_n6n7H || i_ABS_n1H) == 1'b0) B_PROPERTY_DELAY1 <= {i_PR[1:0], i_VHFF, i_VC}; //posedge of pixel 7 + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if((i_ABS_n2n3H || i_ABS_n1H) == 1'b0) B_PROPERTY_DELAY2 <= B_PROPERTY_DELAY1; //posedge of pixel 3 + end +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_SHIFTB == 1'b0) B_PROPERTY_DELAY3 <= B_PROPERTY_DELAY2; //posedge of SHIFT-B + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// SPRITE PIXEL LATCH +//// + +reg [7:0] OBJ_PIXEL0; +reg [7:0] OBJ_PIXEL1; + +wire [7:0] obj_pixel; +wire obj_trn_n = (obj_pixel[3] | obj_pixel[2] | obj_pixel[1] | obj_pixel[0]); +assign obj_pixel = ((~i_ABS_n1H ^ i_HFLIP) == 1'b0) ? OBJ_PIXEL0 : OBJ_PIXEL1; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_ABS_n1H == 1'b0) begin//every odd pixel + OBJ_PIXEL1 <= i_OBJBUF_DATA[15:8]; //BUFFER A = ODD PIXEL + OBJ_PIXEL0 <= i_OBJBUF_DATA[7:0]; //BUFFER B = EVEN PIXEL + end + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// PRIORITY HANDLER +//// + +/* + K005293 priority handler. This chip was reverse-engineered + by Gilles Raimond, Olivier Scherler and me. + + Since the exact behavior of the chip was not well known, I made a + brute-force program to test all PR inputs. The tool was programmed with + the advice of Raimond and Scherler, and was executed on my Bubble System. + + The source of the program can be found on my GitHub page below: + github.com/ika-musume/BubbleDrive8/tree/master/BubbleDrive8_testprogram + + The chip showed us a total of 26 results and suggested that the source + of MAME was a very empirical result. +*/ + +//determines which layer should be displayed first +reg [4:0] priority_mode; //set priority mode +reg [1:0] layer; +wire [2:0] transparency = ~{i_A_TRN_n, i_B_TRN_n, obj_trn_n}; + +//declare layer type +localparam TMA = 2'b00; +localparam TMB = 2'b01; +localparam OBJ = 2'b10; + +//declare cases +`define PRCASE_A 5'd0 // A +`define PRCASE_A_B 5'd1 // A over B +`define PRCASE_A_B_O 5'd2 // A over B over Object +`define PRCASE_A_BMO 5'd3 // A over (B-masked Object) +`define PRCASE_A_O1 5'd4 // A over Object 1 +`define PRCASE_A_O2 5'd5 // A over Object 2 +`define PRCASE_A_O_B 5'd6 // A over Object over B +`define PRCASE_B 5'd7 // B +`define PRCASE_B_A 5'd8 // B over A +`define PRCASE_B_A_O 5'd9 // B over A over Object +`define PRCASE_B_O 5'd10 // B over Object +`define PRCASE_B_O_A 5'd11 // B over Object over A +`define PRCASE_O 5'd12 // Object +`define PRCASE_O_A 5'd13 // Object over A +`define PRCASE_O_A_B 5'd14 // Object over A over B +`define PRCASE_O_B 5'd15 // Object over B +`define PRCASE_O_B_A 5'd16 // Object over B over A +`define PRCASE_A_BMO_B 5'd17 // A over (B-masked Object) over B +`define PRCASE_APB_O 5'd18 // (A-punched B) over Object +`define PRCASE_APB_O_A 5'd19 // (A-punched B) over Object over A +`define PRCASE_B_AMO 5'd20 // B over (A-masked Object) +`define PRCASE_B_AMO_A 5'd21 // B over (A-masked Object) over A +`define PRCASE_BPA_O 5'd22 // (B-punched A) over Object +`define PRCASE_BPA_O_B 5'd23 // (B-punched A) over Object over B +`define PRCASE_O_APB 5'd24 // Object over (A-punched B) +`define PRCASE_O_BPA 5'd25 // Object over (B-punched A) + +//X-decoder +always @(*) begin + casez({b_pr, a_pr}) //PR2, PR1, PR4, PR3, PR2, PR1 + //|--TMB--| |------TMA-------| + 6'b??_0101: priority_mode <= `PRCASE_A; // A + 6'b?1_1101: priority_mode <= `PRCASE_A_B; // A over B + 6'b?1_1111: priority_mode <= `PRCASE_A_B_O; // A over B over Object + 6'b00_1101: priority_mode <= `PRCASE_A_BMO; // A over (B-masked Object) + 6'b??_0111: priority_mode <= `PRCASE_A_O1; // A over Object 1 + 6'b00_1111: priority_mode <= `PRCASE_A_O2; // A over Object 2 + 6'b10_1111: priority_mode <= `PRCASE_A_O_B; // A over Object over B + 6'b01_00??: priority_mode <= `PRCASE_B; // B + 6'b01_10?1: priority_mode <= `PRCASE_B_A; // B over A + 6'b11_10?1: priority_mode <= `PRCASE_B_A_O; // B over A over Object + 6'b11_00??: priority_mode <= `PRCASE_B_O; // B over Object + 6'b11_1000: priority_mode <= `PRCASE_B_O; // | + 6'b11_1010: priority_mode <= `PRCASE_B_O_A; // B over Object over A + 6'b00_00??: priority_mode <= `PRCASE_O; // Object + 6'b00_1?00: priority_mode <= `PRCASE_O; // | + 6'b??_0100: priority_mode <= `PRCASE_O; // | + 6'b??_0110: priority_mode <= `PRCASE_O_A; // Object over A + 6'b00_1110: priority_mode <= `PRCASE_O_A; // | + 6'b10_1110: priority_mode <= `PRCASE_O_A_B; // Object over A over B + 6'b10_00??: priority_mode <= `PRCASE_O_B; // Object over B + 6'b10_1000: priority_mode <= `PRCASE_O_B; // | + 6'b10_1010: priority_mode <= `PRCASE_O_B_A; // Object over B over A + 6'b10_1101: priority_mode <= `PRCASE_A_BMO_B; // A over (B-masked Object) over B + 6'b?1_1100: priority_mode <= `PRCASE_APB_O; // (A-punched B) over Object + 6'b?1_1110: priority_mode <= `PRCASE_APB_O_A; // (A-punched B) over Object over A + 6'b01_1000: priority_mode <= `PRCASE_B_AMO; // B over (A-masked Object) + 6'b01_1010: priority_mode <= `PRCASE_B_AMO_A; // B over (A-masked Object) over A + 6'b00_10?1: priority_mode <= `PRCASE_BPA_O; // (B-punched A) over Object + 6'b10_10?1: priority_mode <= `PRCASE_BPA_O_B; // (B-punched A) over Object over B + 6'b10_1100: priority_mode <= `PRCASE_O_APB; // Object over (A-punched B) + 6'b00_1010: priority_mode <= `PRCASE_O_BPA; // Object over (B-punched A) + endcase +end + +//Y and Z-decoder +always @(*) begin + case(priority_mode) + `PRCASE_A: begin + case(transparency) + + 3'b110: layer <= TMA; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= TMA; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMA; + + endcase + end + `PRCASE_A_B: begin + case(transparency) + + 3'b110: layer <= TMA; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_A_B_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_A_BMO: begin + case(transparency) + + 3'b110: layer <= TMA; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= OBJ; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= OBJ; + + endcase + end + `PRCASE_A_O1: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= OBJ; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMA; + + endcase + end + `PRCASE_A_O2: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= OBJ; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= OBJ; + + endcase + end + `PRCASE_A_O_B: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= OBJ; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B: begin + case(transparency) + + 3'b110: layer <= TMB; 3'b010: layer <= TMB; 3'b011: layer <= TMB; 3'b111: layer <= TMB; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_A: begin + case(transparency) + + 3'b110: layer <= TMB; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMB; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_A_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= OBJ; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_O_A: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= OBJ; 3'b101: layer <= OBJ; + + endcase + end + `PRCASE_O_A: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= TMA; 3'b101: layer <= OBJ; + + endcase + end + `PRCASE_O_A_B: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_O_B: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_O_B_A: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_A_BMO_B: begin + case(transparency) + + 3'b110: layer <= TMA; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= OBJ; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_APB_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= OBJ; + + + 3'b100: layer <= TMB; 3'b000: layer <= OBJ; 3'b001: layer <= OBJ; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_APB_O_A: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= TMB; 3'b000: layer <= OBJ; 3'b001: layer <= TMA; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_AMO: begin + case(transparency) + + 3'b110: layer <= TMB; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= TMB; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_B_AMO_A: begin + case(transparency) + + 3'b110: layer <= TMB; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= TMB; + + + 3'b100: layer <= TMB; 3'b000: layer <= TMB; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_BPA_O: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= OBJ; 3'b101: layer <= OBJ; + + endcase + end + `PRCASE_BPA_O_B: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= TMB; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_O_APB: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= OBJ; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= OBJ; 3'b101: layer <= TMB; + + endcase + end + `PRCASE_O_BPA: begin + case(transparency) + + 3'b110: layer <= OBJ; 3'b010: layer <= OBJ; 3'b011: layer <= TMA; 3'b111: layer <= OBJ; + + + 3'b100: layer <= OBJ; 3'b000: layer <= OBJ; 3'b001: layer <= OBJ; 3'b101: layer <= OBJ; + + endcase + end + default: begin + case(transparency) + + 3'b110: layer <= TMA; 3'b010: layer <= TMA; 3'b011: layer <= TMA; 3'b111: layer <= TMA; + + + 3'b100: layer <= TMA; 3'b000: layer <= TMA; 3'b001: layer <= TMA; 3'b101: layer <= TMA; + + endcase + end + endcase +end + +//output latch +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if (layer == TMA) o_CD <= {a_palette, i_A_PIXEL}; + else if(layer == TMB) o_CD <= {b_palette, i_B_PIXEL}; + else o_CD <= {3'b000, obj_pixel}; + end +end + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/K005294.v b/rtl/GX400_video/K005294.v new file mode 100644 index 0000000..3830991 --- /dev/null +++ b/rtl/GX400_video/K005294.v @@ -0,0 +1,167 @@ +/* + objlinelatch "LINELATCH" +*/ + +module K005294 ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + input wire [31:0] i_GFXDATA, + input wire [3:0] i_OC, + + input wire i_TILELINELATCH_n, + + output reg [7:0] o_DA, + output reg [7:0] o_DB, + + //control signals + input wire i_WRTIME2, + input wire i_COLORLATCH_n, + input wire i_XPOS_D0, + input wire i_PIXELLATCH_WAIT_n, + input wire i_LATCH_A_D2, + input wire [2:0] i_PIXELSEL +); + + + +/////////////////////////////////////////////////////////// +////// COLORLATCH +//// + +//latches pixel palette data from VRAM +reg [3:0] OBJ_PALETTE; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!i_COLORLATCH_n) OBJ_PALETTE <= i_OC; + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// TILELINE LATCH +//// + +reg [31:0] OBJ_TILELINELATCH; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!i_TILELINELATCH_n) OBJ_TILELINELATCH <= i_GFXDATA; //posedge of px7 + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// PIXEL SELECT / PIXELLATCH_WAIT / WRTIME2 DELAY +//// + +reg [2:0] pixelsel_dly [3:0]; +reg [1:0] wrtime2_dly; +reg [3:0] pixellatch_wait_dly; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + pixelsel_dly[0] <= i_PIXELSEL; + pixelsel_dly[1] <= pixelsel_dly[0]; + pixelsel_dly[2] <= pixelsel_dly[1]; + pixelsel_dly[3] <= pixelsel_dly[2]; + end +end + + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + wrtime2_dly[0] <= i_WRTIME2; + wrtime2_dly[1] <= wrtime2_dly[0]; + end +end + + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + pixellatch_wait_dly[3:1] <= pixellatch_wait_dly[2:0]; + pixellatch_wait_dly[0] <= ~i_PIXELLATCH_WAIT_n; + end +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// PIXEL SELECTOR AND PIXEL LATCH +//// + +wire pixellatch_n = wrtime2_dly[1] | pixellatch_wait_dly[2]; +reg [3:0] OBJ_PIXEL_LATCHED; +reg [3:0] OBJ_PIXEL_UNLATCHED; + +always @(*) +begin + case(pixelsel_dly[3]) + 3'b000: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[31:28]; //pixel 0(A) + 3'b001: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[27:24]; //pixel 1(B) + 3'b010: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[23:20]; + 3'b011: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[19:16]; + 3'b100: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[15:12]; + 3'b101: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[11:8]; + 3'b110: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[7:4]; + 3'b111: OBJ_PIXEL_UNLATCHED <= OBJ_TILELINELATCH[3:0]; + endcase +end + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!pixellatch_n) OBJ_PIXEL_LATCHED <= OBJ_PIXEL_UNLATCHED; + end +end + + + + + + + +/////////////////////////////////////////////////////////// +////// DOUT MUX +//// + +always @(*) +begin + case({pixellatch_wait_dly[2], i_XPOS_D0}) + 2'b00: begin + o_DA <= {OBJ_PALETTE, OBJ_PIXEL_LATCHED}; + o_DB <= {OBJ_PALETTE, OBJ_PIXEL_UNLATCHED}; + end + 2'b01: begin + o_DA <= {OBJ_PALETTE, OBJ_PIXEL_UNLATCHED}; + o_DB <= {OBJ_PALETTE, OBJ_PIXEL_LATCHED}; + end + 2'b10: begin + o_DA <= {OBJ_PALETTE, OBJ_PIXEL_LATCHED}; + o_DB <= {4'b0000, 4'b0000}; + end + 2'b11: begin + o_DA <= {4'b0000, 4'b0000}; + o_DB <= {OBJ_PALETTE, OBJ_PIXEL_LATCHED}; + end + endcase +end + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/K005295.v b/rtl/GX400_video/K005295.v new file mode 100644 index 0000000..20dfae4 --- /dev/null +++ b/rtl/GX400_video/K005295.v @@ -0,0 +1,1657 @@ +module K005295 #(parameter ENABLE_DOUBLE_HEIGHT_MODE = 0) ( + input wire i_EMU_MCLK, + input wire i_EMU_CLK6MPCEN_n, + + //timings + input wire i_DMA_n, + input wire i_VBLANKH_n, + input wire i_VBLANK_n, + input wire i_HBLANK_n, + input wire i_ABS_4H, + input wire i_ABS_2H, + input wire i_ABS_1H, + input wire i_CHAMPX, + input wire i_OBJWR, + + //flip + input wire i_FLIP, + + //clocked shift + input wire [7:0] i_OBJDATA, + output wire [2:0] o_ORA, + + //framebuffer CAS + output wire o_CAS, + + //framebuffer test +`ifdef SIM_UNFOLD_DRAM_ADDR + output wire [15:0] o_FA, //ODD BUFFER + output wire [15:0] o_FB, //EVEN BUFFER +`else + output wire [7:0] o_FA, //ODD BUFFER + output wire [7:0] o_FB, //EVEN BUFFER +`endif + + output reg o_XA7, + output reg o_XB7, + + //peripheral control signals + input wire i_OBJHL, + output reg o_CHAOV, + output wire o_ORINC, + + //linelatch control signals + output reg o_WRTIME2, + output wire o_COLORLATCH_n, + output wire o_XPOS_D0, + output reg o_PIXELLATCH_WAIT_n, + output wire o_LATCH_A_D2, + output wire [2:0] o_PIXELSEL, + + //CHARRAM address +`ifdef SIM_UNFOLD_DRAM_ADDR + output wire [13:0] o_OCA +`else + output wire [7:0] o_OCA +`endif +); + + +/* + This engine can draw 8 sizes of + sprites: + 32*32, 16*32, 32*16, 64*64, 8*8, 16*8, 8*16, 16*16 + by enabling double height mode(LATCH_A bit 1), it can draw some + additional sizes: + 32*64, 16*64, 64*128, 8*32 + + All sprite data is stored in CHARRAM. 4bpp, big endian. For example, + think about 16*8 sprite. That can be expressed just like this: + + + |----------- HLINE -----------| + |---TILELINE---|---TILELINE---| + O O O O o o o o A A A A a a a a --- + O O O O o o o o A A A A a a a a | + O O O O o o o o A A A A a a a a | + O O O O o o o o A A A A a a a a VTILE + O O O O o o o o A A A A a a a a | + O O O O o o o o A A A A a a a a | + O O O O o o o o A A A A a a a a | + O O O O o o o o A A A A a a a a --- + + Sprite engine can fetch 8 pixels of sprite data from CHARRAM at + a single time. 4bpp*8 = 32bits. I will call this "TILELINE." + + This sprite is 16*8, so there are two TILELINEs in one "HLINE" + To draw ONE HLINE, TWO TILELINEs are needed to be fetched. + + Again, eight HLINEs are needed to complete this 16*8 sprite. + I will call this eight HLINEs, "VTILE". Width doesn't matter. + + Please remember these three terms, TILELINE, HLINE, VTILE. I + use these terms in variable names. +*/ + + + +/////////////////////////////////////////////////////////// +////// GLOBAL SIGNALS +//// + +reg hsize_parity = 1'b0; +reg pixellatch_wait_n; + + + + + + +/////////////////////////////////////////////////////////// +////// PIXEL3 +//// + +/* + pixel3_n is very important. The most of branches of FSM are occurs + on Pixel 3. +*/ + +wire pixel3_n = ~(i_ABS_1H & i_ABS_2H); + + + + + + +/////////////////////////////////////////////////////////// +////// 4H clocked DMA_n +//// + +/* + Sampling DMA_n at every rising edge of 4H allows FSM to know + the start of a new VBLANK. If the value of sampled DMA_n is 1 + and VBLANK or VBLANKH is 0, it is the beginning of a new VBLANK. +*/ + +reg DMA_4H_CLKD_n = 1'b1; +wire new_vblank_n = DMA_4H_CLKD_n | i_VBLANKH_n; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if({i_ABS_4H, i_ABS_2H, i_ABS_1H} == 3'd3) begin + DMA_4H_CLKD_n <= i_DMA_n; + end + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// ORA/register enable generation +//// + +//latch enable signal +wire LATCH_A_en_n; //OBJRAM BYTE 2: zoom MSBs[7:6], size[5:3], optional size bits[2:1], hflip[0] +wire LATCH_B_en_n; //OBJRAM BYTE 4: zoom LSBs[7:0] +wire LATCH_C_en_n; //OBJRAM BYTE 6: sprite code LSBs[7:0] +wire LATCH_D_en_n; //OBJRAM BYTE 8: sprite code MSBs[7:6], vflip[5], obj palette[4:1], xpos MSB[0] +wire LATCH_E_en_n; //OBJRAM BYTE A: xpos LSBs[7:0] +wire LATCH_F_en_n; //OBJRAM BYTE C: ypos[7:0] + +assign o_COLORLATCH_n = LATCH_D_en_n; + +//if /A ORA = 2, if /B ORA = 3, ... ,if /F, ORA = 7 +//MUDA MUDA MUDA MUDA MUDA MUDA +//ORA ORA ORA ORA ORA ORA ORA +assign o_ORA[2] = ~&{ LATCH_C_en_n, LATCH_D_en_n, LATCH_E_en_n, LATCH_F_en_n}; +assign o_ORA[1] = ~&{LATCH_A_en_n, LATCH_B_en_n, LATCH_E_en_n, LATCH_F_en_n}; +assign o_ORA[0] = ~&{ LATCH_B_en_n, LATCH_D_en_n, LATCH_F_en_n}; + +//latch enable shift register +reg latching_start; +reg [6:0] attr_latch_en_sr; +assign {LATCH_A_en_n, LATCH_B_en_n, LATCH_C_en_n, + LATCH_D_en_n, LATCH_E_en_n, LATCH_F_en_n, o_ORINC} = attr_latch_en_sr; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_ABS_1H == 1'b0) begin + attr_latch_en_sr[6] <= ~latching_start; + attr_latch_en_sr[5:0] <= attr_latch_en_sr[6:1]; + end + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// SPRITE ATTRIBUTE LATCHES +//// + +//LATCH_F is not shown here since ypos data is directly loaded into ypos counter +reg [7:0] LATCH_A; //OBJRAM BYTE 2: zoom MSBs[7:6], size[5:3], optional size bits[2:1], hflip[0] +reg [7:0] LATCH_B; //OBJRAM BYTE 4: zoom LSBs[7:0] +reg [7:0] LATCH_C; //OBJRAM BYTE 6: sprite code LSBs[7:0] +reg [7:0] LATCH_D; //OBJRAM BYTE 8: sprite code MSBs[7:6], vflip[5], obj palette[4:1], xpos MSB[0] +reg [7:0] LATCH_E; //OBJRAM BYTE A: xpos LSBs[7:0] +`ifdef SIMULATION +reg [7:0] LATCH_F; //OBJRAM BYTE C: ypos[7:0] +`endif + +assign o_XPOS_D0 = LATCH_E[0]; +assign o_LATCH_A_D2 = LATCH_A[2]; + +//LATCH_A +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!LATCH_A_en_n) LATCH_A <= i_OBJDATA & {6'b1111_11, ENABLE_DOUBLE_HEIGHT_MODE[0], 1'b1}; + if(!LATCH_B_en_n) LATCH_B <= i_OBJDATA; + if(!LATCH_C_en_n) LATCH_C <= i_OBJDATA; + if(!LATCH_D_en_n) LATCH_D <= i_OBJDATA; + if(!LATCH_E_en_n) LATCH_E <= i_OBJDATA; + end +end + + + + +/////////////////////////////////////////////////////////// +////// HZOOM FEEDBACK ACCUMULATOR +//// + +/* + FEEDBACK LOOP[9:0] + ┌────────────────────────┐ + │ │ + │ ┌─────┐ ┌─────┐ │ + │ │ A │CLK─►│ D │ │ + └─► │ D │RST─►│ F │ │ + │ D │ │ F │ │ + │ E ├(+)─►│ ├──┴──► FEEDBACK_LOOP[9:7] = PIXELSEL[2:0] + ZOOM FACTOR ──────► │ R │ │ │ + │ │ │ │ + └──┬──┘ └─────┘ + │ CARRY + │ ┌─────┐ + │ CLK─►│ C │ + | RST─►│ N ├─────► TILELINE_ADDR[2:0] + └───────►│ T │ + CNT └─────┘ +*/ + +reg hzoom_cnt_n; +reg hzoom_rst_n; +reg [9:0] hzoom_acc = 10'd0; +wire [10:0] hzoom_nextval = hzoom_acc + {LATCH_A[7:6], LATCH_B}; +reg [2:0] hzoom_tileline_cntr; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!hzoom_rst_n) begin + hzoom_acc <= 10'd0; + hzoom_tileline_cntr <= 3'd0; + end + else begin + if(!hzoom_cnt_n) begin + hzoom_acc <= hzoom_nextval[9:0]; + if(hzoom_nextval[10] == 1'b1) begin + hzoom_tileline_cntr <= hzoom_tileline_cntr + 3'd1; + end + end + end + end +end + + + +/////////////////////////////////////////////////////////// +////// TILELINE/HLINE COMPLETE FLAG +//// + +/* + "tileline complete" flag is the carry output of hzoom feedback + accumulator. It notifies the end of the current tileline(8 pixels) + + "hline complete" flag notifies the end of current hline. The multiplexer + selects proper complete flag according to the width of the current + sprite. +*/ + +reg hline_complete; +wire tileline0_complete = hzoom_nextval[10]; +wire tileline1_complete = &{hzoom_nextval[10], hzoom_tileline_cntr[0]}; +wire tileline3_complete = &{hzoom_nextval[10], hzoom_tileline_cntr[0], hzoom_tileline_cntr[1]}; +wire tileline7_complete = &{hzoom_nextval[10], hzoom_tileline_cntr[0], hzoom_tileline_cntr[1], hzoom_tileline_cntr[2]}; + +always @(*) begin + case({LATCH_A[5:3]}) + 4'h0: hline_complete <= tileline3_complete; //32*32 4 horizontal tileline + 4'h1: hline_complete <= tileline1_complete; //16*32 2 horizontal tileline + 4'h2: hline_complete <= tileline3_complete; //32*16 4 horizontal tileline + 4'h3: hline_complete <= tileline7_complete; //64*64 8 horizontal tileline + 4'h4: hline_complete <= tileline0_complete; //8*8 1 horizontal tileline + 4'h5: hline_complete <= tileline1_complete; //16*8 2 horizontal tileline + 4'h6: hline_complete <= tileline0_complete; //8*16 1 horizontal tileline + 4'h7: hline_complete <= tileline1_complete; //16*16 2 horizontal tileline + endcase +end + + + + + +/////////////////////////////////////////////////////////// +////// VZOOM FEEDBACK ACCUMULATOR +//// + +/* + FEEDBACK LOOP[9:0] + ┌────────────────────────┐ + │ │ + │ ┌─────┐ ┌─────┐ │ + │ │ A │CLK─►│ D │ │ + └─► │ D │RST─►│ F │ │ + │ D │ │ F │ │ + │ E ├(+)─►│ ├──┴──► FEEDBACK_LOOP[9:7] = HLINE_ADDR[2:0] + ZOOM FACTOR ──────► │ R │ │ │ + │ │ │ │ + └──┬──┘ └─────┘ + │ CARRY + │ ┌─────┐ + │ CLK─►│ C │ + | RST─►│ N ├─────► VTILE_ADDR[3:0] + └───────►│ T │ + CNT └─────┘ +*/ + +reg vzoom_cnt_n; +reg vzoom_rst_n; +reg [9:0] vzoom_acc = 10'd0; +wire [10:0] vzoom_nextval = vzoom_acc + {LATCH_A[7:6], LATCH_B}; +reg [3:0] vzoom_vtile_cntr; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(!vzoom_rst_n) begin + vzoom_acc <= 10'd0; + vzoom_vtile_cntr <= 4'd0; + end + else begin + if(!vzoom_cnt_n) begin + vzoom_acc <= vzoom_nextval[9:0]; + if(vzoom_nextval[10] == 1'b1) begin + vzoom_vtile_cntr <= vzoom_vtile_cntr + 4'd1; + end + end + end + end +end + + + + + +/////////////////////////////////////////////////////////// +////// DRAWING COMPLETE FLAG +//// + +/* + "vtile_complete" notifies the last hline of the sprite. It is ANDed with + the carry output of the vzoom feedback accumulator, so the flag only + appears on the drawing cycle of the last hline. Stops sprite drawing + after vtile_complete + hline_complete were asserted. +*/ + +reg vtile_complete_n; +wire vtile0_complete_n = ~vzoom_nextval[10]; +wire vtile1_complete_n = ~&{vzoom_nextval[10], vzoom_vtile_cntr[0]}; +wire vtile3_complete_n = ~&{vzoom_nextval[10], vzoom_vtile_cntr[0], vzoom_vtile_cntr[1]}; +wire vtile7_complete_n = ~&{vzoom_nextval[10], vzoom_vtile_cntr[0], vzoom_vtile_cntr[1], vzoom_vtile_cntr[2]}; +wire vtile15_complete_n = ~&{vzoom_nextval[10], vzoom_vtile_cntr[0], vzoom_vtile_cntr[1], vzoom_vtile_cntr[2], vzoom_vtile_cntr[3]}; + +always @(*) begin + case({LATCH_A[1], LATCH_A[5:3]}) + 4'h0: vtile_complete_n <= vtile3_complete_n; //32*32 4 vetrical tiles + 4'h1: vtile_complete_n <= vtile3_complete_n; //16*32 4 vetrical tiles + 4'h2: vtile_complete_n <= vtile1_complete_n; //32*16 2 vetrical tiles + 4'h3: vtile_complete_n <= vtile7_complete_n; //64*64 8 vetrical tiles + 4'h4: vtile_complete_n <= vtile0_complete_n; //8*8 1 vetrical tiles + 4'h5: vtile_complete_n <= vtile0_complete_n; //16*8 1 vetrical tiles + 4'h6: vtile_complete_n <= vtile1_complete_n; //8*16 2 vetrical tiles + 4'h7: vtile_complete_n <= vtile1_complete_n; //16*16 2 vetrical tiles + 4'h8: vtile_complete_n <= vtile7_complete_n; //32*64 8 vetrical tiles + 4'h9: vtile_complete_n <= vtile7_complete_n; //16*64 8 vetrical tiles + 4'hA: vtile_complete_n <= vtile3_complete_n; //32*32 4 vetrical tiles + 4'hB: vtile_complete_n <= vtile15_complete_n; //64*128 16 vetrical tiles + 4'hC: vtile_complete_n <= vtile1_complete_n; //8*16 2 vetrical tiles + 4'hD: vtile_complete_n <= vtile1_complete_n; //16*16 2 vetrical tiles + 4'hE: vtile_complete_n <= vtile3_complete_n; //8*32 4 vetrical tiles + 4'hF: vtile_complete_n <= vtile3_complete_n; //16*32 4 vetrical tiles + endcase +end + + + + + + +/////////////////////////////////////////////////////////// +////// FRAMEBUFFER XYPOS COUNTER +//// + +//countup signal delay registers +reg xpos_cnt_dly_n; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + xpos_cnt_dly_n <= ~o_WRTIME2; + end +end + +reg ypos_cnt_n; +reg [3:0] ypos_cnt_dly_n; +always @(posedge i_EMU_MCLK) +begin if(!i_EMU_CLK6MPCEN_n) begin + ypos_cnt_dly_n[0] <= ypos_cnt_n; + ypos_cnt_dly_n[3:1] <= ypos_cnt_dly_n[2:0]; + end +end + + +//xpos counter +reg [7:0] evenbuffer_xpos_counter; +reg [7:0] oddbuffer_xpos_counter; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) + begin + if(LATCH_F_en_n == 1'b0) begin //2clk delay AND LATCH_F_en_n -> preload data before sprite drawing + evenbuffer_xpos_counter <= {LATCH_D[0], LATCH_E[7:1]} + LATCH_E[0]; + oddbuffer_xpos_counter <= {LATCH_D[0], LATCH_E[7:1]}; + end + else begin + if(ypos_cnt_dly_n[2] == 1'b0) begin + evenbuffer_xpos_counter <= {LATCH_D[0], LATCH_E[7:1]} + LATCH_E[0]; + oddbuffer_xpos_counter <= {LATCH_D[0], LATCH_E[7:1]}; + end + else begin + if(xpos_cnt_dly_n == 1'b0) begin + evenbuffer_xpos_counter <= evenbuffer_xpos_counter + 8'd1; + oddbuffer_xpos_counter <= oddbuffer_xpos_counter + 8'd1; + end + end + end + end +end + + +//ypos counter +reg [7:0] buffer_ypos_counter; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(LATCH_F_en_n == 1'b0) begin + buffer_ypos_counter <= i_OBJDATA; + end + else begin + if(ypos_cnt_dly_n[3] == 1'b0) begin + buffer_ypos_counter <= buffer_ypos_counter + 8'd1; + end + end + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// DRAWING STATUS FLAGS +//// + +wire evenbuffer_xpos_d7 = evenbuffer_xpos_counter[7]; + +wire x_offscreen = ~(~oddbuffer_xpos_counter[7] | oddbuffer_xpos_counter[6]); //0-255 or 384-511 +wire y_offscreen = (buffer_ypos_counter == 8'd255) ? 1'b1 : 1'b0; + +wire end_of_tileline = tileline0_complete | x_offscreen; +wire end_of_hline = hline_complete | x_offscreen; +//wire end_of_last_hline_n = ~(~(vtile_complete_n | vzoom_cnt_n) | y_offscreen); +wire end_of_last_hline_n = ~(~(vtile_complete_n) | y_offscreen); + + + + + + + +/////////////////////////////////////////////////////////// +////// SPRITE ENGINE FSM +//// + +/* + [Comb] STATUS FLAGS +*/ + +wire [2:0] drawing_status = {end_of_last_hline_n, end_of_hline, end_of_tileline}; + +localparam KEEP_DRAWING = 3'b100; +localparam END_OF_TILELINE = 2'b01; //3'bX01 will not work +localparam END_OF_HLINE = 3'b111; +localparam END_OF_SPRITE = 3'b011; + + + +/* + [4H CLK] FSM SUSPEND AND RESUME +*/ + +reg [1:0] FSM_SUSPEND_DLY; +wire FSM_SUSPEND = ((i_HBLANK_n & i_VBLANKH_n) | FSM_SUSPEND_DLY[1]) | ~DMA_4H_CLKD_n; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if({i_ABS_4H, i_ABS_2H, i_ABS_1H} == 3'd3) begin + FSM_SUSPEND_DLY[0] <= (i_HBLANK_n & i_VBLANKH_n); + FSM_SUSPEND_DLY[1] <= FSM_SUSPEND_DLY[0]; + end + end +end + + + +/* + [6M CLK] CHA O/V +*/ + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(pixel3_n == 1'b0) begin + o_CHAOV <= FSM_SUSPEND; + end + end +end + + + +/* + [4H CLK] FOR ATTRIBUTE FETCHING END DETECTION +*/ + +reg LATCH_F_2H_NCLKD_en_n = 1'b1; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(pixel3_n == 1'b0) begin + LATCH_F_2H_NCLKD_en_n <= LATCH_F_en_n; + end + end +end + + + +/* + [6M CLK] HSIZE PARITY +*/ + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(hzoom_rst_n == 1'b0) begin //preload, new hline + hsize_parity <= 1'b1; + end + else begin + if(hzoom_cnt_n == 1'b0) begin + hsize_parity <= ~hsize_parity; + end + end + end +end + + + +/* + [6M CLK] FINITE STATE MACHINE +*/ + +/* + ATTR_LATCHING_S0: + Put 1 in latching_start for 1 pixel. After that, sprite attributes are latched + sequentially while 1H clocked shift register shifting 0(inverted input) + + ATTR_LATCHING_S1: + FSM does nothing while 1H clocked sr working for 14 pixels. FSM jumps to + HCOUNT_S0 if ORed signal of LATCH_F_2H_NCLKD_en_n(sampled at a rising edge of + 4H) and pixel3_n is 0. Reset HV accumulator at this time. + + HCOUNT_S0: + hcounter_en_n becomes 0 during HCOUNT_S0. If H accumulator's carry is enabled, + FSM controls hcounter_en_n according to the hsize_parity(this is important) + if hsize at the point is odd(=1), put 0 in pixellatch_wait_n(stop linelatch to + latch a pixel). In contrast, if hsize at the point is even(=0), put 1 in + pixellatch_wait_n + + HWAIT_S0: + Current tileline data is always latched at a rising edge (pixel3_n = 0) of + the 2H, so if the tileline drawing is finished before that, insert HWAIT_S0 + cycle to wait for the next data. At a rising edge of 2H, the FSM can branch to: + HCOUNT_S0(hline not completed) + ODDSIZE_S0(current hline is ended with an =odd numbered size 7, 9, 11...) + SUSPEND_S0(active video period) + + ODDSIZE_S0: + If the previous state was HCOUNT_S0 or HWAIT_S0, and if it satisfies the + condition that hsize is odd, FSM goes ODDSIZE_S0 to end current hline drawing + cycle. The reason why this state exists is as follows: + 1. The engine draws sprite two pixels(EVEN+ODD) per one buffer access cycle. + It latches the first pixel from pixel selctor, switches selector to pick + the next pixel. Writes these two pixels to the frame buffer. + 2. If the current tileline's size is an odd number, and should be terminate the + cycle, it can't be done. Because the first pixel is still on the pixel + selector's output without being latched. And, WRTIME has not been asserted. + It(the first pixel) can't be written on the buffer. + 3. This cycle maintained for four pixels(next pixel3_n = next rising edge of 2H) + During this cycle, the first pixel is latched and WRTIME is asserted in + pixel3_n of ODDSIZE_S0. + + SUSPEND_S0: + Branches to this state unconditionally when FSM_SUSPEND is 1. When the FSM is in + ATTR_LATCHING_S1, it moves to this state after attrubute latching. The FSM checks + FSM_SUSPEND at every rising edge of 2H. + Note that WRTIME2 and o_PIXELLATCH_WAIT_n will still be on the lines after a + suspension, since they are just delayed signals from the shift registers. + + XOFF_S0: + A true delay to handle sprite clipping. +*/ + +//Declare states +localparam ATTR_LATCHING_S0 = 3'd1; +localparam ATTR_LATCHING_S1 = 3'd2; +localparam HCOUNT_S0 = 3'd3; +localparam HWAIT_S0 = 3'd4; +localparam ODDSIZE_S0 = 3'd5; +localparam XOFF_S0 = 3'd6; +localparam SUSPEND_S0 = 3'd0; + +//Declare state register +reg [2:0] sprite_engine_state = SUSPEND_S0; //3'd0 = reset state, Quartus always reset FSM as 0. Vivado ?? + +//Determine the next state synchronously, based on the current state and the input +always @ (posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + case(sprite_engine_state) + // ATTRIBUTE LATCHING START + ATTR_LATCHING_S0: + sprite_engine_state <= ATTR_LATCHING_S1; + + // WAIT FOR LATCHING COMPLETION + ATTR_LATCHING_S1: + if(pixel3_n == 1'b0) begin//exit condition: 1 pixel just after end of ORINC(negative logic) + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(LATCH_F_2H_NCLKD_en_n == 1'b0) begin + if(FSM_SUSPEND == 1'b0) begin //keep going + sprite_engine_state <= HCOUNT_S0; + end + else begin //if not, go suspend_s0 + sprite_engine_state <= SUSPEND_S0; + end + end + else begin + sprite_engine_state <= ATTR_LATCHING_S1; + end + end + end + else begin + sprite_engine_state <= ATTR_LATCHING_S1; + end + + // DRAWING + // IMPORTANCE LEVEL: END_OF_SPRITE > END_OF_HLINE > END_OF_TILELINE > KEEP_DRAWING + HCOUNT_S0: + if(drawing_status == END_OF_SPRITE) begin + if(pixel3_n == 1'b0) begin //at pixel 3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going + if(hsize_parity == 1'b0) begin //zoomed horizontal size is even + sprite_engine_state <= ATTR_LATCHING_S0; + end + else begin + sprite_engine_state <= ODDSIZE_S0; + end + end + else begin //if not, go suspend_s0 + sprite_engine_state <= SUSPEND_S0; + end + end + end + else begin //at pixel 0, 1, 2 + sprite_engine_state <= HWAIT_S0; + end + end + else if(drawing_status == END_OF_HLINE) begin + if(pixel3_n == 1'b0) begin //at pixel 3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going + if(hsize_parity == 1'b0) begin //zoomed horizontal size is even + if(evenbuffer_xpos_d7 == 1'b1) begin //if END_OF_HLINE flag is triggered by the offscreen flag + sprite_engine_state <= XOFF_S0; + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin //zoomed horizontal size is odd + sprite_engine_state <= ODDSIZE_S0; + end + end + else begin //if not, go SUSPEND_S0 + sprite_engine_state <= SUSPEND_S0; + end + end + end + else begin //at pixel 0, 1, 2 + sprite_engine_state <= HWAIT_S0; + end + end + else if(drawing_status[1:0] == END_OF_TILELINE) begin + if(pixel3_n == 1'b0) begin //at pixel 3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going + sprite_engine_state <= HCOUNT_S0; + end + else begin//if not, go suspend_s0 + sprite_engine_state <= SUSPEND_S0; + end + end + end + else begin //at pixel 0, 1, 2 + sprite_engine_state <= HWAIT_S0; + end + end + else begin // `KEEP_DRAWING + if(pixel3_n == 1'b0) begin //at pixel 3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going + sprite_engine_state <= HCOUNT_S0; + end + else begin //if not, go SUSPEND_S0 + sprite_engine_state <= SUSPEND_S0; + end + end + end + else begin //at pixel 0, 1, 2 + sprite_engine_state <= HCOUNT_S0; + end + end + + + // WAIT STATE: WAITING FOR /PX3 + HWAIT_S0: + if(pixel3_n == 1'b0) begin //exit condition: encounter px3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going, return to HCOUNT_S0 or fetch new attributes + if(drawing_status == END_OF_SPRITE) begin + if(hsize_parity == 1'b0) begin //zoomed horizontal size is even + sprite_engine_state <= ATTR_LATCHING_S0; + end + else begin //zoomed horizontal size is odd + sprite_engine_state <= ODDSIZE_S0; + end + end + else if(drawing_status == END_OF_HLINE) begin + if(hsize_parity == 1'b0) begin //zoomed horizontal size is even + if(evenbuffer_xpos_d7 == 1'b1) begin //if END_OF_HLINE flag is triggered by the offscreen flag + sprite_engine_state <= XOFF_S0; + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin //zoomed horizontal size is odd + sprite_engine_state <= ODDSIZE_S0; + end + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin //if not, go suspend_s0 + sprite_engine_state <= SUSPEND_S0; + end + end + end + else begin + sprite_engine_state <= HWAIT_S0; + end + + + // WAIT FOR WRITE ONLY A SINGLE PIXEL + ODDSIZE_S0: + if(pixel3_n == 1'b0) begin //exit condition: encounter px3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //keep going, return to HCOUNT_S0 or fetch new attributes + if(drawing_status == END_OF_SPRITE) begin + sprite_engine_state <= ATTR_LATCHING_S0; + end + else if(drawing_status == END_OF_HLINE) begin + if(evenbuffer_xpos_d7 == 1'b1) begin //if END_OF_HLINE flag is triggered by the offscreen flag + sprite_engine_state <= XOFF_S0; + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin //if not, go suspend_s0. *But get new properties first* + if(drawing_status == END_OF_SPRITE) begin + sprite_engine_state <= ATTR_LATCHING_S0; + end + else begin + sprite_engine_state <= SUSPEND_S0; + end + end + end + end + else begin + sprite_engine_state <= ODDSIZE_S0; + end + + // TRUE DELAY FOR H CLIPPING + XOFF_S0: + if(pixel3_n == 1'b0) begin //exit condition: encounter px3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin + if(drawing_status == END_OF_SPRITE) begin + sprite_engine_state <= ATTR_LATCHING_S0; + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin + sprite_engine_state <= XOFF_S0; + end + end + end + + + // SUSPEND STATE: WAITING FOR /PX3 + SUSPEND_S0: + if(pixel3_n == 1'b0) begin //exit condition: encounter px3 + if(new_vblank_n == 1'b0) begin + sprite_engine_state <= ATTR_LATCHING_S0; //new vblank + end + else begin + if(FSM_SUSPEND == 1'b0) begin //return to HCOUNT_S0 or fetch new attributes + if(drawing_status == END_OF_SPRITE) begin + sprite_engine_state <= HCOUNT_S0; + end + else if(drawing_status == END_OF_HLINE) begin + if(hsize_parity == 1'b0) begin //zoomed horizontal size is even + if(evenbuffer_xpos_d7 == 1'b1) begin //if END_OF_HLINE flag is triggered by the offscreen flag + sprite_engine_state <= XOFF_S0; + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin //zoomed horizontal size is odd + sprite_engine_state <= ODDSIZE_S0; + end + end + else begin + sprite_engine_state <= HCOUNT_S0; + end + end + else begin + sprite_engine_state <= SUSPEND_S0; + end + end + end + + default: + sprite_engine_state <= SUSPEND_S0; + + endcase + end +end + +//Determine the output based only on the current state and the input (do not wait for a clock edge) +//signal list: +// latching_start +// hzoom_cnt_n +// hzoom_rst_n +// vzoom_cnt_n +// vzoom_rst_n +// ypos_cnt_n +// pixellatch_wait_n +always @(*) //Quartus +begin + case(sprite_engine_state) + ATTR_LATCHING_S0: begin + latching_start <= 1'b1; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + ATTR_LATCHING_S1: begin + if(LATCH_F_2H_NCLKD_en_n == 1'b0 && pixel3_n == 1'b0) begin + latching_start <= 1'b0; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b0; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b0; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + else begin + latching_start <= 1'b0; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + + HCOUNT_S0: begin + /* + HCOUNT_S0 + 대기 상태: 다음 PIXEL3_n까지 기다립니다. + + 1. END_OF_SPRITE가 PIXEL3_n전에 감지되었을 경우 pixellatch_wait_n + 은 0이 되고, hv피드백 카운터를 정지해야 합니다. HWAIT_S0에서 hv피드백 + 카운터를 조작하기 때문입니다. PIXEL3_n에 감지되었을 경우는 + pixellatch_wait_n가 1이고, hv피드백 카운터를 조작해야 합니다. + 2. END_OF_SPRITE가 PIXEL3_n전에 감지되었을 경우 pixellatch_wait_n + 은 0이 되고, hv피드백 카운터를 정지해야 합니다. HWAIT_S0에서 hv피드백 + 카운터를 조작하기 때문입니다. PIXEL3_n에 감지되었을 경우는 + pixellatch_wait_n가 1이고, hv피드백 카운터를 조작해야 합니다. + 3. END_OF_SPRITE가 PIXEL3_n전에 감지되었을 경우 pixellatch_wait_n + 은 0이 되고, hv피드백 카운터를 정지해야 합니다. HWAIT_S0에서 hv피드백 + 카운터를 조작하기 때문입니다. PIXEL3_n에 감지되었을 경우는 + pixellatch_wait_n가 1이고, hv피드백 카운터를 조작해야 합니다. + 4. KEEP_DRAWING에는 pixellatch_wait_n은 1이 되고, hv피드백 카운터를 + 계속 증가시켜야 합니다. + */ + + latching_start <= 1'b0; + + if(drawing_status == END_OF_SPRITE) begin + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= ~hsize_parity; + end + end + else if(drawing_status == END_OF_HLINE) begin + if(hsize_parity == 1'b0) begin //after drawing even pixels + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b0; + + vzoom_cnt_n <= 1'b0; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b0; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= ~hsize_parity; + end + end + else begin + if(pixel3_n == 1'b0) begin //pixel 3, after drawing odd pixles: will go to ODDSIZE_S0 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; //latch immediately + end + else begin //before pixel 3, will go to HWAIT_S0 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; //will be latched on pixel3 of HWAIT_S0 + end + end + + end + else if(drawing_status[1:0] == END_OF_TILELINE) begin + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; //latch anyway + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= ~hsize_parity; //odd size = wait for the even pixel, + //even size = latch(=do not need to be latched, will be drawn immediately) + end + end + else begin //`KEEP_DRAWING + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + end + end + + + HWAIT_S0: begin + /* + HWAIT_S0 + 대기 상태: 다음 PIXEL3_n까지 기다립니다. + + 1. END_OF_SPRITE인 경우 hsize_parity에 따라 출력이 달라집니다. + 짝수개를 그린 후라면 스프라이트를 그만 그려도 되지만, 홀수개를 + 그린 후라면 ODDSIZE_S0을 삽입해야 하기 때문에 hv피드백 카운터를 + 조작해서는 안 됩니다. + 2. END_OF_HLINE인 경우 hsize_parity에 따라 출력이 달라집니다. + 짝수개를 그린 후라면 바로 다음 tileline을 그려야 하지만, 홀수개를 + 그린 후라면 ODDSIZE_S0을 삽입해야 하기 때문에 hv피드백 카운터를 + 조작해서는 안 됩니다. + 3. END_OF_TILELINE인 경우 PIXEL3_n이 오면 카운터를 증가시킵니다 + 4. KEEP_DRAWING은 발생할 수 없지만 모든 경우를 기술해야 하므로 + 작성합니다. + */ + + latching_start <= 1'b0; + + if(drawing_status == END_OF_SPRITE) begin + if(hsize_parity == 1'b0) begin //after drawing even pixels + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else begin //after drawing odd pixels: everything will be changed in ODDSIZE_S0 + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + end + else if(drawing_status == END_OF_HLINE) begin + if(hsize_parity == 1'b0) begin //after drawing even pixels + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b0; + + vzoom_cnt_n <= 1'b0; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b0; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else begin //after drawing odd pixels: everything will be changed in ODDSIZE_S0 + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + end + else if(drawing_status[1:0] == END_OF_TILELINE) begin + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else begin //`KEEP_DRAWING: WILL NOT HAPPEN + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + end + end + + ODDSIZE_S0: begin + /* + ODDSIZE_S0 + 지금까지 그린 픽셀 갯수가 홀수인 상황에서 짝수 버퍼에 0을 쓰고 한 + 라인 그리기를 마쳐야 하는 경우입니다. 이 상태로 넘어온 경우 hsize_ + parity가 홀수인 것은 확정된 상황입니다. + + 1. END_OF_SPRITE인 경우 스프라이트 그리기를 마쳐야 합니다. + 2. END_OF_HLINE인 경우 ypos와 vzoom을 증가시켜야 합니다. + 3. END_OF_TILELINE은 발생할 수 없지만 모든 경우를 기술해야 하므로 + 작성합니다. + 4. KEEP_DRAWING은 발생할 수 없지만 모든 경우를 기술해야 하므로 + 작성합니다. + */ + + latching_start <= 1'b0; + + if(drawing_status == END_OF_SPRITE) begin + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b0; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b0; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else if(drawing_status == END_OF_HLINE) begin + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b0; + + vzoom_cnt_n <= 1'b0; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b0; + + pixellatch_wait_n <= 1'b0; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else if(drawing_status[1:0] == END_OF_TILELINE) begin //WILL NOT HAPPEN + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b0; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + else begin //`KEEP_DRAWING + if(pixel3_n == 1'b0) begin //pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b1; + end + else begin //before pixel 3 + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + end + end + + SUSPEND_S0: begin + /* + SUSPEND_S0 + 작업이 재개될 때 까지 기다립니다. + */ + latching_start <= 1'b0; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + + XOFF_S0: begin + latching_start <= 1'b0; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + + default: begin + latching_start <= 1'b0; + + hzoom_cnt_n <= 1'b1; + hzoom_rst_n <= 1'b1; + + vzoom_cnt_n <= 1'b1; + vzoom_rst_n <= 1'b1; + + ypos_cnt_n <= 1'b1; + + pixellatch_wait_n <= 1'b0; + end + endcase +end + + + +/* + [6M CLK] WRTIME DELAY +*/ + +reg wrtime1; +wire oddsize_wrtime0 = (sprite_engine_state == ODDSIZE_S0 && pixel3_n == 1'b0) ? 1'b1 : 1'b0; +wire evensize_wrtime0 = (sprite_engine_state == HCOUNT_S0) ? ~hsize_parity : 1'b0; +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + //feed hsize_parity normally, but it should be 1 when PIXEL3 at ODDSIZE_S0 + wrtime1 <= evensize_wrtime0 | oddsize_wrtime0; + o_WRTIME2 <= wrtime1; + end +end + + + +/* + [6M CLK] o_PIXELLATCH_WAIT_n DELAY +*/ + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + o_PIXELLATCH_WAIT_n <= pixellatch_wait_n; + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// PIXEL SELECT(linelatch), LINE SELECT, TILE SELECT +//// + +//linelatch PIXEL SELECT +assign o_PIXELSEL = hzoom_acc[9:7] ^ {3{LATCH_A[0]}}; //OBJ_HFLIP + +//CHARRAM ADDRESS +wire [2:0] TILELINE_ADDR = hzoom_tileline_cntr ^ {3{LATCH_A[0]}}; +wire [2:0] HLINE_ADDR = vzoom_acc[9:7] ^ {3{LATCH_D[5]}}; +wire [3:0] VTILE_ADDR = vzoom_vtile_cntr ^ {4{LATCH_D[5]}}; +reg [13:0] CHARRAM_ADDR; //unmultiplexed + +`ifdef SIM_UNFOLD_DRAM_ADDR + assign o_OCA = CHARRAM_ADDR; +`else + assign o_OCA = (i_CHAMPX == 1'b0) ? CHARRAM_ADDR[7:0] : {1'b1, CHARRAM_ADDR[13:8], 1'b1}; //RAS : CAS +`endif + +always @(*) begin + case({LATCH_A[1], LATCH_A[5:3]}) + // |-------(OBJ CODE)-------| + 4'h0: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:3], VTILE_ADDR[1:0], HLINE_ADDR[2:0], TILELINE_ADDR[1:0]}; //32*32 4 vetrical tiles + 4'h1: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:2], VTILE_ADDR[1:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*32 4 vetrical tiles + 4'h2: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:2], VTILE_ADDR[0:0], HLINE_ADDR[2:0], TILELINE_ADDR[1:0]}; //32*16 2 vetrical tiles + 4'h3: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:5], VTILE_ADDR[2:0], HLINE_ADDR[2:0], TILELINE_ADDR[2:0]}; //64*64 8 vetrical tiles + 4'h4: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:0], 1'b0, HLINE_ADDR[2:0] }; //8*8 1 vetrical tiles + 4'h5: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*8 1 vetrical tiles + 4'h6: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:0], VTILE_ADDR[0:0], HLINE_ADDR[2:0] }; //8*16 2 vetrical tiles + 4'h7: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:1], VTILE_ADDR[0:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*16 2 vetrical tiles + + 4'h8: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:4], VTILE_ADDR[2:0], HLINE_ADDR[2:0], TILELINE_ADDR[1:0]}; //32*64 8 vetrical tiles + 4'h9: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:3], VTILE_ADDR[2:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*64 8 vetrical tiles + 4'hA: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:4], VTILE_ADDR[1:0], HLINE_ADDR[2:0], TILELINE_ADDR[1:0]}; //32*32 4 vetrical tiles + 4'hB: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:6], VTILE_ADDR[3:0], HLINE_ADDR[2:0], TILELINE_ADDR[2:0]}; //64*128 16 vetrical tiles + 4'hC: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:0], VTILE_ADDR[0:0], HLINE_ADDR[2:0] }; //8*16 2 vetrical tiles + 4'hD: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:1], VTILE_ADDR[0:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*16 2 vetrical tiles + 4'hE: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:1], VTILE_ADDR[1:0], HLINE_ADDR[2:0] }; //8*32 4 vetrical tiles + 4'hF: CHARRAM_ADDR <= {LATCH_D[7:6], LATCH_C[7:2], VTILE_ADDR[1:0], HLINE_ADDR[2:0], TILELINE_ADDR[0:0]}; //16*32 4 vetrical tiles + endcase +end + + + + + + + + +/////////////////////////////////////////////////////////// +////// SCREEN COUNTER +//// + +//X Screen Counter +reg [6:0] buffer_x_screencounter = 7'd0; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + if(i_ABS_1H == 1'b1) begin //negedge of 1H + if(i_OBJWR == 1'b1) begin + buffer_x_screencounter <= 7'd0; + end + else begin + if(buffer_x_screencounter == 7'd127) buffer_x_screencounter <= 7'd0; + else buffer_x_screencounter <= buffer_x_screencounter + 7'd1; + end + end + end +end + +/* + Y Screen Counter +*/ + +reg prev_hblank; +reg [7:0] buffer_y_screencounter = 8'd15; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + prev_hblank <= i_HBLANK_n; + + if(i_VBLANK_n == 1'b0) begin //async reset by VBLANK + buffer_y_screencounter <= 8'd15; + end + else begin + if(i_HBLANK_n == 1'b1 && prev_hblank == 1'b0) begin //1 clk after the positive edge of vblank + if(buffer_y_screencounter == 8'd255) buffer_y_screencounter <= 8'd0; + else buffer_y_screencounter <= buffer_y_screencounter + 8'd1; + end + end + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// BUFFER MUX +//// + +reg buffer_frame_parity = 1'b0; +reg prev_vblank; + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + prev_vblank <= i_VBLANK_n; + + if(i_VBLANK_n == 1'b0 && prev_vblank == 1'b1) begin + buffer_frame_parity <= ~buffer_frame_parity; + end + end +end + + +reg [15:0] EVENBUFFER_ADDR; +reg [15:0] ODDBUFFER_ADDR; + +`ifdef SIM_UNFOLD_DRAM_ADDR + assign o_FA = EVENBUFFER_ADDR; + assign o_FB = ODDBUFFER_ADDR; +`else + assign o_FA = (o_CAS == 1'b0) ? EVENBUFFER_ADDR[7:0] : EVENBUFFER_ADDR[15:8]; //RAS : CAS + assign o_FB = (o_CAS == 1'b0) ? ODDBUFFER_ADDR[7:0] : ODDBUFFER_ADDR[15:8]; //RAS : CAS +`endif + + +always @(*) begin + case(i_OBJWR) + 1'b1: begin //sprite drawing period + EVENBUFFER_ADDR <= {~buffer_frame_parity, buffer_ypos_counter, evenbuffer_xpos_counter[6:0]}; //sprite double buffering + ODDBUFFER_ADDR <= {~buffer_frame_parity, buffer_ypos_counter, oddbuffer_xpos_counter[6:0]}; //sprite double buffering + end + 1'b0: begin //active video period + EVENBUFFER_ADDR <= {buffer_frame_parity, buffer_y_screencounter ^ {8{i_FLIP}}, buffer_x_screencounter ^ {7{i_FLIP}}}; + ODDBUFFER_ADDR <= {buffer_frame_parity, buffer_y_screencounter ^ {8{i_FLIP}}, buffer_x_screencounter ^ {7{i_FLIP}}}; + end + endcase +end + + + + + + + +/////////////////////////////////////////////////////////// +////// XA7 XB7 +//// + +/* + When the X coordinate goes out of the screen (xpos>255), the xpos counter + value wraps around, which can damage the sprite drawn before, so make XA/XB + as 1 and overwrite it with the existing data without updating the value. + + Need to delay 1 clk. +*/ + +always @(posedge i_EMU_MCLK) begin + if(!i_EMU_CLK6MPCEN_n) begin + o_XA7 <= evenbuffer_xpos_counter[7]; + o_XB7 <= oddbuffer_xpos_counter[7]; + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// CAS +//// + +assign o_CAS = i_OBJHL; + + +endmodule \ No newline at end of file diff --git a/rtl/GX400_video/debug_bitmap_header.txt b/rtl/GX400_video/debug_bitmap_header.txt new file mode 100644 index 0000000..9b9cff5 --- /dev/null +++ b/rtl/GX400_video/debug_bitmap_header.txt @@ -0,0 +1 @@ +42 4D 36 A0 02 00 00 00 00 00 36 00 00 00 28 00 00 00 00 01 00 00 E0 00 00 00 01 00 18 00 00 00 00 00 00 A0 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF \ No newline at end of file diff --git a/rtl/GX400_video/debug_resnet_level.txt b/rtl/GX400_video/debug_resnet_level.txt new file mode 100644 index 0000000..bff043c --- /dev/null +++ b/rtl/GX400_video/debug_resnet_level.txt @@ -0,0 +1 @@ +00 01 02 04 05 06 08 09 0B 0D 0F 12 14 16 19 1C 21 24 29 2E 33 39 40 49 50 5B 68 78 8E A8 CC FF \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297.v b/rtl/ipcores/K005297/K005297.v new file mode 100644 index 0000000..84d9494 --- /dev/null +++ b/rtl/ipcores/K005297/K005297.v @@ -0,0 +1,1530 @@ +module K005297 ( + //master clock + input wire i_MCLK, + + //chip clock from bubble cart, synchronized to i_MCLK + input wire i_CLK4M_PCEN_n, + + //master reset + input wire i_MRST_n, + + //data-address inputs(register RW) + input wire i_REGCS_n, + input wire [15:0] i_DIN, + input wire [2:0] i_AIN, //A3, A2, A1 + input wire i_R_nW, + input wire i_UDS_n, + input wire i_LDS_n, + input wire i_AS_n, + + //data-address outputs(DMA transfer) + output reg [15:0] o_DOUT, + output wire [6:0] o_AOUT, //A7-A1 + output wire o_R_nW, + output wire o_UDS_n, + output wire o_LDS_n, + output wire o_AS_n, + output wire o_ALE, + + //DMA control + output wire o_BR_n, + input wire i_BG_n, + output wire o_BGACK_n, + + //CPU management + output wire o_CPURST_n, + output wire o_IRQ_n, + + //FC + output wire [2:0] o_FCOUT, + input wire [2:0] i_FCIN, + + //bubble side + output wire [3:0] o_BDOUT_n, + input wire [3:0] i_BDIN_n, + output wire o_BOOTEN_n, + output wire o_BSS_n, + output wire o_BSEN_n, + output wire o_REPEN_n, + output wire o_SWAPEN_n, + + input wire i_TEMPLO_n, + output wire o_HEATEN_n, + + input wire i_4BEN_n, + + //test? + output wire o_INT1_ACK_n, //pin 30 + input wire i_TST1, //pin 20 + input wire i_TST2, //pin 21 + input wire i_TST3, //pin 22 + input wire i_TST4, //pin 23 + input wire i_TST5, //pin 24 + + //bidirectional pin OE(internal) + output wire o_CTRL_DMAIO_OE_n, + output wire o_CTRL_DATA_OE_n +); + +/* + Verilog HDL model programmed by Sehyeon Kim(Raki), All .v source files in the K005297 directory are distributed as BSD-2. + GitHub @ika-musume, Twitter @RCAVictorCo + + + Konami 005296/005297 Bubble Memory Controller(BMC) cell level implementation based on the die shot below: + + Die shot: https://www.siliconpr0n.org/archive/doku.php?id=caps0ff:konami:005297 + + Designed in 1984, 3um YAMAHA C2MOS gate array. + + + Variations: + 005296: Comes with Bubble System 07A board, Ceramic Quad In-line Package(Centipede) + 005297: Comes with Bubble System 07E and 07F board, Plastic Shrinked Dual In-line Package(1.778 pitch) + + The main difference between the two is pinout of #1 and #64. These pins are swappable since they have two pads each. + This chip uses dynamic CMOS cells heavily, hence the 2-phase clock generator with delay lines exists. + See clocking information on supervisor module. I can't believe it, but the delay cell seems to give about 240ns of delay. + Probably not. All flip-flops operating at 2MHz SUBCLK output data at the falling edge of 4MHz master clock. + To meet this condition, the clock must be inverted, or put a delay of about 240ns. + + This model works at 4MHz. Use an external 74LVC1G14 for clock cleaning if you are going to make a hardware replacement. + + + Konami 005296/005297 Pinout + ┌───────U───────┐ + │ K005297 │ + D15 ──┤1 IO IO 64├── Vdd <--pin1 and 64 are swapped in K005296 + ┌────── BDO_D3/D1 ──┤2 O IO 63├── D14 + │ BDO_D2/D0 ──┤3 O IO 62├── D13 + │ BDO_D1 ──┤4 O IO 61├── D12 + bitwidth BDO_D0 ──┤5 O IO 60├── D11 + 4bit/2bit BDI_D3/D1 ──┤6 I IO 59├── D10 + │ BDI_D2/D0 ──┤7 I IO 58├── D9 + │ BDI_D1 ──┤8 I IO 57├── D8 + └────── BDI_D0 ──┤9 I IO 56├── D7 + /BSS ──┤10 O IO 55├── D6 + /BSEN ──┤11 O IO 54├── D5 + /REPEN ──┤12 O IO 53├── D4 + /SWAPEN ──┤13 O IO 52├── D3 + /BOOTEN ──┤14 O IO 51├── D2 + /TEMPLO ──┤15 I IO 50├── D1 + /HEATEN ──┤16 O IO 49├── D0 + Vss ──┤17 O 48├── ALE + CLK4M ──┤18 I O 47├── A7 + /4BEN ──┤19 I O 46├── A6 + TST1 ──┤20 I O 45├── A5 + TST2 ──┤21 I O 44├── A4 + TST3 ──┤22 I IO 43├── A3 + TST4 ──┤23 I IO 42├── A2 + TST5 ──┤24 I IO 41├── A1 + /CPURST ──┤25 O IO 40├── R/W + /MRST ──┤26 I IO 39├── /LDS + /BG ──┤27 I IO 38├── /UDS + /BGACK ──┤28 O IO 37├── FC2 + /BR ──┤29 O IO 36├── FC1 + /IACK1 ──┤30 O IO 35├── FC0 + /IRQ ──┤31 O IO 34├── /AS + Vdd ──┤32 I 33├── /REGCS + │ │ + └───────────────┘ + + + IMPLEMENTATION NOTE: + + + 20 Total latches - 4MHz master clock is too slow to sample any asynchronous write of the 68k @ 9.216MHz. + + Page Register(12) + Asynchronous latches have been used. Data is always stabilized before the bubble RW command is written. + + Status Flags(6) + BMC to CPU, unidirectional latces for flags. + + RW Command Register(2) + Asynchronous latches have been used. There's a possibility of timing hazard on the signal path below: + + RW CMD reg(latch) -> PLA FSM(comb) -> PLA output register(DFF) + + The original chip used D-latches for PLA output register. I used two 8bit width DFF sets that act as + a synchronizer. The primary one samples PLA output at negedge of ROT20_n[10], and the secondary one + samples the primary's output at posedge of ROT20_n[10]. Metastability risks still remain, but the + interval between two consecutive positive edge is 500ns(2MHz), so it is unlikely to be a major problem. + ----------------- + + + Wrong decoder + + I fixed wrong output decoder that always causes internal bus contention. See ADDRESS DECODER section + ----------------- + + + ASIC-ish combinational loops and tricks + + Cut some combinational loops. See comments. + ----------------- +*/ + + + +/////////////////////////////////////////////////////////// +////// GLOBAL CLOCKS / FLAGS +//// + +parameter CHECK_CRC14 = 1'b0; + +//all stoarge elements works at falling edge of 4M/2M +//Use LVC1G14 for hardware replacement implementation +wire CLK4P_n = i_CLK4M_PCEN_n; //4MHz clock from bubble memory cartridge 12MHz/3 +wire CLK2P_n; //2MHz internal subclock that can be controlled by start/stop logic + +//global flags +wire SYS_RST_n; +wire SYS_RUN_FLAG, SYS_RUN_FLAG_SET_n; + +//timings +wire [7:0] ROT8; +wire [19:0] ROT20_n; + +assign o_FCOUT = 3'b101; //clip cells + +assign o_CPURST_n = o_BOOTEN_n; //C28 NAND, CPURST_n = BOOTEN_n + + + + + + +/////////////////////////////////////////////////////////// +////// SUPERVISOR MODULE +//// + +wire SYS_RUN_FLAG_RST_n; +wire FSMERR_RESTART_n, BOOTERR_RESTART_n; +wire CLK2M_STOP_n, CLK2M_STOP_DLYD_n; //for tempdet + +K005297_supervisor supervisor_main ( + .i_MCLK (i_MCLK ), + + .i_CLK4M_PCEN_n (CLK4P_n ), + + .i_MRST_n (i_MRST_n ), + + .i_HALT_n (i_TST1 ), + + .i_CLK2M_STOPRQ0_n (FSMERR_RESTART_n ), + .i_CLK2M_STOPRQ1_n (BOOTERR_RESTART_n ), + .o_CLK2M_STOP_n (CLK2M_STOP_n ), + .o_CLK2M_STOP_DLYD_n (CLK2M_STOP_DLYD_n ), + .o_CLK2M_PCEN_n (CLK2P_n ), + + .o_ROT8 (ROT8 ), + .o_ROT20_n (ROT20_n ), + + .o_SYS_RST_n (SYS_RST_n ), + .o_SYS_RUN_FLAG (SYS_RUN_FLAG ), + .o_SYS_RUN_FLAG_SET_n (SYS_RUN_FLAG_SET_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// INTERCONNECTS +//// + +//delayed ~ROT20_n[18] ...why not D19? +reg rot20_d18_dlyd1, rot20_d18_dlyd2; +always @(posedge i_MCLK) begin + if(!CLK2P_n) begin + rot20_d18_dlyd1 <= ~ROT20_n[18]; + rot20_d18_dlyd2 <= rot20_d18_dlyd1; + end +end + +//FSM +wire BDI_EN_SET_n, BDI_EN_RST_n; +wire CMDREG_RST_n; +wire ACC_START; +wire PGREG_SR_LD_EN; +wire CMD_ACCEPTED_n; + +//bubble related +wire BDI, BDI_EN; //bubble input stream + +//Synchronization Pattern Detector(K005297_SPDET) +wire SYNCTIP_n, SYNCED_FLAG, SYNCED_FLAG_SET_n; + +//Cycle Counter +wire CYCLECNTR_LSB; + +//Function Trigger +wire ACC_END, REP_START, SWAP_START, ACQ_START, ADDR_RST; + +//Error Map(mask) Register +wire MSKREG_LD, MSKREG_SR_LD, MSKREG_SR_LSB; + +//Supplementary Bubble Data Counter +wire SUPBD_START_n, SUPBD_END_n, SUPBD_ACT_n, SUPBDLCNTR_CNT; + +//Data Length Counter +wire DLCNTR_LSB, DLCNTR_CFLAG; + +//Byte Acquisition Counter +wire NEWBYTE, BYTEACQ_DONE; + +//Relative Page Counter +wire ABSPGCNTR_CNT_START, ABSPGCNTR_CNT_STOP, ABSPGCNTR_LSB; + +//Page Comparator +wire PGCMP_EQ; + +//Invalid Page Detector +wire ACC_INVAL_n, VALPG_FLAG_SET_n; + +//Page Register +wire PGREG_SR_SHIFT, PGREG_SR_LSB, PGREG_D2, PGREG_D8; + +//Invalid Page Data Generator(data scrambler) +wire MUXED_BDI, EFF_MUXED_BDI; + +//DMA Data Register Load Control +wire DMADREG_BDHI_LD, DMADREG_BDLO_LD; + +//DMA Timings +wire BR_START_n, DMA_END, DMA_WORD_END, DMA_WR_ACT_n, MSKADDR_INC, DMADREG_BDHILO_LD; + +//DMA Frontend +wire DMA_ACT; +assign o_CTRL_DMAIO_OE_n = ~DMA_ACT; + +//Bus Control Frontend +wire DMA_R_nW; //DMA Read/Write Indicator + +//DMA Data Register +wire BDRWADDR_INC, EFF_BDO; + +//Z14 Evaluator(CRC-14) +wire MUXED_BDO, Z14_UNLOCK_n, Z14_LOCKED_n; + +//Timer 25k +wire TIMER25K_CNT, TIMER25K_OUTLATCH_LD_n, TIMER25K_TIMEOVER_n; + +//Checksum Comparator +wire SUMEQ_n, INVALPG_LSB; + +//Temperature Detector +wire TEMPDROP_SET_n; + +//Address Decoder +//read-only register data +wire [15:0] DMATXREG; //0x40000 +wire [3:0] TIMERREG_MSBS; +wire [11:0] TIMERREG_LSBS; //0x40002 +wire [15:0] STFLAG; //0x40004 +//write-only register enables +wire ASYNC_LATCH_EN__PGREG_LD, ASYNC_LATCH_EN__CMDREG_WR_EN, ASYNC_LATCH_EN__STFLAG_CLR; + +//Data Output Mux +wire ALD_EN; //address latch data enable + +wire [3:0] ALD_DMABD; //address latch data for bubble data transfer +wire ALD_DMAMSK; //for mask data(error map) + +reg [15:0] INTLBUS; //When reading 0x40002, there's bus contention with 0x40000 caused by a defect in the decoder design + //The chip gets hot but seems to work well. I think polysilicon acts as a resistor because there's + //only one metal layer on this die. + + + + + + +/////////////////////////////////////////////////////////// +////// ACCESS MODE FLAG +//// + +wire UMODE_SET_n; +wire UMODE_n, BMODE_n; +wire ALD_nB_U; + +K005297_accmodeflag accmodeflag_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + .i_SYS_RUN_FLAG (SYS_RUN_FLAG ), + + .i_CMDREG_RST_n (CMDREG_RST_n ), + .i_BDI_EN_SET_n (BDI_EN_SET_n ), + .i_SYNCED_FLAG_SET_n (SYNCED_FLAG_SET_n ), + + .o_BMODE_n (BMODE_n ), + .o_UMODE_n (UMODE_n ), + .o_ALD_nB_U (ALD_nB_U ), + .o_UMODE_SET_n (UMODE_SET_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// ABSOLUTE PAGE COUNTER CONTROL +//// + +reg abspgcntr_ctrl_0, abspgcntr_ctrl_1; + +always @(posedge i_MCLK) begin + if(!CLK2P_n) begin + abspgcntr_ctrl_0 <= (ROT20_n[16] == 1'b0) ? (((o_HEATEN_n & UMODE_n) | ACC_START) & SYS_RST_n) : (abspgcntr_ctrl_0 & SYS_RST_n); + abspgcntr_ctrl_1 <= (ROT20_n[4] == 1'b0) ? (abspgcntr_ctrl_0 & SYS_RST_n) : (abspgcntr_ctrl_1 & SYS_RST_n); + end +end + +assign ABSPGCNTR_CNT_START = abspgcntr_ctrl_0 & ~abspgcntr_ctrl_1; +assign ABSPGCNTR_CNT_STOP = ~(~(ACC_END & ~ROT20_n[17]) & (o_CPURST_n | UMODE_SET_n)); + + + + + + +/////////////////////////////////////////////////////////// +////// MISC CONTROL SIGNALS AND FLAGS +//// + +//Access Activated +wire ACC_ACT_n; +SRNAND primitive_E24 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(SUPBD_END_n), .i_R_n(~(ACQ_START & rot20_d18_dlyd2)), .o_Q(ACC_ACT_n), .o_Q_n()); + +//Acquisition: Mask Load +reg ACQ_MSK_LD = 1'b0; //this sr latch's outer circuit has a combinational loop +always @(posedge i_MCLK) begin + if(SYS_RST_n == 1'b0) begin //synchronous reset(SR latch originally) + ACQ_MSK_LD <= 1'b0; + end + else begin + if(!CLK2P_n) begin + if(ROT20_n[19] == 1'b0) begin //SR latch's reset works @ ROT20[0], ACQ_START_D0, ACQ-START is always asserted before ROT20[0] + if(ACQ_START == 1'b1) begin + ACQ_MSK_LD <= 1'b1; + end + end + else if(ROT20_n[1] == 1'b0) begin //ACQ_MSK_LD changes @ ROT20[0], MSKREG_SR_LD changes @ ROT20[3] or [18] + if(ACQ_MSK_LD & MSKREG_SR_LD == 1'b1) begin + ACQ_MSK_LD <= 1'b0; + end + end + else begin + ACQ_MSK_LD <= ACQ_MSK_LD; + end + end + end +end + +//ACQ_MSK_LD delayed +reg acq_msk_ld_dlyd = 1'b0; +always @(posedge i_MCLK) begin + if(SYS_RST_n == 1'b0) begin //synchronous reset(SR latch originally) + acq_msk_ld_dlyd <= 1'b0; + end + else begin + if(!CLK2P_n) begin + if(ROT20_n[15] == 1'b0) begin + if(ACQ_MSK_LD == 1'b1) begin + acq_msk_ld_dlyd <= 1'b1; + end + end + else if(ROT20_n[1] == 1'b0) begin + if(ACQ_MSK_LD & MSKREG_SR_LD == 1'b1) begin + acq_msk_ld_dlyd <= 1'b0; + end + end + else begin + acq_msk_ld_dlyd <= acq_msk_ld_dlyd; + end + end + end +end + + +//SRNAND primitive_J62 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(~((ACQ_MSK_LD & MSKREG_SR_LD & ~ROT20_n[2]) | ~SYS_RST_n)), .i_R_n(~(ACQ_MSK_LD & ~ROT20_n[16])), .o_Q(), .o_Q_n(acq_msk_ld_dlyd)); + +wire BUBWR_WAIT = acq_msk_ld_dlyd & ~BDI_EN; +wire GLCNT_RD = (BUBWR_WAIT | MSKREG_SR_LSB | ~o_BOOTEN_n) & + ~(ROT20_n[2] & ROT20_n[7] & ~(~(ROT20_n[12] & ROT20_n[17]) & ~i_4BEN_n)); //0-5_10-15 + +//Data Length Counter +wire DLCNT_EN; +wire DLCNT_START_n = ~(ACQ_MSK_LD & rot20_d18_dlyd1); + + +//Z14 Flag related? +wire Z14_n; + +wire Z14_ERR_n = ~(Z14_n & CHECK_CRC14) | SUPBD_END_n | ~BDI_EN; + +reg supbd_act_n_dlyd; +assign BOOTERR_RESTART_n = BMODE_n | supbd_act_n_dlyd | Z14_ERR_n; +always @(posedge i_MCLK) begin + if(!CLK2P_n) begin + supbd_act_n_dlyd <= SUPBD_ACT_n; + end +end + + +//Operation Done flag +wire OP_DONE_SET_n = ((BDI_EN | SUPBD_END_n) & BOOTERR_RESTART_n) & ((Z14_n & CHECK_CRC14) | SUPBD_END_n | ~BDI_EN); +wire OP_DONE; +SRNAND primitive_F25 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(BDI_EN_SET_n & SYS_RUN_FLAG), .i_R_n(OP_DONE_SET_n), .o_Q(), .o_Q_n(OP_DONE)); + + +//Error flag +wire SYS_ERR_FLAG; +SRNAND primitive_I31 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(BDI_EN_SET_n), .i_R_n(~(ABSPGCNTR_CNT_STOP & ~BDI_EN) & Z14_ERR_n & SYS_RUN_FLAG), .o_Q(), .o_Q_n(SYS_ERR_FLAG)); + + +//Bubble Data Out flag +reg supbd_act_dlyd; +always @(posedge i_MCLK) begin + if(!CLK2P_n) begin + supbd_act_dlyd <= ~SUPBD_ACT_n; + end +end + +wire bdo_en_reset_n = ~((supbd_act_dlyd & rot20_d18_dlyd1) | ~SYS_RST_n); +wire BDO_EN_n, MUXED_BDO_EN; +wire EFFBDO_EN = MUXED_BDO_EN & SUPBD_ACT_n; +SRNAND primitive_J43 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(bdo_en_reset_n), .i_R_n(DLCNT_START_n), .o_Q(BDO_EN_n), .o_Q_n(MUXED_BDO_EN)); + +wire MUXED_BDO_EN_DLYD; +wire SUPBDO_EN_n = MUXED_BDO_EN_DLYD | SUPBD_ACT_n; //J35 NAND demorgan +SRNAND primitive_J36 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(~((BDO_EN_n & ~ROT20_n[14]) | ~SYS_RST_n)), .i_R_n(DLCNT_START_n), .o_Q(), .o_Q_n(MUXED_BDO_EN_DLYD)); + + +//DMA Data Register Control +wire DMADREG_SHIFT = ~(~(~BYTEACQ_DONE | BDI_EN) | BUBWR_WAIT); +wire DMADREG_BDLD_EN = ~(ROT20_n[0] & ROT20_n[5] & ~(~(ROT20_n[10] & ROT20_n[15]) & ~i_4BEN_n)) & BYTEACQ_DONE; + + +//Valid Page Access flag/Cycle Counter Enable +wire VALPG_ACC_FLAG; +SRNAND primitive_H32 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(~((ACC_END | ~SYS_RUN_FLAG) & ~ROT20_n[1])), .i_R_n(VALPG_FLAG_SET_n), .o_Q(), .o_Q_n(VALPG_ACC_FLAG)); + +wire CYCLECNTR_EN; +SRNAND primitive_H30 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(~((ACC_END | ~SYS_RUN_FLAG) & ~ROT20_n[1])), .i_R_n(~(~o_BSEN_n & PGCMP_EQ & ~ROT20_n[7])), .o_Q(), .o_Q_n(CYCLECNTR_EN)); + + + + + + +/////////////////////////////////////////////////////////// +////// BUBBLE IO FRONTEND +//// + +//BUBBLE CONTROL FRONTEND +K005297_bubctrlfe bubctrlfe_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + .i_SYS_RUN_FLAG_SET_n (SYS_RUN_FLAG_SET_n ), + + .i_ABSPGCNTR_CNT_START (ABSPGCNTR_CNT_START ), + .i_ABSPGCNTR_CNT_STOP (ABSPGCNTR_CNT_STOP ), + .i_VALPG_ACC_FLAG (VALPG_ACC_FLAG ), + .i_BMODE_n (BMODE_n ), + .i_REP_START (REP_START ), + .i_SWAP_START (SWAP_START ), + + .o_BOOTEN_n (o_BOOTEN_n ), + .o_BSS_n (o_BSS_n ), + .o_BSEN_n (o_BSEN_n ), + .o_REPEN_n (o_REPEN_n ), + .o_SWAPEN_n (o_SWAPEN_n ) +); + +//BUBBLE READ FRONTEND +K005297_bubrdfe bubrdfe_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_BDI_EN_SET_n (BDI_EN_SET_n ), + .i_BDI_EN_RST_n (BDI_EN_RST_n ), + .i_BDIN_n (i_BDIN_n ), + + .o_BDI (BDI ), + .o_BDI_EN (BDI_EN ) +); + +//BUBBLE WRITE FRONTEND +K005297_bubwrfe bubwrfe_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_TST (i_TST5 ), + .i_4BEN_n (i_4BEN_n ), + + .i_MUXED_BDO (MUXED_BDO ), + .i_MUXED_BDO_EN (MUXED_BDO_EN ), + .i_SUPBD_END_n (SUPBD_END_n ), + + .o_BDOUT_n (o_BDOUT_n ), + + .i_ABSPGCNTR_LSB (ABSPGCNTR_LSB ), + .i_PGREG_SR_LSB (PGREG_SR_LSB ), + .i_DLCNTR_LSB (DLCNTR_LSB ), + .i_CYCLECNTR_LSB (CYCLECNTR_LSB ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// SYNCHRONIZATION PATTERN DETECTOR +//// + +K005297_spdet spdet_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_BDI (BDI ), + .i_GLCNT_RD (GLCNT_RD ), + .i_BOOTEN_n (o_BOOTEN_n ), + .i_BSEN_n (o_BSEN_n ), + .i_4BEN_n (i_4BEN_n ), + + .o_SYNCTIP_n (SYNCTIP_n ), + .o_SYNCED_FLAG (SYNCED_FLAG ), + .o_SYNCED_FLAG_SET_n (SYNCED_FLAG_SET_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// CYCLE COUNTER +//// + +K005297_cyclecntr cyclecntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_CYCLECNTR_EN (CYCLECNTR_EN ), + .o_CYCLECNTR_LSB (CYCLECNTR_LSB ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// FUNCTION TRIGGER +//// + +K005297_functrig functrig_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_HALT (i_TST4 ), + .i_SYS_RST_n (SYS_RST_n ), + + .i_UMODE_n (UMODE_n ), + .i_CYCLECNTR_LSB (CYCLECNTR_LSB ), + .i_ACC_INVAL_n (ACC_INVAL_n ), + .i_PGCMP_EQ (PGCMP_EQ ), + .i_SYNCTIP_n (SYNCTIP_n ), + .i_BDI_EN (BDI_EN ), + + .o_ACC_END (ACC_END ), + .o_SWAP_START (SWAP_START ), + .o_ACQ_START (ACQ_START ), + .o_ADDR_RST (ADDR_RST ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// MASK LOAD TIMER +//// + +K005297_mskldtimer mskldtimer_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_ACC_ACT_n (ACC_ACT_n ), + .i_ACQ_MSK_LD (ACQ_MSK_LD ), + + .o_MSKREG_SR_LD (MSKREG_SR_LD ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// MASK(ERROR MAP) REGISTER +//// + +K005297_mskreg mskreg_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_MSKREG_LD (MSKREG_LD ), + .i_MSKREG_SR_LD (MSKREG_SR_LD ), + .i_BOOTEN_n (o_BOOTEN_n ), + + .i_DIN (i_DIN ), + + .o_MSKREG_SR_LSB (MSKREG_SR_LSB ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DATA LENGTH COUNTER +//// + +K005297_dlcntr dlcntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_DLCNT_START_n (DLCNT_START_n ), + .i_SUPBD_START_n (SUPBD_START_n ), + .i_DLCNT_EN (DLCNT_EN ), + + .o_DLCNTR_LSB (DLCNTR_LSB ), + .o_DLCNTR_CFLAG (DLCNTR_CFLAG ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// BYTE ACQUISITION COUNTER +//// + +K005297_byteacqcntr byteacqcntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_ACC_ACT_n (ACC_ACT_n ), + .i_GLCNT_RD (GLCNT_RD ), + + .i_NEWBYTE (NEWBYTE ), + .i_BUBWR_WAIT (BUBWR_WAIT ), + + .o_BYTEACQ_DONE (BYTEACQ_DONE ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DATA LENGTH EVALUATOR +//// + +K005297_dleval dleval_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_TST (i_TST2 ), + .i_SYS_RST_n (SYS_RST_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_UMODE_n (UMODE_n ), + .i_DLCNTR_LSB (DLCNTR_LSB ), + .i_DLCNTR_CFLAG (DLCNTR_CFLAG ), + + .i_BYTEACQ_DONE (BYTEACQ_DONE ), + .i_SUPBD_END_n (SUPBD_END_n ), + + .o_SUPBD_START_n (SUPBD_START_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// SUPPLEMENTARY BUBBLE DATA LENGTH COUNTER +//// + +K005297_supbdlcntr supbdlcntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RUN_FLAG (SYS_RUN_FLAG ), + + .i_4BEN_n (i_4BEN_n ), + .i_BDI_EN (BDI_EN ), + .i_SUPBD_START_n (SUPBD_START_n ), + .i_MSKREG_SR_LSB (MSKREG_SR_LSB ), + .i_GLCNT_RD (GLCNT_RD ), + + .o_SUPBDLCNTR_CNT (SUPBDLCNTR_CNT ), + .o_SUPBD_ACT_n (SUPBD_ACT_n ), + .o_SUPBD_END_n (SUPBD_END_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// PAGE REGISTER +//// + +K005297_pgreg pgreg_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_PGREG_LD (ASYNC_LATCH_EN__PGREG_LD ), + .i_PGREG_SR_LD_EN (PGREG_SR_LD_EN ), + .o_PGREG_SR_SHIFT (PGREG_SR_SHIFT ), + + .i_DIN (i_DIN ), + + .o_PGREG_D2 (PGREG_D2 ), + .o_PGREG_D8 (PGREG_D8 ), + .o_PGREG_SR_LSB (PGREG_SR_LSB ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// ABSOLUTE PAGE COUNTER +//// + +K005297_abspgcntr abspgcntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_ABSPGCNTR_CNT_STOP (ABSPGCNTR_CNT_STOP ), + .i_ABSPGCNTR_CNT_START (ABSPGCNTR_CNT_START ), + .i_ALD_nB_U (ALD_nB_U ), + .o_ABSPGCNTR_LSB (ABSPGCNTR_LSB ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// PAGE COMPARATOR +//// + +K005297_pgcmp pgcmp_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_BDI_EN (BDI_EN ), + .i_PGREG_SR_LSB (PGREG_SR_LSB ), + .i_ABSPGCNTR_LSB (ABSPGCNTR_LSB ), + .i_UMODE_n (UMODE_n ), + + .o_PGCMP_EQ (PGCMP_EQ ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// INVALID PAGE DETECTOR +//// + +K005297_invalpgdet invalpgdet_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_TST (i_TST3 ), + .i_PGREG_SR_LSB (PGREG_SR_LSB ), + .i_INVALPG_LSB (INVALPG_LSB ), + .i_UMODE_n (UMODE_n ), + .i_PGCMP_EQ (PGCMP_EQ ), + + .o_ACC_INVAL_n (ACC_INVAL_n ), + .o_VALPG_FLAG_SET_n (VALPG_FLAG_SET_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DMA OUTLATCH LOAD CONTROL +//// + +K005297_dmadregldctrl dmadregldctrl_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_4BEN_n (i_4BEN_n ), + .i_BDI_EN (BDI_EN ), + .i_UMODE_n (UMODE_n ), + + .i_ACQ_MSK_LD (ACQ_MSK_LD ), + .i_MSKREG_SR_LD (MSKREG_SR_LD ), + .i_BYTEACQ_DONE (BYTEACQ_DONE ), + .i_GLCNT_RD (GLCNT_RD ), + + .i_ACQ_START (ACQ_START ), + .i_SUPBD_START_n (SUPBD_START_n ), + .i_VALPG_FLAG_SET_n (VALPG_FLAG_SET_n ), + + .i_PGREG_SR_LSB (PGREG_SR_LSB ), + .i_DLCNTR_LSB (DLCNTR_LSB ), + + .i_DMA_WORD_END (DMA_WORD_END ), + + .o_NEWBYTE (NEWBYTE ), + .o_DLCNT_EN (DLCNT_EN ), + .o_DMADREG_BDHI_LD (DMADREG_BDHI_LD ), + .o_DMADREG_BDLO_LD (DMADREG_BDLO_LD ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DMA TIMINGS +//// + +K005297_dmatiming dmatiming_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT8 (ROT8 ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_UMODE_n (UMODE_n ), + .i_ACC_ACT_n (ACC_ACT_n ), + .i_DMA_ACT (DMA_ACT ), + .i_BDI_EN (BDI_EN ), + .i_MSKREG_SR_LD (MSKREG_SR_LD ), + .i_ACQ_MSK_LD (ACQ_MSK_LD ), + .i_ACQ_START (ACQ_START ), + .i_SUPBDO_EN_n (SUPBDO_EN_n ), + .i_DMADREG_BDLO_LD (DMADREG_BDLO_LD ), + + .o_BR_START_n (BR_START_n ), + .o_DMA_END (DMA_END ), + .o_DMA_WORD_END (DMA_WORD_END ), + .o_MSKREG_LD (MSKREG_LD ), + .o_MSKADDR_INC (MSKADDR_INC ), + .o_DMADREG_BDHILO_LD (DMADREG_BDHILO_LD ), + .o_DMA_WR_ACT_n (DMA_WR_ACT_n ) +); + + + + + + + +/////////////////////////////////////////////////////////// +////// DMA FRONTEND +//// + +K005297_dmafe dmafe_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT8 (ROT8 ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_CPURST_n (o_CPURST_n ), + .i_AS_n (i_AS_n ), + .i_BG_n (i_BG_n ), + .o_BR_n (o_BR_n ), + .o_BGACK_n (o_BGACK_n ), + + .i_BR_START_n (BR_START_n ), + .i_DMA_END (DMA_END ), + + .o_ALD_EN (ALD_EN ), + .o_DMA_ACT (DMA_ACT ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// BUS CONTROL FRONTEND +//// + +//Address Latch Enable +assign o_ALE = DMA_ACT & ROT8[1]; + +K005297_busctrlfe busctrlfe_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT8 (ROT8 ), + + .i_DMA_ACT (DMA_ACT ), + .i_DMA_WR_ACT_n (DMA_WR_ACT_n ), + .o_DMA_R_nW (DMA_R_nW ), + + .o_UDS_n (o_UDS_n ), + .o_LDS_n (o_LDS_n ), + .o_AS_n (o_AS_n ), + .o_R_nW (o_R_nW ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// INVALID PAGE DATA GENERATOR(DATA SCRAMBLER) +//// + +K005297_invalpgdgen invalpgdgen_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_PGREG_D2 (PGREG_D2 ), + .i_PGREG_D8 (PGREG_D8 ), + + .i_EFFBDO_EN (EFFBDO_EN ), + .i_BDO_EN_n (BDO_EN_n ), + .i_GLCNT_RD (GLCNT_RD ), + + .i_VALPG_ACC_FLAG (VALPG_ACC_FLAG ), + .i_UMODE_n (UMODE_n ), + .i_SUPBD_ACT_n (SUPBD_ACT_n ), + .i_SYNCED_FLAG (SYNCED_FLAG ), + .i_ALD_nB_U (ALD_nB_U ), + + .i_BDI (BDI ), + .o_MUXED_BDI (MUXED_BDI ), + .o_EFF_MUXED_BDI (EFF_MUXED_BDI ) +); + + + + + + + + +/////////////////////////////////////////////////////////// +////// DMA DATA REGISTER +//// + +K005297_dmadreg dmadreg_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT8 (ROT8 ), + + .i_DMADREG_SHIFT (DMADREG_SHIFT ), + .i_DMADREG_BDLD_EN (DMADREG_BDLD_EN ), + .i_DMADREG_BDHI_LD (DMADREG_BDHI_LD ), + .i_DMADREG_BDLO_LD (DMADREG_BDLO_LD ), + .i_DMADREG_BDHILO_LD (DMADREG_BDHILO_LD ), + + .i_DMA_ACT (DMA_ACT ), + .i_BDI_EN (BDI_EN ), + .i_GLCNT_RD (GLCNT_RD ), + + .o_BDRWADDR_INC (BDRWADDR_INC ), + + .i_MUXED_BDI (BDI ), + .o_DMATXREG (DMATXREG ), + + .o_EFF_BDO (EFF_BDO ), + .i_DIN (16'h0AF5 ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// DMA ADDRESS COUNTER +//// + +K005297_dmaaddrcntr dmaaddrcntr_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT8 (ROT8 ), + + .i_ALD_nB_U (ALD_nB_U ), + .i_ADDR_RST (ADDR_RST ), + .i_BDRWADDR_INC (BDRWADDR_INC ), + .i_MSKADDR_INC (MSKADDR_INC ), + + .o_AOUT (o_AOUT ), + .o_ALD_DMABD (ALD_DMABD ), + .o_ALD_DMAMSK (ALD_DMAMSK ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// Z14(CRC14) checker +//// + +//CRC14 Polynomial = X^14 + X^5 + X^4 + 1 + +K005297_z14eval z14eval_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_SYS_RST_n (SYS_RST_n ), + + .i_TIMER25K_TIMEOVER_n (TIMER25K_TIMEOVER_n ), + .i_Z14_ERR_n (Z14_ERR_n ), + + .o_Z14_UNLOCK_n (Z14_UNLOCK_n ), + .o_Z14_LOCKED_n (Z14_LOCKED_n ), + + .i_BDI_EN (BDI_EN ), + + .i_SUPBD_ACT_n (SUPBD_ACT_n ), + .i_SUPBD_END_n (SUPBD_END_n ), + + .i_DLCNT_START_n (DLCNT_START_n ), + .i_SUPBDLCNTR_CNT (SUPBDLCNTR_CNT ), + .i_ACQ_START (ACQ_START ), + + .i_MSKREG_SR_LSB (MSKREG_SR_LSB ), + + .i_BDI (BDI ), + .i_EFF_BDO (EFF_BDO ), + .o_MUXED_BDO (MUXED_BDO ), + + .o_TIMER25K_CNT (TIMER25K_CNT ), + .o_TIMER25K_OUTLATCH_LD_n (TIMER25K_OUTLATCH_LD_n ), + + .o_Z14_n (Z14_n ), + .o_Z11_d13_n ( ), + .o_TIMERREG_MSBS (TIMERREG_MSBS ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// TIMER25K +//// + +K005297_timer25k timer25k_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_TIMER25K_CNT (TIMER25K_CNT ), + .i_TIMER25K_OUTLATCH_LD_n (TIMER25K_OUTLATCH_LD_n ), + .o_TIMER25K_TIMEOVER_n (TIMER25K_TIMEOVER_n ), + + .o_TIMERREG_LSBS (TIMERREG_LSBS ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// CHECKSUM COMPARATOR +//// + +K005297_sumcmp sumcmp_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_EFF_MUXED_BDI (EFF_MUXED_BDI ), + + .i_UMODE_n (UMODE_n ), + .i_BDO_EN_n (BDO_EN_n ), + .i_EFFBDO_EN (EFFBDO_EN ), + .i_GLCNT_RD (GLCNT_RD ), + .i_PGREG_SR_SHIFT (PGREG_SR_SHIFT ), + .i_DMADREG_BDLD_EN (DMADREG_BDLD_EN ), + + .i_MUXED_BDO_EN_DLYD (MUXED_BDO_EN_DLYD ), + .i_SUPBD_ACT_n (SUPBD_ACT_n ), + .i_ALD_nB_U (ALD_nB_U ), + + .o_INVALPG_LSB (INVALPG_LSB ), + .o_SUMEQ_n (SUMEQ_n ) +); + + + + + + + +/////////////////////////////////////////////////////////// +////// TEMPERATURE DETECTOR +//// + +K005297_tempdet tempdet_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + + .i_TEMPLO_n (i_TEMPLO_n ), + .i_CLK2M_STOP_n (CLK2M_STOP_n ), + .i_CLK2M_STOP_DLYD_n (CLK2M_STOP_DLYD_n ), + + .o_TEMPDROP_SET_n (TEMPDROP_SET_n ), + .o_HEATEN_n (o_HEATEN_n ) +); + + + + + + +/////////////////////////////////////////////////////////// +////// RW COMMAND REGISTER +//// + + +wire CMDREG_RDREQ_n, CMDREG_WRREQ_n; +SYNCDLPS primitive_N33 (.i_CLK(i_MCLK), .i_SET(~(CMDREG_RST_n & SYS_RUN_FLAG)), .i_EN(ASYNC_LATCH_EN__CMDREG_WR_EN), .i_D(~i_DIN[0]), .o_Q(CMDREG_RDREQ_n)); +SYNCDLPS primitive_N31 (.i_CLK(i_MCLK), .i_SET(~(CMDREG_RST_n & SYS_RUN_FLAG)), .i_EN(ASYNC_LATCH_EN__CMDREG_WR_EN), .i_D(~i_DIN[1]), .o_Q(CMDREG_WRREQ_n)); + + + + + + + +/////////////////////////////////////////////////////////// +////// FSM +//// + + +K005297_fsm fsm_main ( + .i_MCLK (i_MCLK ), + .i_CLK4M_PCEN_n (CLK4P_n ), + .i_CLK2M_PCEN_n (CLK2P_n ), + .i_ROT20_n (ROT20_n ), + + .i_CMDREG_RDREQ (~CMDREG_RDREQ_n ), + .i_CMDREG_WRREQ (~CMDREG_WRREQ_n ), + .o_CMDREG_RST_n (CMDREG_RST_n ), + + .i_SYS_RUN_FLAG (SYS_RUN_FLAG ), + .i_SYS_ERR_FLAG (SYS_ERR_FLAG ), + + .o_FSMERR_RESTART_n (FSMERR_RESTART_n ), + + .i_SUPBD_ACT_n (SUPBD_ACT_n ), + .i_PGCMP_EQ (PGCMP_EQ ), + .i_VALPG_ACC_FLAG (VALPG_ACC_FLAG ), + .i_PGREG_SR_SHIFT (PGREG_SR_SHIFT ), + .i_SUMEQ_n (SUMEQ_n ), + .i_MUXED_BDO_EN_DLYD (MUXED_BDO_EN_DLYD ), + .i_OP_DONE (OP_DONE ), + + .o_BDI_EN_SET_n (BDI_EN_SET_n ), + .o_BDI_EN_RST_n (BDI_EN_RST_n ), + .o_PGREG_SRLD_EN (PGREG_SR_LD_EN ), + .o_ACC_START (ACC_START ), + .o_REP_START (REP_START ), + .o_CMD_ACCEPTED_n (CMD_ACCEPTED_n ) //R59 +); + + + + + + +/////////////////////////////////////////////////////////// +////// STATUS FLAGS +//// + +//USER PAGES Z14 ERROR FLAG +//Original circuit used a narrow tip caused by gate delay to reset STFLAG_USER_Z14_ERR_n. +//A small delay occurs on the SRNAND Z14_LOCKED_n output when Z14_UNLOCK_n resets the latch. +reg z14_locked_dlyd_n = 1'b1; +always @(posedge i_MCLK) begin + if(!CLK2P_n) begin + z14_locked_dlyd_n <= Z14_LOCKED_n; + end +end + +//display valid unlock signal when ROT20 = 13 +wire z14_unlock_valid_n = (ROT20_n[13] == 1'b0) ? (Z14_UNLOCK_n | z14_locked_dlyd_n) : 1'b1; + +wire STFLAG_USER_Z14_ERR_n; +SRNAND primitive_D14 (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_S_n(~(ACQ_START & rot20_d18_dlyd2)), .i_R_n(~(~(z14_unlock_valid_n & OP_DONE_SET_n) | ~SYS_RST_n)), .o_Q(), .o_Q_n(STFLAG_USER_Z14_ERR_n)); + + +//ASYNC SR LATCHES +wire STFLAG_OP_DONE_n; +SYNCDLPS primitive_D17 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~OP_DONE_SET_n), .i_D(1'b0), .o_Q(STFLAG_OP_DONE_n)); + +wire STFLAG_Z14_ERR_n; +SYNCDLPS primitive_D18 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~Z14_ERR_n), .i_D(1'b0), .o_Q(STFLAG_Z14_ERR_n)); + +wire STFLAG_TIMER25K_LATCHED_n; +SYNCDLPS primitive_D19 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~TIMER25K_OUTLATCH_LD_n), .i_D(1'b0), .o_Q(STFLAG_TIMER25K_LATCHED_n)); + +wire STFLAG_TIMER25K_TIMEOVER_n; +SYNCDLPS primitive_D20 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~TIMER25K_TIMEOVER_n), .i_D(1'b0), .o_Q(STFLAG_TIMER25K_TIMEOVER_n)); + +wire STFLAG_CMD_ACCEPTED_n; +SYNCDLPS primitive_D21 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~CMD_ACCEPTED_n), .i_D(1'b0), .o_Q(STFLAG_CMD_ACCEPTED_n)); + +wire STFLAG_TEMPDROP_n; +SYNCDLPS primitive_C20 (.i_CLK(i_MCLK), .i_SET(ASYNC_LATCH_EN__STFLAG_CLR), .i_EN(~TEMPDROP_SET_n), .i_D(1'b0), .o_Q(STFLAG_TEMPDROP_n)); + + +//stflag bus assignments +assign STFLAG[15] = ~STFLAG_TIMER25K_LATCHED_n; +assign STFLAG[14] = ~STFLAG_Z14_ERR_n; +assign STFLAG[13] = ~STFLAG_TIMER25K_TIMEOVER_n; +assign STFLAG[12] = ~CMD_ACCEPTED_n; +assign STFLAG[11] = ~STFLAG_OP_DONE_n; +assign STFLAG[10] = ~1'b1; +assign STFLAG[9] = i_TEMPLO_n; +assign STFLAG[8] = ~STFLAG_USER_Z14_ERR_n; +assign STFLAG[7] = ~1'b1; +assign STFLAG[6] = ~1'b0; +assign STFLAG[5] = ~1'b1; +assign STFLAG[4] = ~1'b1; +assign STFLAG[3] = ~1'b1; +assign STFLAG[2] = ~STFLAG_TIMER25K_LATCHED_n; +assign STFLAG[1] = (STFLAG_TIMER25K_LATCHED_n & ~STFLAG_TIMER25K_TIMEOVER_n) | (STFLAG_TIMER25K_LATCHED_n & ~STFLAG_Z14_ERR_n); +assign STFLAG[0] = (STFLAG_TIMER25K_LATCHED_n & STFLAG_TIMER25K_TIMEOVER_n & ~STFLAG_CMD_ACCEPTED_n) | + (STFLAG_TIMER25K_LATCHED_n & ~STFLAG_Z14_ERR_n); + +//controller IRQ +assign o_IRQ_n = &{STFLAG_OP_DONE_n, + STFLAG_CMD_ACCEPTED_n, + STFLAG_Z14_ERR_n, + STFLAG_TIMER25K_LATCHED_n, + STFLAG_TIMER25K_TIMEOVER_n, + ~(STFLAG_USER_Z14_ERR_n & ~STFLAG_TEMPDROP_n)}; + + + + + + +/////////////////////////////////////////////////////////// +////// ADDRESS DECODER +//// + +// +// DATA OUT +// + +//bubble/controller IO +wire dma_tx_n = (DMA_R_nW & ~ALD_EN) | ~DMA_ACT; //DMA data write/Address latch write +wire cpu_reg_read_n = ~(i_FCIN[2] & i_R_nW) | i_REGCS_n; //Supervisor/interrupt + +//interrupt related +wire cpu_interrupted_n = ~&{i_FCIN} | i_AS_n; //FC = 3'b111, CPU interrupted +wire int1_vector_req_n = ~|{cpu_interrupted_n, i_LDS_n, i_AIN[0], ~&{i_AIN[1], i_AIN[2], i_R_nW}}; +assign o_INT1_ACK_n = cpu_interrupted_n | int1_vector_req_n; + +//read-only register decoder +//0: 0x40000: DMA tx register +//1: 0x40002: CRC14 SR upper 4bits + timer 25k 12bits(bus contention with 0x40000) +//2: : no register +//3: 0x40006: BMC status/INT1 vector(lower data) +wire [1:0] internal_bus_addr = (i_AIN[1:0] | {2{int1_vector_req_n}}) & {2{~DMA_ACT}}; + +//internal tri-state bus +always @(*) begin + case(internal_bus_addr) + 2'b00: INTLBUS <= DMATXREG; + 2'b01: INTLBUS <= {TIMERREG_MSBS, TIMERREG_LSBS}; + 2'b10: INTLBUS <= 16'h0000; + 2'b11: INTLBUS <= STFLAG; + endcase +end + +//data bus driver +assign o_CTRL_DATA_OE_n = &{dma_tx_n, cpu_reg_read_n, cpu_interrupted_n}; + + +// +// DATA IN +// + +//write enable +wire write_enable = &{i_FCIN[2], ~DMA_ACT, ~|{i_REGCS_n, i_UDS_n, i_LDS_n, i_R_nW}}; + +//write-only register decoder +//0: 0x40000: page number +//1: 0x40002: r/w command +//2: 0x40004: status flag clear +//3: : no register + +//must promote them as global signals or clocks +assign ASYNC_LATCH_EN__PGREG_LD = &{~i_AIN[1], ~i_AIN[0], write_enable}; +assign ASYNC_LATCH_EN__CMDREG_WR_EN = &{~i_AIN[1], i_AIN[0], write_enable}; +assign ASYNC_LATCH_EN__STFLAG_CLR = &{ i_AIN[1], ~i_AIN[0], write_enable}; + + + + + + +/////////////////////////////////////////////////////////// +////// DATA OUTPUT MUX +//// + +wire [1:0] doutmux_sel = {~((MSKADDR_INC | DMADREG_BDHILO_LD) & ALD_EN), (MSKADDR_INC & ALD_EN)}; + +always @(*) begin + case(doutmux_sel) + 2'b00: o_DOUT <= {12'h000, ALD_DMABD | {4{ALD_nB_U}}}; //0x000-0x480 for bootloader, 0xF00-0xFFF for user pages. Use AND, invert ALD_DMABD once more and apply demorgan + 2'b01: o_DOUT <= {12'h000, 2'b11, ALD_DMAMSK, ~ALD_DMAMSK}; //error map from 0xD00 + 2'b10: o_DOUT <= INTLBUS; //internal tri-state bus + 2'b11: o_DOUT <= 16'h0000; //unselected + endcase +end + +endmodule + + + +/////////////////////////////////////////////////////////// +////// SUBMODULES +//// + +`include "./K005297_abspgcntr.v" //absolute page counter +`include "./K005297_accmodeflag.v" //access mode flag +`include "./K005297_bubctrlfe.v" //bubble control frontend +`include "./K005297_bubrdfe.v" //bubble read frontend +`include "./K005297_bubwrfe.v" //bubble write frontend +`include "./K005297_busctrlfe.v" //bus control frontend +`include "./K005297_byteacqcntr.v" //byte acqusition counter +`include "./K005297_cyclecntr.v" //cycle counter +`include "./K005297_dlcntr.v" //data length counter +`include "./K005297_dleval.v" //data length evaluator +`include "./K005297_dmaaddrcntr.v" //DMA address counter +`include "./K005297_dmadreg.v" //DMA data register +`include "./K005297_dmadregldctrl.v" //DMA data register load control +`include "./K005297_dmafe.v" //DMA frontend +`include "./K005297_dmatiming.v" //DMA timing +`include "./K005297_fsm.v" //FSM +`include "./K005297_functrig.v" //bubble function trigger +`include "./K005297_invalpgdet.v" //invalid page detector +`include "./K005297_invalpgdgen.v" //invalid page data generator +`include "./K005297_mskldtimer.v" //bad loop mask load timer +`include "./K005297_mskreg.v" //bad loop mask register +`include "./K005297_pgcmp.v" //page comparator +`include "./K005297_pgreg.v" //page register +`include "./K005297_primitives.v" //primitives +`include "./K005297_relpgcntr.v" //relative page counter +`include "./K005297_spdet.v" //synchronization pattern detector +`include "./K005297_sumcmp.v" //checksum comparator +`include "./K005297_supbdlcntr.v" //supplement bubble data length counter +`include "./K005297_supervisor.v" //supervisor +`include "./K005297_tempdet.v" //temperature detector +`include "./K005297_timer25k.v" //25k timer +`include "./K005297_z14eval.v" //CRC14 evaluator \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_abspgcntr.v b/rtl/ipcores/K005297/K005297_abspgcntr.v new file mode 100644 index 0000000..ff280d5 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_abspgcntr.v @@ -0,0 +1,93 @@ +module K005297_abspgcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_ABSPGCNTR_CNT_STOP, + input wire i_ABSPGCNTR_CNT_START, + input wire i_ALD_nB_U, + + output wire o_ABSPGCNTR_LSB +); + + + +/////////////////////////////////////////////////////////// +////// RELATIVE PAGE COUNTER +//// + +/* + gte(greater than or equal) flag(>= 1531 evaluation) + relative page 0-1530: +522 + relative page 1531-2052: -1531(loop) +*/ + + +//SR shift enable +wire abspgcntr_shift; //shift flag +SRNAND I24 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[12]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(abspgcntr_shift)); + + +//const add enable +wire abspgcntr_add_en; +SRNOR I34 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S(i_ABSPGCNTR_CNT_STOP), .i_R(i_ABSPGCNTR_CNT_START), .o_Q(), .o_Q_n(abspgcntr_add_en)); + + +reg [11:0] abspgcntr = 12'd0; //abs page counter +wire abspgcntr_const, abspgcntr_fa_sum, abspgcntr_fa_cout; //FA carry out +reg abspgcntr_fa_cflag = 1'b0; //FA carry storage +assign o_ABSPGCNTR_LSB = abspgcntr_fa_sum & i_ALD_nB_U; + +//shift register +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(abspgcntr_shift == 1'b1) begin + abspgcntr[11] <= o_ABSPGCNTR_LSB; + abspgcntr[10:0] <= abspgcntr[11:1]; + end + else begin + abspgcntr <= abspgcntr; + end + end +end + + +//constant generator: +522 or -1531 +wire constP522 = ~&{i_ROT20_n[9], i_ROT20_n[3], i_ROT20_n[1]}; +wire constN1531 = ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}; +reg gte1531_evalreg = 1'b0; +reg gte1531_flag = 1'b0; +assign abspgcntr_const = (gte1531_flag == 1'b0) ? constP522 : constN1531; + //+522 : -1531 +//evaluator: greater than or equal to 1531 +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + gte1531_evalreg <= ((abspgcntr_fa_sum & ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}) | + ((o_ABSPGCNTR_LSB | ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}) & gte1531_evalreg)) & + i_ROT20_n[19]; + + gte1531_flag <= (i_ROT20_n[12] == 1'b0) ? gte1531_evalreg : gte1531_flag; + end +end + + +//adder +FA J30 (.i_A(abspgcntr_add_en & abspgcntr_const), .i_B(abspgcntr_fa_cflag), .i_CIN(abspgcntr[0]), .o_S(abspgcntr_fa_sum), .o_COUT(abspgcntr_fa_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + abspgcntr_fa_cflag <= abspgcntr_fa_cout & i_ROT20_n[19]; + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_accmodeflag.v b/rtl/ipcores/K005297/K005297_accmodeflag.v new file mode 100644 index 0000000..75672d5 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_accmodeflag.v @@ -0,0 +1,37 @@ +module K005297_accmodeflag +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //system flags + input wire i_SYS_RST_n, + input wire i_SYS_RUN_FLAG, + + //control + input wire i_CMDREG_RST_n, + input wire i_BDI_EN_SET_n, + input wire i_SYNCED_FLAG_SET_n, + + //mode flag output + output wire o_BMODE_n, //bootloader mode + output wire o_UMODE_n, //user mode + output wire o_ALD_nB_U, //addres latch data BOOTLOADER_n / USER + output wire o_UMODE_SET_n +); + + +assign o_UMODE_SET_n = i_CMDREG_RST_n | i_BDI_EN_SET_n; + +SRNAND C21 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_UMODE_SET_n), .i_R_n(i_SYS_RST_n), .o_Q(o_BMODE_n), .o_Q_n()); +SRNAND C54 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_UMODE_SET_n), .i_R_n(i_SYS_RUN_FLAG), .o_Q(), .o_Q_n(o_UMODE_n)); +SRNAND C19 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_UMODE_SET_n & i_SYS_RUN_FLAG), .i_R_n(i_SYNCED_FLAG_SET_n), .o_Q(o_ALD_nB_U), .o_Q_n()); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_bubctrlfe.v b/rtl/ipcores/K005297/K005297_bubctrlfe.v new file mode 100644 index 0000000..1808eb3 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_bubctrlfe.v @@ -0,0 +1,69 @@ +module K005297_bubctrlfe +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //system flags + input wire i_SYS_RST_n, + input wire i_SYS_RUN_FLAG_SET_n, + + //control + input wire i_ABSPGCNTR_CNT_START, + input wire i_ABSPGCNTR_CNT_STOP, + input wire i_VALPG_ACC_FLAG, + input wire i_BMODE_n, + + input wire i_REP_START, + input wire i_SWAP_START, + + output wire o_BOOTEN_n, + output wire o_BSS_n, + output wire o_BSEN_n, + output wire o_REPEN_n, + output wire o_SWAPEN_n +); + + +//Bubble Shift Start +SRNAND T6 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(~(i_ABSPGCNTR_CNT_START & ~i_ROT20_n[17])), .i_R_n(i_SYS_RUN_FLAG_SET_n & i_SYS_RST_n), .o_Q(), .o_Q_n(o_BSS_n)); + +//Bubble Shift Enable +SRNAND H22 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(~i_ABSPGCNTR_CNT_STOP & i_SYS_RST_n), .i_R_n(~(i_ABSPGCNTR_CNT_START & ~i_ROT20_n[1])), .o_Q(o_BSEN_n), .o_Q_n()); + +//Replicator Enable +reg bootloop_rep_pulse = 1'b1; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(o_BOOTEN_n | o_BSEN_n == 1'b1) begin //H25 NAND demorgan + bootloop_rep_pulse <= 1'b1; + end + else begin + if(i_ROT20_n[1] == 1'b0) begin + bootloop_rep_pulse <= ~bootloop_rep_pulse; + end + else begin + bootloop_rep_pulse <= bootloop_rep_pulse; + end + end + end +end + +wire replicator_on = ~((~bootloop_rep_pulse | i_REP_START) & ~i_ROT20_n[2]); +SRNAND K24 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SYS_RST_n & i_ROT20_n[16]), .i_R_n(replicator_on), .o_Q(o_REPEN_n), .o_Q_n()); + +//Swap Gate Enable +SRNAND T15 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SYS_RST_n & i_ROT20_n[17]), .i_R_n(~((i_VALPG_ACC_FLAG & i_SWAP_START) & ~i_ROT20_n[3])), .o_Q(o_SWAPEN_n), .o_Q_n()); + +//Bootloop Enabe; +SRNAND C27 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SYS_RST_n), .i_R_n(~(i_BMODE_n & ~i_ROT20_n[0])), .o_Q(), .o_Q_n(o_BOOTEN_n)); + + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_bubrdfe.v b/rtl/ipcores/K005297/K005297_bubrdfe.v new file mode 100644 index 0000000..45ac5f7 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_bubrdfe.v @@ -0,0 +1,81 @@ +module K005297_bubrdfe +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //system reset + input wire i_SYS_RST_n, + + //control + input wire i_4BEN_n, + input wire i_BDI_EN_SET_n, + input wire i_BDI_EN_RST_n, + + input wire [3:0] i_BDIN_n, + + //output + output wire o_BDI, + + output wire o_BDI_EN +); + + +//input enable +SRNAND F32 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n((i_BDI_EN_SET_n & i_SYS_RST_n)), .i_R_n(i_BDI_EN_RST_n), .o_Q(o_BDI_EN), .o_Q_n()); + +//mux select counter +reg [1:0] mux_cntr = 2'd0; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[0] == 1'b0) begin + mux_cntr <= 2'd0; + end + else begin + if(~(i_ROT20_n[3] & i_ROT20_n[8] & ~(~(i_ROT20_n[13] & i_ROT20_n[18]) & ~i_4BEN_n)) == 1'b1) begin //3-8_13-18 + if(mux_cntr == 2'd3) begin + mux_cntr <= 2'd0; + end + else begin + mux_cntr <= mux_cntr + 2'd1; + end + end + else begin + mux_cntr <= mux_cntr; + end + end + end +end + +//bubble inlatch +reg [3:0] bubble_inlatch; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[18] == 1'b0) begin //d-latch latches SR data at ROT20_n[19] + bubble_inlatch <= i_BDIN_n; + end + end +end + +//in mux +reg bubble_stream; +wire [1:0] mux_select = {(mux_cntr[1] & ~i_4BEN_n), mux_cntr[0]}; +always @(*) begin + case(mux_select) //bit3->2->1->0 + 2'd0: bubble_stream <= bubble_inlatch[3]; + 2'd1: bubble_stream <= bubble_inlatch[2]; + 2'd2: bubble_stream <= bubble_inlatch[1]; + 2'd3: bubble_stream <= bubble_inlatch[0]; + endcase +end + +assign o_BDI = ~bubble_stream & o_BDI_EN; + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_bubwrfe.v b/rtl/ipcores/K005297/K005297_bubwrfe.v new file mode 100644 index 0000000..50deda7 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_bubwrfe.v @@ -0,0 +1,69 @@ +module K005297_bubwrfe +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_TST, //TST5 + input wire i_4BEN_n, + + input wire i_MUXED_BDO, + input wire i_MUXED_BDO_EN, + input wire i_SUPBD_END_n, + + output wire [3:0] o_BDOUT_n, + + //test mode + input wire i_ABSPGCNTR_LSB, + input wire i_PGREG_SR_LSB, + input wire i_DLCNTR_LSB, + input wire i_CYCLECNTR_LSB +); + + +//output enable +wire bubble_output_en; +SRNAND K22 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SUPBD_END_n), .i_R_n(~(i_MUXED_BDO_EN & ~i_ROT20_n[17])), .o_Q(), .o_Q_n(bubble_output_en)); + +//bubble shift register +reg [3:0] bubble_sr; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(~(i_ROT20_n[3] & i_ROT20_n[8] & ~(~(i_ROT20_n[13] & i_ROT20_n[18]) & ~i_4BEN_n)) == 1'b1) begin //3-8_13-18 + bubble_sr[0] <= i_MUXED_BDO; + bubble_sr[3:1] <= bubble_sr[2:0]; + end + else begin + bubble_sr <= bubble_sr; + end + end +end + +//bubble outlatch +reg [3:0] bubble_outlatch; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[0] == 1'b0) begin //d-latch latches SR data at ROT20_n[1] + if(i_4BEN_n == 1'b1) begin //2bit mode + bubble_outlatch <= {bubble_sr[3:2], 2'b00}; + end + else begin //4bit mode + bubble_outlatch <= bubble_sr; + end + end + end +end + +//output mux +assign o_BDOUT_n = (i_TST == 1'b1) ? ~(bubble_outlatch & {4{bubble_output_en}}) : + {i_CYCLECNTR_LSB, i_DLCNTR_LSB, i_PGREG_SR_LSB, i_ABSPGCNTR_LSB}; + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_busctrlfe.v b/rtl/ipcores/K005297/K005297_busctrlfe.v new file mode 100644 index 0000000..40deef6 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_busctrlfe.v @@ -0,0 +1,53 @@ +module K005297_busctrlfe +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [7:0] i_ROT8, + + //control + input wire i_DMA_ACT, + input wire i_DMA_WR_ACT_n, + output wire o_DMA_R_nW, + + //bus control + output wire o_UDS_n, + output wire o_LDS_n, + output wire o_AS_n, + output wire o_R_nW +); + +//DMA RW mode indicator +assign o_DMA_R_nW = (i_DMA_WR_ACT_n == 1'b0) ? 1'b0 : 1'b1; //write : read + + +//DATA STROBE(UDS+LDS) +wire data_strobe_set_n = (i_DMA_WR_ACT_n == 1'b0) ? ~i_ROT8[4] : ~i_ROT8[2]; //write : read +wire data_strobe_reset_n = (i_DMA_WR_ACT_n == 1'b0) ? (~i_ROT8[6] & i_DMA_ACT) : (~i_ROT8[7] & i_DMA_ACT); //write : read +wire data_strobe_n; +assign o_UDS_n = data_strobe_n; +assign o_LDS_n = data_strobe_n; + +SRNAND C43 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(data_strobe_set_n), .i_R_n(data_strobe_reset_n), .o_Q(), .o_Q_n(data_strobe_n)); + + +//ADDRESS STROBE +wire addr_strobe_set_n = ~i_ROT8[2]; +wire addr_strobe_reset_n = ~i_ROT8[7] & i_DMA_ACT; + +SRNAND C68 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(addr_strobe_set_n), .i_R_n(addr_strobe_reset_n), .o_Q(), .o_Q_n(o_AS_n)); + + +//R/W +wire bus_read_n = (~i_ROT8[7] & i_DMA_ACT) & ~(i_ROT8[2] & o_DMA_R_nW); +wire bus_write_n = ~i_ROT8[2] | ~(~o_DMA_R_nW & i_DMA_ACT); + +SRNAND C53 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(bus_write_n), .i_R_n(bus_read_n), .o_Q(), .o_Q_n(o_R_nW)); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_byteacqcntr.v b/rtl/ipcores/K005297/K005297_byteacqcntr.v new file mode 100644 index 0000000..ef28f50 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_byteacqcntr.v @@ -0,0 +1,68 @@ +module K005297_byteacqcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_4BEN_n, + input wire i_GLCNT_RD, + input wire i_NEWBYTE, + input wire i_ACC_ACT_n, + input wire i_BUBWR_WAIT, + + output reg o_BYTEACQ_DONE = 1'b0 +); + + + +/////////////////////////////////////////////////////////// +////// BYTE ACQUISITION COUNTER +//// + +//byte acquisition counter +reg [2:0] byte_acq_cntr = 3'h7; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if((i_NEWBYTE | i_ACC_ACT_n) == 1'b1) begin //reset + byte_acq_cntr <= 3'h7; + end + else begin + if(i_GLCNT_RD == 1'b1) begin + if(byte_acq_cntr == 3'h0) begin + byte_acq_cntr <= 3'h7; + end + else begin + byte_acq_cntr <= byte_acq_cntr - 3'h1; + end + end + else begin + byte_acq_cntr <= byte_acq_cntr; + end + end + end +end + +//flag +wire eq7 = (byte_acq_cntr == 3'h0) ? 1'b1 : 1'b0; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(~(i_ROT20_n[3] & i_ROT20_n[8] & ~(~(i_ROT20_n[13] & i_ROT20_n[18]) & ~i_4BEN_n)) == 1'b1) begin //3-8_13-18 + o_BYTEACQ_DONE <= eq7 | i_BUBWR_WAIT; + end + else begin + o_BYTEACQ_DONE <= o_BYTEACQ_DONE; + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_cyclecntr.v b/rtl/ipcores/K005297/K005297_cyclecntr.v new file mode 100644 index 0000000..730cde4 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_cyclecntr.v @@ -0,0 +1,63 @@ +module K005297_cyclecntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_CYCLECNTR_EN, + output wire o_CYCLECNTR_LSB +); + + + +/////////////////////////////////////////////////////////// +////// CYCLE COUNTER +//// + +/* + +1 serial up counter +*/ + +//shift flag +wire cyclecntr_shift; +SRNAND Q67 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[10]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(cyclecntr_shift)); + + +reg [9:0] cyclecntr = 10'd0; //cycle counter +wire cyclecntr_fa_sum; //msb input +wire cyclecntr_fa_cout; //FA carry out +reg cyclecntr_fa_cflag = 1'b0; //FA carry storage +assign o_CYCLECNTR_LSB = cyclecntr[0]; + +//serial full adder cell +FA K20 (.i_A(~i_ROT20_n[0]), .i_B(cyclecntr[0]), .i_CIN(cyclecntr_fa_cflag), .o_S(cyclecntr_fa_sum), .o_COUT(cyclecntr_fa_cout)); + +//previous carry bit storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + cyclecntr_fa_cflag <= cyclecntr_fa_cout & i_ROT20_n[19]; + end +end + +//shift register +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(cyclecntr_shift == 1'b1) begin + cyclecntr[9] <= cyclecntr_fa_sum & i_CYCLECNTR_EN; + cyclecntr[8:0] <= cyclecntr[9:1]; + end + else begin + cyclecntr <= cyclecntr; + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dlcntr.v b/rtl/ipcores/K005297/K005297_dlcntr.v new file mode 100644 index 0000000..860d115 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dlcntr.v @@ -0,0 +1,72 @@ +module K005297_dlcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_DLCNT_START_n, //data length count start + input wire i_SUPBD_START_n, //data length count end + input wire i_DLCNT_EN, //data length + 1 + + output wire o_DLCNTR_LSB, //data length counter lsb + output wire o_DLCNTR_CFLAG //carry of data length's msb +); + + + +/////////////////////////////////////////////////////////// +////// DATA LENGTH COUNTER +//// + +/* + +1 serial up counter +*/ + +//reset flag(load 0) +wire dlcntr_rst_n; +SRNAND I46 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SUPBD_START_n), .i_R_n(i_DLCNT_START_n), .o_Q(), .o_Q_n(dlcntr_rst_n)); + +//shift flag +wire dlcntr_shift; +SRNAND J67 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[10]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(dlcntr_shift)); + + +reg [9:0] dlcntr = 10'd0; //data length counter +wire dlcntr_fa_sum; //msb input +wire dlcntr_fa_cout; //FA carry out +reg dlcntr_fa_cflag = 1'b0; //FA carry storage +assign o_DLCNTR_LSB = dlcntr[0]; +assign o_DLCNTR_CFLAG = dlcntr_fa_cflag; + +//serial full adder cell +FA I61 (.i_A(dlcntr[0]), .i_B(dlcntr_fa_cflag), .i_CIN(i_DLCNT_EN), .o_S(dlcntr_fa_sum), .o_COUT(dlcntr_fa_cout)); + +//previous carry bit storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + dlcntr_fa_cflag <= dlcntr_fa_cout & i_ROT20_n[19]; + end +end + +//shift register +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(dlcntr_shift == 1'b1) begin + dlcntr[9] <= dlcntr_fa_sum & dlcntr_rst_n; + dlcntr[8:0] <= dlcntr[9:1]; + end + else begin + dlcntr <= dlcntr; + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dleval.v b/rtl/ipcores/K005297/K005297_dleval.v new file mode 100644 index 0000000..2392d58 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dleval.v @@ -0,0 +1,80 @@ +module K005297_dleval +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_TST, + input wire i_SYS_RST_n, + + input wire i_4BEN_n, + input wire i_UMODE_n, + input wire i_DLCNTR_LSB, + input wire i_DLCNTR_CFLAG, + + input wire i_BYTEACQ_DONE, + input wire i_SUPBD_END_n, + + output wire o_SUPBD_START_n +); + + + +/////////////////////////////////////////////////////////// +////// DATA LENGTH COUNTER +//// + +//eq480 +wire const480 = ~&{i_ROT20_n[8], i_ROT20_n[7], i_ROT20_n[6], i_ROT20_n[5]}; +reg eq480_flag_n = 1'b0; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + eq480_flag_n <= (((i_DLCNTR_LSB ^ const480) | eq480_flag_n) & i_ROT20_n[19]); + end +end + +//bootloader done flag +reg boot_done = 1'b0; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + boot_done <= (i_ROT20_n[9] == 1'b0) ? (~eq480_flag_n | i_TST) & i_UMODE_n : + boot_done & i_UMODE_n; + end +end + + +//page done flag +reg pg_done = 1'b0; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_4BEN_n == 1'b1) begin //2bit mode + pg_done <= (i_ROT20_n[7] == 1'b0) ? ((i_TST | i_DLCNTR_CFLAG) & ~i_UMODE_n) : pg_done; + end + else begin //4bit mode + pg_done <= (i_ROT20_n[8] == 1'b0) ? ((i_TST | i_DLCNTR_CFLAG) & ~i_UMODE_n) : pg_done; + end + end +end + + + +/////////////////////////////////////////////////////////// +////// EFFECTIVE BUBBLE DATA END FLAG +//// + +wire effbd_done = ~((boot_done | pg_done) & ~i_ROT20_n[10]); +wire supbd_rdy; +assign o_SUPBD_START_n = ~&{supbd_rdy, i_BYTEACQ_DONE, ~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n))} & i_SYS_RST_n; + +SRNAND K23 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SUPBD_END_n), .i_R_n(effbd_done), .o_Q(), .o_Q_n(supbd_rdy)); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dmaaddrcntr.v b/rtl/ipcores/K005297/K005297_dmaaddrcntr.v new file mode 100644 index 0000000..7c4eff1 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dmaaddrcntr.v @@ -0,0 +1,115 @@ +module K005297_dmaaddrcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [7:0] i_ROT8, + + //control + input wire i_ALD_nB_U, + input wire i_ADDR_RST, + input wire i_BDRWADDR_INC, + input wire i_MSKADDR_INC, + + output wire [6:0] o_AOUT, //A7-A1 + output wire [3:0] o_ALD_DMABD, //bubble data + output wire o_ALD_DMAMSK //error map +); + + + +/////////////////////////////////////////////////////////// +////// DMA TX(BUBBLE DATA) ADDRESS COUNTER +//// + +reg [10:0] dmabd_addr_cntr = 11'h000; + +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ADDR_RST == 1'b1) begin + dmabd_addr_cntr <= 11'h000; + end + else begin + if((i_BDRWADDR_INC & i_ROT8[1]) == 1'b1) begin //count up + if(i_ALD_nB_U == 1'b0) begin //bootloader + if(dmabd_addr_cntr == 11'h7FF) begin + dmabd_addr_cntr <= 11'h000; + end + else begin + dmabd_addr_cntr <= dmabd_addr_cntr + 11'h001; + end + end + else begin //user pages + if(dmabd_addr_cntr == 11'h0FF) begin + dmabd_addr_cntr <= 11'h000; + end + else begin + dmabd_addr_cntr <= dmabd_addr_cntr + 11'h001; + end + end + end + else begin + dmabd_addr_cntr <= dmabd_addr_cntr; + end + end + end +end + + + +/////////////////////////////////////////////////////////// +////// DMA RX(ERROR MAP) ADDRESS COUNTER +//// + +//mskaddr inc latch(why?) +reg mskaddr_inc_latched; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[1] == 1'b1) begin //D-latch latches this at ROT8[2] == 1'b1; + mskaddr_inc_latched <= i_MSKADDR_INC; + end + end +end + +//address counter +reg [7:0] dmamsk_addr_cntr = 8'h00; + +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ADDR_RST == 1'b1) begin + dmamsk_addr_cntr <= 8'h00; + end + else begin + if((mskaddr_inc_latched & i_ROT8[1]) == 1'b1) begin //count up + if(dmamsk_addr_cntr == 8'hFF) begin + dmamsk_addr_cntr <= 8'h00; + end + else begin + dmamsk_addr_cntr <= dmamsk_addr_cntr + 8'h01; + end + end + else begin + dmamsk_addr_cntr <= dmamsk_addr_cntr; + end + end + end +end + + + +/////////////////////////////////////////////////////////// +////// OUTPUTS +//// + +assign o_AOUT = (i_MSKADDR_INC == 1'b0) ? dmabd_addr_cntr[6:0] : dmamsk_addr_cntr[6:0]; +assign o_ALD_DMABD = dmabd_addr_cntr[10:7]; +assign o_ALD_DMAMSK = dmamsk_addr_cntr[7]; + + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dmadreg.v b/rtl/ipcores/K005297/K005297_dmadreg.v new file mode 100644 index 0000000..b940ca0 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dmadreg.v @@ -0,0 +1,79 @@ +module K005297_dmadreg +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [7:0] i_ROT8, + + //control + input wire i_DMADREG_SHIFT, + input wire i_DMADREG_BDLD_EN, + input wire i_DMADREG_BDHI_LD, + input wire i_DMADREG_BDLO_LD, + input wire i_DMADREG_BDHILO_LD, + + input wire i_DMA_ACT, + input wire i_BDI_EN, + input wire i_GLCNT_RD, + + output wire o_BDRWADDR_INC, + + input wire i_MUXED_BDI, //muxed bubble data input(bubble read) + output wire [15:0] o_DMATXREG, //parallel bubble read data(DMA TX) + + output wire o_EFF_BDO, //effective bubble data output(bubble write) + input wire [15:0] i_DIN //parallel bubble write data(DMA RX) +); + + + +/////////////////////////////////////////////////////////// +////// DMA DATA REGISTER +//// + +//word load request(for write?) +reg txreg_word_ld_rq = 1'b0; +wire txreg_word_ld = txreg_word_ld_rq & i_DMA_ACT & i_ROT8[6]; +assign o_BDRWADDR_INC = txreg_word_ld_rq; + +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[1] == 1'b1) begin + txreg_word_ld_rq <= i_DMADREG_BDHILO_LD; //latches at i_ROT8[2]; source latch launches at i_ROT8[7] + end + end +end + + +//8 bit shift register for data IO +reg [7:0] bytesr; +assign o_EFF_BDO = bytesr[7]; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + case({i_GLCNT_RD, i_DMADREG_SHIFT}) + 2'b00: bytesr <= bytesr; //hold + 2'b01: bytesr <= bytesr; + 2'b10: bytesr <= (i_DMADREG_BDHI_LD == 1'b0) ? o_DMATXREG[7:0] : o_DMATXREG[15:8]; //parallel load(bubble write) + 2'b11: begin bytesr[0] <= i_MUXED_BDI; bytesr[7:1] <= bytesr[6:0]; end //serial load(bubble read) + endcase + end +end + + + +//D latch * 16 +wire txreg_hi_ld = (i_BDI_EN == 1'b1) ? (i_DMADREG_BDHI_LD & i_DMADREG_BDLD_EN) : txreg_word_ld; +wire txreg_lo_ld = (i_BDI_EN == 1'b1) ? (i_DMADREG_BDLO_LD & i_DMADREG_BDLD_EN) : txreg_word_ld; +wire [7:0] txreg_hi_data = (i_BDI_EN == 1'b1) ? bytesr: i_DIN[15:8]; +wire [7:0] txreg_lo_data = (i_BDI_EN == 1'b1) ? bytesr: i_DIN[7:0]; + +DL #(.dw(8)) DMATXREGHI (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_EN(txreg_hi_ld), .i_D(txreg_hi_data), .o_Q(o_DMATXREG[15:8]), .o_Q_n()); +DL #(.dw(8)) DMATXREGLO (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_EN(txreg_lo_ld), .i_D(txreg_lo_data), .o_Q(o_DMATXREG[7:0]), .o_Q_n()); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dmadregldctrl.v b/rtl/ipcores/K005297/K005297_dmadregldctrl.v new file mode 100644 index 0000000..298f42e --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dmadregldctrl.v @@ -0,0 +1,130 @@ +module K005297_dmadregldctrl +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //control + input wire i_4BEN_n, + input wire i_BDI_EN, + input wire i_UMODE_n, + + input wire i_ACQ_MSK_LD, + input wire i_MSKREG_SR_LD, + input wire i_BYTEACQ_DONE, + input wire i_GLCNT_RD, + + input wire i_ACQ_START, + input wire i_SUPBD_START_n, + input wire i_VALPG_FLAG_SET_n, + + input wire i_PGREG_SR_LSB, + input wire i_DLCNTR_LSB, + + input wire i_DMA_WORD_END, + + output wire o_NEWBYTE, + output wire o_DLCNT_EN, + output reg o_DMADREG_BDHI_LD = 1'b1, + output wire o_DMADREG_BDLO_LD +); + +//NEWBYTE for DMA outlatch control +reg initial_newbyte; //only asserted at the beginning +assign o_NEWBYTE = initial_newbyte | i_BYTEACQ_DONE & i_GLCNT_RD; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + initial_newbyte <= i_ACQ_MSK_LD & (i_MSKREG_SR_LD & ~i_ROT20_n[1]) & i_BDI_EN; + end +end + + + +//bootloader related +wire newbyte_dlyd; +assign o_DLCNT_EN = newbyte_dlyd & ~i_ROT20_n[0]; +SRNAND K33 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[1]), .i_R_n(~o_NEWBYTE), .o_Q(), .o_Q_n(newbyte_dlyd)); + + + +//user page related +wire valpg_dma_req; +SRNAND J38 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SUPBD_START_n), .i_R_n(i_VALPG_FLAG_SET_n), .o_Q(), .o_Q_n(valpg_dma_req)); + + +reg dlcntr_cmp, dlcntr_zero_n; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + dlcntr_cmp <= (((i_DLCNTR_LSB ^ (i_PGREG_SR_LSB | valpg_dma_req)) | dlcntr_cmp) & i_ROT20_n[19]) | i_UMODE_n; + + dlcntr_zero_n <= (i_4BEN_n == 1'b1) ? ((i_ROT20_n[7] == 1'b0) ? dlcntr_cmp : dlcntr_zero_n) : + ((i_ROT20_n[8] == 1'b0) ? dlcntr_cmp : dlcntr_zero_n); //2bit : 4bit + end +end + + +reg init_dma_req = 1'b0; //this sr latch's outer circuit has a combinational loop + //RESET PORT(flag set) ACQ_START @ D0 + //SET PORT(flag reset) ACQ_MSK_LD @ D4(stable before D4) +always @(posedge i_MCLK) begin + if(i_SYS_RST_n == 1'b0) begin //synchronous reset(SR latch originally) + init_dma_req <= 1'b0; + end + else begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[19] == 1'b0) begin //SR latch's reset works @ ROT20[0] + if(i_ACQ_START == 1'b1) begin + init_dma_req <= 1'b1; + end + end + else if(i_ROT20_n[3] == 1'b0) begin + if(init_dma_req & ~i_ACQ_MSK_LD == 1'b1) begin + init_dma_req <= 1'b0; + end + end + else begin + init_dma_req <= init_dma_req; + end + end + end +end + + +//SR latch +wire bootloader_dma_req; +SRNAND K38 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(~(o_NEWBYTE & dlcntr_zero_n)), .i_R_n(~(o_DLCNT_EN & ~dlcntr_zero_n)), .o_Q(bootloader_dma_req), .o_Q_n()); + +//DMADREG HI/LO toggle +wire dmadreg_toggle_hilo = ~(init_dma_req & i_BDI_EN) & (~valpg_dma_req | bootloader_dma_req) & o_NEWBYTE; + +//K50 TFF +assign o_DMADREG_BDLO_LD = ~o_DMADREG_BDHI_LD; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_DMA_WORD_END == 1'b1) begin //reset + o_DMADREG_BDHI_LD <= 1'b1; + end + else begin + if(dmadreg_toggle_hilo == 1'b1) begin + o_DMADREG_BDHI_LD <= ~o_DMADREG_BDHI_LD; + end + else begin + o_DMADREG_BDHI_LD <= o_DMADREG_BDHI_LD; + end + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dmafe.v b/rtl/ipcores/K005297/K005297_dmafe.v new file mode 100644 index 0000000..155a03c --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dmafe.v @@ -0,0 +1,97 @@ +module K005297_dmafe +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [7:0] i_ROT8, + + //reset + input wire i_SYS_RST_n, + + //68000 + input wire i_CPURST_n, + input wire i_AS_n, + input wire i_BG_n, + output wire o_BR_n, + output wire o_BGACK_n, + + //control + input wire i_BR_START_n, + input wire i_DMA_END, + + output wire o_ALD_EN, + output wire o_DMA_ACT +); + + +/////////////////////////////////////////////////////////// +////// DMA FRONTEND +//// + +// +// USE 4MHz CLOCK +// + + +//DMA ACT flag +//This SR latch receives the SET signal from the asynchronous source during ROT8[7] = 1 +//so, sample the SET signal twice, at both posedge and negedge of ROT8[7] = 1 +reg dma_act_set_n; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[6] == 1'b1) begin //async signal from CPU, sample them here, latch C83 @ posedge ROT8[7] + dma_act_set_n <= ~(~o_BR_n & (i_AS_n | ~i_CPURST_n) & ~(i_BG_n & i_CPURST_n)); //C87 NAND + end + else if(i_ROT8[7] == 1'b1) begin //async signal from CPU, sample them here, latch C83 @ negedge ROT8[7] + dma_act_set_n <= ~(~o_BR_n & (i_AS_n | ~i_CPURST_n) & ~(i_BG_n & i_CPURST_n)); //C87 NAND + end + else begin //disable + dma_act_set_n <= 1'b1; + end + end +end + +reg dma_act_reset_n; + +reg dma_end_dlyd; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + dma_end_dlyd <= i_DMA_END; + + dma_act_reset_n <= ~((i_DMA_END & ~dma_end_dlyd) | ~i_SYS_RST_n); + end +end + +SRNAND C83 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(dma_act_set_n), .i_R_n(dma_act_reset_n), .o_Q(o_DMA_ACT), .o_Q_n()); + + +//BGACK +SRNAND C86 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(dma_act_reset_n | o_DMA_ACT), .i_R_n(dma_act_set_n), .o_Q(o_BGACK_n), .o_Q_n()); //set port: demorgan + + +//BR +reg br_start_dlyd; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + br_start_dlyd <= ~i_BR_START_n; + end +end + +wire br_set_n = i_BR_START_n | br_start_dlyd; +wire br_reset_n = ~((o_DMA_ACT & i_ROT8[1]) | ~i_SYS_RST_n); +SRNAND C88 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(br_reset_n), .i_R_n(br_set_n), .o_Q(o_BR_n), .o_Q_n()); //set port: demorgan + + +//Address Latch Enable +//Glitch can occur here. Not a serious one. Solve. +wire ald_en_set_n = ~(o_DMA_ACT & i_ROT8[0]); +wire ald_en_reset_n = ~((o_DMA_ACT & i_ROT8[2]) | ~i_SYS_RST_n); +SRNAND C70 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(ald_en_reset_n), .i_R_n(ald_en_set_n), .o_Q(), .o_Q_n(o_ALD_EN)); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_dmatiming.v b/rtl/ipcores/K005297/K005297_dmatiming.v new file mode 100644 index 0000000..5f395af --- /dev/null +++ b/rtl/ipcores/K005297/K005297_dmatiming.v @@ -0,0 +1,148 @@ +module K005297_dmatiming +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [7:0] i_ROT8, + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //system flags + input wire i_UMODE_n, + input wire i_ACC_ACT_n, + input wire i_DMA_ACT, + input wire i_BDI_EN, + input wire i_MSKREG_SR_LD, + input wire i_ACQ_MSK_LD, + input wire i_ACQ_START, + input wire i_SUPBDO_EN_n, + input wire i_DMADREG_BDLO_LD, + + output reg o_BR_START_n, + output wire o_DMA_END, + output wire o_DMA_WORD_END, + output wire o_MSKREG_LD, + output wire o_MSKADDR_INC, + output wire o_DMADREG_BDHILO_LD, + output wire o_DMA_WR_ACT_n +); + +/////////////////////////////////////////////////////////// +////// DMA TIMINGS +//// + +// +// USE 4MHz CLOCK +// + +//BDLO_LD negedge detection +reg dmareg_bdlo_ld_dlyd; +wire dmareg_bdlo_ld_negedge = dmareg_bdlo_ld_dlyd & ~i_DMADREG_BDLO_LD; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + dmareg_bdlo_ld_dlyd <= i_DMADREG_BDLO_LD; + end +end + +//dma command d1 SRNOR control +wire dma_command_d1_set = o_MSKREG_LD | ~i_SYS_RST_n; +wire dma_command_d1_reset = ~(i_UMODE_n | ~((i_MSKREG_SR_LD & ~i_ROT20_n[1]) | (i_ACQ_MSK_LD & ~i_ROT20_n[3]))); + +//dma command d0 SRNAND control +wire dma_command_d0_set_n = ~(~(~(o_DMADREG_BDHILO_LD & i_ROT8[3]) & ~(i_ACQ_START & ~i_ROT20_n[0]) & i_SUPBDO_EN_n) | ~i_SYS_RST_n); +wire dma_command_d0_reset_n = ~(((i_ACQ_MSK_LD & ~i_ROT20_n[3]) & ~i_BDI_EN) | dmareg_bdlo_ld_negedge); +assign o_DMA_WORD_END = ~dma_command_d0_set_n; + +//dma commands from sr latches +wire [1:0] dma_command_input; //[G5, F20] + +//G5, d1 +SRNOR G5 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S(dma_command_d1_set), .i_R(dma_command_d1_reset), .o_Q(), .o_Q_n(dma_command_input[1])); + +//F50, d0 +SRNAND F50 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(dma_command_d0_set_n), .i_R_n(dma_command_d0_reset_n), .o_Q(), .o_Q_n(dma_command_input[0])); + + + + +//dma command control block +//rot8 4 5 6 7 0 1 2 3 4 5 6 7 +//rot20 0 1 2 3 4 5 + +//dma command input is stable at falling edge of ROT8[3], because the launching latches are all enabled by ROT8[3] or ROT20[3] +reg dma_command_lock_n = 1'b0; //latches command status at ROT8[3] == 1 +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[3] == 1'b1) begin + if(dma_command_lock_n == 1'b0) begin + if(i_ACC_ACT_n == 1'b0) begin + dma_command_lock_n <= 1'b1; //unlock + end + else begin + dma_command_lock_n <= 1'b0; //lock hold + end + end + else begin + if(i_ACC_ACT_n & ~|{dma_command_input} == 1'b1) begin + dma_command_lock_n <= 1'b0; //lock + end + else begin + dma_command_lock_n <= 1'b1; //unlock + end + end + + if(dma_command_lock_n == 1'b0) begin + if(i_ACC_ACT_n == 1'b0) begin //unlock + o_BR_START_n <= ~|{dma_command_input}; + end + else begin + o_BR_START_n <= 1'b1; //still locked + end + end + else begin + if(i_ACC_ACT_n == 1'b0) begin //free + o_BR_START_n <= ~|{dma_command_input}; + end + else begin + o_BR_START_n <= ~|{dma_command_input}; //locks when NOR(dmainput) is 1 + end + end + end + end +end + +reg [1:0] dma_command_0; //d-latch @ ROT8[4] +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[4] == 1'b1) begin + dma_command_0 <= dma_command_input & {2{(dma_command_lock_n & i_SYS_RST_n)}}; + end + end +end + +reg [1:0] dma_command_1; //d-latch @ ROT8[7] +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + if(i_ROT8[6] == 1'b1) begin + dma_command_1 <= dma_command_0 & {2{(dma_command_lock_n)}}; + end + end +end + + +assign o_DMA_END = ~( dma_command_1[1] | dma_command_1[0]); +assign o_MSKADDR_INC = ( dma_command_1[1] & ~dma_command_1[0] & i_DMA_ACT); +assign o_MSKREG_LD = o_MSKADDR_INC & i_ROT8[3]; +assign o_DMADREG_BDHILO_LD = ( dma_command_1[1] & dma_command_1[0] & i_DMA_ACT) | + (~dma_command_1[1] & dma_command_1[0] & i_DMA_ACT); +assign o_DMA_WR_ACT_n = o_MSKADDR_INC | ~o_DMADREG_BDHILO_LD | ~i_BDI_EN; + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_fsm.v b/rtl/ipcores/K005297/K005297_fsm.v new file mode 100644 index 0000000..23c741a --- /dev/null +++ b/rtl/ipcores/K005297/K005297_fsm.v @@ -0,0 +1,355 @@ +module K005297_fsm +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //CMDREG related + input wire i_CMDREG_RDREQ, + input wire i_CMDREG_WRREQ, + output wire o_CMDREG_RST_n, + + //system flags + input wire i_SYS_RUN_FLAG, + input wire i_SYS_ERR_FLAG, + output wire o_FSMERR_RESTART_n, + + input wire i_SUPBD_ACT_n, + input wire i_PGCMP_EQ, + input wire i_VALPG_ACC_FLAG, + input wire i_PGREG_SR_SHIFT, + input wire i_SUMEQ_n, + input wire i_MUXED_BDO_EN_DLYD, + input wire i_OP_DONE, //??? + + //bubble input enable + output wire o_BDI_EN_SET_n, + output wire o_BDI_EN_RST_n, + + //page register shift register parallel load enable + output wire o_PGREG_SRLD_EN, + + //bubble IO related + output wire o_ACC_START, + output wire o_REP_START, + + //??? + output wire o_CMD_ACCEPTED_n //??? +); + + +/* + FSM STATE + + 0: Initial state + 1: Bootloader Z14(CRC14 zero) flag check state. If nz, hangs on here. + 2: User mode idle + 3: R/W request acceptance + 4: Wait for page swapping + 5: Wait for page replication + 6: Swap start + 7: Page R/W operation + + bootloader: + 0->1->2 + + page read: + 2->3->5->7->2 + + page write: + 2->3->4->7->2 +*/ + +/////////////////////////////////////////////////////////// +////// FSM STATE REGISTER +//// + +reg [2:0] fsmstat_sr = 3'b000; //state register +wire fsmstat_shift; //shift flag: 4-5-6, Q38 SRNAND +SRNAND Q38 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[7]), .i_R_n(i_ROT20_n[4]), .o_Q(), .o_Q_n(fsmstat_shift)); + +//state adder variable +reg [1:0] fsmstat_nxtstat = 2'd3; //3: 1'b0, 2: nROT20[5], 1: nROT20[4], 0: nROT20[4, 5] +reg fsmstat_var; + +always @(*) begin + case(fsmstat_nxtstat) + 2'd0: fsmstat_var <= ~(i_ROT20_n[4] & i_ROT20_n[5]); + 2'd1: fsmstat_var <= ~i_ROT20_n[4]; + 2'd2: fsmstat_var <= ~i_ROT20_n[5]; + 2'd3: fsmstat_var <= 1'b0; + endcase +end +//wire fsmstat_var = (fsmstat_nxtstat[1] == 1'b1) ? ((fsmstat_nxtstat[0] == 1'b1) ? 1'b0 : ~i_ROT20_n[5]) : +// ((fsmstat_nxtstat[0] == 1'b1) ? ~i_ROT20_n[4] : ~(i_ROT20_n[4] & i_ROT20_n[5])); + +//full adder +wire fsmstat_fa_sum, fsmstat_fa_cout; +reg fsmstat_fa_cflag; +FA P56 (.i_A(fsmstat_var), .i_B(fsmstat_sr[0]), .i_CIN(fsmstat_fa_cflag), .o_S(fsmstat_fa_sum), .o_COUT(fsmstat_fa_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + fsmstat_fa_cflag <= fsmstat_fa_cout & i_ROT20_n[19]; + end +end + +//fsm state shift +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(fsmstat_shift == 1'b1) begin //shift + fsmstat_sr[2] <= fsmstat_fa_sum & i_SYS_RUN_FLAG; + fsmstat_sr[1:0] <= fsmstat_sr[2:1]; + end + else begin //hold + fsmstat_sr[2] <= fsmstat_sr[2] & i_SYS_RUN_FLAG; + fsmstat_sr[1:0] <= fsmstat_sr[1:0]; + end + end +end + +//parallel load +reg [2:0] fsmstat_parallel = 3'b000; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[7] == 1'b0) begin //D-latch loads at nROT20[8] + fsmstat_parallel <= fsmstat_sr; + end + else begin + fsmstat_parallel <= fsmstat_parallel; + end + end +end + + + +/////////////////////////////////////////////////////////// +////// FSM FLAG +//// + +reg fsmflag; +always @(*) begin + case(fsmstat_parallel) + 3'd0: fsmflag <= ~i_SUPBD_ACT_n; + 3'd1: fsmflag <= i_OP_DONE; + 3'd2: fsmflag <= 1'b0; + 3'd3: fsmflag <= 1'b0; + 3'd4: fsmflag <= i_PGCMP_EQ; + 3'd5: fsmflag <= i_PGCMP_EQ; + 3'd6: fsmflag <= 1'b0; + 3'd7: fsmflag <= &{~i_ROT20_n[8], ~i_SUPBD_ACT_n, ~i_VALPG_ACC_FLAG, (i_PGREG_SR_SHIFT & i_MUXED_BDO_EN_DLYD), i_SUMEQ_n}; + endcase +end + + + +/////////////////////////////////////////////////////////// +////// AND-OR MATRIX +//// + +wire [7:0] pla_output; + +reg [1:0] command_a_en = 2'b00; //initialize output register +reg [1:0] command_b_en = 2'b00; + +reg [1:0] command_a_0 = 2'b00; //command synchronizer chain: async input from CPU(RD/WR commands) +reg [1:0] command_b_0 = 2'b00; + +reg [1:0] command_a_1 = 2'b00; +reg [1:0] command_b_1 = 2'b00; + +K005297_fsm_pla pla_main +( + .i_A (i_CMDREG_RDREQ ), //CMDREG.RDREQ + .i_B (i_CMDREG_WRREQ ), //CMDREG.WRREQ + .i_C (fsmstat_parallel[0] ), //FSMSTAT.D0 + .i_D (fsmstat_parallel[1] ), //FSMSTAT.D1 + .i_E (fsmstat_parallel[2] ), //FSMSTAT.D2 + .i_F (i_OP_DONE ), //OP_DONE + .i_G (fsmflag ), //FSMFLAGIN + .i_H (i_SYS_ERR_FLAG ), //SYS_ERR_FLAG + + .o_S (pla_output[5] ), + .o_T (pla_output[4] ), + .o_U (pla_output[3] ), + + .o_V (pla_output[2] ), + .o_W (pla_output[1] ), + .o_X (pla_output[0] ), + + .o_Y (pla_output[7] ), + .o_Z (pla_output[6] ) +); + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[9] == 1'b0) begin //D-latch loads at nROT20[10] + fsmstat_nxtstat <= pla_output[7:6]; + end + end +end + + +wire r59 = pla_output[5] & ~pla_output[4] & ~pla_output[3]; + + + +// +// FSM COMMAND/ENABLE SYNCHRONIZER CHAIN(2) +// + +//The FSM gets bubble RW command from the asynchronous latch and decodes it. +//Sample the value @ negedge ROT20_n[10] and shift it @ posedge ROT20_n[10]. +//RW command output automatically disabled @ ROT20_n[10], so shifter's output +//can be presented @ posedge ROT20_n[10]. + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[9] == 1'b0) begin //D-latch loads at nROT20[10] + command_a_en[0] <= pla_output[5]; + command_a_en[1] <= 1'b0; + + command_b_en[0] <= pla_output[2]; + command_b_en[1] <= 1'b0; + end + else if(i_ROT20_n[10] == 1'b0) begin + command_a_en[1] <= command_a_en[0]; + + command_b_en[1] <= command_b_en[0]; + end + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_ROT20_n[9] == 1'b0) begin //D-latch loads at nROT20[10] + command_a_0 <= pla_output[4:3]; + + command_b_0 <= pla_output[1:0]; + end + else if(i_ROT20_n[10] == 1'b0) begin + command_a_1 <= command_a_0; + + command_b_1 <= command_b_0; + end + end +end + + + +/////////////////////////////////////////////////////////// +////// COMMAND DECODER +//// + + +assign o_CMDREG_RST_n = ~&{ command_a_1[1], command_a_1[0], command_a_en[1]}; //NAND /3'b111 + +assign o_FSMERR_RESTART_n = ~&{~command_a_1[1], command_a_1[0], command_a_en[1]}; //NAND /3'b101 + +assign o_BDI_EN_SET_n = ~&{ command_b_1[1], command_b_1[0], command_b_en[1]}; //NAND /3'b111 +assign o_BDI_EN_RST_n = ~&{~command_b_1[1], command_b_1[0], command_b_en[1]}; //NAND /3'b101 + +assign o_PGREG_SRLD_EN = &{ command_a_1[1], ~command_a_1[0], command_a_en[1]}; //AND 3'b110 + +assign o_ACC_START = &{ command_b_1[1], ~command_b_1[0], command_b_en[1]}; //AND 3'b110 +assign o_REP_START = &{~command_b_1[1], ~command_b_1[0], command_b_en[1]}; //AND 3'b100 + +assign o_CMD_ACCEPTED_n = ~&{~command_a_1[1], ~command_a_1[0], command_a_en[1]}; //NAND 3'b100 //NOR?? + +endmodule + + +module K005297_fsm_pla +( + input wire i_A, + input wire i_B, + input wire i_C, + input wire i_D, + input wire i_E, + input wire i_F, + input wire i_G, + input wire i_H, + + output wire o_S, + output wire o_T, + output wire o_U, + output wire o_V, + output wire o_W, + output wire o_X, + output wire o_Y, + output wire o_Z +); + +//internal wires +wire A = i_A; //CMDREG.RDREQ +wire B = i_B; //CMDREG.WRREQ +wire C = i_C; //FSMSTAT.D0 +wire D = i_D; //FSMSTAT.D1 +wire E = i_E; //FSMSTAT.D2 +wire F = i_F; //F25/Q +wire G = i_G; //FSMFLAGIN +wire H = i_H; //SYS_ERR_FLAG + + +//AND array 1 +wire S36 = &{ A, ~B, C, ~D, E, ~F, ~H }; +wire S44 = &{ ~A, B, ~F, ~G }; +wire S43 = &{ ~A, B, ~C, ~D, E, ~F, ~H }; +wire R49 = &{ ~C, D, ~E, ~H }; +wire S42 = &{ ~A, B, ~C, D, E, ~F, ~H }; +wire R50 = &{ C, D, ~E, ~H }; +wire S41 = &{ A, ~B, ~F, ~G }; +wire S29 = &{ ~A, ~B, ~F, ~G }; +wire R36 = &{ C, D, E, ~H }; +wire S37 = &{ ~A, ~B, F, G }; + +//misc +wire S45 = S44 | S37; //~A +wire R33 = A ^ B; + +//AND array 2 +wire R35 = &{ ~D, ~E, ~H } & S29; +wire R32 = &{ ~A, B } & R36; +wire S31 = &{ ~G } & S43; +wire R29 = &{ A, ~B, ~F } & R36; +wire S30 = &{ ~G } & S36; +wire S27 = R49 & S29; +wire S50 = &{ ~A, ~B, ~C, ~D, ~E, H }; +wire S49 = &{ ~A, ~B, ~C, ~D, ~E, ~F, G, ~H }; +wire S46 = S44 & R50; +wire S38 = &{ G } & S36; +wire T42 = &{ ~G } & S42; +wire T40 = &{ G } & S43; +wire S48 = R49 & S41; +wire S47 = S44 & R49; +wire R52 = R50 & S41; +wire S51 = &{ C, ~D, ~E, ~H } & S45; +wire T41 = &{ G } & S42; +wire R34 = S29 & R36; +wire R37 = &{ C, D, E, H } & R33; +wire R30 = &{ A, ~B, F } & R36; +wire S40 = &{ C, ~D, ~E, H } & S29; + +//OR array +wire S28 = |{R35, R32, S31, R29, S30, S27}; + +assign o_S = ~(|{S50, S49, S46, S38, T42, T40, R52, T41, R34} | S28); +assign o_T = ~ S40; +assign o_U = ~|{S48, S47}; + +assign o_V = ~(|{S49, T42, T40, T41, R34, S40} | S28); +assign o_W = ~|{S38, S47}; +assign o_X = ~|{S46, S38, R52}; + +assign o_Y = ~|{S49, S46, T42, S48, S47, S51, T41, R34, R37, R30}; +assign o_Z = ~|{S38, T40, R52, T41, R34, R37, R30, S40}; + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_functrig.v b/rtl/ipcores/K005297/K005297_functrig.v new file mode 100644 index 0000000..c53dd50 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_functrig.v @@ -0,0 +1,128 @@ +module K005297_functrig +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_HALT, //TST4 + input wire i_SYS_RST_n, + + input wire i_UMODE_n, + input wire i_CYCLECNTR_LSB, + + input wire i_ACC_INVAL_n, + input wire i_PGCMP_EQ, + input wire i_SYNCTIP_n, + input wire i_BDI_EN, + + output wire o_ACC_END, + output wire o_SWAP_START, + output wire o_ACQ_START, + output wire o_ADDR_RST +); + + + +/////////////////////////////////////////////////////////// +////// ACCESS TERMINATION +//// + +//terminates magnetic field roation after 7030us +wire const702 = ~&{i_ROT20_n[9], i_ROT20_n[7], i_ROT20_n[5], i_ROT20_n[4], i_ROT20_n[3], i_ROT20_n[2], i_ROT20_n[1]}; +reg eq702_flag_n = 1'b1; +reg acc_end_flag_n = 1'b1; + +assign o_ACC_END = ~acc_end_flag_n; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + eq702_flag_n <= (((i_CYCLECNTR_LSB | i_HALT) ^ const702) | eq702_flag_n | i_UMODE_n) & i_ROT20_n[19]; + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + acc_end_flag_n <= (i_SYS_RST_n == 1'b0) ? 1'b1 : + (i_ROT20_n[10] == 1'b0) ? eq702_flag_n : acc_end_flag_n; + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// SWAP START +//// + +//turn on swap gate after 6240us +wire const623 = ~&{i_ROT20_n[9], i_ROT20_n[6], i_ROT20_n[5], i_ROT20_n[3], i_ROT20_n[2], i_ROT20_n[1], i_ROT20_n[0]}; +reg eq623_flag_n = 1'b1; +reg swap_start_flag_n = 1'b1; + +assign o_SWAP_START = ~swap_start_flag_n; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + eq623_flag_n <= (((i_CYCLECNTR_LSB | i_HALT) ^ const623) | eq623_flag_n) & i_ROT20_n[19]; + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + swap_start_flag_n <= (i_BDI_EN == 1'b1) ? 1'b1 : + (i_ROT20_n[10] == 1'b0) ? eq623_flag_n : swap_start_flag_n; + end +end + + + + + + +/////////////////////////////////////////////////////////// +////// ACQUISITION START +//// + +//start bubble data acquisition after 980us +wire const97 = ~&{i_ROT20_n[6], i_ROT20_n[5], i_ROT20_n[0]}; +reg eq97_flag_n = 1'b1; +reg acq_start_flag_n = 1'b1; +wire acq_start_flag_feedback = (i_SYS_RST_n == 1'b0) ? 1'b1 : + (i_ROT20_n[10] == 1'b0) ? (eq97_flag_n | ~i_BDI_EN) : acq_start_flag_n; + +assign o_ACQ_START = ~acq_start_flag_n; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + eq97_flag_n <= (((i_CYCLECNTR_LSB | i_HALT) ^ const97) | eq97_flag_n | i_UMODE_n) & i_ROT20_n[19]; + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + acq_start_flag_n <= (|{~i_ACC_INVAL_n, i_BDI_EN, ~i_PGCMP_EQ, i_ROT20_n[14]} & i_SYNCTIP_n) & acq_start_flag_feedback; + end +end + + +//delayed ~ROT20_n[18] ...why not D19? +reg rot20_d18_dlyd; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + rot20_d18_dlyd <= ~i_ROT20_n[18]; + end +end + +assign o_ADDR_RST = o_ACQ_START & rot20_d18_dlyd; + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_invalpgdet.v b/rtl/ipcores/K005297/K005297_invalpgdet.v new file mode 100644 index 0000000..25c75f9 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_invalpgdet.v @@ -0,0 +1,48 @@ +module K005297_invalpgdet +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_TST, //test pin(normally 1) + input wire i_PGREG_SR_LSB, //page number shift register's lsb + input wire i_INVALPG_LSB, //invalid page reference point + input wire i_UMODE_n, + input wire i_PGCMP_EQ, + + //output + output wire o_ACC_INVAL_n, + output wire o_VALPG_FLAG_SET_n +); + + +/////////////////////////////////////////////////////////// +////// INVALID PAGE DETECTOR +//// + +//invalid page +reg invalid_page = 1'b0; +reg access_invalid_n = 1'b1; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + //TST3 = 1: eq 0 + //TST3 = 0: gte INVALPG + invalid_page <= ~(~(((i_TST | i_INVALPG_LSB) & i_PGREG_SR_LSB) | ((i_TST | i_INVALPG_LSB | i_PGREG_SR_LSB) & invalid_page)) | ~i_ROT20_n[19]); + + access_invalid_n <= (i_ROT20_n[12] == 1'b0) ? (invalid_page & ~i_UMODE_n) : (access_invalid_n & ~i_UMODE_n); + end +end + +assign o_ACC_INVAL_n = access_invalid_n & i_PGCMP_EQ; +assign o_VALPG_FLAG_SET_n = ~(o_ACC_INVAL_n & ~i_ROT20_n[14]); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_invalpgdgen.v b/rtl/ipcores/K005297/K005297_invalpgdgen.v new file mode 100644 index 0000000..70fb817 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_invalpgdgen.v @@ -0,0 +1,115 @@ +module K005297_invalpgdgen +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //control + input wire i_PGREG_D2, + input wire i_PGREG_D8, + + input wire i_EFFBDO_EN, + input wire i_BDO_EN_n, + input wire i_GLCNT_RD, + + input wire i_VALPG_ACC_FLAG, + input wire i_UMODE_n, + input wire i_SUPBD_ACT_n, + input wire i_SYNCED_FLAG, + input wire i_ALD_nB_U, + + input wire i_BDI, + output wire o_MUXED_BDI, + output wire o_EFF_MUXED_BDI +); + + + +/////////////////////////////////////////////////////////// +////// INVALID PAGE DATA GENERATOR +//// + +//muxed bdi = bubble data + invalid page data +//effective muxed bdi = excepts supplementary bubble data +assign o_EFF_MUXED_BDI = o_MUXED_BDI & i_SUPBD_ACT_n; + + +//SR shift enable +wire sr8_last_shift; //shift flag +wire sr8_shift = (i_EFFBDO_EN & i_GLCNT_RD) | (i_BDO_EN_n & sr8_last_shift); //mux? + +SRNAND F37 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[8]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(sr8_last_shift)); + + +//shift register +reg [7:0] sr8; +wire sr8_msb; +wire sr8_lsb = sr8[0]; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(sr8_shift == 1'b1) begin + sr8[7] <= sr8_msb; + sr8[6:0] <= sr8[7:1]; + end + else begin + sr8 <= sr8; + end + end +end + + +//adder +wire sr8_const, sr8_fa_sum, sr8_fa_cout; //FA carry out +reg sr8_fa_cflag = 1'b0; //FA carry storage +assign sr8_msb = (i_ALD_nB_U == 1'b0) ? sr8_fa_sum & i_SYNCED_FLAG : sr8_lsb & i_SYNCED_FLAG; //bootloader : user pages + +FA Q59 (.i_A(o_EFF_MUXED_BDI), .i_B(sr8_lsb), .i_CIN(sr8_fa_cflag), .o_S(sr8_fa_sum), .o_COUT(sr8_fa_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(sr8_shift == 1'b1) begin + sr8_fa_cflag <= sr8_fa_cout & (i_SUPBD_ACT_n & ~i_ALD_nB_U); + end + else begin + sr8_fa_cflag <= sr8_fa_cflag & (i_SUPBD_ACT_n & ~i_ALD_nB_U); + end + end +end + + +//page number synchronizer(signal from true D-latch) +reg [1:0] sr8_bitmux_sel_0; +reg [1:0] sr8_bitmux_sel_1; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + sr8_bitmux_sel_0 <= {i_PGREG_D8, i_PGREG_D2}; + sr8_bitmux_sel_1 <= sr8_bitmux_sel_0; + end +end + +//sr8 bit selector for scrambling? +reg sr8_bitmux; +always @(*) begin + case(sr8_bitmux_sel_1) + 2'b00: sr8_bitmux <= sr8[7]; + 2'b01: sr8_bitmux <= sr8[6]; + 2'b10: sr8_bitmux <= sr8[5]; + 2'b11: sr8_bitmux <= sr8[4]; + endcase +end + +assign o_MUXED_BDI = i_BDI ^ (sr8_bitmux & ~(i_VALPG_ACC_FLAG | i_UMODE_n | ~i_SUPBD_ACT_n)); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_mskldtimer.v b/rtl/ipcores/K005297/K005297_mskldtimer.v new file mode 100644 index 0000000..e65c0dd --- /dev/null +++ b/rtl/ipcores/K005297/K005297_mskldtimer.v @@ -0,0 +1,52 @@ +module K005297_mskldtimer +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_4BEN_n, + input wire i_ACC_ACT_n, + input wire i_ACQ_MSK_LD, + + + output reg o_MSKREG_SR_LD = 1'b0 +); + + +reg [3:0] mask_load_timer = 4'hF; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if((i_ACC_ACT_n | (o_MSKREG_SR_LD & ~i_ROT20_n[1])) == 1'b1) begin //reset + mask_load_timer <= 4'hF; + end + else begin + if(~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n)) == 1'b1) begin //0-5_10-15 + if(mask_load_timer == 4'h0) begin + mask_load_timer <= 4'hF; + end + else begin + mask_load_timer <= mask_load_timer - 4'h1; + end + end + else begin + mask_load_timer <= mask_load_timer; + end + end + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + o_MSKREG_SR_LD <= ((i_ROT20_n[3] & i_ROT20_n[18]) == 1'b0) ? (&{~mask_load_timer} | i_ACQ_MSK_LD) : o_MSKREG_SR_LD; + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_mskreg.v b/rtl/ipcores/K005297/K005297_mskreg.v new file mode 100644 index 0000000..2cb5bfc --- /dev/null +++ b/rtl/ipcores/K005297/K005297_mskreg.v @@ -0,0 +1,66 @@ +module K005297_mskreg +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_4BEN_n, + input wire i_MSKREG_LD, + input wire i_MSKREG_SR_LD, + input wire i_BOOTEN_n, + + //data + input wire [15:0] i_DIN, + + //serial data + output wire o_MSKREG_SR_LSB +); + + + +/////////////////////////////////////////////////////////// +////// MASK REGISTER +//// + +//D latch * 16 +wire [15:0] mskreg_q; +DL #(.dw(16)) MSKREG (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_EN(i_MSKREG_LD), .i_D(i_DIN), .o_Q(mskreg_q), .o_Q_n()); + +//mask register sr control +wire [1:0] mskreg_sr_ctrl; //11:hold(invalid), 10:load, 01:shift, 00:hold +assign mskreg_sr_ctrl[1] = ~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n)) & (i_MSKREG_SR_LD & i_BOOTEN_n); //0-5_10-15 +assign mskreg_sr_ctrl[0] = ~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n)) & ~(i_MSKREG_SR_LD & i_BOOTEN_n); + +//mask register sr +reg [15:0] mskreg_sr; +assign o_MSKREG_SR_LSB = mskreg_sr[0]; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + case(mskreg_sr_ctrl) + 2'b11: begin + mskreg_sr <= mskreg_sr; + end + 2'b10: begin //load + mskreg_sr <= mskreg_q; + end + 2'b01: begin //shift + mskreg_sr[15] <= ~i_BOOTEN_n; + mskreg_sr[14:0] <= mskreg_sr[15:1]; + end + 2'b00: begin + mskreg_sr <= mskreg_sr; + end + endcase + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_pgcmp.v b/rtl/ipcores/K005297/K005297_pgcmp.v new file mode 100644 index 0000000..46e6bf2 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_pgcmp.v @@ -0,0 +1,112 @@ +module K005297_pgcmp +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_BDI_EN, //bubble input data enable + input wire i_PGREG_SR_LSB, //page number shift register's lsb + input wire i_ABSPGCNTR_LSB, //absolute page counter's lsb + input wire i_UMODE_n, //user mode flag + + //output + output wire o_PGCMP_EQ +); + + +/////////////////////////////////////////////////////////// +////// RELPAGE ABSPAGE CONVERTER +//// + +/* + use carry of relpg-1299 as a gte flag(>= 1299) + relative page 0-1298: carry of relpg-1299(unsigned relpg+2979) is 0, use relpg+754 as the abspg + relative page 1299-4095: carry of relpage-1299 is 1, use relpg-1299 as the abspg + + relpg 1296 -> 1296-1299 C=0 -> 1296+754 = 2050(abspg) + relpg 1298 -> 1298-1299 C=0 -> 1298+754 = 2052(abspg) + + relpg 1299 -> 1299-1299 C=1 -> 1299-1299 = 0(abspg) + relpg 1300 -> 1300-1299 C=1 -> 1230-1299 = 1(abspg) + + relpg 2052 -> 2052-1299 C=1 -> 2052-1299 = 753(abspg) + relpg 2053(invalid) -> 2053-1299 C=1 -> 2053-1299 = 754(abspg) +*/ + + +//sub1299 +wire const2797 = ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[7], i_ROT20_n[6], + i_ROT20_n[5], i_ROT20_n[3], i_ROT20_n[2], i_ROT20_n[0]}; //12'b1010_1110_1101 = unsigned 2797/signed -1299 +wire sub1299_cout, sub1299_sum; +reg sub1299_cflag = 1'b0; +reg gte1299_flag = 1'b0; + +FA O28 (.i_A(i_PGREG_SR_LSB), .i_B(const2797), .i_CIN(sub1299_cflag), .o_S(sub1299_sum), .o_COUT(sub1299_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + sub1299_cflag <= sub1299_cout & i_ROT20_n[19]; + end +end + +//gte flag: greater than or equal to 1299 +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + gte1299_flag <= (i_ROT20_n[12] == 1'b0) ? sub1299_cflag : gte1299_flag; //store bit 11's carry + end +end + + +//add754 +wire const754 = ~&{i_ROT20_n[9], i_ROT20_n[7], i_ROT20_n[6], + i_ROT20_n[5], i_ROT20_n[4], i_ROT20_n[1]}; //12'b0010_1111_0010 = 754 +wire add754_cout, add754_sum; +reg add754_cflag = 1'b0; + +FA O29 (.i_A(const754), .i_B(add754_cflag), .i_CIN(i_PGREG_SR_LSB), .o_S(add754_sum), .o_COUT(add754_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + add754_cflag <= add754_cout & i_ROT20_n[19]; + end +end + + + +/////////////////////////////////////////////////////////// +////// COMPARATOR +//// + +wire target_abspg = (i_BDI_EN == 1'b0) ? i_PGREG_SR_LSB : + (gte1299_flag == 1'b0) ? add754_sum : sub1299_sum; +wire abspg_comparator = target_abspg ^ i_ABSPGCNTR_LSB; //goes high if different bit exists(XOR) + + + +/////////////////////////////////////////////////////////// +////// FLAG BIT +//// + +reg delay0_n, pgcmp_eq_n; +assign o_PGCMP_EQ = ~pgcmp_eq_n; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + delay0_n <= (delay0_n | abspg_comparator) & i_ROT20_n[19]; + + pgcmp_eq_n <= (i_UMODE_n == 1'b1) ? 1'b1 : + (i_ROT20_n[12] == 1'b0) ? delay0_n : pgcmp_eq_n; + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_pgreg.v b/rtl/ipcores/K005297/K005297_pgreg.v new file mode 100644 index 0000000..12ee71e --- /dev/null +++ b/rtl/ipcores/K005297/K005297_pgreg.v @@ -0,0 +1,77 @@ +module K005297_pgreg +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //control + input wire i_PGREG_LD, //async + input wire i_PGREG_SR_LD_EN, + output wire o_PGREG_SR_SHIFT, + + //data + input wire [15:0] i_DIN, + + output wire o_PGREG_D2, + output wire o_PGREG_D8, + output wire o_PGREG_SR_LSB +); + + + +/////////////////////////////////////////////////////////// +////// PAGE REGISTER +//// + + +//Pseudo D latch * 12 +wire [11:0] pgreg_q; +DL #(.dw(12)) PGREG (.i_CLK(i_MCLK), .i_CEN_n(1'b0), .i_EN(i_PGREG_LD), .i_D(i_DIN[11:0]), .o_Q(pgreg_q), .o_Q_n()); + + +//True D latch primitive +/* +reg [11:0] pgreg_q; +always @(*) begin + if(i_PGREG_LD == 1'b1) begin + pgreg_q <= i_DIN[11:0]; + end + else begin + pgreg_q <= pgreg_q; + end +end +*/ + +assign o_PGREG_D2 = pgreg_q[2]; +assign o_PGREG_D8 = pgreg_q[8]; + +//shift flag +SRNAND N28 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[12]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(o_PGREG_SR_SHIFT)); + + +//page shift register +reg [11:0] pgsr = 12'h000; +assign o_PGREG_SR_LSB = pgsr[0]; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + case({(i_PGREG_SR_LD_EN & ~i_ROT20_n[19]), o_PGREG_SR_SHIFT}) + 2'b00: pgsr <= pgsr; //hold + 2'b01: begin pgsr[10:0] <= pgsr[11:1]; pgsr[11] <= o_PGREG_SR_LSB & i_SYS_RST_n; end //shift + 2'b10: pgsr <= pgreg_q; //load TEST// + 2'b11: pgsr <= pgsr; //hold(invalid) + endcase + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_primitives.v b/rtl/ipcores/K005297/K005297_primitives.v new file mode 100644 index 0000000..20df06b --- /dev/null +++ b/rtl/ipcores/K005297/K005297_primitives.v @@ -0,0 +1,180 @@ +module ASYNCDLPS +( + input wire i_SET, + input wire i_EN, + input wire i_D, + output reg o_Q +); + +always @(*) begin + if(i_SET) begin + o_Q <= 1'b1; + end + else begin + if(i_EN) begin + o_Q <= i_D; + end + else begin + o_Q <= o_Q; + end + end +end + +endmodule + +module SYNCDLPS +( + input wire i_CLK, + input wire i_SET, + input wire i_EN, + input wire i_D, + output reg o_Q +); + +always @(posedge i_CLK) begin + if(i_SET) begin + o_Q <= 1'b1; + end + else begin + if(i_EN) begin + o_Q <= i_D; + end + else begin + o_Q <= o_Q; + end + end +end + +endmodule + + +module DL #(parameter dw=1) +( + input wire i_CLK, + input wire i_CEN_n, + + input wire i_EN, + input wire [dw-1:0] i_D, + output wire [dw-1:0] o_Q, + output wire [dw-1:0] o_Q_n +); + +reg [dw-1:0] DFF; +wire [dw-1:0] OUTPUT = (i_EN == 1'b0) ? DFF : i_D; + +assign o_Q = OUTPUT; +assign o_Q_n = ~OUTPUT; + +always @(posedge i_CLK) begin + if(!i_CEN_n) begin + if(i_EN) begin + DFF <= i_D; + end + end +end + +endmodule + + +module FA +( + input wire i_A, + input wire i_B, + input wire i_CIN, + + output wire o_S, + output wire o_COUT +); + +assign o_S = (i_CIN == 1'b0) ? (i_A ^ i_B) : ~(i_A ^ i_B); +assign o_COUT = (i_CIN == 1'b0) ? (i_A & i_B) : (i_A | i_B); + +endmodule + + +module SRNAND +( + input wire i_CLK, + input wire i_CEN_n, + + input wire i_S_n, + input wire i_R_n, + output wire o_Q, + output wire o_Q_n +); + +reg DFF = 1'b1; +reg Q; + +assign o_Q = Q; +assign o_Q_n = ~Q; + +always @(posedge i_CLK) begin + if(!i_CEN_n) begin + case({i_S_n, i_R_n}) + 2'b00: DFF <= DFF; //hold(illegal) + 2'b01: DFF <= 1'b1; //set + 2'b10: DFF <= 1'b0; //reset + 2'b11: DFF <= DFF; //hold + endcase + end +end + +always @(*) begin + case({i_S_n, i_R_n, DFF}) + 3'b000: Q <= DFF; //illegal + 3'b001: Q <= DFF; //illegal + 3'b010: Q <= 1'b1; //set인데 DFF가 0인경우 + 3'b011: Q <= DFF; //set이고 DFF가 1인경우 + 3'b100: Q <= DFF; //reset이고 DFF가 0인경우 + 3'b101: Q <= 1'b0; //reset인데 DFF가 1인경우 + 3'b110: Q <= DFF; //유지 + 3'b111: Q <= DFF; //유지 + endcase +end + +endmodule + + +module SRNOR +( + input wire i_CLK, + input wire i_CEN_n, + + input wire i_S, + input wire i_R, + output wire o_Q, + output wire o_Q_n +); + +reg DFF = 1'b1; +reg Q; + +assign o_Q = Q; +assign o_Q_n = ~Q; + +always @(posedge i_CLK) begin + if(!i_CEN_n) begin + case({i_S, i_R}) + 2'b00: DFF <= DFF; //hold + 2'b01: DFF <= 1'b0; //reset + 2'b10: DFF <= 1'b1; //set + 2'b11: DFF <= DFF; //hold(illegal) + endcase + end +end + +always @(*) begin + case({i_S, i_R, DFF}) + 3'b000: Q <= DFF; //유지 + 3'b001: Q <= DFF; //유지 + 3'b010: Q <= DFF; //reset이고 DFF가 0인경우 + 3'b011: Q <= 1'b0; //reset인데 DFF가 1인경우 + 3'b100: Q <= 1'b1; //set인데 DFF가 0인경우 + 3'b101: Q <= DFF; //set이고 DFF가 1인경우 + 3'b110: Q <= DFF; //illegal + 3'b111: Q <= DFF; //illegal + endcase +end + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_relpgcntr.v b/rtl/ipcores/K005297/K005297_relpgcntr.v new file mode 100644 index 0000000..bc8e3e7 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_relpgcntr.v @@ -0,0 +1,93 @@ +module K005297_relpgcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_RELPGCNTR_CNT_STOP, + input wire i_RELPGCNTR_CNT_START, + input wire i_ALD_nB_U, + + output wire o_RELPGCNTR_LSB +); + + + +/////////////////////////////////////////////////////////// +////// RELATIVE PAGE COUNTER +//// + +/* + gte(greater than or equal) flag(>= 1531 evaluation) + relative page 0-1530: +522 + relative page 1531-2052: -1531(loop) +*/ + + +//SR shift enable +wire relpgcntr_shift; //shift flag +SRNAND I24 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[12]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(relpgcntr_shift)); + + +//const add enable +wire relpgcntr_add_en; +SRNOR I34 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S(i_RELPGCNTR_CNT_STOP), .i_R(i_RELPGCNTR_CNT_START), .o_Q(), .o_Q_n(relpgcntr_add_en)); + + +reg [11:0] relpgcntr = 12'd0; //abs page counter +wire relpgcntr_const, relpgcntr_fa_sum, relpgcntr_fa_cout; //FA carry out +reg relpgcntr_fa_cflag = 1'b0; //FA carry storage +assign o_RELPGCNTR_LSB = relpgcntr_fa_sum & i_ALD_nB_U; + +//shift register +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(relpgcntr_shift == 1'b1) begin + relpgcntr[11] <= o_RELPGCNTR_LSB; + relpgcntr[10:0] <= relpgcntr[11:1]; + end + else begin + relpgcntr <= relpgcntr; + end + end +end + + +//constant generator: +522 or -1531 +wire constP522 = ~&{i_ROT20_n[9], i_ROT20_n[3], i_ROT20_n[1]}; +wire constN1531 = ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}; +reg gte1531_evalreg = 1'b0; +reg gte1531_flag = 1'b0; +assign relpgcntr_const = (gte1531_flag == 1'b0) ? constP522 : constN1531; + //+522 : -1531 +//evaluator: greater than or equal to 1531 +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + gte1531_evalreg <= ((relpgcntr_fa_sum & ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}) | + ((o_RELPGCNTR_LSB | ~&{i_ROT20_n[11], i_ROT20_n[9], i_ROT20_n[2], i_ROT20_n[0]}) & gte1531_evalreg)) & + i_ROT20_n[19]; + + gte1531_flag <= (i_ROT20_n[12] == 1'b0) ? gte1531_evalreg : gte1531_flag; + end +end + + +//adder +FA J30 (.i_A(relpgcntr_add_en & relpgcntr_const), .i_B(relpgcntr_fa_cflag), .i_CIN(relpgcntr[0]), .o_S(relpgcntr_fa_sum), .o_COUT(relpgcntr_fa_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + relpgcntr_fa_cflag <= relpgcntr_fa_cout & i_ROT20_n[19]; + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_spdet.v b/rtl/ipcores/K005297/K005297_spdet.v new file mode 100644 index 0000000..5cda2de --- /dev/null +++ b/rtl/ipcores/K005297/K005297_spdet.v @@ -0,0 +1,91 @@ +module K005297_spdet +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //control + input wire i_BDI, //bubble input data stream + input wire i_GLCNT_RD, //good loop count + input wire i_BOOTEN_n, //bootloader enable(bubble cartridge) + input wire i_BSEN_n, //bubble shift enable(bc) + input wire i_4BEN_n, + + //output + output wire o_SYNCTIP_n, + output wire o_SYNCED_FLAG, + output wire o_SYNCED_FLAG_SET_n +); + + + + +//zero bit counter: needs 128 zero bits + 1 "one" bit +reg [7:0] zerobit_cntr = 8'd255; +wire zerobit_cntr_rst; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(zerobit_cntr_rst == 1'b1) begin + zerobit_cntr <= 8'd255; + end + else begin + if(i_GLCNT_RD == 1'b1) begin + if(zerobit_cntr == 8'd0) begin //loop counter + zerobit_cntr <= 8'd255; + end + else begin + zerobit_cntr <= zerobit_cntr - 8'd1; + end + end + else begin //hold + zerobit_cntr <= zerobit_cntr; + end + end + end +end + + +//invalid pattern: reset the counter if "one" comes in before a complete pattern is detected +reg invalid_pattern = 1'b1; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + invalid_pattern <= (i_GLCNT_RD == 1'b0) ? invalid_pattern : i_BDI; //0:1 + end +end + + +//zero bit counter reset and synced flag SR latch +wire synced_flag; +assign o_SYNCED_FLAG_SET_n = i_BOOTEN_n | o_SYNCTIP_n; + +assign zerobit_cntr_rst = i_BSEN_n | synced_flag | invalid_pattern; //resets zerobit counter +assign o_SYNCED_FLAG = synced_flag; + +SRNAND D60 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_SYNCED_FLAG_SET_n), .i_R_n(i_SYS_RST_n), .o_Q(synced_flag), .o_Q_n()); + + +//sync tip +wire synctip_en = (i_4BEN_n == 1'b0) ? ~i_ROT20_n[18] : ~i_ROT20_n[8]; //4bit mode : 2bit mode +wire synctip_4b = ~&{synctip_en, i_BDI, ~zerobit_cntr[7]}; //D51 TFF +reg [7:0] synctip_2b_dlyd; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + synctip_2b_dlyd[7] <= synctip_4b; + synctip_2b_dlyd[6:0] <= synctip_2b_dlyd[7:1]; + end +end + +assign o_SYNCTIP_n = (i_4BEN_n == 1'b0) ? synctip_4b : synctip_2b_dlyd[0]; //4bit mode : 2bit mode + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_sumcmp.v b/rtl/ipcores/K005297/K005297_sumcmp.v new file mode 100644 index 0000000..60b5b48 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_sumcmp.v @@ -0,0 +1,124 @@ +module K005297_sumcmp +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //data in + input wire i_EFF_MUXED_BDI, + + //control + input wire i_UMODE_n, + input wire i_BDO_EN_n, + input wire i_EFFBDO_EN, + input wire i_GLCNT_RD, + input wire i_PGREG_SR_SHIFT, + input wire i_DMADREG_BDLD_EN, + + input wire i_MUXED_BDO_EN_DLYD, + input wire i_SUPBD_ACT_n, + input wire i_ALD_nB_U, + + //output + output wire o_INVALPG_LSB, + output reg o_SUMEQ_n +); + + + + +// +// VARIABLE +// + +//variable shift register +reg [11:0] sr_var = 12'h000; +wire sr_var_shift = (i_EFFBDO_EN & i_GLCNT_RD) | (i_BDO_EN_n & i_PGREG_SR_SHIFT); + +//sr_var serial FA +wire sr_var_fa_sum, sr_var_fa_cout; //FA carry out +reg sr_var_fa_cflag = 1'b0; //FA carry storage + +//msb/lsb +wire sr_var_msb = sr_var_fa_sum & i_MUXED_BDO_EN_DLYD; +wire sr_var_lsb = (i_UMODE_n == 1'b1) ? sr_var[0] : sr_var[4]; //bootloader:user page + + +//Full adder +FA N48 (.i_A(i_EFF_MUXED_BDI), .i_B(sr_var_fa_cflag), .i_CIN(sr_var_lsb), .o_S(sr_var_fa_sum), .o_COUT(sr_var_fa_cout)); + +//carry storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + sr_var_fa_cflag <= (sr_var_shift == 1'b1) ? (sr_var_fa_cout & ~i_DMADREG_BDLD_EN) : (sr_var_fa_cflag & ~i_DMADREG_BDLD_EN); //update:hold + end +end + + +//sr +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(sr_var_shift == 1'b1) begin + sr_var[11] <= sr_var_msb; + sr_var[10:0] <= sr_var[11:1]; + end + else begin + sr_var <= sr_var; + end + end +end + + + +// +// CONSTANT +// + +//constant shift register +reg [11:0] sr_const = 12'h000; +wire sr_const_shift; + +//msb in +wire sr_const_msb = (&{i_MUXED_BDO_EN_DLYD, i_PGREG_SR_SHIFT, ~i_SUPBD_ACT_n, ~i_ALD_nB_U} == 1'b1) ? sr_var_lsb : sr_const[0]; //load : hold +wire sr_const_lsb = sr_const[0]; +assign o_INVALPG_LSB = sr_const_lsb; + +//shift +SRNAND O35 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[12]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(sr_const_shift)); + + +//sr +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(sr_const_shift == 1'b1) begin + sr_const[11] <= sr_const_msb; + sr_const[10:0] <= sr_const[11:1]; + end + else begin + sr_const <= sr_const; + end + end +end + + + +// +// COMPARATOR +// + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + o_SUMEQ_n <= ((sr_var_lsb ^ sr_const_lsb) | o_SUMEQ_n) & i_ROT20_n[19]; + end +end + + + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_supbdlcntr.v b/rtl/ipcores/K005297/K005297_supbdlcntr.v new file mode 100644 index 0000000..436c7c6 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_supbdlcntr.v @@ -0,0 +1,84 @@ +module K005297_supbdlcntr +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //control + input wire i_SYS_RUN_FLAG, + + input wire i_4BEN_n, + input wire i_BDI_EN, + input wire i_SUPBD_START_n, + + input wire i_MSKREG_SR_LSB, + input wire i_GLCNT_RD, + + + output wire o_SUPBDLCNTR_CNT, + output wire o_SUPBD_ACT_n, + output wire o_SUPBD_END_n +); + + + +/////////////////////////////////////////////////////////// +////// SUPPLEMENTARY BUBBLE DATA LENGTH COUNTER +//// + +//count enable +SRNAND J34 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_SUPBD_END_n), .i_R_n(i_SUPBD_START_n), .o_Q(o_SUPBD_ACT_n), .o_Q_n()); + +//delay something? +reg supbd_act_n_dlyd = 1'b1; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n)) == 1'b1) begin //0-5_10-15 + supbd_act_n_dlyd <= o_SUPBD_ACT_n; + end + else begin + supbd_act_n_dlyd <= supbd_act_n_dlyd; + end + end +end + +//supplementary data count up +wire glcnt_wr = ((~supbd_act_n_dlyd | o_SUPBD_ACT_n) & ~(i_ROT20_n[3] & i_ROT20_n[8] & ~(~(i_ROT20_n[13] & i_ROT20_n[18]) & ~i_4BEN_n)) & i_MSKREG_SR_LSB); +assign o_SUPBDLCNTR_CNT = (i_BDI_EN == 1'b0) ? glcnt_wr : i_GLCNT_RD; + +//supplementary data bit counter +reg [3:0] supbd_length_cntr = 4'hF; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(o_SUPBD_ACT_n == 1'b1) begin //reset + supbd_length_cntr <= 4'hF; + end + else begin + if(o_SUPBDLCNTR_CNT == 1'b1) begin + if(supbd_length_cntr == 4'h0) begin + supbd_length_cntr <= 4'hF; + end + else begin + supbd_length_cntr <= supbd_length_cntr - 4'h1; + end + end + else begin + supbd_length_cntr <= supbd_length_cntr; + end + end + end +end + +//flag +wire eq14 = (supbd_length_cntr == 4'h1) ? 1'b1 : 1'b0; //4'd14 +assign o_SUPBD_END_n = (~(eq14 & ~(i_ROT20_n[0] & i_ROT20_n[5] & ~(~(i_ROT20_n[10] & i_ROT20_n[15]) & ~i_4BEN_n))) & i_SYS_RUN_FLAG); //0-5_10-15 + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_supervisor.v b/rtl/ipcores/K005297/K005297_supervisor.v new file mode 100644 index 0000000..87b8da8 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_supervisor.v @@ -0,0 +1,291 @@ +module K005297_supervisor +( + //master clock + input wire i_MCLK, + + //chip clock from bubble cart, synchronized to i_MCLK + input wire i_CLK4M_PCEN_n, + + //master reset + input wire i_MRST_n, + + //halt + input wire i_HALT_n, + + //subclock control + input wire i_CLK2M_STOPRQ0_n, + input wire i_CLK2M_STOPRQ1_n, + output wire o_CLK2M_STOP_n, + output wire o_CLK2M_STOP_DLYD_n, + output wire o_CLK2M_PCEN_n, + + //rotators + output wire [7:0] o_ROT8, + output wire [19:0] o_ROT20_n, + + //system flags + output wire o_SYS_RST_n, + output wire o_SYS_RUN_FLAG, + output wire o_SYS_RUN_FLAG_SET_n +); + +/* + CLOCKING INFORMATION + + 4MHz _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + + + NCLK + orig in _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + + stage 0 ¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|________ + stage 5 __________|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯ + 0 AND 5 _______________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________| + + + PCLK + orig in ¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|________ + + stage 0 _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + stage 5 ¯¯¯¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_____ + 0 AND 5 _______|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|_____ + + + 4MHz _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + 4M NCLK _______________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________| + 4M PCLK _______|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|_____ + + ROT8 -(7)---|------(0)------|------(1)------|------(2)------|------(3)------|------(4)------|------(5)------|----(6)- + ROT8[0] _______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|________________________________________________________________________________________ + + C2STOPDLYn _______|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + + A59 OUT ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯ + A60 OUT _______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|________ + + A62 EN _______________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________| + A62 OUT _______________________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| + + A60 _______________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|________ + A62 _______________________________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| + + A64(01)PCLK _______________________________________|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯| + A66(10)NCLK _______________________|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯|_______________________|¯¯¯¯¯¯¯|________________ + + 4MHz _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + 2MHz ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯ + + + 4MHz _______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯|_______|¯¯¯¯¯¯¯| + 2MHz ¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_______________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|________ + + ROT8 -(7)---|------(0)------|------(1)------|------(2)------|------(3)------|------(4)------|------(5)------|----(6)- + PORCNTR -----------------(7)-------------------|-------------------------------------(6)-------------------------------- + 4M PCLK _______|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|____________|¯¯|_____ + + C2RDYn ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|__|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ + OPSTOP ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|________________________________________________________________________ + ROT20n -----------------------(invalid)-----------------------|--------------(0)--------------|--------------(1)------- +*/ + + +/////////////////////////////////////////////////////////// +////// GLOBAL CLOCKS / FLAGS +//// + +//all stoarge elements works at falling edge of 4M/2M +wire CLK4P_n = i_CLK4M_PCEN_n; //4MHz clock from bubble memory cartridge 12MHz/3 +wire CLK2P_n; //2MHz internal subclock that can be controlled by start/stop logic + + + +/////////////////////////////////////////////////////////// +////// MODULE ROT8 +//// + +K005297_supervisor_rot8 rot8_main (.i_CLK(i_MCLK), .i_CEN_n(CLK4P_n), .i_STOP_n(i_HALT_n), .o_ROT8(o_ROT8)); //FREE-RUNNING 8-BIT ROTATOR, rotates bit 1 from LSB to MSB + + + +/////////////////////////////////////////////////////////// +////// CLK2M(SUBCLK) CONTROL/GENERATOR +//// + +//subclk control +//SYS_RUN_FLAG가 0이면 clk2m시동을 걸어줌, 1로 올라간 후에는 clk2m정지 플래그들이 제어 +wire clk2m_ctrl = &{i_MRST_n, i_CLK2M_STOPRQ0_n, i_CLK2M_STOPRQ1_n} | ~o_SYS_RUN_FLAG; //A37 A36 A38 + +reg A41 = 1'b0; +wire clk2m_stop_n = i_MRST_n & A41; +wire clk2m_stop_dlyd_n; +assign o_CLK2M_STOP_n = clk2m_stop_n; +assign o_CLK2M_STOP_DLYD_n = clk2m_stop_dlyd_n; + +always @(posedge i_MCLK) begin + if(!CLK4P_n) begin + A41 <= (o_ROT8[5] == 1'b0) ? A41 : clk2m_ctrl; //MUX 0:1 + end +end + +DL A42 (.i_CLK(i_MCLK), .i_CEN_n(CLK4P_n), .i_EN(o_ROT8[0]), .i_D(clk2m_stop_n), .o_Q(clk2m_stop_dlyd_n), .o_Q_n()); + +//subclk generator +//negative clock enable신호 생성 +reg A59 = 1'b0; +always @(posedge i_MCLK) begin + if(!CLK4P_n) begin + A59 <= ~(A59 & clk2m_stop_dlyd_n); //1이면 flip, 0이면 1유지 + end +end + +assign CLK2P_n = (A59 | CLK4P_n); +assign o_CLK2M_PCEN_n = CLK2P_n; + + + +/////////////////////////////////////////////////////////// +////// POR CONTROL +//// + +//this counter is for ring counter synchronization; they follow the order below: +//rot8 4 5 6 7 0 1 2 3 4 5 6 7 +//rot20 0 1 2 3 4 5 + +reg [3:0] por_cntr = 4'b1111; //cascaded T flip flops; A23 A24 A25 A27 +always @(posedge i_MCLK) begin + if(!CLK4P_n) begin + if(~clk2m_stop_dlyd_n == 1'b1) begin //set + por_cntr <= 4'b1111; + end + else begin + if(~o_ROT8[1] == 1'b0) begin //count + if(por_cntr == 4'b0000) begin + por_cntr <= 4'b1111; //loop + end + else begin + por_cntr <= por_cntr - 4'b1; + end + end + else begin + por_cntr <= por_cntr; //hold + end + end + end +end + +wire op_start_n = ~&{o_ROT8[0], por_cntr[3:1], ~por_cntr[0]}; //A22 +wire op_stop; +wire clk2m_ready_n = ~&{~por_cntr[3], ~por_cntr[0]}; //A29 + +wire A30Q; +assign op_stop = ~A30Q; + +SRNAND A30 (.i_CLK(i_MCLK), .i_CEN_n(CLK4P_n), .i_S_n(clk2m_ready_n), .i_R_n(clk2m_stop_n), .o_Q(A30Q), .o_Q_n()); +SRNAND A21 (.i_CLK(i_MCLK), .i_CEN_n(CLK4P_n), .i_S_n(op_start_n), .i_R_n(A30Q), .o_Q(o_SYS_RST_n), .o_Q_n()); + + + +/////////////////////////////////////////////////////////// +////// MODULE ROT20 +//// + +K005297_supervisor_rot20 rot20_main (.i_CLK(i_MCLK), .i_CEN_n(CLK2P_n), .i_STOP(op_stop), .o_ROT20_n(o_ROT20_n)); //20-BIT ROTATOR, rotates bit 1 from LSB to MSB + + + +/////////////////////////////////////////////////////////// +////// SYS_RUN_FLAG_n +//// + +assign o_SYS_RUN_FLAG_SET_n = ~(o_SYS_RST_n & ~o_ROT20_n[19]); + +SRNAND C30 (.i_CLK(i_MCLK), .i_CEN_n(CLK4P_n), .i_S_n(o_SYS_RST_n), .i_R_n(o_SYS_RUN_FLAG_SET_n), .o_Q(), .o_Q_n(o_SYS_RUN_FLAG)); + + + +/////////////////////////////////////////////////////////// +////// RING COUNTER DECODER +//// + +reg [4:0] debug_rot20_val; +reg [2:0] debug_rot8_val; + +always @(*) begin + case(o_ROT20_n) + 20'b1111_1111_1111_1111_1110: debug_rot20_val <= 5'd0; + 20'b1111_1111_1111_1111_1101: debug_rot20_val <= 5'd1; + 20'b1111_1111_1111_1111_1011: debug_rot20_val <= 5'd2; + 20'b1111_1111_1111_1111_0111: debug_rot20_val <= 5'd3; + 20'b1111_1111_1111_1110_1111: debug_rot20_val <= 5'd4; + 20'b1111_1111_1111_1101_1111: debug_rot20_val <= 5'd5; + 20'b1111_1111_1111_1011_1111: debug_rot20_val <= 5'd6; + 20'b1111_1111_1111_0111_1111: debug_rot20_val <= 5'd7; + 20'b1111_1111_1110_1111_1111: debug_rot20_val <= 5'd8; + 20'b1111_1111_1101_1111_1111: debug_rot20_val <= 5'd9; + 20'b1111_1111_1011_1111_1111: debug_rot20_val <= 5'd10; + 20'b1111_1111_0111_1111_1111: debug_rot20_val <= 5'd11; + 20'b1111_1110_1111_1111_1111: debug_rot20_val <= 5'd12; + 20'b1111_1101_1111_1111_1111: debug_rot20_val <= 5'd13; + 20'b1111_1011_1111_1111_1111: debug_rot20_val <= 5'd14; + 20'b1111_0111_1111_1111_1111: debug_rot20_val <= 5'd15; + 20'b1110_1111_1111_1111_1111: debug_rot20_val <= 5'd16; + 20'b1101_1111_1111_1111_1111: debug_rot20_val <= 5'd17; + 20'b1011_1111_1111_1111_1111: debug_rot20_val <= 5'd18; + 20'b0111_1111_1111_1111_1111: debug_rot20_val <= 5'd19; + endcase + + case(o_ROT8) + 8'b0000_0001: debug_rot8_val <= 3'd0; + 8'b0000_0010: debug_rot8_val <= 3'd1; + 8'b0000_0100: debug_rot8_val <= 3'd2; + 8'b0000_1000: debug_rot8_val <= 3'd3; + 8'b0001_0000: debug_rot8_val <= 3'd4; + 8'b0010_0000: debug_rot8_val <= 3'd5; + 8'b0100_0000: debug_rot8_val <= 3'd6; + 8'b1000_0000: debug_rot8_val <= 3'd7; + endcase +end + +endmodule + +module K005297_supervisor_rot8 +( + input wire i_CLK, + input wire i_CEN_n, + + input wire i_STOP_n, + output wire [7:0] o_ROT8 +); + +reg [7:0] SR8 = 8'b0; +assign o_ROT8 = SR8; + +always @(posedge i_CLK) begin + if(~i_CEN_n) begin + SR8[7:1] <= SR8[6:0]; + SR8[0] <= ~|{SR8[6:0], ~i_STOP_n}; //A55 NOT + end +end + +endmodule + +module K005297_supervisor_rot20 +( + input wire i_CLK, + input wire i_CEN_n, + + input wire i_STOP, + output wire [19:0] o_ROT20_n +); + +reg [19:0] SR20 = 20'b0000_0001_0000_0010_0000; +assign o_ROT20_n = ~SR20; + +always @(posedge i_CLK) begin + if(~i_CEN_n) begin + SR20[19:1] <= SR20[18:0]; + SR20[0] <= ~|{SR20[18:0], i_STOP}; + end +end + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_tempdet.v b/rtl/ipcores/K005297/K005297_tempdet.v new file mode 100644 index 0000000..6ed1160 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_tempdet.v @@ -0,0 +1,49 @@ +module K005297_tempdet +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //control + input wire i_TEMPLO_n, + input wire i_CLK2M_STOP_n, + input wire i_CLK2M_STOP_DLYD_n, + + output wire o_TEMPDROP_SET_n, + output wire o_HEATEN_n +); + + +//register for edge detection +reg edgedet_0, edgedet_1; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + edgedet_0 <= i_CLK2M_STOP_n & i_TEMPLO_n; + edgedet_1 <= i_CLK2M_STOP_DLYD_n; + end +end + +//TEMPDROP flag +assign o_TEMPDROP_SET_n = ~(edgedet_0 & ~(i_CLK2M_STOP_n & i_TEMPLO_n)); //negative edge detection + + +wire heaten_clr_n = ~(~edgedet_0 & (i_CLK2M_STOP_n & i_TEMPLO_n)) & i_CLK2M_STOP_n; //positive edge detection +wire heaten_set_n = ~((~edgedet_1 & i_CLK2M_STOP_DLYD_n & ~i_TEMPLO_n) & heaten_clr_n); + +//delay +reg [1:0] heaten_ctrl_n; +always @(posedge i_MCLK) begin + if(!i_CLK4M_PCEN_n) begin + heaten_ctrl_n[1] <= heaten_clr_n; + heaten_ctrl_n[0] <= heaten_set_n; + end +end + +//HEATEN_n out +SRNAND C20 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK4M_PCEN_n), .i_S_n(heaten_ctrl_n[1]), .i_R_n(heaten_ctrl_n[0]), .o_Q(o_HEATEN_n), .o_Q_n()); + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_timer25k.v b/rtl/ipcores/K005297/K005297_timer25k.v new file mode 100644 index 0000000..c184145 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_timer25k.v @@ -0,0 +1,107 @@ +module K005297_timer25k +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //timer + input wire i_TIMER25K_CNT, + input wire i_TIMER25K_OUTLATCH_LD_n, + output wire o_TIMER25K_TIMEOVER_n, + + output reg [11:0] o_TIMERREG_LSBS = 12'd0 +); + + + +/////////////////////////////////////////////////////////// +////// 2556 TIMER(500ns*2556 = 1.278ms) +//// + +/////////////////////////////////////////////////////////// +////// CYCLE COUNTER +//// + +/* + +1 serial up counter +*/ + +//shift flag +wire timer25k_shift; +SRNAND K3 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_ROT20_n[12]), .i_R_n(i_ROT20_n[0]), .o_Q(), .o_Q_n(timer25k_shift)); + + +reg [11:0] timer25k = 12'd0; //timer +wire timer25k_fa_sum; //msb input +wire timer25k_fa_cout; //FA carry out +reg timer25k_fa_cflag = 1'b0; //FA carry storage + +//serial full adder cell +FA K4 (.i_A(timer25k[0]), .i_B(timer25k_fa_cflag), .i_CIN((i_TIMER25K_CNT & ~i_ROT20_n[0])), .o_S(timer25k_fa_sum), .o_COUT(timer25k_fa_cout)); + +//previous carry bit storage +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + timer25k_fa_cflag <= timer25k_fa_cout & i_ROT20_n[19]; + end +end + +//shift register +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(timer25k_shift == 1'b1) begin + timer25k[11] <= timer25k_fa_sum & i_TIMER25K_CNT; + timer25k[10:0] <= timer25k[11:1]; + end + else begin + timer25k <= timer25k; + end + end +end + + + +/* + evaluation +*/ + +wire const2555 = ~&{i_ROT20_n[11], i_ROT20_n[8], i_ROT20_n[7], i_ROT20_n[6], i_ROT20_n[5], i_ROT20_n[4], i_ROT20_n[3], i_ROT20_n[1], i_ROT20_n[0]}; +reg eq2555_flag_n = 1'b1; +reg timeover_flag_n = 1'b1; + +assign o_TIMER25K_TIMEOVER_n = ~(~timeover_flag_n & ~i_ROT20_n[13]); + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + eq2555_flag_n <= ((timer25k_fa_sum ^ const2555) | eq2555_flag_n) & i_ROT20_n[19]; + end +end + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + timeover_flag_n <= (i_ROT20_n[12] == 1'b0) ? eq2555_flag_n : timeover_flag_n; + end +end + + + +/* + counter register +*/ + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(i_TIMER25K_OUTLATCH_LD_n == 1'b0) begin + o_TIMERREG_LSBS <= timer25k; + end + end +end + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/K005297/K005297_z14eval.v b/rtl/ipcores/K005297/K005297_z14eval.v new file mode 100644 index 0000000..4fbeee7 --- /dev/null +++ b/rtl/ipcores/K005297/K005297_z14eval.v @@ -0,0 +1,138 @@ +module K005297_z14eval +( + //master clock + input wire i_MCLK, + + //clock enables + input wire i_CLK4M_PCEN_n, + input wire i_CLK2M_PCEN_n, + + //timing + input wire [19:0] i_ROT20_n, + + //reset + input wire i_SYS_RST_n, + + //lock control + input wire i_TIMER25K_TIMEOVER_n, + input wire i_Z14_ERR_n, + + //lock flag related + output wire o_Z14_UNLOCK_n, + output wire o_Z14_LOCKED_n, + + //control + input wire i_BDI_EN, + + input wire i_SUPBD_ACT_n, + input wire i_SUPBD_END_n, + + input wire i_DLCNT_START_n, + input wire i_SUPBDLCNTR_CNT, + input wire i_ACQ_START, + + input wire i_MSKREG_SR_LSB, + + input wire i_BDI, + input wire i_EFF_BDO, + output wire o_MUXED_BDO, + + output wire o_TIMER25K_CNT, + output wire o_TIMER25K_OUTLATCH_LD_n, + + //flags output + output wire o_Z14_n, + output wire o_Z11_d13_n, + + output wire [3:0] o_TIMERREG_MSBS +); + + +reg rot20_d18_dlyd1, rot20_d18_dlyd2; +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + rot20_d18_dlyd1 <= ~i_ROT20_n[18]; + rot20_d18_dlyd2 <= rot20_d18_dlyd1; + end +end + + +/////////////////////////////////////////////////////////// +////// Z14 FLAG EVALUATOR +//// + +//Actually, this is a CRC14 calculator + +//Z14 lock flag bit +assign o_Z14_UNLOCK_n = i_TIMER25K_TIMEOVER_n & o_Z11_d13_n; + +//original implementation +assign o_TIMER25K_OUTLATCH_LD_n = o_Z14_LOCKED_n | o_Z11_d13_n; + +SRNAND I7 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(o_Z14_UNLOCK_n), .i_R_n(i_Z14_ERR_n), .o_Q(o_Z14_LOCKED_n), .o_Q_n(o_TIMER25K_CNT)); + + +//SR14 control +wire bdi_act, srctrl_en_n; +wire srctrl_shift = (bdi_act == 1'b1) ? i_SUPBDLCNTR_CNT : rot20_d18_dlyd2; //J47 AO22 + +SRNAND J48 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(i_SUPBD_END_n), .i_R_n(i_DLCNT_START_n), .o_Q(), .o_Q_n(bdi_act)); +SRNAND F47 (.i_CLK(i_MCLK), .i_CEN_n(i_CLK2M_PCEN_n), .i_S_n(~(i_ACQ_START & ~i_ROT20_n[0]) & i_SYS_RST_n), .i_R_n(i_DLCNT_START_n), .o_Q(srctrl_en_n), .o_Q_n()); + + +//SR14 data in +wire output_data_n = ~((~i_BDI_EN & i_EFF_BDO) | i_BDI); //M35 +wire output_data_n_gated = ~(output_data_n | ~o_Z14_LOCKED_n); //M7 +wire sr14_msb; +wire sr14_lsb = (sr14_msb ^ output_data_n_gated) & ~(~i_BDI_EN & ~i_SUPBD_ACT_n); + + +//SR14 +reg [3:0] sr14_4; +reg sr14_1; +reg [8:0] sr14_9; +wire [13:0] sr14 = {sr14_9, sr14_1, sr14_4}; + //MSB //LSB <- INPUT +wire [15:0] __DEBUG_CRC12_VAL = {sr14, 2'b00}; + +assign sr14_msb = sr14[13]; +assign o_Z11_d13_n = |{sr14[13:3]} | i_ROT20_n[13]; +assign o_Z14_n = |{sr14}; +assign o_TIMERREG_MSBS = sr14[13:10]; + +always @(posedge i_MCLK) begin + if(!i_CLK2M_PCEN_n) begin + if(srctrl_en_n == 1'b1) begin //reset + sr14_4 <= 4'b0000; + sr14_1 <= 1'b0; + sr14_9 <= 9'b0_0000_0000; + end + else begin + if(srctrl_shift == 1'b1) begin //shift + //sr14_4 + sr14_4[0] <= sr14_lsb; + sr14_4[3:1] <= sr14_4[2:0]; + + //sr14_1 + sr14_1 <= sr14_4[3] ^ sr14_lsb; + + //sr14_9 + sr14_9[0] <= sr14_1 ^ sr14_lsb; + sr14_9[8:1] <= sr14_9[7:0]; + end + else begin //hold + sr14_4 <= sr14_4; + sr14_1 <= sr14_1; + sr14_9 <= sr14_9; + end + end + end +end + + +//bubble data output +assign o_MUXED_BDO = ((~i_BDI_EN & ~i_SUPBD_ACT_n) == 1'b0) ? output_data_n_gated & i_MSKREG_SR_LSB : sr14_msb & i_MSKREG_SR_LSB; + + + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/fx68k/fx68k.qip b/rtl/ipcores/fx68k/fx68k.qip new file mode 100644 index 0000000..b8e872c --- /dev/null +++ b/rtl/ipcores/fx68k/fx68k.qip @@ -0,0 +1,5 @@ +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) fx68k.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) fx68kAlu.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) uaddrPla.sv ] +set_global_assignment -name SOURCE_FILE [file join $::quartus(qip_path) microrom.mem ] +set_global_assignment -name SOURCE_FILE [file join $::quartus(qip_path) nanorom.mem ] \ No newline at end of file diff --git a/rtl/ipcores/fx68k/fx68k.sv b/rtl/ipcores/fx68k/fx68k.sv new file mode 100644 index 0000000..dbac825 --- /dev/null +++ b/rtl/ipcores/fx68k/fx68k.sv @@ -0,0 +1,2709 @@ +// +// FX68K +// +// M68000 cycle accurate, fully synchronous +// Copyright (c) 2018,2021 by Jorge Cwik +// +// TODO: +// - Everything except bus retry already implemented. + +`timescale 1 ns / 1 ns + +//`define USE_E_CLKEN +/* + Define USE_E_CLKEN will output two signals that generate a single cycle pulse just before the raising and falling edges of E. + Use this when you need to generate changes that must be simultaneous with these edges. + Most systems don't need this. Note that these signals are not registered. + */ + +// Define this to run a self contained compilation test build +// `define FX68K_TEST + +localparam CF = 0, VF = 1, ZF = 2, NF = 3, XF = 4, SF = 13; + +localparam UADDR_WIDTH = 10; +localparam UROM_WIDTH = 17; +localparam UROM_DEPTH = 1024; + +localparam NADDR_WIDTH = 9; +localparam NANO_WIDTH = 68; +localparam NANO_DEPTH = 336; + +localparam BSER1_NMA = 'h003; +localparam RSTP0_NMA = 'h002; +localparam HALT1_NMA = 'h001; +localparam TRAC1_NMA = 'h1C0; +localparam ITLX1_NMA = 'h1C4; + +localparam TVN_SPURIOUS = 12; +localparam TVN_AUTOVEC = 13; +localparam TVN_INTERRUPT = 15; + +localparam NANO_DOB_DBD = 2'b01; +localparam NANO_DOB_ADB = 2'b10; +localparam NANO_DOB_ALU = 2'b11; + + +// Clocks, phases and resets +typedef struct { + logic clk; + logic extReset; // External sync reset on emulated system + logic pwrUp; // Asserted together with reset on emulated system coldstart + logic enPhi1, enPhi2; // Clock enables. Next cycle is PHI1 or PHI2 +} s_clks; + +// IRD decoded signals +typedef struct { + logic isPcRel; + logic isTas; + logic implicitSp; + logic toCcr; + logic rxIsDt, ryIsDt; + logic rxIsUsp, rxIsMovem, movemPreDecr; + logic isByte; + logic isMovep; + logic [2:0] rx, ry; + logic rxIsAreg, ryIsAreg; + logic [15:0] ftuConst; + logic [5:0] macroTvn; + logic inhibitCcr; +} s_irdecod; + +// Nano code decoded signals +typedef struct { + logic permStart; + logic waitBusFinish; + logic isWrite; + logic busByte; + logic isRmc; + logic noLowByte, noHighByte; + + logic updTpend, clrTpend; + logic tvn2Ftu, const2Ftu; + logic ftu2Dbl, ftu2Abl; + logic abl2Pren, updPren; + logic inl2psw, ftu2Sr, sr2Ftu, ftu2Ccr, pswIToFtu; + logic ird2Ftu, ssw2Ftu; + logic initST; + logic Ir2Ird; + + logic auClkEn, noSpAlign; + logic [2:0] auCntrl; + logic todbin, toIrc; + logic dbl2Atl, abl2Atl, atl2Abl, atl2Dbl; + logic abh2Ath, dbh2Ath; + logic ath2Dbh, ath2Abh; + + logic db2Aob, ab2Aob, au2Aob; + logic aob2Ab, updSsw; + // logic adb2Dob, dbd2Dob, alu2Dob; + logic [1:0] dobCtrl; + + logic abh2reg, abl2reg; + logic reg2abl, reg2abh; + logic dbh2reg, dbl2reg; + logic reg2dbl, reg2dbh; + logic ssp, pchdbh, pcldbl, pclabl, pchabh; + + logic rxh2dbh, rxh2abh; + logic dbl2rxl, dbh2rxh; + logic rxl2db, rxl2ab; + logic abl2rxl, abh2rxh; + logic dbh2ryh, abh2ryh; + logic ryl2db, ryl2ab; + logic ryh2dbh, ryh2abh; + logic dbl2ryl, abl2ryl; + logic rz; + logic rxlDbl; + + logic [2:0] aluColumn; + logic [1:0] aluDctrl; + logic aluActrl; + logic aluInit, aluFinish; + logic abd2Dcr, dcr2Dbd; + logic dbd2Alue, alue2Dbd; + logic dbd2Alub, abd2Alub; + + logic alu2Dbd, alu2Abd; + logic au2Db, au2Ab, au2Pc; + logic dbin2Abd, dbin2Dbd; + logic extDbh, extAbh; + logic ablAbd, ablAbh; + logic dblDbd, dblDbh; + logic abdIsByte; +} s_nanod; + +module fx68k( + input clk, + input HALTn, // Used for single step only. Force high if not used + // input logic HALTn = 1'b1, // Not all tools support default port values + + // These two signals don't need to be registered. They are not async reset. + input extReset, // External sync reset on emulated system + input pwrUp, // Asserted together with reset on emulated system coldstart + input enPhi1, enPhi2, // Clock enables. Next cycle is PHI1 or PHI2 + + output eRWn, output ASn, output LDSn, output UDSn, + output logic E, output VMAn, + +`ifdef USE_E_CLKEN + // Next cycle would be raising/falling edge of E output + output E_PosClkEn, E_NegClkEn, +`endif + + output FC0, output FC1, output FC2, + output BGn, + output oRESETn, output oHALTEDn, + input DTACKn, input VPAn, + input BERRn, + input BRn, BGACKn, + input IPL0n, input IPL1n, input IPL2n, + input [15:0] iEdb, output [15:0] oEdb, + output [23:1] eab + ); + + // wire clock = Clks.clk; + s_clks Clks; + + assign Clks.clk = clk; + assign Clks.extReset = extReset; + assign Clks.pwrUp = pwrUp; + assign Clks.enPhi1 = enPhi1; + assign Clks.enPhi2 = enPhi2; + + wire wClk; + + // Internal sub clocks T1-T4 + enum int unsigned { T0 = 0, T1, T2, T3, T4} tState; + wire enT1 = Clks.enPhi1 & (tState == T4) & ~wClk; + wire enT2 = Clks.enPhi2 & (tState == T1); + wire enT3 = Clks.enPhi1 & (tState == T2); + wire enT4 = Clks.enPhi2 & ((tState == T0) | (tState == T3)); + + // T4 continues ticking during reset and group0 exception. + // We also need it to erase ucode output latched on T4. + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) + tState <= T0; + else begin + case( tState) + T0: if( Clks.enPhi2) tState <= T4; + T1: if( Clks.enPhi2) tState <= T2; + T2: if( Clks.enPhi1) tState <= T3; + T3: if( Clks.enPhi2) tState <= T4; + T4: if( Clks.enPhi1) tState <= wClk ? T0 : T1; + endcase + end + end + + // The following signals are synchronized with 3 couplers, phi1-phi2-phi1. + // Will be valid internally one cycle later if changed at the rasing edge of the clock. + // + // DTACK, BERR + + // DTACK valid at S6 if changed at the rasing edge of S4 to avoid wait states. + // SNC (sncClkEn) is deasserted together (unless DTACK asserted too early). + // + // We synchronize some signals half clock earlier. We compensate later + reg rDtack, rBerr; + reg [2:0] rIpl, iIpl; + reg Vpai, BeI, Halti, BRi, BgackI, BeiDelay; + // reg rBR, rHALT; + wire BeDebounced = ~( BeI | BeiDelay); + + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) begin + rBerr <= 1'b0; + BeI <= 1'b0; + end + else if( Clks.enPhi2) begin + rDtack <= DTACKn; + rBerr <= BERRn; + rIpl <= ~{ IPL2n, IPL1n, IPL0n}; + iIpl <= rIpl; + + // Needed for cycle accuracy but only if BR or HALT are asserted on the wrong edge of the clock + // rBR <= BRn; + // rHALT <= HALTn; + end + else if( Clks.enPhi1) begin + Vpai <= VPAn; + BeI <= rBerr; + BeiDelay <= BeI; + BgackI <= BGACKn; + + BRi <= BRn; + Halti <= HALTn; + // BRi <= rBR; + // Halti <= rHALT; + end + end + + // Instantiate micro and nano rom + logic [NANO_WIDTH-1:0] nanoLatch; + logic [NANO_WIDTH-1:0] nanoOutput; + logic [UROM_WIDTH-1:0] microLatch; + logic [UROM_WIDTH-1:0] microOutput; + + logic [UADDR_WIDTH-1:0] microAddr, nma; + logic [NADDR_WIDTH-1:0] nanoAddr, orgAddr; + wire rstUrom; + + // For the time being, address translation is done for nanorom only. + microToNanoAddr microToNanoAddr( .uAddr( nma), .orgAddr); + + // Output of these modules will be updated at T2 at the latest (depending on clock division) + + nanoRom nanoRom( .clk( Clks.clk), .nanoAddr, .nanoOutput); + uRom uRom( .clk( Clks.clk), .microAddr, .microOutput); + + always_ff @( posedge Clks.clk) begin + // uaddr originally latched on T1, except bits 6 & 7, the conditional bits, on T2 + // Seems we can latch whole address at either T1 or T2 + + // Originally it's invalid on hardware reset, and forced later when coming out of reset + if( Clks.pwrUp) begin + microAddr <= RSTP0_NMA; + nanoAddr <= RSTP0_NMA; + end + else if( enT1) begin + microAddr <= nma; + nanoAddr <= orgAddr; // Register translated uaddr to naddr + end + + if( Clks.extReset) begin + microLatch <= '0; + nanoLatch <= '0; + end + else if( rstUrom) begin + // Originally reset these bits only. Not strictly needed like this. + // Can reset the whole register if it is important. + { microLatch[16], microLatch[15], microLatch[0]} <= '0; + nanoLatch <= '0; + end + else if( enT3) begin + microLatch <= microOutput; + nanoLatch <= nanoOutput; + end + + end + + + // Decoded nanocode signals + s_nanod Nanod; + // IRD decoded control signals + s_irdecod Irdecod; + + // + reg Tpend; + reg intPend; // Interrupt pending + reg pswT, pswS; + reg [ 2:0] pswI; + wire [7:0] ccr; + + wire [15:0] psw = { pswT, 1'b0, pswS, 2'b00, pswI, ccr}; + + reg [15:0] ftu; + reg [15:0] Irc, Ir, Ird; + + wire [15:0] alue; + wire [15:0] Abl; + wire prenEmpty, au05z, dcr4, ze; + + wire [UADDR_WIDTH-1:0] a1, a2, a3; + wire isPriv, isIllegal, isLineA, isLineF; + + + // IR & IRD forwarding + always_ff @( posedge Clks.clk) begin + if( enT1) begin + if( Nanod.Ir2Ird) + Ird <= Ir; + else if(microLatch[0]) // prevented by IR => IRD ! + Ir <= Irc; + end + end + + wire [3:0] tvn; + wire waitBusCycle, busStarting; + wire BusRetry = 1'b0; + wire busAddrErr; + wire bciWrite; // Last bus cycle was write + wire bgBlock, busAvail; + wire addrOe; + + wire busIsByte = Nanod.busByte & (Irdecod.isByte | Irdecod.isMovep); + wire aob0; + + reg iStop; // Internal signal for ending bus cycle + reg A0Err; // Force bus/address error ucode + reg excRst; // Signal reset exception to sequencer + reg BerrA; + reg Spuria, Avia; + wire Iac; + + reg rAddrErr, iBusErr, Err6591; + wire iAddrErr = rAddrErr & addrOe; // To simulate async reset + wire enErrClk; + + // Reset micro/nano latch after T4 of the current ublock. + assign rstUrom = Clks.enPhi1 & enErrClk; + + uaddrDecode uaddrDecode( .opcode( Ir), .a1, .a2, .a3, .isPriv, .isIllegal, .isLineA, .isLineF, .lineBmap()); + + sequencer sequencer( .Clks, .enT3, .microLatch, .Ird, + .A0Err, .excRst, .BerrA, .busAddrErr, .Spuria, .Avia, + .Tpend, .intPend, .isIllegal, .isPriv, .isLineA, .isLineF, + .nma, .a1, .a2, .a3, .tvn, + .psw, .prenEmpty, .au05z, .dcr4, .ze, .alue01( alue[1:0]), .i11( Irc[ 11]) ); + + excUnit excUnit( .Clks, .Nanod, .Irdecod, .enT1, .enT2, .enT3, .enT4, + .Ird, .ftu, .iEdb, .pswS, + .prenEmpty, .au05z, .dcr4, .ze, .AblOut( Abl), .eab, .aob0, .Irc, .oEdb, + .alue, .ccr); + + nDecoder3 nDecoder( .Clks, .Nanod, .Irdecod, .enT2, .enT4, .microLatch, .nanoLatch); + + irdDecode irdDecode( .ird( Ird), .Irdecod); + + busControl busControl( .Clks, .enT1, .enT4, .permStart( Nanod.permStart), .permStop( Nanod.waitBusFinish), .iStop, + .aob0, .isWrite( Nanod.isWrite), .isRmc( Nanod.isRmc), .isByte( busIsByte), .busAvail, + .bciWrite, .addrOe, .bgBlock, .waitBusCycle, .busStarting, .busAddrErr, + .rDtack, .BeDebounced, .Vpai, + .ASn, .LDSn, .UDSn, .eRWn); + + busArbiter busArbiter( .Clks, .BRi, .BgackI, .Halti, .bgBlock, .busAvail, .BGn); + + + // Output reset & halt control + wire [1:0] uFc = microLatch[ 16:15]; + logic oReset, oHalted; + assign oRESETn = !oReset; + assign oHALTEDn = !oHalted; + + // FC without permStart is special, either reset or halt + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) begin + oReset <= 1'b0; + oHalted <= 1'b0; + end + else if( enT1) begin + oReset <= (uFc == 2'b01) & !Nanod.permStart; + oHalted <= (uFc == 2'b10) & !Nanod.permStart; + end + end + + logic [2:0] rFC; + assign { FC2, FC1, FC0} = rFC; // ~rFC; + assign Iac = {rFC == 3'b111}; // & Control output enable !! + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) + rFC <= '0; + else if( enT1 & Nanod.permStart) begin // S0 phase of bus cycle + rFC[2] <= pswS; + // If FC is type 'n' (0) at ucode, access type depends on PC relative mode + // We don't care about RZ in this case. Those uinstructions with RZ don't start a bus cycle. + rFC[1] <= microLatch[ 16] | ( ~microLatch[ 15] & Irdecod.isPcRel); + rFC[0] <= microLatch[ 15] | ( ~microLatch[ 16] & ~Irdecod.isPcRel); + end + end + + + // IPL interface + reg [2:0] inl; // Int level latch + reg updIll; + reg prevNmi; + + wire nmi = (iIpl == 3'b111); + wire iplStable = (iIpl == rIpl); + wire iplComp = iIpl > pswI; + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) begin + intPend <= 1'b0; + prevNmi <= 1'b0; + end + else begin + if( Clks.enPhi2) + prevNmi <= nmi; + + // Originally async RS-Latch on PHI2, followed by a transparent latch on T2 + // Tricky because they might change simultaneously + // Syncronous on PHI2 is equivalent as long as the output is read on T3! + + // Set on stable & NMI edge or compare + // Clear on: NMI Iack or (stable & !NMI & !Compare) + + if( Clks.enPhi2) begin + if( iplStable & ((nmi & ~prevNmi) | iplComp) ) + intPend <= 1'b1; + else if( ((inl == 3'b111) & Iac) | (iplStable & !nmi & !iplComp) ) + intPend <= 1'b0; + end + end + + if( Clks.extReset) begin + inl <= '1; + updIll <= 1'b0; + end + else if( enT4) + updIll <= microLatch[0]; // Update on any IRC->IR + else if( enT1 & updIll) + inl <= iIpl; // Timing is correct. + + // Spurious interrupt, BERR on Interrupt Ack. + // Autovector interrupt. VPA on IACK. + // Timing is tight. Spuria is deasserted just after exception exception is recorded. + if( enT4) begin + Spuria <= ~BeiDelay & Iac; + Avia <= ~Vpai & Iac; + end + + end + + assign enErrClk = iAddrErr | iBusErr; + assign wClk = waitBusCycle | ~BeI | iAddrErr | Err6591; + + // E clock and counter, VMA + reg [3:0] eCntr; + reg rVma; + + assign VMAn = rVma; + + // Internal stop just one cycle before E falling edge + wire xVma = ~rVma & (eCntr == 8); + +`ifdef USE_E_CLKEN + assign E_PosClkEn = (Clks.enPhi2 & (eCntr == 5)); + assign E_NegClkEn = (Clks.enPhi2 & (eCntr == 9)); +`endif + + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) begin + E <= 1'b0; + eCntr <='0; + rVma <= 1'b1; + end + if( Clks.enPhi2) begin + if( eCntr == 9) + E <= 1'b0; + else if( eCntr == 5) + E <= 1'b1; + + if( eCntr == 9) + eCntr <= '0; + else + eCntr <= eCntr + 1'b1; + end + + if( Clks.enPhi2 & addrOe & ~Vpai & (eCntr == 3)) + rVma <= 1'b0; + else if( Clks.enPhi1 & eCntr == '0) + rVma <= 1'b1; + end + + always_ff @( posedge Clks.clk) begin + + // This timing is critical to stop the clock phases at the exact point on bus/addr error. + // Timing should be such that current ublock completes (up to T3 or T4). + // But T1 for the next ublock shouldn't happen. Next T1 only after resetting ucode and ncode latches. + + if( Clks.extReset) + rAddrErr <= 1'b0; + else if( Clks.enPhi1) begin + if( busAddrErr & addrOe) // Not on T1 ?! + rAddrErr <= 1'b1; + else if( ~addrOe) // Actually async reset! + rAddrErr <= 1'b0; + end + + if( Clks.extReset) + iBusErr <= 1'b0; + else if( Clks.enPhi1) begin + iBusErr <= ( BerrA & ~BeI & ~Iac & !BusRetry); + end + + if( Clks.extReset) + BerrA <= 1'b0; + else if( Clks.enPhi2) begin + if( ~BeI & ~Iac & addrOe) + BerrA <= 1'b1; + // else if( BeI & addrOe) // Bad, async reset since addrOe raising edge + else if( BeI & busStarting) // So replaced with this that raises one cycle earlier + BerrA <= 1'b0; + end + + // Signal reset exception to sequencer. + // Originally cleared on 1st T2 after permstart. Must keep it until TVN latched. + if( Clks.extReset) + excRst <= 1'b1; + else if( enT2 & Nanod.permStart) + excRst <= 1'b0; + + if( Clks.extReset) + A0Err <= 1'b1; // A0 Reset + else if( enT3) // Keep set until new urom words are being latched + A0Err <= 1'b0; + else if( Clks.enPhi1 & enErrClk & (busAddrErr | BerrA)) // Check bus error timing + A0Err <= 1'b1; + + if( Clks.extReset) begin + iStop <= 1'b0; + Err6591 <= 1'b0; + end + else if( Clks.enPhi1) + Err6591 <= enErrClk; + else if( Clks.enPhi2) + iStop <= xVma | (Vpai & (iAddrErr | ~rBerr)); + end + + // PSW + logic irdToCcr_t4; + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) begin + Tpend <= 1'b0; + {pswT, pswS, pswI } <= '0; + irdToCcr_t4 <= '0; + end + + else if( enT4) begin + irdToCcr_t4 <= Irdecod.toCcr; + end + + else if( enT3) begin + + // UNIQUE IF !! + if( Nanod.updTpend) + Tpend <= pswT; + else if( Nanod.clrTpend) + Tpend <= 1'b0; + + // UNIQUE IF !! + if( Nanod.ftu2Sr & !irdToCcr_t4) + {pswT, pswS, pswI } <= { ftu[ 15], ftu[13], ftu[10:8]}; + else begin + if( Nanod.initST) begin + pswS <= 1'b1; + pswT <= 1'b0; + end + if( Nanod.inl2psw) + pswI <= inl; + end + + end + end + + // FTU + reg [4:0] ssw; + reg [3:0] tvnLatch; + logic [15:0] tvnMux; + reg inExcept01; + + // Seems CPU has a buglet here. + // Flagging group 0 exceptions from TVN might not work because some bus cycles happen before TVN is updated. + // But doesn't matter because a group 0 exception inside another one will halt the CPU anyway and won't save the SSW. + + always_ff @( posedge Clks.clk) begin + + // Updated at the start of the exception ucode + if( Nanod.updSsw & enT3) begin + ssw <= { ~bciWrite, inExcept01, rFC}; + end + + // Update TVN on T1 & IR=>IRD + if( enT1 & Nanod.Ir2Ird) begin + tvnLatch <= tvn; + inExcept01 <= (tvn != 1); + end + + if( Clks.pwrUp) + ftu <= '0; + else if( enT3) begin + unique case( 1'b1) + Nanod.tvn2Ftu: ftu <= tvnMux; + + // 0 on unused bits seem to come from ftuConst PLA previously clearing FBUS + Nanod.sr2Ftu: ftu <= {pswT, 1'b0, pswS, 2'b00, pswI, 3'b000, ccr[4:0] }; + + Nanod.ird2Ftu: ftu <= Ird; + Nanod.ssw2Ftu: ftu[4:0] <= ssw; // Undoc. Other bits must be preserved from IRD saved above! + Nanod.pswIToFtu: ftu <= { 12'hFFF, pswI, 1'b0}; // Interrupt level shifted + Nanod.const2Ftu: ftu <= Irdecod.ftuConst; + Nanod.abl2Pren: ftu <= Abl; // From ALU or datareg. Used for SR modify + default: ftu <= ftu; + endcase + end + end + + always_comb begin + if( inExcept01) begin + // Unique IF !!! + if( tvnLatch == TVN_SPURIOUS) + tvnMux = {9'b0, 5'd24, 2'b00}; + else if( tvnLatch == TVN_AUTOVEC) + tvnMux = {9'b0, 2'b11, pswI, 2'b00}; // Set TVN PLA decoder + else if( tvnLatch == TVN_INTERRUPT) + tvnMux = {6'b0, Ird[7:0], 2'b00}; // Interrupt vector was read and transferred to IRD + else + tvnMux = {10'b0, tvnLatch, 2'b00}; + end + else + tvnMux = { 8'h0, Irdecod.macroTvn, 2'b00}; + end + +endmodule + +// Nanorom (plus) decoder for die nanocode +module nDecoder3( input s_clks Clks, input s_irdecod Irdecod, output s_nanod Nanod, + input enT2, enT4, + input [UROM_WIDTH-1:0] microLatch, + input [NANO_WIDTH-1:0] nanoLatch); + +localparam NANO_IR2IRD = 67; +localparam NANO_TOIRC = 66; +localparam NANO_ALU_COL = 63; // ALU operator column order is 63-64-65 ! +localparam NANO_ALU_FI = 61; // ALU finish-init 62-61 +localparam NANO_TODBIN = 60; +localparam NANO_ALUE = 57; // 57-59 shared with DCR control +localparam NANO_DCR = 57; // 57-59 shared with ALUE control +localparam NANO_DOBCTRL_1 = 56; // Input to control and permwrite +localparam NANO_LOWBYTE = 55; // Used by MOVEP +localparam NANO_HIGHBYTE = 54; +localparam NANO_DOBCTRL_0 = 53; // Input to control and permwrite +localparam NANO_ALU_DCTRL = 51; // 52-51 databus input mux control +localparam NANO_ALU_ACTRL = 50; // addrbus input mux control +localparam NANO_DBD2ALUB = 49; +localparam NANO_ABD2ALUB = 48; +localparam NANO_DBIN2DBD = 47; +localparam NANO_DBIN2ABD = 46; +localparam NANO_ALU2ABD = 45; +localparam NANO_ALU2DBD = 44; +localparam NANO_RZ = 43; +localparam NANO_BUSBYTE = 42; // If *both* this set and instruction is byte sized, then bus cycle is byte sized. +localparam NANO_PCLABL = 41; +localparam NANO_RXL_DBL = 40; // Switches RXL/RYL on DBL/ABL buses +localparam NANO_PCLDBL = 39; +localparam NANO_ABDHRECHARGE = 38; +localparam NANO_REG2ABL = 37; // register to ABL +localparam NANO_ABL2REG = 36; // ABL to register +localparam NANO_ABLABD = 35; +localparam NANO_DBLDBD = 34; +localparam NANO_DBL2REG = 33; // DBL to register +localparam NANO_REG2DBL = 32; // register to DBL +localparam NANO_ATLCTRL = 29; // 31-29 +localparam NANO_FTUCONTROL = 25; +localparam NANO_SSP = 24; +localparam NANO_RXH_DBH = 22; // Switches RXH/RYH on DBH/ABH buses +localparam NANO_AUOUT = 20; // 21-20 +localparam NANO_AUCLKEN = 19; +localparam NANO_AUCTRL = 16; // 18-16 +localparam NANO_DBLDBH = 15; +localparam NANO_ABLABH = 14; +localparam NANO_EXT_ABH = 13; +localparam NANO_EXT_DBH = 12; +localparam NANO_ATHCTRL = 9; // 11-9 +localparam NANO_REG2ABH = 8; // register to ABH +localparam NANO_ABH2REG = 7; // ABH to register +localparam NANO_REG2DBH = 6; // register to DBH +localparam NANO_DBH2REG = 5; // DBH to register +localparam NANO_AOBCTRL = 3; // 4-3 +localparam NANO_PCH = 0; // 1-0 PchDbh PchAbh +localparam NANO_NO_SP_ALGN = 0; // Same bits as above when both set + +localparam NANO_FTU_UPDTPEND = 1; // Also loads FTU constant according to IRD ! +localparam NANO_FTU_INIT_ST = 15; // Set S, clear T (but not TPEND) +localparam NANO_FTU_CLRTPEND = 14; +localparam NANO_FTU_TVN = 13; +localparam NANO_FTU_ABL2PREN = 12; // ABL => FTU & ABL => PREN. Both transfers enabled, but only one will be used depending on uroutine. +localparam NANO_FTU_SSW = 11; +localparam NANO_FTU_RSTPREN = 10; +localparam NANO_FTU_IRD = 9; +localparam NANO_FTU_2ABL = 8; +localparam NANO_FTU_RDSR = 7; +localparam NANO_FTU_INL = 6; +localparam NANO_FTU_PSWI = 5; // Read Int Mask into FTU +localparam NANO_FTU_DBL = 4; +localparam NANO_FTU_2SR = 2; +localparam NANO_FTU_CONST = 1; + + reg [3:0] ftuCtrl; + + logic [2:0] athCtrl, atlCtrl; + assign athCtrl = nanoLatch[ NANO_ATHCTRL+2: NANO_ATHCTRL]; + assign atlCtrl = nanoLatch[ NANO_ATLCTRL+2: NANO_ATLCTRL]; + wire [1:0] aobCtrl = nanoLatch[ NANO_AOBCTRL+1:NANO_AOBCTRL]; + wire [1:0] dobCtrl = {nanoLatch[ NANO_DOBCTRL_1], nanoLatch[NANO_DOBCTRL_0]}; + + always_ff @( posedge Clks.clk) begin + if( enT4) begin + // Reverse order! + ftuCtrl <= { nanoLatch[ NANO_FTUCONTROL+0], nanoLatch[ NANO_FTUCONTROL+1], nanoLatch[ NANO_FTUCONTROL+2], nanoLatch[ NANO_FTUCONTROL+3]} ; + + Nanod.auClkEn <= !nanoLatch[ NANO_AUCLKEN]; + Nanod.auCntrl <= nanoLatch[ NANO_AUCTRL+2 : NANO_AUCTRL+0]; + Nanod.noSpAlign <= (nanoLatch[ NANO_NO_SP_ALGN + 1:NANO_NO_SP_ALGN] == 2'b11); + Nanod.extDbh <= nanoLatch[ NANO_EXT_DBH]; + Nanod.extAbh <= nanoLatch[ NANO_EXT_ABH]; + Nanod.todbin <= nanoLatch[ NANO_TODBIN]; + Nanod.toIrc <= nanoLatch[ NANO_TOIRC]; + + // ablAbd is disabled on byte transfers (adbhCharge plus irdIsByte). Not sure the combination makes much sense. + // It happens in a few cases but I don't see anything enabled on abL (or abH) section anyway. + + Nanod.ablAbd <= nanoLatch[ NANO_ABLABD]; + Nanod.ablAbh <= nanoLatch[ NANO_ABLABH]; + Nanod.dblDbd <= nanoLatch[ NANO_DBLDBD]; + Nanod.dblDbh <= nanoLatch[ NANO_DBLDBH]; + + Nanod.dbl2Atl <= (atlCtrl == 3'b010); + Nanod.atl2Dbl <= (atlCtrl == 3'b011); + Nanod.abl2Atl <= (atlCtrl == 3'b100); + Nanod.atl2Abl <= (atlCtrl == 3'b101); + + Nanod.aob2Ab <= (athCtrl == 3'b101); // Used on BSER1 only + + Nanod.abh2Ath <= (athCtrl == 3'b001) | (athCtrl == 3'b101); + Nanod.dbh2Ath <= (athCtrl == 3'b100); + Nanod.ath2Dbh <= (athCtrl == 3'b110); + Nanod.ath2Abh <= (athCtrl == 3'b011); + + Nanod.alu2Dbd <= nanoLatch[ NANO_ALU2DBD]; + Nanod.alu2Abd <= nanoLatch[ NANO_ALU2ABD]; + + Nanod.abd2Dcr <= (nanoLatch[ NANO_DCR+1:NANO_DCR] == 2'b11); + Nanod.dcr2Dbd <= (nanoLatch[ NANO_DCR+2:NANO_DCR+1] == 2'b11); + Nanod.dbd2Alue <= (nanoLatch[ NANO_ALUE+2:NANO_ALUE+1] == 2'b10); + Nanod.alue2Dbd <= (nanoLatch[ NANO_ALUE+1:NANO_ALUE] == 2'b01); + + Nanod.dbd2Alub <= nanoLatch[ NANO_DBD2ALUB]; + Nanod.abd2Alub <= nanoLatch[ NANO_ABD2ALUB]; + + // Originally not latched. We better should because we transfer one cycle later, T3 instead of T1. + Nanod.dobCtrl <= dobCtrl; + // Nanod.adb2Dob <= (dobCtrl == 2'b10); Nanod.dbd2Dob <= (dobCtrl == 2'b01); Nanod.alu2Dob <= (dobCtrl == 2'b11); + + end + end + + // Update SSW at the start of Bus/Addr error ucode + assign Nanod.updSsw = Nanod.aob2Ab; + + assign Nanod.updTpend = (ftuCtrl == NANO_FTU_UPDTPEND); + assign Nanod.clrTpend = (ftuCtrl == NANO_FTU_CLRTPEND); + assign Nanod.tvn2Ftu = (ftuCtrl == NANO_FTU_TVN); + assign Nanod.const2Ftu = (ftuCtrl == NANO_FTU_CONST); + assign Nanod.ftu2Dbl = (ftuCtrl == NANO_FTU_DBL) | ( ftuCtrl == NANO_FTU_INL); + assign Nanod.ftu2Abl = (ftuCtrl == NANO_FTU_2ABL); + assign Nanod.inl2psw = (ftuCtrl == NANO_FTU_INL); + assign Nanod.pswIToFtu = (ftuCtrl == NANO_FTU_PSWI); + assign Nanod.ftu2Sr = (ftuCtrl == NANO_FTU_2SR); + assign Nanod.sr2Ftu = (ftuCtrl == NANO_FTU_RDSR); + assign Nanod.ird2Ftu = (ftuCtrl == NANO_FTU_IRD); // Used on bus/addr error + assign Nanod.ssw2Ftu = (ftuCtrl == NANO_FTU_SSW); + assign Nanod.initST = (ftuCtrl == NANO_FTU_INL) | (ftuCtrl == NANO_FTU_CLRTPEND) | (ftuCtrl == NANO_FTU_INIT_ST); + assign Nanod.abl2Pren = (ftuCtrl == NANO_FTU_ABL2PREN); + assign Nanod.updPren = (ftuCtrl == NANO_FTU_RSTPREN); + + assign Nanod.Ir2Ird = nanoLatch[ NANO_IR2IRD]; + + // ALU control better latched later after combining with IRD decoding + + assign Nanod.aluDctrl = nanoLatch[ NANO_ALU_DCTRL+1 : NANO_ALU_DCTRL]; + assign Nanod.aluActrl = nanoLatch[ NANO_ALU_ACTRL]; + assign Nanod.aluColumn = { nanoLatch[ NANO_ALU_COL], nanoLatch[ NANO_ALU_COL+1], nanoLatch[ NANO_ALU_COL+2]}; + wire [1:0] aluFinInit = nanoLatch[ NANO_ALU_FI+1:NANO_ALU_FI]; + assign Nanod.aluFinish = (aluFinInit == 2'b10); + assign Nanod.aluInit = (aluFinInit == 2'b01); + + // FTU 2 CCR encoded as both ALU Init and ALU Finish set. + // In theory this encoding allows writes to CCR without writing to SR + // But FTU 2 CCR and to SR are both set together at nanorom. + assign Nanod.ftu2Ccr = ( aluFinInit == 2'b11); + + assign Nanod.abdIsByte = nanoLatch[ NANO_ABDHRECHARGE]; + + // Not being latched on T4 creates non unique case warning! + assign Nanod.au2Db = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b01); + assign Nanod.au2Ab = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b10); + assign Nanod.au2Pc = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b11); + + assign Nanod.db2Aob = (aobCtrl == 2'b10); + assign Nanod.ab2Aob = (aobCtrl == 2'b01); + assign Nanod.au2Aob = (aobCtrl == 2'b11); + + assign Nanod.dbin2Abd = nanoLatch[ NANO_DBIN2ABD]; + assign Nanod.dbin2Dbd = nanoLatch[ NANO_DBIN2DBD]; + + assign Nanod.permStart = (| aobCtrl); + assign Nanod.isWrite = ( | dobCtrl); + assign Nanod.waitBusFinish = nanoLatch[ NANO_TOIRC] | nanoLatch[ NANO_TODBIN] | Nanod.isWrite; + assign Nanod.busByte = nanoLatch[ NANO_BUSBYTE]; + + assign Nanod.noLowByte = nanoLatch[ NANO_LOWBYTE]; + assign Nanod.noHighByte = nanoLatch[ NANO_HIGHBYTE]; + + // Not registered. Register at T4 after combining + // Might be better to remove all those and combine here instead of at execution unit !! + assign Nanod.abl2reg = nanoLatch[ NANO_ABL2REG]; + assign Nanod.abh2reg = nanoLatch[ NANO_ABH2REG]; + assign Nanod.dbl2reg = nanoLatch[ NANO_DBL2REG]; + assign Nanod.dbh2reg = nanoLatch[ NANO_DBH2REG]; + assign Nanod.reg2dbl = nanoLatch[ NANO_REG2DBL]; + assign Nanod.reg2dbh = nanoLatch[ NANO_REG2DBH]; + assign Nanod.reg2abl = nanoLatch[ NANO_REG2ABL]; + assign Nanod.reg2abh = nanoLatch[ NANO_REG2ABH]; + + assign Nanod.ssp = nanoLatch[ NANO_SSP]; + + assign Nanod.rz = nanoLatch[ NANO_RZ]; + + // Actually DTL can't happen on PC relative mode. See IR decoder. + + wire dtldbd = 1'b0; + wire dthdbh = 1'b0; + wire dtlabd = 1'b0; + wire dthabh = 1'b0; + + wire dblSpecial = Nanod.pcldbl | dtldbd; + wire dbhSpecial = Nanod.pchdbh | dthdbh; + wire ablSpecial = Nanod.pclabl | dtlabd; + wire abhSpecial = Nanod.pchabh | dthabh; + + // + // Combine with IRD decoding + // Careful that IRD is updated only on T1! All output depending on IRD must be latched on T4! + // + + // PC used instead of RY on PC relative instuctions + + assign Nanod.rxlDbl = nanoLatch[ NANO_RXL_DBL]; + wire isPcRel = Irdecod.isPcRel & !Nanod.rz; + wire pcRelDbl = isPcRel & !nanoLatch[ NANO_RXL_DBL]; + wire pcRelDbh = isPcRel & !nanoLatch[ NANO_RXH_DBH]; + wire pcRelAbl = isPcRel & nanoLatch[ NANO_RXL_DBL]; + wire pcRelAbh = isPcRel & nanoLatch[ NANO_RXH_DBH]; + + assign Nanod.pcldbl = nanoLatch[ NANO_PCLDBL] | pcRelDbl; + assign Nanod.pchdbh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b01) | pcRelDbh; + + assign Nanod.pclabl = nanoLatch[ NANO_PCLABL] | pcRelAbl; + assign Nanod.pchabh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b10) | pcRelAbh; + + // Might be better not to register these signals to allow latching RX/RY mux earlier! + // But then must latch Irdecod.isPcRel on T3! + + always_ff @( posedge Clks.clk) begin + if( enT4) begin + Nanod.rxl2db <= Nanod.reg2dbl & !dblSpecial & nanoLatch[ NANO_RXL_DBL]; + Nanod.rxl2ab <= Nanod.reg2abl & !ablSpecial & !nanoLatch[ NANO_RXL_DBL]; + + Nanod.dbl2rxl <= Nanod.dbl2reg & !dblSpecial & nanoLatch[ NANO_RXL_DBL]; + Nanod.abl2rxl <= Nanod.abl2reg & !ablSpecial & !nanoLatch[ NANO_RXL_DBL]; + + Nanod.rxh2dbh <= Nanod.reg2dbh & !dbhSpecial & nanoLatch[ NANO_RXH_DBH]; + Nanod.rxh2abh <= Nanod.reg2abh & !abhSpecial & !nanoLatch[ NANO_RXH_DBH]; + + Nanod.dbh2rxh <= Nanod.dbh2reg & !dbhSpecial & nanoLatch[ NANO_RXH_DBH]; + Nanod.abh2rxh <= Nanod.abh2reg & !abhSpecial & !nanoLatch[ NANO_RXH_DBH]; + + Nanod.dbh2ryh <= Nanod.dbh2reg & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH]; + Nanod.abh2ryh <= Nanod.abh2reg & !abhSpecial & nanoLatch[ NANO_RXH_DBH]; + + Nanod.dbl2ryl <= Nanod.dbl2reg & !dblSpecial & !nanoLatch[ NANO_RXL_DBL]; + Nanod.abl2ryl <= Nanod.abl2reg & !ablSpecial & nanoLatch[ NANO_RXL_DBL]; + + Nanod.ryl2db <= Nanod.reg2dbl & !dblSpecial & !nanoLatch[ NANO_RXL_DBL]; + Nanod.ryl2ab <= Nanod.reg2abl & !ablSpecial & nanoLatch[ NANO_RXL_DBL]; + + Nanod.ryh2dbh <= Nanod.reg2dbh & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH]; + Nanod.ryh2abh <= Nanod.reg2abh & !abhSpecial & nanoLatch[ NANO_RXH_DBH]; + end + + // Originally isTas only delayed on T2 (and seems only a late mask rev fix) + // Better latch the combination on T4 + if( enT4) + Nanod.isRmc <= Irdecod.isTas & nanoLatch[ NANO_BUSBYTE]; + end + + +endmodule + +// +// IRD execution decoder. Complements nano code decoder +// +// IRD updated on T1, while ncode still executing. To avoid using the next IRD, +// decoded signals must be registered on T3, or T4 before using them. +// +module irdDecode( input [15:0] ird, + output s_irdecod Irdecod); + + wire [3:0] line = ird[15:12]; + logic [15:0] lineOnehot; + + // This can be registered and pipelined from the IR decoder ! + onehotEncoder4 irdLines( line, lineOnehot); + + wire isRegShift = (lineOnehot['he]) & (ird[7:6] != 2'b11); + wire isDynShift = isRegShift & ird[5]; + + assign Irdecod.isPcRel = (& ird[ 5:3]) & ~isDynShift & !ird[2] & ird[1]; + assign Irdecod.isTas = lineOnehot[4] & (ird[11:6] == 6'b101011); + + assign Irdecod.rx = ird[11:9]; + assign Irdecod.ry = ird[ 2:0]; + + wire isPreDecr = (ird[ 5:3] == 3'b100); + wire eaAreg = (ird[5:3] == 3'b001); + + // rx is A or D + // movem + always_comb begin + unique case( 1'b1) + lineOnehot[1], + lineOnehot[2], + lineOnehot[3]: + // MOVE: RX always Areg except if dest mode is Dn 000 + Irdecod.rxIsAreg = (| ird[8:6]); + + lineOnehot[4]: Irdecod.rxIsAreg = (& ird[8:6]); // not CHK (LEA) + + lineOnehot['h8]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // SBCD + lineOnehot['hc]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // ABCD/EXG An,An + + lineOnehot['h9], + lineOnehot['hb], + lineOnehot['hd]: Irdecod.rxIsAreg = + (ird[7] & ird[6]) | // SUBA/CMPA/ADDA + (eaAreg & ird[8] & (ird[7:6] != 2'b11)); // SUBX/CMPM/ADDX + default: + Irdecod.rxIsAreg = Irdecod.implicitSp; + endcase + end + + // RX is movem + always_comb begin + Irdecod.rxIsMovem = lineOnehot[4] & ~ird[8] & ~Irdecod.implicitSp; + end + assign Irdecod.movemPreDecr = Irdecod.rxIsMovem & isPreDecr; + + // RX is DT. + // but SSP explicit or pc explicit has higher priority! + // addq/subq (scc & dbcc also, but don't use rx) + // Immediate including static bit + assign Irdecod.rxIsDt = lineOnehot[5] | (lineOnehot[0] & ~ird[8]); + + // RX is USP + assign Irdecod.rxIsUsp = lineOnehot[4] & (ird[ 11:4] == 8'he6); + + // RY is DT + // rz or PC explicit has higher priority + + wire eaImmOrAbs = (ird[5:3] == 3'b111) & ~ird[1]; + assign Irdecod.ryIsDt = eaImmOrAbs & ~isRegShift; + + // RY is Address register + always_comb begin + logic eaIsAreg; + + // On most cases RY is Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL) + eaIsAreg = (ird[5:3] != 3'b000) & (ird[5:3] != 3'b111); + + unique case( 1'b1) + // MOVE: RY always Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL) + // Most lines, including misc line 4, also. + default: Irdecod.ryIsAreg = eaIsAreg; + + lineOnehot[5]: // DBcc is an exception + Irdecod.ryIsAreg = eaIsAreg & (ird[7:3] != 5'b11001); + + lineOnehot[6], + lineOnehot[7]: Irdecod.ryIsAreg = 1'b0; + + lineOnehot['he]: + Irdecod.ryIsAreg = ~isRegShift; + endcase + end + + // Byte sized instruction + + // Original implementation sets this for some instructions that aren't really byte size + // but doesn't matter because they don't have a byte transfer enabled at nanocode, such as MOVEQ + + wire xIsScc = (ird[7:6] == 2'b11) & (ird[5:3] != 3'b001); + wire xStaticMem = (ird[11:8] == 4'b1000) & (ird[5:4] == 2'b00); // Static bit to mem + always_comb begin + unique case( 1'b1) + lineOnehot[0]: + Irdecod.isByte = + ( ird[8] & (ird[5:4] != 2'b00) ) | // Dynamic bit to mem + ( (ird[11:8] == 4'b1000) & (ird[5:4] != 2'b00) ) | // Static bit to mem + ( (ird[8:7] == 2'b10) & (ird[5:3] == 3'b001) ) | // Movep from mem only! For byte mux + ( (ird[8:6] == 3'b000) & !xStaticMem ); // Immediate byte + + lineOnehot[1]: Irdecod.isByte = 1'b1; // MOVE.B + + + lineOnehot[4]: Irdecod.isByte = (ird[7:6] == 2'b00) | Irdecod.isTas; + lineOnehot[5]: Irdecod.isByte = (ird[7:6] == 2'b00) | xIsScc; + + lineOnehot[8], + lineOnehot[9], + lineOnehot['hb], + lineOnehot['hc], + lineOnehot['hd], + lineOnehot['he]: Irdecod.isByte = (ird[7:6] == 2'b00); + + default: Irdecod.isByte = 1'b0; + endcase + end + + // Need it for special byte size. Bus is byte, but whole register word is modified. + assign Irdecod.isMovep = lineOnehot[0] & ird[8] & eaAreg; + + + // rxIsSP implicit use of RX for actual SP transfer + // + // This logic is simple and will include some instructions that don't actually reference SP. + // But doesn't matter as long as they don't perform any RX transfer. + + always_comb begin + unique case( 1'b1) + lineOnehot[6]: Irdecod.implicitSp = (ird[11:8] == 4'b0001); // BSR + lineOnehot[4]: + // Misc like RTS, JSR, etc + Irdecod.implicitSp = (ird[11:8] == 4'b1110) | (ird[11:6] == 6'b1000_01); + default: Irdecod.implicitSp = 1'b0; + endcase + end + + // Modify CCR (and not SR) + // Probably overkill !! Only needs to distinguish SR vs CCR + // RTR, MOVE to CCR, xxxI to CCR + assign Irdecod.toCcr = ( lineOnehot[4] & ((ird[11:0] == 12'he77) | (ird[11:6] == 6'b010011)) ) | + ( lineOnehot[0] & (ird[8:6] == 3'b000)); + + // FTU constants + // This should not be latched on T3/T4. Latch on T2 or not at all. FTU needs it on next T3. + // Note: Reset instruction gets constant from ALU not from FTU! + logic [15:0] ftuConst; + wire [3:0] zero28 = (ird[11:9] == 0) ? 4'h8 : { 1'b0, ird[11:9]}; // xltate 0,1-7 into 8,1-7 + + always_comb begin + unique case( 1'b1) + lineOnehot[6], // Bcc short + lineOnehot[7]: ftuConst = { { 8{ ird[ 7]}}, ird[ 7:0] }; // MOVEQ + + lineOnehot['h5], // addq/subq/static shift double check this + lineOnehot['he]: ftuConst = { 12'b0, zero28}; + + // MULU/MULS DIVU/DIVS + lineOnehot['h8], + lineOnehot['hc]: ftuConst = 16'h0f; + + lineOnehot[4]: ftuConst = 16'h80; // TAS + + default: ftuConst = '0; + endcase + end + assign Irdecod.ftuConst = ftuConst; + + // + // TRAP Vector # for group 2 exceptions + // + + always_comb begin + if( lineOnehot[4]) begin + case ( ird[6:5]) + 2'b00,2'b01: Irdecod.macroTvn = 6; // CHK + 2'b11: Irdecod.macroTvn = 7; // TRAPV + 2'b10: Irdecod.macroTvn = {2'b10, ird[3:0]}; // TRAP + endcase + end + else + Irdecod.macroTvn = 5; // Division by zero + end + + + wire eaAdir = (ird[ 5:3] == 3'b001); + wire size11 = ird[7] & ird[6]; + + // Opcodes variants that don't affect flags + // ADDA/SUBA ADDQ/SUBQ MOVEA + + assign Irdecod.inhibitCcr = + ( (lineOnehot[9] | lineOnehot['hd]) & size11) | // ADDA/SUBA + ( lineOnehot[5] & eaAdir) | // ADDQ/SUBQ to An (originally checks for line[4] as well !?) + ( (lineOnehot[2] | lineOnehot[3]) & ird[8:6] == 3'b001); // MOVEA + +endmodule + +/* + Execution unit + + Executes register transfers set by the microcode. Originally through a set of bidirectional buses. + Most sources are available at T3, but DBIN only at T4! CCR also might be updated at T4, but it is not connected to these buses. + We mux at T1 and T2, then transfer to the destination at T3. The exception is AOB that need to be updated earlier. + +*/ + +module excUnit( input s_clks Clks, + input enT1, enT2, enT3, enT4, + input s_nanod Nanod, input s_irdecod Irdecod, + input [15:0] Ird, // ALU row (and others) decoder needs it + input pswS, + input [15:0] ftu, + input [15:0] iEdb, + + output logic [7:0] ccr, + output [15:0] alue, + + output prenEmpty, au05z, + output logic dcr4, ze, + output logic aob0, + output [15:0] AblOut, + output logic [15:0] Irc, + output logic [15:0] oEdb, + output logic [23:1] eab); + +localparam REG_USP = 15; +localparam REG_SSP = 16; +localparam REG_DT = 17; + + // Register file + reg [15:0] regs68L[ 18]; + reg [15:0] regs68H[ 18]; + +// synthesis translate off + /* + It is bad practice to initialize simulation registers that the hardware doesn't. + There is risk that simulation would be different than the real hardware. But in this case is the other way around. + Some ROM uses something like sub.l An,An at powerup which clears the register + Simulator power ups the registers with 'X, as they are really undetermined at the real hardware. + But the simulator doesn't realize (it can't) that the same value is substracting from itself, + and that the result should be zero even when it's 'X - 'X. + */ + + /* + initial begin + for( int i = 0; i < 18; i++) begin + regs68L[i] <= '0; + regs68H[i] <= '0; + end + end + */ + + // For simulation display only + wire [31:0] SSP = { regs68H[REG_SSP], regs68L[REG_SSP]}; + +// synthesis translate on + + + wire [15:0] aluOut; + wire [15:0] dbin; + logic [15:0] dcrOutput; + + reg [15:0] PcL, PcH; + + reg [31:0] auReg, aob; + + reg [15:0] Ath, Atl; + + // Bus execution + reg [15:0] Dbl, Dbh; + reg [15:0] Abh, Abl; + reg [15:0] Abd, Dbd; + + assign AblOut = Abl; + assign au05z = (~| auReg[5:0]); + + logic [15:0] dblMux, dbhMux; + logic [15:0] abhMux, ablMux; + logic [15:0] abdMux, dbdMux; + + logic abdIsByte; + + logic Pcl2Dbl, Pch2Dbh; + logic Pcl2Abl, Pch2Abh; + + + // RX RY muxes + // RX and RY actual registers + logic [4:0] actualRx, actualRy; + logic [3:0] movemRx; + logic byteNotSpAlign; // Byte instruction and no sp word align + + // IRD decoded signals must be latched. See comments on decoder + // But nanostore decoding can't be latched before T4. + // + // If we need this earlier we can register IRD decode on T3 and use nano async + + logic [4:0] rxMux, ryMux; + logic [3:0] rxReg, ryReg; + logic rxIsSp, ryIsSp; + logic rxIsAreg, ryIsAreg; + + always_comb begin + + // Unique IF !! + if( Nanod.ssp) begin + rxMux = REG_SSP; + rxIsSp = 1'b1; + rxReg = 1'bX; + end + else if( Irdecod.rxIsUsp) begin + rxMux = REG_USP; + rxIsSp = 1'b1; + rxReg = 1'bX; + end + else if( Irdecod.rxIsDt & !Irdecod.implicitSp) begin + rxMux = REG_DT; + rxIsSp = 1'b0; + rxReg = 1'bX; + end + else begin + if( Irdecod.implicitSp) + rxReg = 15; + else if( Irdecod.rxIsMovem) + rxReg = movemRx; + else + rxReg = { Irdecod.rxIsAreg, Irdecod.rx}; + + if( (& rxReg)) begin + rxMux = pswS ? REG_SSP : 15; + rxIsSp = 1'b1; + end + else begin + rxMux = { 1'b0, rxReg}; + rxIsSp = 1'b0; + end + end + + // RZ has higher priority! + if( Irdecod.ryIsDt & !Nanod.rz) begin + ryMux = REG_DT; + ryIsSp = 1'b0; + ryReg = 'X; + end + else begin + ryReg = Nanod.rz ? Irc[15:12] : {Irdecod.ryIsAreg, Irdecod.ry}; + ryIsSp = (& ryReg); + if( ryIsSp & pswS) // No implicit SP on RY + ryMux = REG_SSP; + else + ryMux = { 1'b0, ryReg}; + end + + end + + always_ff @( posedge Clks.clk) begin + if( enT4) begin + byteNotSpAlign <= Irdecod.isByte & ~(Nanod.rxlDbl ? rxIsSp : ryIsSp); + + actualRx <= rxMux; + actualRy <= ryMux; + + rxIsAreg <= rxIsSp | rxMux[3]; + ryIsAreg <= ryIsSp | ryMux[3]; + end + + if( enT4) + abdIsByte <= Nanod.abdIsByte & Irdecod.isByte; + end + + // Set RX/RY low word to which bus segment is connected. + + wire ryl2Abl = Nanod.ryl2ab & (ryIsAreg | Nanod.ablAbd); + wire ryl2Abd = Nanod.ryl2ab & (~ryIsAreg | Nanod.ablAbd); + wire ryl2Dbl = Nanod.ryl2db & (ryIsAreg | Nanod.dblDbd); + wire ryl2Dbd = Nanod.ryl2db & (~ryIsAreg | Nanod.dblDbd); + + wire rxl2Abl = Nanod.rxl2ab & (rxIsAreg | Nanod.ablAbd); + wire rxl2Abd = Nanod.rxl2ab & (~rxIsAreg | Nanod.ablAbd); + wire rxl2Dbl = Nanod.rxl2db & (rxIsAreg | Nanod.dblDbd); + wire rxl2Dbd = Nanod.rxl2db & (~rxIsAreg | Nanod.dblDbd); + + // Buses. Main mux + + logic abhIdle, ablIdle, abdIdle; + logic dbhIdle, dblIdle, dbdIdle; + + always_comb begin + {abhIdle, ablIdle, abdIdle} = '0; + {dbhIdle, dblIdle, dbdIdle} = '0; + + unique case( 1'b1) + ryl2Dbd: dbdMux = regs68L[ actualRy]; + rxl2Dbd: dbdMux = regs68L[ actualRx]; + Nanod.alue2Dbd: dbdMux = alue; + Nanod.dbin2Dbd: dbdMux = dbin; + Nanod.alu2Dbd: dbdMux = aluOut; + Nanod.dcr2Dbd: dbdMux = dcrOutput; + default: begin dbdMux = 'X; dbdIdle = 1'b1; end + endcase + + unique case( 1'b1) + rxl2Dbl: dblMux = regs68L[ actualRx]; + ryl2Dbl: dblMux = regs68L[ actualRy]; + Nanod.ftu2Dbl: dblMux = ftu; + Nanod.au2Db: dblMux = auReg[15:0]; + Nanod.atl2Dbl: dblMux = Atl; + Pcl2Dbl: dblMux = PcL; + default: begin dblMux = 'X; dblIdle = 1'b1; end + endcase + + unique case( 1'b1) + Nanod.rxh2dbh: dbhMux = regs68H[ actualRx]; + Nanod.ryh2dbh: dbhMux = regs68H[ actualRy]; + Nanod.au2Db: dbhMux = auReg[31:16]; + Nanod.ath2Dbh: dbhMux = Ath; + Pch2Dbh: dbhMux = PcH; + default: begin dbhMux = 'X; dbhIdle = 1'b1; end + endcase + + unique case( 1'b1) + ryl2Abd: abdMux = regs68L[ actualRy]; + rxl2Abd: abdMux = regs68L[ actualRx]; + Nanod.dbin2Abd: abdMux = dbin; + Nanod.alu2Abd: abdMux = aluOut; + default: begin abdMux = 'X; abdIdle = 1'b1; end + endcase + + unique case( 1'b1) + Pcl2Abl: ablMux = PcL; + rxl2Abl: ablMux = regs68L[ actualRx]; + ryl2Abl: ablMux = regs68L[ actualRy]; + Nanod.ftu2Abl: ablMux = ftu; + Nanod.au2Ab: ablMux = auReg[15:0]; + Nanod.aob2Ab: ablMux = aob[15:0]; + Nanod.atl2Abl: ablMux = Atl; + default: begin ablMux = 'X; ablIdle = 1'b1; end + endcase + + unique case( 1'b1) + Pch2Abh: abhMux = PcH; + Nanod.rxh2abh: abhMux = regs68H[ actualRx]; + Nanod.ryh2abh: abhMux = regs68H[ actualRy]; + Nanod.au2Ab: abhMux = auReg[31:16]; + Nanod.aob2Ab: abhMux = aob[31:16]; + Nanod.ath2Abh: abhMux = Ath; + default: begin abhMux = 'X; abhIdle = 1'b1; end + endcase + + end + + // Source starts driving the bus on T1. Bus holds data until end of T3. Destination latches at T3. + + // These registers store the first level mux, without bus interconnections. + // Even when this uses almost to 100 registers, it saves a lot of comb muxing and it is much faster. + reg [15:0] preAbh, preAbl, preAbd; + reg [15:0] preDbh, preDbl, preDbd; + + always_ff @( posedge Clks.clk) begin + + // Register first level mux at T1 + if( enT1) begin + {preAbh, preAbl, preAbd} <= { abhMux, ablMux, abdMux}; + {preDbh, preDbl, preDbd} <= { dbhMux, dblMux, dbdMux}; + end + + // Process bus interconnection at T2. Many combinations only used on DIV + // We use a simple method. If a specific bus segment is not driven we know that it should get data from a neighbour segment. + // In some cases this is not true and the segment is really idle without any destination. But then it doesn't matter. + + if( enT2) begin + if( Nanod.extAbh) + Abh <= { 16{ ablIdle ? preAbd[ 15] : preAbl[ 15] }}; + else if( abhIdle) + Abh <= ablIdle ? preAbd : preAbl; + else + Abh <= preAbh; + + if( ~ablIdle) + Abl <= preAbl; + else + Abl <= Nanod.ablAbh ? preAbh : preAbd; + + Abd <= ~abdIdle ? preAbd : ablIdle ? preAbh : preAbl; + + if( Nanod.extDbh) + Dbh <= { 16{ dblIdle ? preDbd[ 15] : preDbl[ 15] }}; + else if( dbhIdle) + Dbh <= dblIdle ? preDbd : preDbl; + else + Dbh <= preDbh; + + if( ~dblIdle) + Dbl <= preDbl; + else + Dbl <= Nanod.dblDbh ? preDbh : preDbd; + + Dbd <= ~dbdIdle ? preDbd: dblIdle ? preDbh : preDbl; + + /* + Dbl <= dblMux; Dbh <= dbhMux; + Abd <= abdMux; Dbd <= dbdMux; + Abh <= abhMux; Abl <= ablMux; */ + end + end + + // AOB + // + // Originally change on T1. We do on T2, only then the output is enabled anyway. + // + // AOB[0] is used for address error. But even when raises on T1, seems not actually used until T2 or possibly T3. + // It is used on T1 when deasserted at the BSER exception ucode. Probably deassertion timing is not critical. + // But in that case (at BSER), AOB is loaded from AU, so we can safely transfer on T1. + + // We need to take directly from first level muxes that are updated and T1 + + wire au2Aob = Nanod.au2Aob | (Nanod.au2Db & Nanod.db2Aob); + + always_ff @( posedge Clks.clk) begin + // UNIQUE IF ! + + if( enT1 & au2Aob) // From AU we do can on T1 + aob <= auReg; + else if( enT2) begin + if( Nanod.db2Aob) + aob <= { preDbh, ~dblIdle ? preDbl : preDbd}; + else if( Nanod.ab2Aob) + aob <= { preAbh, ~ablIdle ? preAbl : preAbd}; + end + end + + assign eab = aob[23:1]; + assign aob0 = aob[0]; + + // AU + logic [31:0] auInpMux; + + // `ifdef ALW_COMB_BUG + // Old Modelsim bug. Doesn't update ouput always. Need excplicit sensitivity list !? + // always @( Nanod.auCntrl) begin + + always_comb begin + unique case( Nanod.auCntrl) + 3'b000: auInpMux = 0; + 3'b001: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? 1 : 2; // +1/+2 + 3'b010: auInpMux = -4; + 3'b011: auInpMux = { Abh, Abl}; + 3'b100: auInpMux = 2; + 3'b101: auInpMux = 4; + 3'b110: auInpMux = -2; + 3'b111: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? -1 : -2; // -1/-2 + default: auInpMux = 'X; + endcase + end + + // Simulation problem + // Sometimes (like in MULM1) DBH is not set. AU is used in these cases just as a 6 bits counter testing if bits 5-0 are zero. + // But when adding something like 32'hXXXX0000, the simulator (incorrectly) will set *all the 32 bits* of the result as X. + +// synthesis translate_off + `define SIMULBUGX32 1 + wire [16:0] aulow = Dbl + auInpMux[15:0]; + wire [31:0] auResult = {Dbh + auInpMux[31:16] + aulow[16], aulow[15:0]}; +// synthesis translate_on + + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) + auReg <= '0; + else if( enT3 & Nanod.auClkEn) + `ifdef SIMULBUGX32 + auReg <= auResult; + `else + auReg <= { Dbh, Dbl } + auInpMux; + `endif + end + + + // Main A/D registers + + always_ff @( posedge Clks.clk) begin + if( enT3) begin + if( Nanod.dbl2rxl | Nanod.abl2rxl) begin + if( ~rxIsAreg) begin + if( Nanod.dbl2rxl) regs68L[ actualRx] <= Dbd; + else if( abdIsByte) regs68L[ actualRx][7:0] <= Abd[7:0]; + else regs68L[ actualRx] <= Abd; + end + else + regs68L[ actualRx] <= Nanod.dbl2rxl ? Dbl : Abl; + end + + if( Nanod.dbl2ryl | Nanod.abl2ryl) begin + if( ~ryIsAreg) begin + if( Nanod.dbl2ryl) regs68L[ actualRy] <= Dbd; + else if( abdIsByte) regs68L[ actualRy][7:0] <= Abd[7:0]; + else regs68L[ actualRy] <= Abd; + end + else + regs68L[ actualRy] <= Nanod.dbl2ryl ? Dbl : Abl; + end + + // High registers are easier. Both A & D on the same buses, and not byte ops. + if( Nanod.dbh2rxh | Nanod.abh2rxh) + regs68H[ actualRx] <= Nanod.dbh2rxh ? Dbh : Abh; + if( Nanod.dbh2ryh | Nanod.abh2ryh) + regs68H[ actualRy] <= Nanod.dbh2ryh ? Dbh : Abh; + + end + end + + // PC & AT + reg dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl; + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) begin + { dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl } <= '0; + + Pcl2Dbl <= 1'b0; + Pch2Dbh <= 1'b0; + Pcl2Abl <= 1'b0; + Pch2Abh <= 1'b0; + end + else if( enT4) begin // Must latch on T4 ! + dbl2Pcl <= Nanod.dbl2reg & Nanod.pcldbl; + dbh2Pch <= Nanod.dbh2reg & Nanod.pchdbh; + abh2Pch <= Nanod.abh2reg & Nanod.pchabh; + abl2Pcl <= Nanod.abl2reg & Nanod.pclabl; + + Pcl2Dbl <= Nanod.reg2dbl & Nanod.pcldbl; + Pch2Dbh <= Nanod.reg2dbh & Nanod.pchdbh; + Pcl2Abl <= Nanod.reg2abl & Nanod.pclabl; + Pch2Abh <= Nanod.reg2abh & Nanod.pchabh; + end + + // Unique IF !!! + if( enT1 & Nanod.au2Pc) + PcL <= auReg[15:0]; + else if( enT3) begin + if( dbl2Pcl) + PcL <= Dbl; + else if( abl2Pcl) + PcL <= Abl; + end + + // Unique IF !!! + if( enT1 & Nanod.au2Pc) + PcH <= auReg[31:16]; + else if( enT3) begin + if( dbh2Pch) + PcH <= Dbh; + else if( abh2Pch) + PcH <= Abh; + end + + // Unique IF !!! + if( enT3) begin + if( Nanod.dbl2Atl) + Atl <= Dbl; + else if( Nanod.abl2Atl) + Atl <= Abl; + end + + // Unique IF !!! + if( enT3) begin + if( Nanod.abh2Ath) + Ath <= Abh; + else if( Nanod.dbh2Ath) + Ath <= Dbh; + end + + end + + // Movem reg mask priority encoder + + wire rmIdle; + logic [3:0] prHbit; + logic [15:0] prenLatch; + + // Invert reg order for predecrement mode + assign prenEmpty = (~| prenLatch); + pren rmPren( .mask( prenLatch), .hbit (prHbit)); + + always_ff @( posedge Clks.clk) begin + // Cheating: PREN always loaded from DBIN + // Must be on T1 to branch earlier if reg mask is empty! + if( enT1 & Nanod.abl2Pren) + prenLatch <= dbin; + else if( enT3 & Nanod.updPren) begin + prenLatch [prHbit] <= 1'b0; + movemRx <= Irdecod.movemPreDecr ? ~prHbit : prHbit; + end + end + + // DCR + wire [15:0] dcrCode; + + wire [3:0] dcrInput = abdIsByte ? { 1'b0, Abd[ 2:0]} : Abd[ 3:0]; + onehotEncoder4 dcrDecoder( .bin( dcrInput), .bitMap( dcrCode)); + + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) + dcr4 <= '0; + else if( enT3 & Nanod.abd2Dcr) begin + dcrOutput <= dcrCode; + dcr4 <= Abd[4]; + end + end + + // ALUB + reg [15:0] alub; + + always_ff @( posedge Clks.clk) begin + if( enT3) begin + // UNIQUE IF !! + if( Nanod.dbd2Alub) + alub <= Dbd; + else if( Nanod.abd2Alub) + alub <= Abd; // abdIsByte affects this !!?? + end + end + + wire alueClkEn = enT3 & Nanod.dbd2Alue; + + // DOB/DBIN/IRC + + logic [15:0] dobInput; + wire dobIdle = (~| Nanod.dobCtrl); + + always_comb begin + unique case (Nanod.dobCtrl) + NANO_DOB_ADB: dobInput = Abd; + NANO_DOB_DBD: dobInput = Dbd; + NANO_DOB_ALU: dobInput = aluOut; + default: dobInput = 'X; + endcase + end + + dataIo dataIo( .Clks, .enT1, .enT2, .enT3, .enT4, .Nanod, .Irdecod, + .iEdb, .dobIdle, .dobInput, .aob0, + .Irc, .dbin, .oEdb); + + fx68kAlu alu( + .clk( Clks.clk), .pwrUp( Clks.pwrUp), .enT1, .enT3, .enT4, + .ird( Ird), + .aluColumn( Nanod.aluColumn), .aluAddrCtrl( Nanod.aluActrl), + .init( Nanod.aluInit), .finish( Nanod.aluFinish), .aluIsByte( Irdecod.isByte), + .ftu2Ccr( Nanod.ftu2Ccr), + .alub, .ftu, .alueClkEn, .alue, + .aluDataCtrl( Nanod.aluDctrl), .iDataBus( Dbd), .iAddrBus(Abd), + .ze, .aluOut, .ccr); + +endmodule + +// +// Data bus I/O +// At a separate module because it is a bit complicated and the timing is special. +// Here we do the low/high byte mux and the special case of MOVEP. +// +// Original implementation is rather complex because both the internal and external buses are bidirectional. +// Input is latched async at the EDB register. +// We capture directly from the external data bus to the internal registers (IRC & DBIN) on PHI2, starting the external S7 phase, at a T4 internal period. + +module dataIo( input s_clks Clks, + input enT1, enT2, enT3, enT4, + input s_nanod Nanod, input s_irdecod Irdecod, + input [15:0] iEdb, + input aob0, + + input dobIdle, + input [15:0] dobInput, + + output logic [15:0] Irc, + output logic [15:0] dbin, + output logic [15:0] oEdb + ); + + reg [15:0] dob; + + // DBIN/IRC + + // Timing is different than any other register. We can latch only on the next T4 (bus phase S7). + // We need to register all control signals correctly because the next ublock will already be started. + // Can't latch control on T4 because if there are wait states there might be multiple T4 before we latch. + + reg xToDbin, xToIrc; + reg dbinNoLow, dbinNoHigh; + reg byteMux, isByte_T4; + + always_ff @( posedge Clks.clk) begin + + // Byte mux control. Can't latch at T1. AOB might be not ready yet. + // Must latch IRD decode at T1 (or T4). Then combine and latch only at T3. + + // Can't latch at T3, a new IRD might be loaded already at T1. + // Ok to latch at T4 if combination latched then at T3 + if( enT4) + isByte_T4 <= Irdecod.isByte; // Includes MOVEP from mem, we could OR it here + + if( enT3) begin + dbinNoHigh <= Nanod.noHighByte; + dbinNoLow <= Nanod.noLowByte; + byteMux <= Nanod.busByte & isByte_T4 & ~aob0; + end + + if( enT1) begin + // If on wait states, we continue latching until next T1 + xToDbin <= 1'b0; + xToIrc <= 1'b0; + end + else if( enT3) begin + xToDbin <= Nanod.todbin; + xToIrc <= Nanod.toIrc; + end + + // Capture on T4 of the next ucycle + // If there are wait states, we keep capturing every PHI2 until the next T1 + + if( xToIrc & Clks.enPhi2) + Irc <= iEdb; + if( xToDbin & Clks.enPhi2) begin + // Original connects both halves of EDB. + if( ~dbinNoLow) + dbin[ 7:0] <= byteMux ? iEdb[ 15:8] : iEdb[7:0]; + if( ~dbinNoHigh) + dbin[ 15:8] <= ~byteMux & dbinNoLow ? iEdb[ 7:0] : iEdb[ 15:8]; + end + end + + // DOB + logic byteCycle; + + always_ff @( posedge Clks.clk) begin + // Originaly on T1. Transfer to internal EDB also on T1 (stays enabled upto the next T1). But only on T4 (S3) output enables. + // It is safe to do on T3, then, but control signals if derived from IRD must be registered. + // Originally control signals are not registered. + + // Wait states don't affect DOB operation that is done at the start of the bus cycle. + + if( enT4) + byteCycle <= Nanod.busByte & Irdecod.isByte; // busIsByte but not MOVEP + + // Originally byte low/high interconnect is done at EDB, not at DOB. + if( enT3 & ~dobIdle) begin + dob[7:0] <= Nanod.noLowByte ? dobInput[15:8] : dobInput[ 7:0]; + dob[15:8] <= (byteCycle | Nanod.noHighByte) ? dobInput[ 7:0] : dobInput[15:8]; + end + end + assign oEdb = dob; + +endmodule + + +// Provides ucode routine entries (A1/A3) for each opcode +// Also checks for illegal opcode and priv violation + +// This is one of the slowest part of the processor. +// But no need to optimize or pipeline because the result for a1-a3 is not needed until at least 4 cycles. +// IR updated at the least one microinstruction earlier. +// Just need to configure the timing analizer correctly. +// isPriv, isIllegal might be needed as soon as two cycles later + + +module uaddrDecode( + input [15:0] opcode, + output [UADDR_WIDTH-1:0] a1, a2, a3, + output logic isPriv, isIllegal, isLineA, isLineF, + output [15:0] lineBmap); + + wire [3:0] line = opcode[15:12]; + logic [3:0] eaCol, movEa; + + onehotEncoder4 irLineDecod( line, lineBmap); + + assign isLineA = lineBmap[ 'hA]; + assign isLineF = lineBmap[ 'hF]; + + pla_lined pla_lined( .movEa( movEa), .col( eaCol), + .opcode( opcode), .lineBmap( lineBmap), + .palIll( isIllegal), .plaA1( a1), .plaA2( a2), .plaA3( a3) ); + + // ea decoding + assign eaCol = eaDecode( opcode[ 5:0]); + assign movEa = eaDecode( {opcode[ 8:6], opcode[ 11:9]} ); + + // EA decode + function [3:0] eaDecode; + input [5:0] eaBits; + begin + unique case( eaBits[ 5:3]) + 3'b111: + case( eaBits[ 2:0]) + 3'b000: eaDecode = 7; // Absolute short + 3'b001: eaDecode = 8; // Absolute long + 3'b010: eaDecode = 9; // PC displacement + 3'b011: eaDecode = 10; // PC offset + 3'b100: eaDecode = 11; // Immediate + default: eaDecode = 12; // Invalid + endcase + + default: eaDecode = eaBits[5:3]; // Register based EAs + endcase + end + endfunction + + + /* + Privileged instructions: + + ANDI/EORI/ORI SR + MOVE to SR + MOVE to/from USP + RESET + RTE + STOP + */ + + always_comb begin + unique case( lineBmap) + + // ori/andi/eori SR + 'h01: isPriv = ((opcode & 16'hf5ff) == 16'h007c); + + 'h10: + begin + // No priority !!! + if( (opcode & 16'hffc0) == 16'h46c0) // move to sr + isPriv = 1'b1; + + else if( (opcode & 16'hfff0) == 16'h4e60) // move usp + isPriv = 1'b1; + + else if( opcode == 16'h4e70 || // reset + opcode == 16'h4e73 || // rte + opcode == 16'h4e72) // stop + isPriv = 1'b1; + else + isPriv = 1'b0; + end + + default: isPriv = 1'b0; + endcase + end + + +endmodule + +// bin to one-hot, 4 bits to 16-bit bitmap +module onehotEncoder4( input [3:0] bin, output reg [15:0] bitMap); + always_comb begin + case( bin) + 'b0000: bitMap = 16'h0001; + 'b0001: bitMap = 16'h0002; + 'b0010: bitMap = 16'h0004; + 'b0011: bitMap = 16'h0008; + 'b0100: bitMap = 16'h0010; + 'b0101: bitMap = 16'h0020; + 'b0110: bitMap = 16'h0040; + 'b0111: bitMap = 16'h0080; + 'b1000: bitMap = 16'h0100; + 'b1001: bitMap = 16'h0200; + 'b1010: bitMap = 16'h0400; + 'b1011: bitMap = 16'h0800; + 'b1100: bitMap = 16'h1000; + 'b1101: bitMap = 16'h2000; + 'b1110: bitMap = 16'h4000; + 'b1111: bitMap = 16'h8000; + endcase + end +endmodule + +// priority encoder +// used by MOVEM regmask +// this might benefit from device specific features +// MOVEM doesn't need speed, will read the result 2 CPU cycles after each update. +module pren( mask, hbit); + parameter size = 16; + parameter outbits = 4; + + input [size-1:0] mask; + output reg [outbits-1:0] hbit; + // output reg idle; + + always @( mask) begin + integer i; + hbit = 0; + // idle = 1; + for( i = size-1; i >= 0; i = i - 1) begin + if( mask[ i]) begin + hbit = i; + // idle = 0; + end + end + end + +endmodule + +// Microcode sequencer + +module sequencer( input s_clks Clks, input enT3, + input [UROM_WIDTH-1:0] microLatch, + input A0Err, BerrA, busAddrErr, Spuria, Avia, + input Tpend, intPend, isIllegal, isPriv, excRst, isLineA, isLineF, + input [15:0] psw, + input prenEmpty, au05z, dcr4, ze, i11, + input [1:0] alue01, + input [15:0] Ird, + input [UADDR_WIDTH-1:0] a1, a2, a3, + output logic [3:0] tvn, + output logic [UADDR_WIDTH-1:0] nma); + + logic [UADDR_WIDTH-1:0] uNma; + logic [UADDR_WIDTH-1:0] grp1Nma; + logic [1:0] c0c1; + reg a0Rst; + wire A0Sel; + wire inGrp0Exc; + + // assign nma = Clks.extReset ? RSTP0_NMA : (A0Err ? BSER1_NMA : uNma); + // assign nma = A0Err ? (a0Rst ? RSTP0_NMA : BSER1_NMA) : uNma; + + // word type I: 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + // NMA : .. .. 09 08 01 00 05 04 03 02 07 06 .. .. .. .. .. + + wire [UADDR_WIDTH-1:0] dbNma = { microLatch[ 14:13], microLatch[ 6:5], microLatch[ 10:7], microLatch[ 12:11]}; + + // Group 0 exception. + // Separated block from regular NMA. Otherwise simulation might depend on order of assigments. + always_comb begin + if( A0Err) begin + if( a0Rst) // Reset + nma = RSTP0_NMA; + else if( inGrp0Exc) // Double fault + nma = HALT1_NMA; + else // Bus or address error + nma = BSER1_NMA; + end + else + nma = uNma; + end + + always_comb begin + // Format II (conditional) or I (direct branch) + if( microLatch[1]) + uNma = { microLatch[ 14:13], c0c1, microLatch[ 10:7], microLatch[ 12:11]}; + else + case( microLatch[ 3:2]) + 0: uNma = dbNma; // DB + 1: uNma = A0Sel ? grp1Nma : a1; + 2: uNma = a2; + 3: uNma = a3; + endcase + end + + // Format II, conditional, NMA decoding + wire [1:0] enl = { Ird[6], prenEmpty}; // Updated on T3 + + wire [1:0] ms0 = { Ird[8], alue01[0]}; + wire [3:0] m01 = { au05z, Ird[8], alue01}; + wire [1:0] nz1 = { psw[ NF], psw[ ZF]}; + wire [1:0] nv = { psw[ NF], psw[ VF]}; + + logic ccTest; + wire [4:0] cbc = microLatch[ 6:2]; // CBC bits + + always_comb begin + unique case( cbc) + 'h0: c0c1 = {i11, i11}; // W/L offset EA, from IRC + + 'h1: c0c1 = (au05z) ? 2'b01 : 2'b11; // Updated on T3 + 'h11: c0c1 = (au05z) ? 2'b00 : 2'b11; + + 'h02: c0c1 = { 1'b0, ~psw[ CF]}; // C used in DIV + 'h12: c0c1 = { 1'b1, ~psw[ CF]}; + + 'h03: c0c1 = {psw[ ZF], psw[ ZF]}; // Z used in DIVU + + 'h04: // nz1, used in DIVS + case( nz1) + 'b00: c0c1 = 2'b10; + 'b10: c0c1 = 2'b01; + 'b01,'b11: c0c1 = 2'b11; + endcase + + 'h05: c0c1 = {psw[ NF], 1'b1}; // N used in CHK and DIV + 'h15: c0c1 = {1'b1, psw[ NF]}; + + // nz2, used in DIVS (same combination as nz1) + 'h06: c0c1 = { ~nz1[1] & ~nz1[0], 1'b1}; + + 'h07: // ms0 used in MUL + case( ms0) + 'b10, 'b00: c0c1 = 2'b11; + 'b01: c0c1 = 2'b01; + 'b11: c0c1 = 2'b10; + endcase + + 'h08: // m01 used in MUL + case( m01) + 'b0000,'b0001,'b0100,'b0111: c0c1 = 2'b11; + 'b0010,'b0011,'b0101: c0c1 = 2'b01; + 'b0110: c0c1 = 2'b10; + default: c0c1 = 2'b00; + endcase + + // Conditional + 'h09: c0c1 = (ccTest) ? 2'b11 : 2'b01; + 'h19: c0c1 = (ccTest) ? 2'b11 : 2'b10; + + // DCR bit 4 (high or low word) + 'h0c: c0c1 = dcr4 ? 2'b01: 2'b11; + 'h1c: c0c1 = dcr4 ? 2'b10: 2'b11; + + // DBcc done + 'h0a: c0c1 = ze ? 2'b11 : 2'b00; + + // nv, used in CHK + 'h0b: c0c1 = (nv == 2'b00) ? 2'b00 : 2'b11; + + // V, used in trapv + 'h0d: c0c1 = { ~psw[ VF], ~psw[VF]}; + + // enl, combination of pren idle and word/long on IRD + 'h0e,'h1e: + case( enl) + 2'b00: c0c1 = 'b10; + 2'b10: c0c1 = 'b11; + // 'hx1 result 00/01 depending on condition 0e/1e + 2'b01,2'b11: + c0c1 = { 1'b0, microLatch[ 6]}; + endcase + + default: c0c1 = 'X; + endcase + end + + // CCR conditional + always_comb begin + unique case( Ird[ 11:8]) + 'h0: ccTest = 1'b1; // T + 'h1: ccTest = 1'b0; // F + 'h2: ccTest = ~psw[ CF] & ~psw[ ZF]; // HI + 'h3: ccTest = psw[ CF] | psw[ZF]; // LS + 'h4: ccTest = ~psw[ CF]; // CC (HS) + 'h5: ccTest = psw[ CF]; // CS (LO) + 'h6: ccTest = ~psw[ ZF]; // NE + 'h7: ccTest = psw[ ZF]; // EQ + 'h8: ccTest = ~psw[ VF]; // VC + 'h9: ccTest = psw[ VF]; // VS + 'ha: ccTest = ~psw[ NF]; // PL + 'hb: ccTest = psw[ NF]; // MI + 'hc: ccTest = (psw[ NF] & psw[ VF]) | (~psw[ NF] & ~psw[ VF]); // GE + 'hd: ccTest = (psw[ NF] & ~psw[ VF]) | (~psw[ NF] & psw[ VF]); // LT + 'he: ccTest = (psw[ NF] & psw[ VF] & ~psw[ ZF]) | + (~psw[ NF] & ~psw[ VF] & ~psw[ ZF]); // GT + 'hf: ccTest = psw[ ZF] | (psw[ NF] & ~psw[VF]) | (~psw[ NF] & psw[VF]); // LE + endcase + end + + // Exception logic + logic rTrace, rInterrupt; + logic rIllegal, rPriv, rLineA, rLineF; + logic rExcRst, rExcAdrErr, rExcBusErr; + logic rSpurious, rAutovec; + wire grp1LatchEn, grp0LatchEn; + + // Originally control signals latched on T4. Then exception latches updated on T3 + assign grp1LatchEn = microLatch[0] & (microLatch[1] | !microLatch[4]); + assign grp0LatchEn = microLatch[4] & !microLatch[1]; + + assign inGrp0Exc = rExcRst | rExcBusErr | rExcAdrErr; + + always_ff @( posedge Clks.clk) begin + if( grp0LatchEn & enT3) begin + rExcRst <= excRst; + rExcBusErr <= BerrA; + rExcAdrErr <= busAddrErr; + rSpurious <= Spuria; + rAutovec <= Avia; + end + + // Update group 1 exception latches + // Inputs from IR decoder updated on T1 as soon as IR loaded + // Trace pending updated on T3 at the start of the instruction + // Interrupt pending on T2 + if( grp1LatchEn & enT3) begin + rTrace <= Tpend; + rInterrupt <= intPend; + rIllegal <= isIllegal & ~isLineA & ~isLineF; + rLineA <= isLineA; + rLineF <= isLineF; + rPriv <= isPriv & !psw[ SF]; + end + end + + // exception priority + always_comb begin + grp1Nma = TRAC1_NMA; + if( rExcRst) + tvn = '0; // Might need to change that to signal in exception + else if( rExcBusErr | rExcAdrErr) + tvn = { 1'b1, rExcAdrErr}; + + // Seudo group 0 exceptions. Just for updating TVN + else if( rSpurious | rAutovec) + tvn = rSpurious ? TVN_SPURIOUS : TVN_AUTOVEC; + + else if( rTrace) + tvn = 9; + else if( rInterrupt) begin + tvn = TVN_INTERRUPT; + grp1Nma = ITLX1_NMA; + end + else begin + unique case( 1'b1) // Can't happen more than one of these + rIllegal: tvn = 4; + rPriv: tvn = 8; + rLineA: tvn = 10; + rLineF: tvn = 11; + default: tvn = 1; // Signal no group 0/1 exception + endcase + end + end + + assign A0Sel = rIllegal | rLineF | rLineA | rPriv | rTrace | rInterrupt; + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) + a0Rst <= 1'b1; + else if( enT3) + a0Rst <= 1'b0; + end + +endmodule + + +// +// DMA/BUS Arbitration +// + +module busArbiter( input s_clks Clks, + input BRi, BgackI, Halti, bgBlock, + output busAvail, + output logic BGn); + + enum int unsigned { DRESET = 0, DIDLE, D1, D_BR, D_BA, D_BRA, D3, D2} dmaPhase, next; + + always_comb begin + case(dmaPhase) + DRESET: next = DIDLE; + DIDLE: begin + if( bgBlock) + next = DIDLE; + else if( ~BgackI) + next = D_BA; + else if( ~BRi) + next = D1; + else + next = DIDLE; + end + + D_BA: begin // Loop while only BGACK asserted, BG negated here + if( ~BRi & !bgBlock) + next = D3; + else if( ~BgackI & !bgBlock) + next = D_BA; + else + next = DIDLE; + end + + D1: next = D_BR; // Loop while only BR asserted + D_BR: next = ~BRi & BgackI ? D_BR : D_BA; // No direct path to IDLE ! + + D3: next = D_BRA; + D_BRA: begin // Loop while both BR and BGACK asserted + case( {BgackI, BRi} ) + 2'b11: next = DIDLE; // Both deasserted + 2'b10: next = D_BR; // BR asserted only + 2'b01: next = D2; // BGACK asserted only + 2'b00: next = D_BRA; // Stay here while both asserted + endcase + end + + // Might loop here if both deasserted, should normally don't arrive here anyway? + // D2: next = (BgackI & BRi) | bgBlock ? D2: D_BA; + + D2: next = D_BA; + + default: next = DIDLE; // Should not reach here normally + endcase + end + + logic granting; + always_comb begin + unique case( next) + D1, D3, D_BR, D_BRA: granting = 1'b1; + default: granting = 1'b0; + endcase + end + + reg rGranted; + assign busAvail = Halti & BRi & BgackI & ~rGranted; + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) begin + dmaPhase <= DRESET; + rGranted <= 1'b0; + end + else if( Clks.enPhi2) begin + dmaPhase <= next; + // Internal signal changed on PHI2 + rGranted <= granting; + end + + // External Output changed on PHI1 + if( Clks.extReset) + BGn <= 1'b1; + else if( Clks.enPhi1) + BGn <= ~rGranted; + + end + +endmodule + +module busControl( input s_clks Clks, input enT1, input enT4, + input permStart, permStop, iStop, + input aob0, + input isWrite, isByte, isRmc, + input busAvail, + output bgBlock, + output busAddrErr, + output waitBusCycle, + output busStarting, // Asserted during S0 + output logic addrOe, // Asserted from S1 to the end, whole bus cycle except S0 + output bciWrite, // Used for SSW on bus/addr error + + input rDtack, BeDebounced, Vpai, + output ASn, output LDSn, output UDSn, eRWn); + + reg rAS, rLDS, rUDS, rRWn; + assign ASn = rAS; + assign LDSn = rLDS; + assign UDSn = rUDS; + assign eRWn = rRWn; + + reg dataOe; + + reg bcPend; + reg isWriteReg, bciByte, isRmcReg, wendReg; + assign bciWrite = isWriteReg; + reg addrOeDelay; + reg isByteT4; + + wire canStart, busEnd; + wire bcComplete, bcReset; + + wire isRcmReset = bcComplete & bcReset & isRmcReg; + + assign busAddrErr = aob0 & ~bciByte; + + // Bus retry not really supported. + // It's BERR and HALT and not address error, and not read-modify cycle. + wire busRetry = ~busAddrErr & 1'b0; + + enum int unsigned { SRESET = 0, SIDLE, S0, S2, S4, S6, SRMC_RES} busPhase, next; + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) + busPhase <= SRESET; + else if( Clks.enPhi1) + busPhase <= next; + end + + always_comb begin + case( busPhase) + SRESET: next = SIDLE; + SRMC_RES: next = SIDLE; // Single cycle special state when read phase of RMC reset + S0: next = S2; + S2: next = S4; + S4: next = busEnd ? S6 : S4; + S6: next = isRcmReset ? SRMC_RES : (canStart ? S0 : SIDLE); + SIDLE: next = canStart ? S0 : SIDLE; + default: next = SIDLE; + endcase + end + + // Idle phase of RMC bus cycle. Might be better to just add a new state + wire rmcIdle = (busPhase == SIDLE) & ~ASn & isRmcReg; + + assign canStart = (busAvail | rmcIdle) & (bcPend | permStart) & !busRetry & !bcReset; + + wire busEnding = (next == SIDLE) | (next == S0); + + assign busStarting = (busPhase == S0); + + // term signal (DTACK, BERR, VPA, adress error) + assign busEnd = ~rDtack | iStop; + + // bcComplete asserted on raising edge of S6 (together with SNC). + assign bcComplete = (busPhase == S6); + + // Clear bus info latch on completion (regular or aborted) and no bus retry (and not PHI1). + // bciClear asserted half clock later on PHI2, and bci latches cleared async concurrently + wire bciClear = bcComplete & ~busRetry; + + // Reset on reset or (berr & berrDelay & (not halt or rmc) & not 6800 & in bus cycle) (and not PHI1) + assign bcReset = Clks.extReset | (addrOeDelay & BeDebounced & Vpai); + + // Enable uclock only on S6 (S8 on Bus Error) or not bciPermStop + assign waitBusCycle = wendReg & !bcComplete; + + // Block Bus Grant when starting new bus cycle. But No need if AS already asserted (read phase of RMC) + // Except that when that RMC phase aborted on bus error, it's asserted one cycle later! + assign bgBlock = ((busPhase == S0) & ASn) | (busPhase == SRMC_RES); + + always_ff @( posedge Clks.clk) begin + if( Clks.extReset) begin + addrOe <= 1'b0; + end + else if( Clks.enPhi2 & ( busPhase == S0)) // From S1, whole bus cycle except S0 + addrOe <= 1'b1; + else if( Clks.enPhi1 & (busPhase == SRMC_RES)) + addrOe <= 1'b0; + else if( Clks.enPhi1 & ~isRmcReg & busEnding) + addrOe <= 1'b0; + + if( Clks.enPhi1) + addrOeDelay <= addrOe; + + if( Clks.extReset) begin + rAS <= 1'b1; + rUDS <= 1'b1; + rLDS <= 1'b1; + rRWn <= 1'b1; + dataOe <= '0; + end + else begin + + if( Clks.enPhi2 & isWriteReg & (busPhase == S2)) + dataOe <= 1'b1; + else if( Clks.enPhi1 & (busEnding | (busPhase == SIDLE)) ) + dataOe <= 1'b0; + + if( Clks.enPhi1 & busEnding) + rRWn <= 1'b1; + else if( Clks.enPhi1 & isWriteReg) begin + // Unlike LDS/UDS Asserted even in address error + if( (busPhase == S0) & isWriteReg) + rRWn <= 1'b0; + end + + // AS. Actually follows addrOe half cycle later! + if( Clks.enPhi1 & (busPhase == S0)) + rAS <= 1'b0; + else if( Clks.enPhi2 & (busPhase == SRMC_RES)) // Bus error on read phase of RMC. Deasserted one cycle later + rAS <= 1'b1; + else if( Clks.enPhi2 & bcComplete & ~SRMC_RES) + if( ~isRmcReg) // Keep AS asserted on the IDLE phase of RMC + rAS <= 1'b1; + + if( Clks.enPhi1 & (busPhase == S0)) begin + if( ~isWriteReg & !busAddrErr) begin + rUDS <= ~(~bciByte | ~aob0); + rLDS <= ~(~bciByte | aob0); + end + end + else if( Clks.enPhi1 & isWriteReg & (busPhase == S2) & !busAddrErr) begin + rUDS <= ~(~bciByte | ~aob0); + rLDS <= ~(~bciByte | aob0); + end + else if( Clks.enPhi2 & bcComplete) begin + rUDS <= 1'b1; + rLDS <= 1'b1; + end + + end + + end + + // Bus cycle info latch. Needed because uinstr might change if the bus is busy and we must wait. + // Note that urom advances even on wait states. It waits *after* updating urom and nanorom latches. + // Even without wait states, ublocks of type ir (init reading) will not wait for bus completion. + // Originally latched on (permStart AND T1). + + // Bus cycle info latch: isRead, isByte, read-modify-cycle, and permStart (bus cycle pending). Some previously latched on T4? + // permStop also latched, but unconditionally on T1 + + // Might make more sense to register this outside this module + always_ff @( posedge Clks.clk) begin + if( enT4) begin + isByteT4 <= isByte; + end + end + + // Bus Cycle Info Latch + always_ff @( posedge Clks.clk) begin + if( Clks.pwrUp) begin + bcPend <= 1'b0; + wendReg <= 1'b0; + isWriteReg <= 1'b0; + bciByte <= 1'b0; + isRmcReg <= 1'b0; + end + + else if( Clks.enPhi2 & (bciClear | bcReset)) begin + bcPend <= 1'b0; + wendReg <= 1'b0; + end + else begin + if( enT1 & permStart) begin + isWriteReg <= isWrite; + bciByte <= isByteT4; + isRmcReg <= isRmc & ~isWrite; // We need special case the end of the read phase only. + bcPend <= 1'b1; + end + if( enT1) + wendReg <= permStop; + end + end + +endmodule + +// +// microrom and nanorom instantiation +// +// There is bit of wasting of resources here. An extra registering pipeline happens that is not needed. +// This is just for the purpose of helping inferring block RAM using pure generic code. Inferring RAM is important for performance. +// Might be more efficient to use vendor specific features such as clock enable. +// + +module uRom( input clk, input [UADDR_WIDTH-1:0] microAddr, output logic [UROM_WIDTH-1:0] microOutput); + reg [UROM_WIDTH-1:0] uRam[ UROM_DEPTH]; + initial begin + $readmemb("./rtl/ipcores/fx68k/microrom.mem", uRam); + end + + always_ff @( posedge clk) + microOutput <= uRam[ microAddr]; +endmodule + + +module nanoRom( input clk, input [NADDR_WIDTH-1:0] nanoAddr, output logic [NANO_WIDTH-1:0] nanoOutput); + reg [NANO_WIDTH-1:0] nRam[ NANO_DEPTH]; + initial begin + $readmemb("./rtl/ipcores/fx68k/nanorom.mem", nRam); + end + + always_ff @( posedge clk) + nanoOutput <= nRam[ nanoAddr]; +endmodule + +// Translate uaddr to nanoaddr +module microToNanoAddr( + input [UADDR_WIDTH-1:0] uAddr, + output [NADDR_WIDTH-1:0] orgAddr); + + wire [UADDR_WIDTH-1:2] baseAddr = uAddr[UADDR_WIDTH-1:2]; + logic [NADDR_WIDTH-1:2] orgBase; + assign orgAddr = { orgBase, uAddr[1:0]}; + + always @( baseAddr) + begin + // nano ROM (136 addresses) + case( baseAddr) + +'h00: orgBase = 7'h0 ; +'h01: orgBase = 7'h1 ; +'h02: orgBase = 7'h2 ; +'h03: orgBase = 7'h2 ; +'h08: orgBase = 7'h3 ; +'h09: orgBase = 7'h4 ; +'h0A: orgBase = 7'h5 ; +'h0B: orgBase = 7'h5 ; +'h10: orgBase = 7'h6 ; +'h11: orgBase = 7'h7 ; +'h12: orgBase = 7'h8 ; +'h13: orgBase = 7'h8 ; +'h18: orgBase = 7'h9 ; +'h19: orgBase = 7'hA ; +'h1A: orgBase = 7'hB ; +'h1B: orgBase = 7'hB ; +'h20: orgBase = 7'hC ; +'h21: orgBase = 7'hD ; +'h22: orgBase = 7'hE ; +'h23: orgBase = 7'hD ; +'h28: orgBase = 7'hF ; +'h29: orgBase = 7'h10 ; +'h2A: orgBase = 7'h11 ; +'h2B: orgBase = 7'h10 ; +'h30: orgBase = 7'h12 ; +'h31: orgBase = 7'h13 ; +'h32: orgBase = 7'h14 ; +'h33: orgBase = 7'h14 ; +'h38: orgBase = 7'h15 ; +'h39: orgBase = 7'h16 ; +'h3A: orgBase = 7'h17 ; +'h3B: orgBase = 7'h17 ; +'h40: orgBase = 7'h18 ; +'h41: orgBase = 7'h18 ; +'h42: orgBase = 7'h18 ; +'h43: orgBase = 7'h18 ; +'h44: orgBase = 7'h19 ; +'h45: orgBase = 7'h19 ; +'h46: orgBase = 7'h19 ; +'h47: orgBase = 7'h19 ; +'h48: orgBase = 7'h1A ; +'h49: orgBase = 7'h1A ; +'h4A: orgBase = 7'h1A ; +'h4B: orgBase = 7'h1A ; +'h4C: orgBase = 7'h1B ; +'h4D: orgBase = 7'h1B ; +'h4E: orgBase = 7'h1B ; +'h4F: orgBase = 7'h1B ; +'h54: orgBase = 7'h1C ; +'h55: orgBase = 7'h1D ; +'h56: orgBase = 7'h1E ; +'h57: orgBase = 7'h1F ; +'h5C: orgBase = 7'h20 ; +'h5D: orgBase = 7'h21 ; +'h5E: orgBase = 7'h22 ; +'h5F: orgBase = 7'h23 ; +'h70: orgBase = 7'h24 ; +'h71: orgBase = 7'h24 ; +'h72: orgBase = 7'h24 ; +'h73: orgBase = 7'h24 ; +'h74: orgBase = 7'h24 ; +'h75: orgBase = 7'h24 ; +'h76: orgBase = 7'h24 ; +'h77: orgBase = 7'h24 ; +'h78: orgBase = 7'h25 ; +'h79: orgBase = 7'h25 ; +'h7A: orgBase = 7'h25 ; +'h7B: orgBase = 7'h25 ; +'h7C: orgBase = 7'h25 ; +'h7D: orgBase = 7'h25 ; +'h7E: orgBase = 7'h25 ; +'h7F: orgBase = 7'h25 ; +'h84: orgBase = 7'h26 ; +'h85: orgBase = 7'h27 ; +'h86: orgBase = 7'h28 ; +'h87: orgBase = 7'h29 ; +'h8C: orgBase = 7'h2A ; +'h8D: orgBase = 7'h2B ; +'h8E: orgBase = 7'h2C ; +'h8F: orgBase = 7'h2D ; +'h94: orgBase = 7'h2E ; +'h95: orgBase = 7'h2F ; +'h96: orgBase = 7'h30 ; +'h97: orgBase = 7'h31 ; +'h9C: orgBase = 7'h32 ; +'h9D: orgBase = 7'h33 ; +'h9E: orgBase = 7'h34 ; +'h9F: orgBase = 7'h35 ; +'hA4: orgBase = 7'h36 ; +'hA5: orgBase = 7'h36 ; +'hA6: orgBase = 7'h37 ; +'hA7: orgBase = 7'h37 ; +'hAC: orgBase = 7'h38 ; +'hAD: orgBase = 7'h38 ; +'hAE: orgBase = 7'h39 ; +'hAF: orgBase = 7'h39 ; +'hB4: orgBase = 7'h3A ; +'hB5: orgBase = 7'h3A ; +'hB6: orgBase = 7'h3B ; +'hB7: orgBase = 7'h3B ; +'hBC: orgBase = 7'h3C ; +'hBD: orgBase = 7'h3C ; +'hBE: orgBase = 7'h3D ; +'hBF: orgBase = 7'h3D ; +'hC0: orgBase = 7'h3E ; +'hC1: orgBase = 7'h3F ; +'hC2: orgBase = 7'h40 ; +'hC3: orgBase = 7'h41 ; +'hC8: orgBase = 7'h42 ; +'hC9: orgBase = 7'h43 ; +'hCA: orgBase = 7'h44 ; +'hCB: orgBase = 7'h45 ; +'hD0: orgBase = 7'h46 ; +'hD1: orgBase = 7'h47 ; +'hD2: orgBase = 7'h48 ; +'hD3: orgBase = 7'h49 ; +'hD8: orgBase = 7'h4A ; +'hD9: orgBase = 7'h4B ; +'hDA: orgBase = 7'h4C ; +'hDB: orgBase = 7'h4D ; +'hE0: orgBase = 7'h4E ; +'hE1: orgBase = 7'h4E ; +'hE2: orgBase = 7'h4F ; +'hE3: orgBase = 7'h4F ; +'hE8: orgBase = 7'h50 ; +'hE9: orgBase = 7'h50 ; +'hEA: orgBase = 7'h51 ; +'hEB: orgBase = 7'h51 ; +'hF0: orgBase = 7'h52 ; +'hF1: orgBase = 7'h52 ; +'hF2: orgBase = 7'h52 ; +'hF3: orgBase = 7'h52 ; +'hF8: orgBase = 7'h53 ; +'hF9: orgBase = 7'h53 ; +'hFA: orgBase = 7'h53 ; +'hFB: orgBase = 7'h53 ; + + default: + orgBase = 'X; + endcase + end + +endmodule + +// +// For compilation test only +// + +`ifdef FX68K_TEST +module fx68kTop( input clk32, + input extReset, + // input pwrUp, + + input DTACKn, input VPAn, + input BERRn, + input BRn, BGACKn, + input IPL0n, input IPL1n, input IPL2n, + input [15:0] iEdb, + + output [15:0] oEdb, + output eRWn, output ASn, output LDSn, output UDSn, + output logic E, output VMAn, + output FC0, output FC1, output FC2, + output BGn, + output oRESETn, output oHALTEDn, + output [23:1] eab + ); + + // Clock must be at least twice the desired frequency. A 32 MHz clock means a maximum 16 MHz effective frequency. + // In this example we divide the clock by 4. Resulting on an effective processor running at 8 MHz. + + reg [1:0] clkDivisor = '0; + always @( posedge clk32) begin + clkDivisor <= clkDivisor + 1'b1; + end + + /* + These two signals must be a single cycle pulse. They don't need to be registered. + Same signal can't be asserted twice in a row. Other than that there are no restrictions. + There can be any number of cycles, or none, even variable non constant cycles, between each pulse. + */ + + wire enPhi1 = (clkDivisor == 2'b11); + wire enPhi2 = (clkDivisor == 2'b01); + + + fx68k fx68k( .clk( clk32), + .extReset, .pwrUp( extReset), .enPhi1, .enPhi2, + + .DTACKn, .VPAn, .BERRn, .BRn, .BGACKn, + .IPL0n, .IPL1n, .IPL2n, + .iEdb, + + .oEdb, + .eRWn, .ASn, .LDSn, .UDSn, + .E, .VMAn, + .FC0, .FC1, .FC2, + .BGn, + .oRESETn, .oHALTEDn, .eab); + +endmodule +`endif diff --git a/rtl/ipcores/fx68k/fx68k.txt b/rtl/ipcores/fx68k/fx68k.txt new file mode 100644 index 0000000..3397c02 --- /dev/null +++ b/rtl/ipcores/fx68k/fx68k.txt @@ -0,0 +1,87 @@ +FX68K + +68000 cycle accurate core +Copyright (c) 2018 by Jorge Cwik +fx68k@fxatari.com + + +FX68K is a 68K cycle exact compatible core. In theory at least, it should be impossible to distinguish functionally from a real 68K processor. + +On Cyclone families it uses just over 5,100 LEs and about 5KB internal ram, reaching a max clock frequency close to 40MHz. Some optimizations are still possible to implement and increase the performance. + +The core is fully synchronous. Considerable effort was done to avoid any asynchronous logic. + +Written in SystemVerilog. + +The timing of the external bus signals is exactly as the original processor. The only feature that is not implemented yet is bus retry using the external HALT input signal. + +It was designed to replace an actual chip on a real board. This wasn't yet tested however and not all necessary output enable control signals are fully implemented. + + +Copyright + +// +// This source file is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + + +Developer Notes + + +The core receives a clock that must be at least twice the frequency of the desired nominal speed. The core also receives two signals for masking both phases of the clock (PHI1 and PHI2). These signals are implemented as simple clock enable for all the flip flops used by the core. This way, the original clock frequency can be any multiple and it doesn't even need to be regular or constant. + +These two signals are enPhi1 and enPhi2. They must be a single cycle pulse, and they don't need to be registered. Because they are actually used as clock enable, the output signals change one cycle later. + +enPhi1 should be asserted one cycle before the high phase of the nominal clock, and enPhi2 one cycle before the low phase. + +E.g., during a bus cycle, AS is asserted one cycle after enPhi1 is asserted, and AS is deasserted one cycle after enPhi2 is asserted. This follows the original bus timing that specify AS being asserted on the raising edge of the clock, and deasserted on the falling edge one. + +All signals follow the original polarity and then most are low active. + +extReset is external reset and is synchronous and high active. Hence is doesn't have to be registered. + +pwrUp qualifies external reset as being a cold power up reset. If it is asserted, then extReset must be asserted as well. Most system don't need to distinguish between a cold and a warm reset at the CPU level. Then both signals can be always asserted together. The core does expect pwrUp to be asserted initially because there is no true asynchronous reset. The signal is high active. + + +Timing analysis + +Microcode access is one of the slowest paths on the core. But the microcode output is not needed immediately. Use the following constraints to get a more accurate timing analysis. Note that the full path might need to be modified: + +# Altera/Intel + +set_multicycle_path -start -setup -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|microAddr[*]] 2 +set_multicycle_path -start -hold -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|microAddr[*]] 1 +set_multicycle_path -start -setup -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|nanoAddr[*]] 2 +set_multicycle_path -start -hold -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|nanoAddr[*]] 1 + +# For Xilinx Vivado + +set_multicycle_path -setup -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/nanoAddr_reg*/D] 2 +set_multicycle_path -setup -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/microAddr_reg*/D] 2 +set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/nanoAddr_reg*/D] 1 +set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/microAddr_reg*/D] 1 + + +The update of the CCR flags is also time critical. Some compilers might benefit with the following constraints, but this wasn't fully verified yet: + + +# Altera/Intel +# set_multicycle_path -start -setup -from [fx68k:fx68k|nanoLatch[*]] +# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 2 +# set_multicycle_path -start -setup -from [fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|oper[*]] +# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 2 +# set_multicycle_path -start -hold -from [fx68k:fx68k|nanoLatch[*]] +# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 1 +# set_multicycle_path -start -hold -from [fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|oper[*]] +# -to [get_keepers fx68k:fx68k|excUnit:excUnit|fx68kAlu:alu|pswCcr[*]] 1 diff --git a/rtl/ipcores/fx68k/fx68kAlu.sv b/rtl/ipcores/fx68k/fx68kAlu.sv new file mode 100644 index 0000000..95059c4 --- /dev/null +++ b/rtl/ipcores/fx68k/fx68kAlu.sv @@ -0,0 +1,839 @@ +// +// FX 68K +// +// M68K cycle accurate, fully synchronous +// Copyright (c) 2018 by Jorge Cwik +// +// ALU +// + +`timescale 1 ns / 1 ns + +localparam MASK_NBITS = 5; + +localparam + OP_AND = 1, + OP_SUB = 2, OP_SUBX = 3, OP_ADD = 4, + OP_EXT = 5, OP_SBCD = 6, OP_SUB0 = 7, + OP_OR = 8, OP_EOR = 9, + OP_SUBC = 10, OP_ADDC = 11, OP_ADDX = 12, + OP_ASL = 13, + OP_ASR = 14, + OP_LSL = 15, + OP_LSR = 16, + OP_ROL = 17, + OP_ROR = 18, + OP_ROXL = 19, + OP_ROXR = 20, + OP_SLAA = 21, + OP_ABCD = 22; + +module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4, + input [15:0] ird, + input [2:0] aluColumn, + input [1:0] aluDataCtrl, + input aluAddrCtrl, alueClkEn, ftu2Ccr, init, finish, aluIsByte, + input [15:0] ftu, + input [15:0] alub, + input [15:0] iDataBus, input [15:0] iAddrBus, + output ze, + output reg [15:0] alue, + output reg [7:0] ccr, + output [15:0] aluOut); + + +`define ALU_ROW_01 16'h0002 +`define ALU_ROW_02 16'h0004 +`define ALU_ROW_03 16'h0008 +`define ALU_ROW_04 16'h0010 +`define ALU_ROW_05 16'h0020 +`define ALU_ROW_06 16'h0040 +`define ALU_ROW_07 16'h0080 +`define ALU_ROW_08 16'h0100 +`define ALU_ROW_09 16'h0200 +`define ALU_ROW_10 16'h0400 +`define ALU_ROW_11 16'h0800 +`define ALU_ROW_12 16'h1000 +`define ALU_ROW_13 16'h2000 +`define ALU_ROW_14 16'h4000 +`define ALU_ROW_15 16'h8000 + + + // Bit positions for flags in CCR + localparam CF = 0, VF = 1, ZF = 2, NF = 3, XF = 4; + + reg [15:0] aluLatch; + reg [4:0] pswCcr; + reg [4:0] ccrCore; + + logic [15:0] result; + logic [4:0] ccrTemp; + reg coreH; // half carry latch + + logic [15:0] subResult; + logic subHcarry; + logic subCout, subOv; + + assign aluOut = aluLatch; + assign ze = ~ccrCore[ ZF]; // Check polarity !!! + + // + // Control + // Signals derived from IRD *must* be registered on either T3 or T4 + // Signals derived from nano rom can be registered on T4. + + reg [15:0] row; + reg isArX; // Don't set Z + reg noCcrEn; + reg isByte; + + reg [4:0] ccrMask; + reg [4:0] oper; + + logic [15:0] aOperand, dOperand; + wire isCorf = ( aluDataCtrl == 2'b10); + + wire [15:0] cRow; + wire cIsArX; + wire cNoCcrEn; + rowDecoder rowDecoder( .ird( ird), .row( cRow), .noCcrEn( cNoCcrEn), .isArX( cIsArX)); + + // Get Operation & CCR Mask from row/col + // Registering them on T4 increase performance. But slowest part seems to be corf ! + wire [4:0] cMask; + wire [4:0] aluOp; + + aluGetOp aluGetOp( .row, .col( aluColumn), .isCorf, .aluOp); + ccrTable ccrTable( .col( aluColumn), .row( row), .finish, .ccrMask( cMask)); + + // Inefficient, uCode could help ! + wire shftIsMul = row[7]; + wire shftIsDiv = row[1]; + + wire [31:0] shftResult; + reg [7:0] bcdLatch; + reg bcdCarry, bcdOverf; + + reg isLong; + reg rIrd8; + logic isShift; + logic shftCin, shftRight, addCin; + + // Register some decoded signals + always_ff @( posedge clk) begin + if( enT3) begin + row <= cRow; + isArX <= cIsArX; + noCcrEn <= cNoCcrEn; + rIrd8 <= ird[8]; + isByte <= aluIsByte; + end + + if( enT4) begin + // Decode if long shift + // MUL and DIV are long (but special !) + isLong <= (ird[7] & ~ird[6]) | shftIsMul | shftIsDiv; + + ccrMask <= cMask; + oper <= aluOp; + end + end + + + always_comb begin + // Dest (addr) operand source + // If aluCsr (depends on column/row) addrbus is shifted !! + aOperand = (aluAddrCtrl ? alub : iAddrBus); + + // Second (data,source) operand mux + case( aluDataCtrl) + 2'b00: dOperand = iDataBus; + 2'b01: dOperand = 'h0000; + 2'b11: dOperand = 'hffff; + // 2'b10: dOperand = bcdResult; + 2'b10: dOperand = 'X; + endcase + end + + // Execution + + // shift operand MSB. Input in ASR/ROL. Carry in right. + // Can't be registered because uses bus operands that aren't available early ! + wire shftMsb = isLong ? alue[15] : (isByte ? aOperand[7] : aOperand[15]); + + aluShifter shifter( .data( { alue, aOperand}), + .swapWords( shftIsMul | shftIsDiv), + .cin( shftCin), .dir( shftRight), .isByte( isByte), .isLong( isLong), + .result( shftResult)); + + wire [7:0] bcdResult; + wire bcdC, bcdV; + aluCorf aluCorf( .binResult( aluLatch[7:0]), .hCarry( coreH), + .bAdd( (oper != OP_SBCD) ), .cin( pswCcr[ XF]), + .bcdResult( bcdResult), .dC( bcdC), .ov( bcdV)); + + // BCD adjust is among the slowest processing on ALU ! + // Precompute and register BCD result on T1 + // We don't need to wait for execution buses because corf is always added to ALU previous result + always_ff @( posedge clk) + if( enT1) begin + bcdLatch <= bcdResult; + bcdCarry <= bcdC; + bcdOverf <= bcdV; + end + + // Adder carry in selector + always_comb + begin + case( oper) + OP_ADD, OP_SUB: addCin = 1'b0; + OP_SUB0: addCin = 1'b1; // NOT = 0 - op - 1 + OP_ADDC,OP_SUBC: addCin = ccrCore[ CF]; + OP_ADDX,OP_SUBX: addCin = pswCcr[ XF]; + default: addCin = 1'bX; + endcase + end + + // Shifter carry in and direction selector + always_comb begin + case( oper) + OP_LSL, OP_ASL, OP_ROL, OP_ROXL, OP_SLAA: shftRight = 1'b0; + OP_LSR, OP_ASR, OP_ROR, OP_ROXR: shftRight = 1'b1; + default: shftRight = 1'bX; + endcase + + case( oper) + OP_LSR, + OP_ASL, + OP_LSL: shftCin = 1'b0; + OP_ROL, + OP_ASR: shftCin = shftMsb; + OP_ROR: shftCin = aOperand[0]; + OP_ROXL, + OP_ROXR: + if( shftIsMul) + shftCin = rIrd8 ? pswCcr[NF] ^ pswCcr[VF] : pswCcr[ CF]; + else + shftCin = pswCcr[ XF]; + + OP_SLAA: shftCin = aluColumn[1]; // col4 -> 0, col 6-> 1 + default: shftCin = 'X; + endcase + end + + // ALU operation selector + always_comb begin + + // sub is DATA - ADDR + mySubber( aOperand, dOperand, addCin, + (oper == OP_ADD) | (oper == OP_ADDC) | (oper == OP_ADDX), + isByte, subResult, subCout, subOv); + + isShift = 1'b0; + case( oper) + OP_AND: result = aOperand & dOperand; + OP_OR: result = aOperand | dOperand; + OP_EOR: result = aOperand ^ dOperand; + + OP_EXT: result = { {8{aOperand[7]}}, aOperand[7:0]}; + + OP_SLAA, + OP_ASL, OP_ASR, + OP_LSL, OP_LSR, + OP_ROL, OP_ROR, + OP_ROXL, OP_ROXR: + begin + result = shftResult[15:0]; + isShift = 1'b1; + end + + OP_ADD, + OP_ADDC, + OP_ADDX, + OP_SUB, + OP_SUBC, + OP_SUB0, + OP_SUBX: result = subResult; + + OP_ABCD, + OP_SBCD: result = { 8'hXX, bcdLatch}; + + default: result = 'X; + endcase + end + + task mySubber; + input [15:0] inpa, inpb; + input cin, bAdd, isByte; + output reg [15:0] result; + output cout, ov; + + // Not very efficient! + logic [16:0] rtemp; + logic rm,sm,dm,tsm; + + begin + if( isByte) + begin + rtemp = bAdd ? { 1'b0, inpb[7:0]} + { 1'b0, inpa[7:0]} + cin: + { 1'b0, inpb[7:0] } - { 1'b0, inpa[7:0]} - cin; + result = { {8{ rtemp[7]}}, rtemp[7:0]}; + cout = rtemp[8]; + end + else begin + rtemp = bAdd ? { 1'b0, inpb } + { 1'b0, inpa} + cin: + { 1'b0, inpb } - { 1'b0, inpa} - cin; + result = rtemp[ 15:0]; + cout = rtemp[16]; + end + + rm = isByte ? rtemp[7] : rtemp[15]; + dm = isByte ? inpb[ 7] : inpb[ 15]; + tsm = isByte ? inpa[ 7] : inpa[ 15]; + sm = bAdd ? tsm : ~tsm; + + ov = (sm & dm & ~rm) | (~sm & ~dm & rm); + + // Store half carry for bcd correction + subHcarry = inpa[4] ^ inpb[4] ^ rtemp[4]; + + end + endtask + + + // CCR flags process + always_comb begin + + ccrTemp[XF] = pswCcr[XF]; ccrTemp[CF] = 0; ccrTemp[VF] = 0; + + // Not on all operators + ccrTemp[ ZF] = isByte ? ~(| result[7:0]) : ~(| result); + ccrTemp[ NF] = isByte ? result[7] : result[15]; + + unique case( oper) + + OP_EXT: + // Division overflow. + if( aluColumn == 5) begin + ccrTemp[VF] = 1'b1; + ccrTemp[NF] = 1'b1; ccrTemp[ ZF] = 1'b0; + end + + OP_SUB0, // used by NOT + OP_OR, + OP_EOR: + begin + ccrTemp[CF] = 0; ccrTemp[VF] = 0; + end + + OP_AND: + begin + // ROXL/ROXR indeed copy X to C in column 1 (OP_AND), executed before entering the loop. + // Needed when rotate count is zero, the ucode with the ROX operator never reached. + // C must be set to the value of X, X remains unaffected. + if( (aluColumn == 1) & (row[11] | row[8])) + ccrTemp[CF] = pswCcr[XF]; + else + ccrTemp[CF] = 0; + ccrTemp[VF] = 0; + end + + // Assumes col 3 of DIV use C and not X ! + // V will be set in other cols (2/3) of DIV + OP_SLAA: ccrTemp[ CF] = aOperand[15]; + + OP_LSL,OP_ROXL: + begin + ccrTemp[ CF] = shftMsb; + ccrTemp[ XF] = shftMsb; + ccrTemp[ VF] = 1'b0; + end + + OP_LSR,OP_ROXR: + begin + // 0 Needed for mul, or carry gets in high word + ccrTemp[ CF] = shftIsMul ? 1'b0 : aOperand[0]; + ccrTemp[ XF] = aOperand[0]; + // Not relevant for MUL, we clear it at mulm6 (1f) anyway. + // Not that MUL can never overlow! + ccrTemp[ VF] = 0; + // Z is checking here ALU (low result is actually in ALUE). + // But it is correct, see comment above. + end + + OP_ASL: + begin + ccrTemp[ XF] = shftMsb; ccrTemp[ CF] = shftMsb; + // V set if msb changed on any shift. + // Otherwise clear previously on OP_AND (col 1i). + ccrTemp[ VF] = pswCcr[VF] | (shftMsb ^ + (isLong ? alue[15-1] : (isByte ? aOperand[7-1] : aOperand[15-1])) ); + end + OP_ASR: + begin + ccrTemp[ XF] = aOperand[0]; ccrTemp[ CF] = aOperand[0]; + ccrTemp[ VF] = 0; + end + + // X not changed on ROL/ROR ! + OP_ROL: ccrTemp[ CF] = shftMsb; + OP_ROR: ccrTemp[ CF] = aOperand[0]; + + OP_ADD, + OP_ADDC, + OP_ADDX, + OP_SUB, + OP_SUBC, + OP_SUBX: + begin + ccrTemp[ CF] = subCout; + ccrTemp[ XF] = subCout; + ccrTemp[ VF] = subOv; + end + + OP_ABCD, + OP_SBCD: + begin + ccrTemp[ XF] = bcdCarry; + ccrTemp[ CF] = bcdCarry; + ccrTemp[ VF] = bcdOverf; + end + + endcase + + end + + // Core and psw latched at the same cycle + + // CCR filter + // CCR out mux for Z & C flags + // Z flag for 32-bit result + // Not described, but should be used also for instructions + // that clear but not set Z (ADDX/SUBX/ABCD, etc)! + logic [4:0] ccrMasked; + always_comb begin + ccrMasked = (ccrTemp & ccrMask) | (pswCcr & ~ccrMask); + // if( finish | isCorf | isArX) // No need to check specicially for isCorf as they always have the "finish" flag anyway + if( finish | isArX) + ccrMasked[ ZF] = ccrTemp[ ZF] & pswCcr[ ZF]; + end + + always_ff @( posedge clk) begin + if( enT3) begin + // Update latches from ALU operators + if( (| aluColumn)) begin + aluLatch <= result; + + coreH <= subHcarry; + + // Update CCR core + if( (| aluColumn)) + ccrCore <= ccrTemp; // Most bits not really used + end + + if( alueClkEn) + alue <= iDataBus; + else if( isShift & (| aluColumn)) + alue <= shftResult[31:16]; + end + + // CCR + // Originally on T3-T4 edge pulse !! + // Might be possible to update on T4 (but not after T0) from partial result registered on T3, it will increase performance! + if( pwrUp) + pswCcr <= '0; + else if( enT3 & ftu2Ccr) + pswCcr <= ftu[4:0]; + else if( enT3 & ~noCcrEn & (finish | init)) + pswCcr <= ccrMasked; + end + assign ccr = { 3'b0, pswCcr}; + + +endmodule + +// add bcd correction factor +// It would be more efficient to merge add/sub with main ALU !!! +module aluCorf( input [7:0] binResult, input bAdd, input cin, input hCarry, + output [7:0] bcdResult, output dC, output logic ov); + + reg [8:0] htemp; + reg [4:0] hNib; + + wire lowC = hCarry | (bAdd ? gt9( binResult[ 3:0]) : 1'b0); + wire highC = cin | (bAdd ? (gt9( htemp[7:4]) | htemp[8]) : 1'b0); + + always_comb begin + if( bAdd) begin + htemp = { 1'b0, binResult} + (lowC ? 4'h6 : 4'h0); + hNib = htemp[8:4] + (highC ? 4'h6 : 4'h0); + ov = hNib[3] & ~binResult[7]; + end + else begin + htemp = { 1'b0, binResult} - (lowC ? 4'h6 : 4'h0); + hNib = htemp[8:4] - (highC ? 4'h6 : 4'h0); + ov = ~hNib[3] & binResult[7]; + end + end + + assign bcdResult = { hNib[ 3:0], htemp[3:0]}; + assign dC = hNib[4] | cin; + + // Nibble > 9 + function gt9 (input [3:0] nib); + begin + gt9 = nib[3] & (nib[2] | nib[1]); + end + endfunction + +endmodule + + +module aluShifter( input [31:0] data, + input isByte, input isLong, swapWords, + input dir, input cin, + output logic [31:0] result); + // output reg cout + + logic [31:0] tdata; + + // size mux, put cin in position if dir == right + always_comb begin + tdata = data; + if( isByte & dir) + tdata[8] = cin; + else if( !isLong & dir) + tdata[16] = cin; + end + + always_comb begin + // Reverse alu/alue position for MUL & DIV + // Result reversed again + if( swapWords & dir) + result = { tdata[0], tdata[31:17], cin, tdata[15:1]}; + else if( swapWords) + result = { tdata[30:16], cin, tdata[14:0], tdata[31]}; + + else if( dir) + result = { cin, tdata[31:1]}; + else + result = { tdata[30:0], cin}; + end + +endmodule + + +// Get current OP from row & col +module aluGetOp( input [15:0] row, input [2:0] col, input isCorf, + output logic [4:0] aluOp); + + always_comb begin + aluOp = 'X; + unique case( col) + 1: aluOp = OP_AND; + 5: aluOp = OP_EXT; + + default: + unique case( 1'b1) + row[1]: + unique case( col) + 2: aluOp = OP_SUB; + 3: aluOp = OP_SUBC; + 4,6: aluOp = OP_SLAA; + endcase + + row[2]: + unique case( col) + 2: aluOp = OP_ADD; + 3: aluOp = OP_ADDC; + 4: aluOp = OP_ASR; + endcase + + row[3]: + unique case( col) + 2: aluOp = OP_ADDX; + 3: aluOp = isCorf ? OP_ABCD : OP_ADD; + 4: aluOp = OP_ASL; + endcase + + row[4]: + aluOp = ( col == 4) ? OP_LSL : OP_AND; + + row[5], + row[6]: + unique case( col) + 2: aluOp = OP_SUB; + 3: aluOp = OP_SUBC; + 4: aluOp = OP_LSR; + endcase + + row[7]: // MUL + unique case( col) + 2: aluOp = OP_SUB; + 3: aluOp = OP_ADD; + 4: aluOp = OP_ROXR; + endcase + + row[8]: + // OP_AND For EXT.L + // But would be more efficient to change ucode and use column 1 instead of col3 at ublock extr1! + unique case( col) + 2: aluOp = OP_EXT; + 3: aluOp = OP_AND; + 4: aluOp = OP_ROXR; + endcase + + row[9]: + unique case( col) + 2: aluOp = OP_SUBX; + 3: aluOp = OP_SBCD; + 4: aluOp = OP_ROL; + endcase + + row[10]: + unique case( col) + 2: aluOp = OP_SUBX; + 3: aluOp = OP_SUBC; + 4: aluOp = OP_ROR; + endcase + + row[11]: + unique case( col) + 2: aluOp = OP_SUB0; + 3: aluOp = OP_SUB0; + 4: aluOp = OP_ROXL; + endcase + + row[12]: aluOp = OP_ADDX; + row[13]: aluOp = OP_EOR; + row[14]: aluOp = (col == 4) ? OP_EOR : OP_OR; + row[15]: aluOp = (col == 3) ? OP_ADD : OP_OR; // OP_ADD used by DBcc + + endcase + endcase + end +endmodule + +// Decodes IRD into ALU row (1-15) +// Slow, but no need to optimize for speed since IRD is latched at least two CPU cycles before it is used +// We also register the result after combining with column from nanocode +// +// Many opcodes are not decoded because they either don't do any ALU op, +// or use only columns 1 and 5 that are the same for all rows. + +module rowDecoder( input [15:0] ird, + output logic [15:0] row, output noCcrEn, output logic isArX); + + + // Addr or data register direct + wire eaRdir = (ird[ 5:4] == 2'b00); + // Addr register direct + wire eaAdir = (ird[ 5:3] == 3'b001); + wire size11 = ird[7] & ird[6]; + + always_comb begin + case( ird[15:12]) + 'h4, + 'h9, + 'hd: + isArX = row[10] | row[12]; + default: + isArX = 1'b0; + endcase + end + + always_comb begin + unique case( ird[15:12]) + + 'h4: begin + if( ird[8]) + row = `ALU_ROW_06; // chk (or lea) + else case( ird[11:9]) + 'b000: row = `ALU_ROW_10; // negx + 'b001: row = `ALU_ROW_04; // clr + 'b010: row = `ALU_ROW_05; // neg + 'b011: row = `ALU_ROW_11; // not + 'b100: row = (ird[7]) ? `ALU_ROW_08 : `ALU_ROW_09; // nbcd/swap/ext(or pea) + 'b101: row = `ALU_ROW_15; // tst & tas + default: row = 0; + endcase + end + + 'h0: begin + if( ird[8]) // dynamic bit + row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13; + else case( ird[ 11:9]) + 'b000: row = `ALU_ROW_14; // ori + 'b001: row = `ALU_ROW_04; // andi + 'b010: row = `ALU_ROW_05; // subi + 'b011: row = `ALU_ROW_02; // addi + 'b100: row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13; // static bit + 'b101: row = `ALU_ROW_13; // eori + 'b110: row = `ALU_ROW_06; // cmpi + default: row = 0; + endcase + end + + // MOVE + // move.b originally also rows 5 & 15. Only because IRD bit 14 is not decoded. + // It's the same for move the operations performed by MOVE.B + + 'h1,'h2,'h3: row = `ALU_ROW_02; + + 'h5: + if( size11) + row = `ALU_ROW_15; // As originally and easier to decode + else + row = ird[8] ? `ALU_ROW_05 : `ALU_ROW_02; // addq/subq + 'h6: row = 0; //bcc/bra/bsr + 'h7: row = `ALU_ROW_02; // moveq + 'h8: + if( size11) // div + row = `ALU_ROW_01; + else if( ird[8] & eaRdir) // sbcd + row = `ALU_ROW_09; + else + row = `ALU_ROW_14; // or + 'h9: + if( ird[8] & ~size11 & eaRdir) + row = `ALU_ROW_10; // subx + else + row = `ALU_ROW_05; // sub/suba + 'hb: + if( ird[8] & ~size11 & ~eaAdir) + row = `ALU_ROW_13; // eor + else + row = `ALU_ROW_06; // cmp/cmpa/cmpm + 'hc: + if( size11) + row = `ALU_ROW_07; // mul + else if( ird[8] & eaRdir) // abcd + row = `ALU_ROW_03; + else + row = `ALU_ROW_04; // and + 'hd: + if( ird[8] & ~size11 & eaRdir) + row = `ALU_ROW_12; // addx + else + row = `ALU_ROW_02; // add/adda + 'he: + begin + reg [1:0] stype; + + if( size11) // memory shift/rotate + stype = ird[ 10:9]; + else // register shift/rotate + stype = ird[ 4:3]; + + case( {stype, ird[8]}) + 0: row = `ALU_ROW_02; // ASR + 1: row = `ALU_ROW_03; // ASL + 2: row = `ALU_ROW_05; // LSR + 3: row = `ALU_ROW_04; // LSL + 4: row = `ALU_ROW_08; // ROXR + 5: row = `ALU_ROW_11; // ROXL + 6: row = `ALU_ROW_10; // ROR + 7: row = `ALU_ROW_09; // ROL + endcase + end + + default: row = 0; + endcase + end + + // Decode opcodes that don't affect flags + // ADDA/SUBA ADDQ/SUBQ MOVEA + + assign noCcrEn = + // ADDA/SUBA + ( ird[15] & ~ird[13] & ird[12] & size11) | + // ADDQ/SUBQ to An + ( (ird[15:12] == 4'h5) & eaAdir) | + // MOVEA + ( (~ird[15] & ~ird[14] & ird[13]) & ird[8:6] == 3'b001); + +endmodule + +// Row/col CCR update table +module ccrTable( + input [2:0] col, input [15:0] row, input finish, + output logic [MASK_NBITS-1:0] ccrMask); + + localparam + KNZ00 = 5'b01111, // ok coz operators clear them + KKZKK = 5'b00100, + KNZKK = 5'b01100, + KNZ10 = 5'b01111, // Used by OP_EXT on divison overflow + KNZ0C = 5'b01111, // Used by DIV. V should be 0, but it is ok: + // DIVU: ends with quotient - 0, so V & C always clear. + // DIVS: ends with 1i (AND), again, V & C always clear. + + KNZVC = 5'b01111, + XNKVC = 5'b11011, // Used by BCD instructions. Don't modify Z at all at the binary operation. Only at the BCD correction cycle + + CUPDALL = 5'b11111, + CUNUSED = 5'bxxxxx; + + + logic [MASK_NBITS-1:0] ccrMask1; + + always_comb begin + unique case( col) + 1: ccrMask = ccrMask1; + + 2,3: + unique case( 1'b1) + row[1]: ccrMask = KNZ0C; // DIV, used as 3n in col3 + + row[3], // ABCD + row[9]: // SBCD/NBCD + ccrMask = (col == 2) ? XNKVC : CUPDALL; + + row[2], + row[5], + row[10], // SUBX/NEGX + row[12]: ccrMask = CUPDALL; // ADDX + + row[6], // CMP + row[7], // MUL + row[11]: ccrMask = KNZVC; // NOT + row[4], + row[8], // Not used in col 3 + row[13], + row[14]: ccrMask = KNZ00; + row[15]: ccrMask = 5'b0; // TAS/Scc, not used in col 3 + // default: ccrMask = CUNUSED; + endcase + + 4: + unique case( row) + // 1: DIV, only n (4n & 6n) + // 14: BCLR 4n + // 6,12,13,15 // not used + `ALU_ROW_02, + `ALU_ROW_03, // ASL (originally ANZVA) + `ALU_ROW_04, + `ALU_ROW_05: ccrMask = CUPDALL; // Shifts (originally ANZ0A) + + `ALU_ROW_07: ccrMask = KNZ00; // MUL (originally KNZ0A) + `ALU_ROW_09, + `ALU_ROW_10: ccrMask = KNZ00; // RO[lr] (originally KNZ0A) + `ALU_ROW_08, // ROXR (originally ANZ0A) + `ALU_ROW_11: ccrMask = CUPDALL; // ROXL (originally ANZ0A) + default: ccrMask = CUNUSED; + endcase + + 5: ccrMask = row[1] ? KNZ10 : 5'b0; + default: ccrMask = CUNUSED; + endcase + end + + // Column 1 (AND) + always_comb begin + if( finish) + ccrMask1 = row[7] ? KNZ00 : KNZKK; + else + ccrMask1 = row[13] | row[14] ? KKZKK : KNZ00; + end + +endmodule diff --git a/rtl/ipcores/fx68k/microrom.mem b/rtl/ipcores/fx68k/microrom.mem new file mode 100644 index 0000000..9fc7cb1 --- /dev/null +++ b/rtl/ipcores/fx68k/microrom.mem @@ -0,0 +1,1024 @@ +10010000101100000 +10000100000000000 +00101001011010000 +00111110011000000 +01000000000001100 +01000000000001100 +01000010010000000 +10001100011100000 +01000100010000000 +10000000010000000 +10000000010000000 +01000100010000000 +00001010010000000 +10000000100000000 +10000000100000000 +01101001100000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000100 +00001010110000000 +00111000001100000 +00100101001001010 +00000000000001100 +10110000110100001 +00000000000001100 +00001110100000000 +00110100101000000 +00100011010100000 +00000010010000000 +10000110000000010 +00111110110000000 +00000100011100000 +00101111010100000 +10010011100000010 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10011101000000000 +00000100110010110 +00101001010000000 +10110000110100001 +00000000000000100 +00111110000100000 +10010111010100000 +01000110000100000 +01010111100000000 +10001010010011010 +01000110010100001 +00000110010111010 +01001100010100000 +10001010010010111 +01000000000100001 +00110100111000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000010001100000 +01001010000100001 +10110100111000000 +00011011010100000 +10000000000000100 +10110100111000000 +00000000000000100 +00001000001000000 +00000100011100110 +10001110010100001 +00000000011110010 +01001000011000000 +00001000010100110 +10001010000110111 +00000000111110010 +01001000111000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10101001000000001 +10001000001000001 +01000000000000100 +01001100001111010 +00000110001000000 +00010110001100000 +00011010000000000 +10110000110100001 +01111000001100000 +00011000000000000 +00000100100100001 +00000000000000100 +00000000101100000 +00000000000000100 +00010001010100000 +10010111000100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000010001100000 +00000000000000100 +01111000011100000 +00011011010100000 +00101101000000000 +01000110010111010 +00101101000000000 +10001010101100000 +01010110001100000 +00011000110000000 +01010110001100000 +10001110011100001 +00000100101100000 +01000110010111010 +00000100101100000 +10001010111100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10101001000000001 +00001000101010110 +00011111010100000 +01101101110000000 +00000000000000100 +10111110000100000 +00000100011100000 +10001100101000001 +00000110001000000 +00001110000010010 +00100101000010110 +00101101000100000 +00000000011100000 +00001000111100000 +00100101000011010 +00110100111000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000010000100010 +00001010110000000 +00000000000000100 +00101101010000000 +01010001010000000 +01000110111000000 +00000000000000100 +00000000010110010 +00110100101000000 +00100011010100000 +10000000000001000 +01101011010000000 +00111110110000000 +00000100011100000 +10010101000000000 +01111110010100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10001100101000001 +10000010100000010 +01000010101000000 +00011111100100000 +10100111100000001 +10010010110000010 +01110100111000000 +00010111010000000 +10101011100000001 +10010010100000010 +01110000100100000 +00000000100100000 +10100101100100001 +10000010110000010 +01001010101000000 +00010111000000000 +00010001000010110 +01110010100111010 +10110100010000000 +00110100111000000 +01000010010000110 +01110010110111011 +01111100000000000 +00101101000100000 +00101001001010001 +01011011111100000 +01101111011000000 +00100011100000000 +00111110000110000 +00000000000000000 +10101111011000000 +00000000000000000 +00001010100000000 +10101011100100001 +01010011000100001 +10010101010000000 +00000000110000000 +10111010000100001 +01011001010000000 +10010101000000000 +00101101101100000 +10100011100100001 +01011110100000000 +01110100011100000 +00101011111000000 +10110000110100001 +01010101010100001 +00000000000000000 +00111000100000000 +01011011000000000 +00001000100100000 +10001100101000001 +00100001100000000 +01011011010000000 +00001000110100000 +10011001110100001 +00000110010111010 +01011011100000000 +00000000110100000 +10011101010000001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10110000110100001 +00011101000100000 +00011101000100000 +00010001000101110 +01011010110000000 +01011001010100000 +10011101010100000 +00000000000000100 +10110000110100001 +00110110000000000 +10110000011100001 +10110000011100001 +10011101000000001 +01110100111000000 +00101101100100000 +10011000100000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10000000000000100 +00000000000000100 +00000100111000000 +00000100111000000 +00000100111000000 +00001100010101010 +00001000000010110 +00101001010000000 +10011000100000000 +00011011100100000 +01000100010000000 +01000000000001100 +10011000010000001 +10011011110100000 +10011111110100001 +00011000010000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00111110001000000 +10101011100100001 +10001010100000000 +10101011100100001 +00100011010000000 +10110000001100001 +10000000110000000 +10110000101100001 +00000000000000000 +10110000101100001 +10110110110100000 +10100001110100001 +00111100010000000 +10011101100000001 +10111110100100000 +10010011010100001 +00111100010100000 +10101011100000001 +10101001101000000 +10101011100000001 +00000000000000000 +10011111000100001 +10101001111000000 +10011011000100001 +00000000000000000 +10010011010100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00001010100000000 +10111110000100000 +10000100100000000 +00111010001100000 +00000000110000000 +10011001000000000 +10000100110000000 +00111010011100000 +00101101101100000 +10001110111000000 +10101111101000000 +00010100100000000 +00101011111000000 +10110100001100000 +10101111111000000 +00010100010000000 +00111000100000000 +10110100101100000 +10101001010100000 +00101011001000000 +00100001100000000 +10001110010000000 +10101111001000000 +00101011011000000 +00000110010111010 +10111000110000000 +10011101110100000 +00111010101100000 +00000000000000000 +10101011011100000 +01100011110100001 +00111010111100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00100101000000000 +00000100000010110 +00000000000000100 +00001110000001110 +00100001000000000 +10110000110100001 +00100101011001010 +00111000001100000 +00100101100000001 +10011000010000000 +01101101100000000 +00000000000001100 +01100101110000000 +00000000000001100 +00001100001111010 +01001100001111010 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10101111000000001 +00000100111000000 +10101111000000001 +00000000000000100 +00100111010000000 +00001110101100000 +11010001100000000 +00110010100111010 +00000000000000100 +00000100111000000 +00000000000000100 +10110000110100001 +01100111110000001 +10000000000000100 +01111100100100000 +01100001100100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000001100000 +10001010010100001 +00110110100000110 +00000000000000100 +00100001000000000 +10111110000100000 +10100111000100000 +00111000010000000 +10000000000000100 +00101001100100000 +00101101100100000 +00000000000000100 +00100101110100000 +00000000000000100 +00100101110100000 +00100101110100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10100111000100000 +01101011000100000 +01111110000100001 +10100111000100000 +10100111001000000 +10111110000100000 +00101111010000000 +00110010100111010 +00000000000000100 +10100011100100001 +00000000000000100 +00000010011100001 +10100111110100000 +00000000000000100 +00101111110100000 +00101111101100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00100101001000000 +00101001000010110 +00110010000100000 +00100011000100000 +00100101011000000 +00101001011100000 +00101011110110000 +00101111001000000 +00010100000000000 +10110100111000001 +01110010100100000 +10110000110100001 +00010100110000000 +10110100110100001 +01111000110100000 +10111110110100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00100011010100000 +00100111000100000 +00000110100000010 +10111110000100000 +00000100011100000 +00110000110000000 +00000110110000010 +10010001110000000 +10110100111000001 +10000000000001000 +01110000100100000 +10110100101000000 +10010101110100001 +10111110000100000 +01101101111100000 +10101011101000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00101001000010110 +10001010011100001 +00100001000000110 +00101101000000110 +00101001011100000 +10001010011100001 +00110110111000110 +00101101010000110 +10001100101000001 +10110100101000000 +10101101101100000 +01111110000100001 +10100101100100001 +10101011101000000 +10101011111000000 +01100001100100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00110010100111010 +10001010010100001 +10110100100000000 +10110100111000001 +01110010110111010 +10001010010100001 +10101011010100000 +10110100110100001 +10111100100100001 +01101111110000000 +01000110010000001 +10101111111100000 +10101011110000001 +01100011110000000 +01110100100100001 +10110000000000000 +10011001110000000 +00110110000000000 +00101111001000000 +10111110000100000 +00110100111000000 +10001100100100000 +00000000000000100 +00110010000000000 +00000100010100110 +00111110000100000 +00111110000100000 +10100111011000000 +01110100110000001 +01110100100100000 +10010101000000000 +10110110100000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00110110000000000 +00010110001100000 +00000110010111010 +00000110010111010 +00110100111000000 +10111010010000000 +00001110110000000 +00000000000000100 +10110000110100001 +01111010100000000 +01010110001100001 +10111010110000000 +10110000110100000 +00100001010001010 +01010110001100001 +01110000100100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000100111000000 +10111000000100001 +00000000000000100 +00110000010100000 +01111110000100000 +10111000010100001 +00000000000000100 +00111000001100000 +01111110000100000 +10000000000000100 +01111100100100000 +01000000000000100 +00000000000000100 +01110100111000000 +01111100110100000 +01110010100100000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +01001110111100000 +00000000000000100 +00000000000000100 +10110000110100001 +00000000000000000 +00000000000000000 +00000000000000000 +01011001100000000 +01111010100100001 +00000000001001010 +10000000000000100 +01110010110100000 +01110110110100000 +01111010110100001 +01111110000100000 +00000000000000100 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10001100110100111 +10111100001000001 +10111100001000001 +00101101000000110 +10001100101100111 +10111100011000001 +10111100011000001 +00101101010000110 +10110100101000000 +01111110000100000 +10110100101000000 +10111100100100001 +10111110110000000 +01000000000000100 +10111110110000000 +10111000100100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10111110000000000 +10110010010000001 +00111110010000001 +00111000001100000 +10101001110000000 +10110000000100001 +00101111100100000 +00111000101110000 +00110010100111010 +01111010101000000 +01000110010000001 +01000110010000000 +01110010110111010 +01111010111000000 +01110100100100001 +01110100100100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00101001110100000 +10001100100100000 +01110010000100000 +10110000110100001 +00000010000011110 +01111000000000000 +01000000101000000 +10110000010000001 +00101101110100000 +10111010000000000 +01001010001000000 +10110110000100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +10100111101000000 +00000000000000000 +10010010000000010 +10100111000000001 +10100111111000000 +00000000000000000 +10010010010000010 +10001110011100001 +00100011001100000 +00100001001001010 +10010011000000010 +10001010110100001 +01100011011100000 +00100001011001010 +10010011010000010 +10001010100100001 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 diff --git a/rtl/ipcores/fx68k/nanorom.mem b/rtl/ipcores/fx68k/nanorom.mem new file mode 100644 index 0000000..be86896 --- /dev/null +++ b/rtl/ipcores/fx68k/nanorom.mem @@ -0,0 +1,336 @@ +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000000000001000000110011100000000000000101001000001 +00100001000000011000010001001000000110100000000001000000011001001001 +00000001100000000010100000001000000110000000001001000000001001001001 +00100000000000011000010001000000000101000000000010000000100001010000 +11000001000000000000000000001000000100010000000001000000000001010001 +00100001000000011000010000000000000000000000000101000000000000010000 +01000001011000000000100000000110010001000000001100000000110100011000 +01000001011000000000100000000110010001000000001100000001100100011000 +00100001000000011000010000000000000100000000000001000000000001010000 +10100100001000011000001000010000101001110000000001000100110010100001 +01000000000000000000000010000000010100000000001000110001000000000000 +00100001000000011000000000110010100100011111010001100000000001000000 +00100010000000011000000000000000100010000100000000010100000100000011 +00000001011000000000000001000110000000000000000010000000000100000000 +00000000000000000000000000001000000100000000000001000000000001010001 +00000001100000000010100000001000000110000000001001010000001001001001 +00101000000000001000010000000000000000000000000010000000000000000000 +01100010000000011000010010000000010100000000001000110001000000000000 +00000000000000000000000010010010100000000000000100110010000000000000 +00100000000000011000010001001000000110000000001001010000001001001001 +00000000000000000000001000000000100100000000000000110010000001011000 +00010010000000000100100000001000000100000000000010000000000001010001 +00100010000000011100000000000000000001100000000010001000100000000000 +00010010000000000100000000000000010001100000000010000000000000000000 +00000000000000000000000000011001100110100000010001000000011011010001 +10100010110000000000000000000000100000010000010010000100000100000000 +10000000000000000000000000001000000100010000000001000000000001000001 +00100000000000011001000000011010000110000000001001000000001001001001 +00010011000000000000101000010000001001000000010101000000100000110000 +00000001000000000001010000000000000000000000000101100000000000010000 +00100010000000011000001000001000100110000000000001000000000001010001 +00000001000000000010100001010000001001000000010110000000100000110000 +01000001000000000000000000000000000001101010001100000000110000000000 +00110100000000000100000100000000000000000000000010000000000000000000 +00000000000100100000100000000000010000000000000000000001000000011000 +01110101000000000100100000100010000001100000000000000000110100001010 +00100010000000011010000100000000100010000100000000010100000100000011 +11000001000000000000000000001000000100010000000001000000000001010001 +01010011000000000100100000100010000001100000000000000000110100001010 +11000001000000000000000000001001100110110000000001000000011011000001 +01001001110000000000001000001000001000000000000101000000000000100001 +00000000000000000000100000100010010000000000000000110001000100000010 +00010000110000000001010000000000000000011100000010000000000000011000 +01010001110000000001000000011010100100000000000001000000000001000001 +00000000000000000000000001000000000100000000001100010000000001010000 +00001000000000011001001000001000000110100000000001000100000011010001 +01010001110000000001010000001000001000000000000101000000000000110001 +10100010110100100100000001000000000001110000000010000000110000010000 +00000000000100000000000000000010100001001010000101100000100000010000 +00010000110000000001000000000000100000000000010010000100000100000000 +10000000000000000000000000001000000100010000000001000000000001000001 +00000001000000000000000001000000001001000000000101000000100000100000 +00010010000000000000100000001010101000000000000101000000000000110001 +10100000000100111000000000100001100010111010000101100000011010010010 +00100000000000011000000000110010100110000000010000100000001101000010 +00010010000000001100000000000000000000000000000010000000000000000000 +11000001000000000000001000011101100100010000000001000000000001000001 +00010100000000000100000100000000000000000000000010000000000000000000 +10100010110000000100001000000000100000010000010010000100000010000000 +00100000000100111000000000000000100000010010000101000100000100010010 +00100010000000011000000000000000100010000100000000010100000100000011 +00100010100000011001010000010000100100000000001110000100001000000000 +00000000000100000000000000000010100000001010000101000000000000010000 +00100010100000011001000000010010100100000000001110000100001000000000 +00000001000000000000010000000000100000000000010101000100000010010000 +00000000000100100000000000100010000000000100000000110001000100011010 +00100000000000011000000000010000100110000000011000100000001001000000 +00000000000100100000100000100010010000000000000000110001000100011010 +00000000011000000000000000000110000000000000001110000000110100111000 +00011000000000011001001000001000000100000000000001000000000001010001 +00100010000000011100000000000000000001100000000010001000100000000000 +00110000100000001000000100000000100000000000000010000100000100000000 +00000000000100000000000000000010100001000000000101100000100000010000 +10100010110000000100001000010001100000010000000010000000000000000000 +01000001000000000000000000000000000000000000000101000000000000010000 +10000000000000000000000000001000000100010000000001000000000001000001 +00000000000000000000000000001000001000000000000101000000000000110001 +00001000110000000000001000000000000000000000000010000000000000000000 +00010010000000001100000000000000000000000000000010000000000000000000 +00010000000000001010000100000000110001000000000010000100011000000000 +01010001000000011000001000000000000001100000000000000000110000000000 +00001100000000011000001000100001000010100000000101110000000000000011 +01000000000000000000000010000000010100000000001000110000000001000000 +11000001000000000000000000001000001000010000000101000000000000100001 +00000000000000000000000000001000000100011100000001100000000001000001 +00000000000000000000000000000000000000000000000101100000000000000000 +00000000000100000000000000000000100000000000000101000100000100010000 +11101011000000000000000000000000000000010000000010000000000000000000 +01100001000000011001000000011010100100000000000001000000000001000001 +01100010000000011000010010000000010100000000001000110000000001000000 +00000000000000000000000010010010100000000000010100110000000100000000 +01000001000000000000010000011001101000000000000101000100001000110001 +00100000000100111100000000000000000010000010000100100010001000010000 +00010010000000000000000000000010110100000000001110000000000000011000 +00000000000000000000001000010000100100000000011100110010000001011000 +00000000000100000000000000010000111000000000010101000100011000110000 +00000000011000000010100000000110000100000000001101110000000101000000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000001000000000000000000000000010101001010001101000000100001010000 +00000001000000000000010000000000100000000000000101000100001000010000 +01110101000000010000001000000000000001100000000000000000110000000000 +01000001000000000000000010000000010100001010001000110001000000000000 +00100010000000011000000000011010101010000000010101000000001100110001 +00100001000000011000010001010000000100000000010000010000000001010000 +01000001000000000000010000000000100000000110000101000000000000010000 +01000001000000000000000010000000010100001010001000110001000000000000 +00100000000000011000010001010001000000000000011010000000000010001000 +00000001000000000000000001010000000100000000010001110000000001000000 +00010010000000001000000000011010101000000000000101000000000000110001 +00000000000000000000000000001000001000000000000101000000000000110001 +00010010000000000001100000000010000000000000000101100000000000000000 +00010010000000000001000000000010000100000000000101100000000000000000 +00100010000000011100000000001000001000000000000101000000000000100001 +00000001000000000001010000000000001010100000000110000000011000101000 +00000001100000000000100000000000000000000000000101000000000000010000 +00010010000000000000101000001001000100000000001001000000000011010001 +11110101001000000100000000000000000000010000000010000000000000000000 +00000000000000000000010000001001101000000000000101000010000010110001 +00000000000000000000010000000000100000000110000101100000000000000000 +00100010100000001001100000000010000010000100001000000000001000001000 +00100010100000001001000000000010000110000100001000000000001000001000 +00010010000000001000010000000000000000000000001110000000000000011000 +00110100000100101100000000000000000001100000000001100000110000010000 +01110101000000001000000100000000111000000000010010000100000100000000 +01000000000000000000010000010000100110000000011100100000000001011000 +11010011000000000000101000001001000100010000001001000000000011010001 +11110101001000000000000000000000100000010000000010000100000100000000 +01110101000000000100000000000000010000000000010010001000000001000000 +01110101000000000000000000000000110000000000010010001100000101000000 +01110101000000000000000000000000110000000000010010001100011001000000 +01110000000000011100000000000000000001100000001101000000110000000000 +00010000000000001000000000000010100000000000000010000000000000000000 +00010010000000000100000100000000010001000000000010000000000000000000 +01000000000000000000010000010000100110000000011100100010001001011000 +00100000000000011000010000000000000100000000000000100000000001000000 +00000001000000000000000000000000001000000000000101000000000000110000 +00100001000000011100000001011001000110000000011000000000001011001001 +01100001000000011000000000010010100110000000011100100000001101011000 +01100001000000011000010000010010000010000000010101000000001100010000 +00000000000000000000000100000000010010100000001100110001011000011000 +01100001000000011000000000010000100110000000011000100000001001000000 +00000000000000000000000000001000000100011100000001100000000001000001 +00010010000000000000000000010010110110000000001110000010001000011000 +01000001000000000000100000010010010000000000010000110001000100011000 +00010010000000000000010000010000110110000000001110000010001000011000 +01000001000000000000000010000000010100001010001000110000000001000000 +01000001000000000000010000001000101000000110000101000000000000110001 +00000001000000000000010000000000100000000000000101000100001000010000 +00101000000000001000010000000000000000000000000010000000000000000000 +00100010000000011000000000000000100000000000000010000100011000000000 +00100010001000011010000000000000100000000000000010000100000100000000 +11010011001000000100000000010000011000010000000010000000000000000000 +00010010000000000100000000000000010000000000010010001000000001000000 +00001000000000011000001000000000000000000000000101110000000000000011 +00100010110000000000010000001000001000000000000101000000000000110001 +00100010000000011000000000000000100010100000000010000000000000000000 +00100000000000011000000000110001100100011111011001100000000011000010 +00100000000000011000000000001000100110000000001001010000001001000001 +01000001000000000000000000010000000100000000011100100000000001011000 +00000000100000000010100000000000000001000000000101000000100000010000 +00000001000000000000000000011001000100000000011001000000000011000001 +00000000011000000010100001000110000101000000000000010000100101010000 +00100001000000011100000001011001000100000000011001000000000011000001 +01000000000000000000000000000000000101001010001101100000100001000000 +00000000000100000000000000000000100001001010000101100100100100010000 +00000000011000000000000000000010110110000000001100000000001101011000 +01000001000000000000000000000001111001100000001010000000110010100000 +00110010000000011000000000010010100010000000001110000010001000011000 +11000001000000000000000000011001100110110000010001000000011011000001 +00100000000000011010000000100001110000001100001010000000000010000010 +00000000000000000000000000010000000100010101010001100000000001000000 +01000000000000000000000000000000000010100000000010000000011000001000 +00000001000000000000000000000000000001101010001101000000110000010000 +10000000000000000000001000001101100100010000000001000000000001000001 +01110101000000000000000000000000110000000000000010001100000101000000 +11000001000000000000000000001000000100010000000001000000000001000001 +00100010000000011000000000001001101000000010000101000010000010110001 +00100010000100011000000000010010100000000000000101000000000000010000 +11100101000000011100000000001001000100010000001001000000000011010001 +00100100000100111000000000000000100000000000010101100100000100010000 +00100010000100011000000000011010100100000000000000000000000001011001 +00100000000000001000001000000000100000000000000010000100000010000000 +00100010000000011100001000001000100100000000000001000100001001010001 +00010010000000000100000100000000010001000000000010000000000000000000 +10000000000000000000001000011101000100010000000001000000000001000001 +00011000000000011000001000000000100010000000000010000000000000000000 +01000000000000000000000000000000000100000000000001000000000001010000 +01000000000000000000010000010000100110000000011100100000011001001000 +00000000001000000010001000010001010000000000000010001000000000100000 +11100101000000011100000000001000001000010000000101000000000000110001 +01000001000000000000001000010001100000000000000010000000000000000000 +00110100000000000000000000000000110000000000000010001100000101000000 +10000000000000000000001000001000100100010000010001000100000011000001 +01110101000000000100001000000001110000000000010010001000000001000000 +10000000000000000000001000001000100100010000000001000100000011000001 +00110100000000000000000000000000110000000000010010001100000101000000 +00110100000000000000000000000000110000000000010010001100011001000000 +01000000000000000000000000010000000110100000011100100000011001001000 +00000000000100000000000000010000111000000000010101000100000100110010 +00000000000100000000000000100010100001100000000001000000110000011000 +01000000000000000000000000010010000110000000010000100000001101001000 +00000000000000000000000000001000000110000000001001000000001001001001 +01000000000000000000010000000001100000000000000101000010000010010000 +01000000000000000000000000001000000110000000001001010000001001000001 +00000001000000000000000000000000000001101010001101000000110000000000 +11100101000000011000000000010000111001110000010010000100110100100000 +00000000000000000000000000011010101010000000000101000010001000110001 +11000001000000000000001000001101100100010000000001000000000001000001 +00000000000000000000000100000000010000000000000001100001000000000000 +00000000000000000000000000001001100100000000001001000000000011010001 +11000001000000000000010000010001100000010000010010000000011010000000 +00000000000000000000000000000000000000010110000010000000000000000000 +00000000000000000000000000000000000000001100000000000001000000000000 +00100010000000011000000000000000100010100000000010000000000000000000 +00001000000000011000001000000000000000000000000101110000000000000011 +10000000000000000000000000000000000000010000000010000000000000000000 +00000000000000000000010000000000100010000000000010000010001000000000 +00101000000000001000001000000000000000000000000010000000000000000000 +01010011000000000000100000000010100001100000001100000000110000011000 +00000001000010000000000001000000000000000000000101000000000000010000 +00100010000000011000010000001101101000000000000101000000000000110001 +00000000000000000000100000010010010000000000010000110001000100000000 +01000000000000000000000000010000000100000000011100100000000001000000 +00000000000000000000000100010010010000000000010000110001000100000000 +01000000000000000000100000000000010000000000000001000000110000010000 +01010011000000001000010000000000000001100000001100000000110000011000 +01000001000000000000010000001001101000000000000101000000000000110001 +00100100000100011001000000000000100000000000010101000100000100010000 +01100010000000011000100000010010110010000000001100000000110000011000 +00011000000000011000001000000000000000000000000101110000000000000011 +00000000000000000000000000001000000100000000000001000000000001010001 +00010010000000000100000100000000010001000000000010000000000000000000 +00001010000000011000001000000000000000000000000101110000000000000011 +00010010000000000000000000000001110100000010001110000010000010011000 +01100010000000011000100000010010110010000000001100000001000000011000 +01000000000000000000100000000010010000000000001100110001000100011000 +00100010000100011000000001011010100100000000000001000000000001011001 +00000001000000000000010000000001100001001010000101000000100000010000 +00000000000000000000010000000000100101000110001110000000100001011000 +00000000000000000000100000010010010000000000010000110001000100011000 +01010011000000000000100000000001100001100010001100000010110010011000 +01100011000000011000000000010010100100000000011101110000000001011000 +00000000000100000001000000010000100100000000011101000100000101010000 +00100010000100011000000001010010100100000000011100010000000001010000 +00000001000000000000010000000000100000000001000101000100000010010000 +00000001000000000000010000000001100000001111000101000000000000010000 +00000000000000000000000000010010100000000110010101100000000100000000 +00000111000000000000010000010000111000001000010110000100001000100000 +01000000000000000000100000000001110000000000001001000000110010010000 +01001011000000011000001000000000000001100000000000000000110000000000 +00000000000000000000010000000000100010000000000101000000000000010000 +10100100000000011100000000001000000100010000000001000000000001000001 +00010000000000000000000000010000100100000010000010000000000000000000 +00000000000000000000000000001000000100000010000000110010000001000001 +01000000000000000000000000001001100100000000001001010000000011000001 +00000000000000000000000000001001100100000000001001010000000011000001 +00100000000000011000000000010010100010000000010101000000001100010000 +00000000000100000000000000000000101000000000000101000100011000110000 +00000000000100100000100000010010010000000000010000110001000100011000 +01000000000000000000010000010001100000000000010101000010000010010000 +00100001000000011100010100000000110010000000001110001000100000011000 +00000000000000000000001000000000100000000110000101000000000000000000 +00000110000000000000000000000000000000001000000010000000000000000000 +01000000000000000000010000000000100100001010001100110010000001000000 +01000000000000000000000000000000000100001010001100000000000001000000 +01100001000000011000000000000000100001100010000000000000110000000000 +01000001000000000000010000000000100000000110000101010000000000010000 +00101000000000001000010000001000101010000000000101100000000000100001 +10000110000000000000000000001000001000001000000101100000000000100001 +00000000000000000000000000001000000100000000000001000000000001010001 +00100010000100111000100000000000110010100000000001000000110000010000 +00100100000100111100000000001000000100000000000001000000000001011001 +00100011000000011000010100000000010000000000001110001000100000011000 +00000000000000000000000000011001100110100000010001000000011011010001 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000100100000010001001000100100000000000001000000011001001001 +00100100001000111100001000000000100010000000000101000000000000010000 +01000001000000000000000000010001100000000010000010000000000000000000 +00100010000000011010000000000000110100000000011110001100100100011000 +11100101000000011100000100000000001000010000010101000000011010000000 +00010000000000000000100000000000100001100010001100000000110000000000 +00100010000100111000010001001000000100000000000000000000000001011001 +00010000000000000010000000000000100100000010001110000000000000011000 +11100011000000011100001000010101100000010000000101000000000000000000 +00100000000000011000000000110010100100011111010001100000000001000000 +10000000000100000000000000001000100110110000000001000000000001011001 +11000001000000000000000000001001000100010000001001000000000011010001 +00100100000100111100000000000000000000000000000101100000000000010000 +10000000000100100000000001001001000100010000001001000000000011001001 +11000001000000000000000000000000000000010000000010000000000000000000 +00110100001100100000000000000000100000000000000101100100000100010000 +00000001000001000000000001000000000000000000000101000000000000010000 +00000001000010000000010001000000100000000000000101000100000010010000 +00100000000100111000000000010000101000010111010101000100000100110010 +11100101000000011100000000000000000000010000000010000000000000000000 +11100101000000011000000000000000100000010000010010000100000100000000 +00000000000000000000000000001000001000000000000101000000000000110001 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000001000000000000000000001000001001100000000001000000110000110001 +00000001000001000000000001001000000100000000000001010000000001011001 +00100000000000001000001000000000100000000000000010000100000010000000 +11000001000000000000010000001001001000010000000101000000000000110001 +00000000000110000000000001000000100000000000000101000100000100010000 +00000000000101000000000001000000100000000000000101000100000100010000 +00000000000010100000000001010000000100000000000101000000000000010000 +00000000000101000000000001001010000100000000000001010000000001011001 +11100101001000011100000000000000010000010000010010001000000000100000 +00100000000000001000000000001000001000000000000110000000000000110001 +00100000000000011000000000000000100000000100011100000101000100011000 +00100000000000011000000000010000110100000000011100000101000100011000 +01100011100000011000000100010010000000000000000101110000000000000011 +01100010000000011000010100000000010000000000001100000001000000011000 +10000000000100100000000001001000000100010000000001000000000001011001 +01100010000000011000010100000010010000000000001100110001000100011000 +01100011000000011000010000010000000100000000011101110000000001011000 +00000000000000000000010000000000100000000110000101000000000000010000 +00000000000000000000000000000000000000011100001110000000000000011000 +10100000000000001000010000001000101000000110000101000000000000100001 +00100000000000011000000000110001100100001111011001100000000011000010 +00000001000000000000010000000001100001001010000101000010100010010000 +00100010001000111000010000010000000100000000011101000000000001010000 +00100100000100111100000000000000000000000000000101000000000000010000 +00100010000100011000010001010000000100000000011100010000000001010000 +01000001000000000000000100010000011000000000000010000000000000000000 +00000000000000000000010000000000100010000000000101000010001000010000 +00100000000100111000000000000000100000000010000100100000000000010000 +00100010000000011000010000001000001000000000000101000000000000110001 +00000001000000000000010000000000100000000000000101000100000010010000 +00000000000000000000000000000000000000000000000010000000000000000000 +00000000000000000000001000000000100100000000000000110010000001011000 +00000000011000000000000000000010110110000000001100000000001101011000 diff --git a/rtl/ipcores/fx68k/uaddrPla.sv b/rtl/ipcores/fx68k/uaddrPla.sv new file mode 100644 index 0000000..40544c6 --- /dev/null +++ b/rtl/ipcores/fx68k/uaddrPla.sv @@ -0,0 +1,2192 @@ +// +// FX68K +// +// Opcode to uaddr entry routines (A2-A2-A3) PLA +// + +`timescale 1 ns / 1 ns + +`define NMA_BITS 10 + +`define SFTM1 'h3C7 +`define SRRW1 'h382 +`define SRIW1 'h381 +`define SRRL1 'h386 +`define SRIL1 'h385 +`define BSRI1 'h089 +`define BSRW1 'h0A9 +`define BBCI1 'h308 +`define BBCW1 'h068 +`define RLQL1 'h23B +`define ADRW1 'h006 +`define PINW1 'h21C +`define PDCW1 'h103 +`define ADSW1 'h1C2 +`define AIXW0 'h1E3 +`define ABWW1 'h00A +`define ABLW1 'h1E2 +`define TRAP1 'h1D0 +`define LINK1 'h30B +`define UNLK1 'h119 +`define LUSP1 'h2F5 +`define SUSP1 'h230 +`define TRPV1 'h06D +`define RSET1 'h3A6 +`define B 'h363 +`define STOP1 'h3A2 +`define RTR1 'h12A +`define RTS1 'h126 + + +module pla_lined( + input [3:0] movEa, + input [3:0] col, + + input [15:0] opcode, + input [15:0] lineBmap, + + output palIll, + output logic [`NMA_BITS-1:0] plaA1, + output logic [`NMA_BITS-1:0] plaA2, + output logic [`NMA_BITS-1:0] plaA3 + ); + + wire [3:0] line = opcode[ 15:12]; + wire [2:0] row86 = opcode[8:6]; + + logic [15:0] arIll; + logic [`NMA_BITS-1:0] arA1[ 15:0]; + logic [`NMA_BITS-1:0] arA23[ 15:0]; + logic [`NMA_BITS-1:0] scA3; + + logic illMisc; + logic [`NMA_BITS-1:0] a1Misc; + + /* + reg [`NMA_BITS-1:0] lineMask[ 15:0]; + always_comb begin + integer i; + for( i = 0; i < 16; i = i + 1) + lineMask[i] = { 16{lineBmap[ i]}}; + end + */ + + assign palIll = (| (arIll & lineBmap)); + + // Only line 0 has 3 subs + assign plaA1 = arA1[ line]; + assign plaA2 = arA23[ line]; + assign plaA3 = lineBmap[0] ? scA3 : arA23[ line]; + + + // Simple lines + always_comb begin + // Line 6: Branch + arIll[ 'h6] = 1'b0; + arA23[ 'h6] = 'X; + if( opcode[ 11:8] == 4'h1) + arA1[ 'h6] = (| opcode[7:0]) ? `BSRI1 : `BSRW1; + else + arA1[ 'h6] = (| opcode[7:0]) ? `BBCI1 : `BBCW1; + + // Line 7: moveq + arIll[ 'h7] = opcode[ 8]; + arA23[ 'h7] = 'X; + arA1[ 'h7] = `RLQL1; + + // Line A & F + arIll[ 'ha] = 1'b1; arIll[ 'hf] = 1'b1; + arA1[ 'ha] = 'X; arA1[ 'hf] = 'X; + arA23[ 'ha] = 'X; arA23[ 'hf] = 'X; + + end + + // Special lines + + // Line e: shifts + always_comb begin + if( ~opcode[11] & opcode[7] & opcode[6]) + begin + arA23[ 'he] = `SFTM1; + unique case( col) + 2: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ADRW1; end + 3: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `PINW1; end + 4: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `PDCW1; end + 5: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ADSW1; end + 6: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `AIXW0; end + 7: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ABWW1; end + 8: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ABLW1; end + default: begin arIll[ 'he] = 1'b1; arA1[ 'he] = 'X; end + endcase + end + else + begin + arA23[ 'he] = 'X; + unique case( opcode[ 7:6]) + 2'b00, + 2'b01: begin + arIll[ 'he] = 1'b0; + arA1[ 'he] = opcode[ 5] ? `SRRW1 : `SRIW1; + end + 2'b10: begin + arIll[ 'he] = 1'b0; + arA1[ 'he] = opcode[ 5] ? `SRRL1 : `SRIL1; + end + 2'b11: begin arIll[ 'he] = 1'b1; arA1[ 'he] = 'X; end + endcase + end + end + + // Misc. line 4 row + always_comb begin + illMisc = 1'b0; + case( opcode[ 5:3]) + 3'b000, + 3'b001: a1Misc = `TRAP1; + 3'b010: a1Misc = `LINK1; + 3'b011: a1Misc = `UNLK1; + 3'b100: a1Misc = `LUSP1; + 3'b101: a1Misc = `SUSP1; + + 3'b110: + case( opcode[ 2:0]) + 3'b110: a1Misc = `TRPV1; + 3'b000: a1Misc = `RSET1; + 3'b001: a1Misc = `B; + 3'b010: a1Misc = `STOP1; + 3'b011: a1Misc = `RTR1; + 3'b111: a1Misc = `RTR1; + 3'b101: a1Misc = `RTS1; + default: begin illMisc = 1'b1; a1Misc = 'X; end + endcase + + default: begin illMisc = 1'b1; a1Misc = 'X; end + endcase + end + +// +// Past here +// + + +// +// Line: 0 +// +always_comb begin + +if( (opcode[11:6] & 'h1F) == 'h8) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h0) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h1F) == 'h9) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h1) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h1F) == 'hA) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h2) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h10) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h11) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h37) == 'h12) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h4) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E7; arA23[ 'h0] = 'X; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1D2; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h215; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h215; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h215; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h215; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h215; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h215; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h215; end + 9: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h215; end + 10: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h215; end + 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h0EA; arA23[ 'h0] = 'h0AB; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h5) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EF; arA23[ 'h0] = 'X; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1D6; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h081; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h081; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h081; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h081; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h081; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h081; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h081; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h7) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EF; arA23[ 'h0] = 'X; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1CE; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h081; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h081; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h081; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h081; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h081; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h081; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h081; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h6) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EB; arA23[ 'h0] = 'X; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1CA; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h069; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h069; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h069; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h069; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h069; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h069; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h069; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h20) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3E7; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h215; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h215; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h215; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h215; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h215; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h215; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h215; end + 9: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h215; end + 10: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h215; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h21) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EF; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h081; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h081; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h081; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h081; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h081; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h081; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h081; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h23) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EF; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h081; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h081; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h081; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h081; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h081; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h081; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h081; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h22) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EB; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h069; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h069; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h069; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h069; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h069; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h069; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h069; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h30) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h108; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h087; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h087; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h087; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h087; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h087; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h087; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h087; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h31) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h108; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h087; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h087; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h087; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h087; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h087; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h087; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h087; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else if( opcode[11:6] == 'h32) begin + unique case ( col) + 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h104; scA3 = 'X; end + 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h08F; end + 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h08F; end + 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h08F; end + 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h08F; end + 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h08F; end + 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h08F; end + 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h08F; end + 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + endcase +end + +else begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end + +end + + +// +// Line: 4 +// +always_comb begin + +if( (opcode[11:6] & 'h27) == 'h0) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h2B8; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h2B8; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h2B8; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h2B8; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h2B8; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h2B8; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h2B8; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h27) == 'h1) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h2B8; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h2B8; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h2B8; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h2B8; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h2B8; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h2B8; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h2B8; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h27) == 'h2) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h137; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00B; arA23[ 'h4] = 'h2BC; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00F; arA23[ 'h4] = 'h2BC; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h179; arA23[ 'h4] = 'h2BC; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C6; arA23[ 'h4] = 'h2BC; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E7; arA23[ 'h4] = 'h2BC; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00E; arA23[ 'h4] = 'h2BC; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E6; arA23[ 'h4] = 'h2BC; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h3) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A5; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3A1; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3A1; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3A1; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3A1; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3A1; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3A1; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3A1; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h13) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h301; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h159; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h159; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h159; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h159; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h159; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end + 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h301; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h1B) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h301; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h159; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h159; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h159; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h159; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h159; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end + 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h301; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h20) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h13B; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h15C; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h15C; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h15C; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h15C; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h15C; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h15C; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h15C; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h21) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h341; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17C; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17D; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FF; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h178; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FA; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17D; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FF; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h22) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A0; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A4; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F1; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h325; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1ED; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E5; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h23) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h232; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A0; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A4; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F1; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h325; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1ED; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E5; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h28) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h12D; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3C3; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3C3; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3C3; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3C3; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3C3; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3C3; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3C3; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h29) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h12D; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3C3; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3C3; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3C3; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3C3; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3C3; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3C3; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3C3; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h2A) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h125; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00B; arA23[ 'h4] = 'h3CB; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00F; arA23[ 'h4] = 'h3CB; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h179; arA23[ 'h4] = 'h3CB; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C6; arA23[ 'h4] = 'h3CB; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E7; arA23[ 'h4] = 'h3CB; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00E; arA23[ 'h4] = 'h3CB; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E6; arA23[ 'h4] = 'h3CB; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h2B) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h345; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h343; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h343; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h343; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h343; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h343; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h343; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h343; end + 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h3E) == 'h32) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h127; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h123; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FD; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F5; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F9; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E9; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FD; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F5; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h6) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h152; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h151; end + 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h151; end + 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h151; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h151; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h151; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h151; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h151; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h151; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h151; end + 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h152; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( (opcode[11:6] & 'h7) == 'h7) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F1; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F2; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FB; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h275; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3E4; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F2; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FB; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h3A) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h273; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B0; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F3; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h293; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F2; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B0; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F3; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h3B) begin + unique case ( col) + 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h255; arA23[ 'h4] = 'X; end + 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B4; arA23[ 'h4] = 'X; end + 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F7; arA23[ 'h4] = 'X; end + 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h297; arA23[ 'h4] = 'X; end + 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F6; arA23[ 'h4] = 'X; end + 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B4; arA23[ 'h4] = 'X; end + 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F7; arA23[ 'h4] = 'X; end + 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + endcase +end + +else if( opcode[11:6] == 'h39) begin + arIll[ 'h4] = illMisc; arA1[ 'h4] = a1Misc ; arA23[ 'h4] = 'X; +end + +else begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end + +end + +always_comb begin + +// +// Line: 1 +// +unique case( movEa) + +0: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h121; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h29B; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h29B; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h29B; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h29B; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h29B; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h29B; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h29B; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h29B; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h29B; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h121; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +2: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2FA; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h3AB; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h3AB; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h3AB; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AB; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AB; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h3AB; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h3AB; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AB; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AB; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2FA; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +3: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2FE; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h3AF; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h3AF; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h3AF; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AF; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AF; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h3AF; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h3AF; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AF; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AF; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2FE; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +4: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2F8; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h38B; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h38B; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h38B; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38B; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38B; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h38B; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h38B; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38B; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38B; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2F8; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +5: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2DA; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h38A; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h38A; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h38A; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38A; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38A; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h38A; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h38A; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38A; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38A; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2DA; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +6: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1EB; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h298; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h298; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h298; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h298; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h298; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h298; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h298; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h298; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h298; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h1EB; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +7: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2D9; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h388; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h388; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h388; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h388; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h388; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h388; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h388; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h388; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h388; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2D9; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase + +8: // Row: 8 + unique case ( col) + 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1EA; arA23[ 'h1] = 'X; end + 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h32B; end + 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h32B; end + 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h32B; end + 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h32B; end + 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h32B; end + 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h32B; end + 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h32B; end + 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h32B; end + 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h32B; end + 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h1EA; end + default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end + endcase +default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end +endcase + +// +// Line: 2 +// +unique case( movEa) + +0: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29F; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29F; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29F; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29F; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29F; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h129; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +1: // Row: 1 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29F; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29F; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29F; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29F; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29F; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h129; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +2: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2F9; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2F9; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h3A9; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h3A9; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h3A9; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3A9; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3A9; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h3A9; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h3A9; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3A9; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3A9; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2F9; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +3: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FD; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FD; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h3AD; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h3AD; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h3AD; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3AD; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3AD; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h3AD; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h3AD; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3AD; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3AD; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2FD; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +4: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FC; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FC; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38F; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38F; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38F; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38F; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38F; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38F; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38F; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38F; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38F; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2FC; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +5: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DE; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DE; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38E; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38E; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38E; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38E; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38E; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38E; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38E; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38E; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38E; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2DE; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +6: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EF; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EF; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29C; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29C; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29C; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29C; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29C; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29C; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29C; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29C; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29C; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h1EF; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +7: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DD; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DD; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38C; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38C; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38C; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38C; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38C; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38C; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38C; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38C; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38C; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2DD; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase + +8: // Row: 8 + unique case ( col) + 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EE; arA23[ 'h2] = 'X; end + 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EE; arA23[ 'h2] = 'X; end + 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h30F; end + 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h30F; end + 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h30F; end + 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h30F; end + 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h30F; end + 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h30F; end + 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h30F; end + 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h30F; end + 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h30F; end + 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h1EE; end + default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end + endcase +default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end +endcase + +// +// Line: 3 +// +unique case( movEa) + +0: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h121; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h121; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h29B; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h29B; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h29B; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h29B; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h29B; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h29B; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h29B; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h29B; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h29B; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h121; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +1: // Row: 1 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h279; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h279; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h158; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h158; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h158; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h158; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h158; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h158; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h158; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h158; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h158; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h279; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +2: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FA; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FA; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h3AB; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h3AB; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h3AB; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AB; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AB; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h3AB; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h3AB; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AB; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AB; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2FA; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +3: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FE; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FE; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h3AF; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h3AF; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h3AF; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AF; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AF; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h3AF; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h3AF; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AF; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AF; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2FE; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +4: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2F8; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2F8; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h38B; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h38B; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h38B; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38B; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38B; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h38B; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h38B; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38B; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38B; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2F8; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +5: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2DA; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2DA; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h38A; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h38A; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h38A; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38A; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38A; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h38A; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h38A; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38A; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38A; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2DA; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +6: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EB; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EB; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h298; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h298; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h298; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h298; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h298; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h298; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h298; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h298; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h298; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h1EB; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +7: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2D9; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2D9; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h388; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h388; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h388; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h388; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h388; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h388; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h388; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h388; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h388; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2D9; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase + +8: // Row: 8 + unique case ( col) + 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EA; arA23[ 'h3] = 'X; end + 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EA; arA23[ 'h3] = 'X; end + 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h32B; end + 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h32B; end + 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h32B; end + 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h32B; end + 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h32B; end + 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h32B; end + 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h32B; end + 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h32B; end + 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h32B; end + 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h1EA; end + default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end + endcase +default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end +endcase + +// +// Line: 5 +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00B; arA23[ 'h5] = 'h2F7; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00F; arA23[ 'h5] = 'h2F7; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h179; arA23[ 'h5] = 'h2F7; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C6; arA23[ 'h5] = 'h2F7; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E7; arA23[ 'h5] = 'h2F7; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00E; arA23[ 'h5] = 'h2F7; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E6; arA23[ 'h5] = 'h2F7; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h384; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h06C; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h380; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h380; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h380; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h380; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h380; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h380; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h380; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00B; arA23[ 'h5] = 'h2F7; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00F; arA23[ 'h5] = 'h2F7; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h179; arA23[ 'h5] = 'h2F7; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C6; arA23[ 'h5] = 'h2F7; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E7; arA23[ 'h5] = 'h2F7; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00E; arA23[ 'h5] = 'h2F7; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E6; arA23[ 'h5] = 'h2F7; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h384; arA23[ 'h5] = 'X; end + 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h06C; arA23[ 'h5] = 'X; end + 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h380; end + 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h380; end + 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h380; end + 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h380; end + 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h380; end + 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h380; end + 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h380; end + default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end + endcase +endcase + +// +// Line: 8 +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C1; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h1C3; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h1C3; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h1C3; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h1C3; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h1C3; end + 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end + 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end + 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h1C1; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C1; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h1C3; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h1C3; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h1C3; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h1C3; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h1C3; end + 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end + 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end + 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h1C1; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C5; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00B; arA23[ 'h8] = 'h1CB; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00F; arA23[ 'h8] = 'h1CB; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h179; arA23[ 'h8] = 'h1CB; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h1CB; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h1CB; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00E; arA23[ 'h8] = 'h1CB; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E6; arA23[ 'h8] = 'h1CB; end + 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h1CB; end + 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h1CB; end + 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0A7; arA23[ 'h8] = 'h1C5; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0A6; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h0A4; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h0A4; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h0A4; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0A4; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0A4; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h0A4; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h0A4; end + 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0A4; end + 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0A4; end + 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h0A6; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1CD; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h107; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h299; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h299; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h299; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h299; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h299; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h299; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h299; end + 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h299; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h299; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h299; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h299; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h299; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h299; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h299; end + 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00B; arA23[ 'h8] = 'h29D; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00F; arA23[ 'h8] = 'h29D; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h179; arA23[ 'h8] = 'h29D; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h29D; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h29D; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00E; arA23[ 'h8] = 'h29D; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E6; arA23[ 'h8] = 'h29D; end + 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0AE; arA23[ 'h8] = 'X; end + 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h0AC; end + 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h0AC; end + 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h0AC; end + 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0AC; end + 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0AC; end + 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h0AC; end + 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h0AC; end + 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0AC; end + 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0AC; end + 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h0AE; end + default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end + endcase +endcase + +// +// Line: 9 +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C3; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C3; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C3; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C3; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C3; end + 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end + 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end + 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C1; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C3; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C3; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C3; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C3; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C3; end + 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end + 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end + 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C1; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h1CB; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h1CB; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h1CB; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h1CB; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h1CB; end + 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end + 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end + 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0A7; arA23[ 'h9] = 'h1C5; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C9; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C9; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C7; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C7; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C7; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C7; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C7; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C7; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C7; end + 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C7; end + 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C7; end + 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C9; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10F; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h299; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h299; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h299; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h299; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h299; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h299; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h299; end + 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10F; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h299; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h299; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h299; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h299; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h299; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h299; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h299; end + 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10B; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h29D; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h29D; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h29D; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h29D; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h29D; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h29D; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h29D; end + 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end + 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end + 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h1CB; end + 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h1CB; end + 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h1CB; end + 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end + 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end + 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h1CB; end + 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h1CB; end + 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end + 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end + 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0A7; arA23[ 'h9] = 'h1C5; end + default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end + endcase +endcase + +// +// Line: B +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1D3; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1D3; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1D3; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1D3; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1D3; end + 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end + 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end + 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D1; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1D3; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1D3; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1D3; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1D3; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1D3; end + 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end + 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end + 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D1; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h1D7; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h1D7; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h1D7; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h1D7; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h1D7; end + 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end + 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end + 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0A7; arA23[ 'hb] = 'h1D5; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D9; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D9; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1CF; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1CF; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1CF; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1CF; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1CF; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1CF; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1CF; end + 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1CF; end + 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1CF; end + 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D9; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h100; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06B; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h299; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h299; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h299; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h299; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h299; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h299; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h299; end + 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h100; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06B; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h299; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h299; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h299; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h299; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h299; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h299; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h299; end + 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h10C; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06F; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h29D; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h29D; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h29D; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h29D; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h29D; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h29D; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h29D; end + 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end + 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end + 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h1D7; end + 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h1D7; end + 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h1D7; end + 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end + 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end + 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h1D7; end + 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h1D7; end + 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end + 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end + 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0A7; arA23[ 'hb] = 'h1D5; end + default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end + endcase +endcase + +// +// Line: C +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C1; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h1C3; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h1C3; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h1C3; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h1C3; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h1C3; end + 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end + 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end + 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h1C1; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C1; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h1C3; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h1C3; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h1C3; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h1C3; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h1C3; end + 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end + 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end + 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h1C1; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C5; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00B; arA23[ 'hc] = 'h1CB; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00F; arA23[ 'hc] = 'h1CB; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h179; arA23[ 'hc] = 'h1CB; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h1CB; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h1CB; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00E; arA23[ 'hc] = 'h1CB; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E6; arA23[ 'hc] = 'h1CB; end + 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h1CB; end + 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h1CB; end + 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0A7; arA23[ 'hc] = 'h1C5; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h15B; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h15A; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h15A; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h15A; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h15A; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h15A; end + 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end + 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end + 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h15B; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1CD; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h107; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h299; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h299; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h299; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h299; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h299; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h299; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h299; end + 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h299; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h299; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h299; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h299; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h299; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h299; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h299; end + 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00B; arA23[ 'hc] = 'h29D; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00F; arA23[ 'hc] = 'h29D; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h179; arA23[ 'hc] = 'h29D; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h29D; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h29D; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00E; arA23[ 'hc] = 'h29D; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E6; arA23[ 'hc] = 'h29D; end + 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h15B; arA23[ 'hc] = 'X; end + 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h15A; end + 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h15A; end + 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h15A; end + 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end + 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end + 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h15A; end + 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h15A; end + 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end + 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end + 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h15B; end + default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end + endcase +endcase + +// +// Line: D +// +unique case( row86) + +3'b000: // Row: 0 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C3; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C3; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C3; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C3; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C3; end + 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end + 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end + 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C1; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b001: // Row: 1 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C3; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C3; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C3; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C3; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C3; end + 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end + 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end + 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C1; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b010: // Row: 2 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h1CB; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h1CB; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h1CB; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h1CB; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h1CB; end + 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end + 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end + 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0A7; arA23[ 'hd] = 'h1C5; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b011: // Row: 3 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C9; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C9; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C7; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C7; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C7; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C7; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C7; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C7; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C7; end + 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C7; end + 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C7; end + 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C9; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b100: // Row: 4 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10F; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h299; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h299; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h299; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h299; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h299; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h299; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h299; end + 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b101: // Row: 5 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10F; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h299; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h299; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h299; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h299; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h299; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h299; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h299; end + 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b110: // Row: 6 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10B; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h29D; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h29D; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h29D; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h29D; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h29D; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h29D; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h29D; end + 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase + +3'b111: // Row: 7 + unique case ( col) + 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end + 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end + 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h1CB; end + 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h1CB; end + 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h1CB; end + 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end + 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end + 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h1CB; end + 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h1CB; end + 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end + 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end + 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0A7; arA23[ 'hd] = 'h1C5; end + default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end + endcase +endcase +end + + +endmodule diff --git a/rtl/ipcores/jt49/filter/jt49_dcrm.v b/rtl/ipcores/jt49/filter/jt49_dcrm.v new file mode 100644 index 0000000..32d4660 --- /dev/null +++ b/rtl/ipcores/jt49/filter/jt49_dcrm.v @@ -0,0 +1,56 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed +/* verilator tracing_off */ +module jt49_dcrm( + input clk, + input cen, + input rst, + input [7:0] din, + output reg signed [7:0] dout +); + +wire signed [7:0] ave0, ave1; + +jt49_mave u_mave0( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( {1'b0, din[7:1] } ), + .dout ( ave0 ) +); + +jt49_mave u_mave1( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( ave0 ), + .dout ( ave1 ) +); + +always @(posedge clk) + if( cen ) + dout <= ({1'b0,din} - {ave1,1'b0})>>>1; + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jt49/filter/jt49_dcrm2.v b/rtl/ipcores/jt49/filter/jt49_dcrm2.v new file mode 100644 index 0000000..f775d03 --- /dev/null +++ b/rtl/ipcores/jt49/filter/jt49_dcrm2.v @@ -0,0 +1,64 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam DW=10; // width of the decimal portion + +reg signed [sw+DW:0] integ, exact, error; +//reg signed [2*(9+DW)-1:0] mult; +// wire signed [sw+DW:0] plus1 = { {sw+DW{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+DW:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+DW:DW]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {DW{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+DW+1{1'b0}}; + error <= {sw+DW+1{1'b0}}; + end else if( cen ) begin + /* verilator lint_off WIDTH */ + integ <= integ + pre_dout; //mult[sw+DW*2:DW]; + /* verilator lint_on WIDTH */ + error <= exact-{q, {DW{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jt49/filter/jt49_dly.v b/rtl/ipcores/jt49/filter/jt49_dly.v new file mode 100644 index 0000000..3ac2541 --- /dev/null +++ b/rtl/ipcores/jt49/filter/jt49_dly.v @@ -0,0 +1,67 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// Delay stage +// use for long delays + +module jt49_dly #(parameter DW=8, depth=10)( + input clk, + input cen, + input rst, + input [7:0] din, + output reg [7:0] dout, + output reg [7:0] pre_dout + +); + +reg [depth-1:0] rdpos, wrpos; + + +// memory +reg [DW-1:0] ram[0:2**depth-1]; +always @(posedge clk) + if(rst) + pre_dout <= {DW{1'b0}}; + else begin + pre_dout <= ram[rdpos]; + if( cen ) ram[wrpos] <= din; + end + +`ifdef SIMULATION +integer k; +initial begin + for(k=0;k<=2**depth-1;k=k+1) + ram[k] = 0; +end +`endif + +always @(posedge clk) + if( rst ) begin + rdpos <= { {depth-1{1'b0}}, 1'b1}; + wrpos <= {depth{1'b1}}; + dout <= {DW{1'b0}}; + end else if(cen) begin + dout <= pre_dout; + rdpos <= rdpos+1'b1; + wrpos <= wrpos+1'b1; + end + +endmodule // jt49_dly \ No newline at end of file diff --git a/rtl/ipcores/jt49/filter/jt49_mave.v b/rtl/ipcores/jt49/filter/jt49_mave.v new file mode 100644 index 0000000..02a0916 --- /dev/null +++ b/rtl/ipcores/jt49/filter/jt49_mave.v @@ -0,0 +1,60 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// Moving averager + +module jt49_mave #(parameter depth=8, DW=8)( + input clk, + input cen, + input rst, + input signed [DW-1:0] din, + output signed [DW-1:0] dout +); + +wire [DW-1:0] dly0; +wire [DW-1:0] pre_dly0; + +jt49_dly #(.depth(depth),.DW(DW)) u_dly0( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( din ), + .dout ( dly0 ), + .pre_dout ( pre_dly0 ) +); + +// moving average +// D=2048 +reg signed [DW:0] diff; +reg signed [DW+depth-1:0] sum; + + +always @(posedge clk) + if( rst ) begin + diff <= {DW+1{1'd0}}; + sum <= {DW+depth+1{1'd0}}; + end else if(cen) begin + diff <= {1'b0,din } - { 1'b0, dly0 }; + sum <= { {depth{diff[DW]}}, diff } + sum; + end +assign dout = sum[DW+depth-1:depth]; + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jt49/jt49.qip b/rtl/ipcores/jt49/jt49.qip new file mode 100644 index 0000000..24a7f78 --- /dev/null +++ b/rtl/ipcores/jt49/jt49.qip @@ -0,0 +1,11 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_bus.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_cen.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_div.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_eg.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_exp.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_noise.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path)/filter/jt49_dcrm.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path)/filter/jt49_dcrm2.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path)/filter/jt49_dly.v] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path)/filter/jt49_mave.v] diff --git a/rtl/ipcores/jt49/jt49.v b/rtl/ipcores/jt49/jt49.v new file mode 100644 index 0000000..08145bf --- /dev/null +++ b/rtl/ipcores/jt49/jt49.v @@ -0,0 +1,258 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49 ( // note that input ports are not multiplexed + input rst_n, + input clk, // signal on positive edge + input clk_en /* synthesis direct_enable = 1 */, + input [3:0] addr, + input cs_n, + input wr_n, // write + input [7:0] din, + input sel, // if sel is low, the clock is divided by 2 + output reg [7:0] dout, + output reg [9:0] sound, // combined channel output + output reg [7:0] A, // linearised channel output + output reg [7:0] B, + output reg [7:0] C, + output sample, + + input [7:0] IOA_in, + output [7:0] IOA_out, + output IOA_oe, + + input [7:0] IOB_in, + output [7:0] IOB_out, + output IOB_oe +); + +parameter [2:0] COMP=3'b000; +parameter YM2203_LUMPED=0; +parameter CLKDIV=3; +wire [2:0] comp = COMP; + +reg [7:0] regarray[15:0]; +wire [7:0] port_A, port_B; + +wire [4:0] envelope; +wire bitA, bitB, bitC; +wire noise; +reg Amix, Bmix, Cmix; + +wire cen16, cen256; + +assign IOA_out = regarray[14]; +assign IOB_out = regarray[15]; +assign port_A = IOA_in; +assign port_B = IOB_in; +assign IOA_oe = regarray[7][6]; +assign IOB_oe = regarray[7][7]; +assign sample = cen16; + +jt49_cen #(.CLKDIV(CLKDIV)) u_cen( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( clk_en ), + .sel ( sel ), + .cen16 ( cen16 ), + .cen256 ( cen256 ) +); + +// internal modules operate at clk/16 +jt49_div #(12) u_chA( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[1][3:0], regarray[0][7:0] } ), + .div ( bitA ) +); + +jt49_div #(12) u_chB( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[3][3:0], regarray[2][7:0] } ), + .div ( bitB ) +); + +jt49_div #(12) u_chC( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[5][3:0], regarray[4][7:0] } ), + .div ( bitC ) +); + +jt49_noise u_ng( + .clk ( clk ), + .cen ( cen16 ), + .rst_n ( rst_n ), + .period ( regarray[6][4:0] ), + .noise ( noise ) +); + +// envelope generator +wire eg_step; +wire [15:0] eg_period = {regarray[4'hc],regarray[4'hb]}; +wire null_period = eg_period == 16'h0; + +jt49_div #(16) u_envdiv( + .clk ( clk ), + .cen ( cen256 ), + .rst_n ( rst_n ), + .period ( eg_period ), + .div ( eg_step ) +); + +reg eg_restart; + +jt49_eg u_env( + .clk ( clk ), + .cen ( cen256 ), + .step ( eg_step ), + .rst_n ( rst_n ), + .restart ( eg_restart ), + .null_period( null_period ), + .ctrl ( regarray[4'hD][3:0] ), + .env ( envelope ) +); + +reg [4:0] logA, logB, logC, log; +wire [7:0] lin; + +jt49_exp u_exp( + .clk ( clk ), + .comp ( comp ), + .din ( log ), + .dout ( lin ) +); + +wire [4:0] volA = { regarray[ 8][3:0], regarray[ 8][3] }; +wire [4:0] volB = { regarray[ 9][3:0], regarray[ 9][3] }; +wire [4:0] volC = { regarray[10][3:0], regarray[10][3] }; +wire use_envA = regarray[ 8][4]; +wire use_envB = regarray[ 9][4]; +wire use_envC = regarray[10][4]; +wire use_noA = regarray[ 7][3]; +wire use_noB = regarray[ 7][4]; +wire use_noC = regarray[ 7][5]; + +reg [3:0] acc_st; + +always @(posedge clk) if( clk_en ) begin + Amix <= (noise|use_noA) & (bitA|regarray[7][0]); + Bmix <= (noise|use_noB) & (bitB|regarray[7][1]); + Cmix <= (noise|use_noC) & (bitC|regarray[7][2]); + + logA <= !Amix ? 5'd0 : (use_envA ? envelope : volA ); + logB <= !Bmix ? 5'd0 : (use_envB ? envelope : volB ); + logC <= !Cmix ? 5'd0 : (use_envC ? envelope : volC ); +end + +reg [9:0] acc; +wire [9:0] elin; + +assign elin = {2'd0,lin}; + +always @(posedge clk, negedge rst_n) begin + if( !rst_n ) begin + acc_st <= 4'b1; + acc <= 10'd0; + A <= 8'd0; + B <= 8'd0; + C <= 8'd0; + sound <= 10'd0; + end else if(clk_en) begin + acc_st <= { acc_st[2:0], acc_st[3] }; + // Lumping the channel outputs for YM2203 will cause only the higher + // voltage to pass throuh, as the outputs seem to use a source follower. + acc <= YM2203_LUMPED==1 ? (acc>elin ? acc : elin) : acc + elin; + case( acc_st ) + 4'b0001: begin + log <= logA; + acc <= 10'd0; + sound <= acc; + end + 4'b0010: begin + A <= lin; + log <= logB; + end + 4'b0100: begin + B <= lin; + log <= logC; + end + 4'b1000: begin // last sum + C <= lin; + end + default:; + endcase + end +end + +reg [7:0] read_mask; + +always @(*) + case(addr) + 4'h0,4'h2,4'h4,4'h7,4'hb,4'hc,4'he,4'hf: + read_mask = 8'hff; + 4'h1,4'h3,4'h5,4'hd: + read_mask = 8'h0f; + 4'h6,4'h8,4'h9,4'ha: + read_mask = 8'h1f; + endcase // addr + +// register array +wire write; +reg last_write; +wire wr_edge = write & ~last_write; + +assign write = !wr_n && !cs_n; + +always @(posedge clk, negedge rst_n) begin + if( !rst_n ) begin + dout <= 8'd0; + last_write <= 0; + eg_restart <= 0; + regarray[0]<=8'd0; regarray[4]<=8'd0; regarray[ 8]<=8'd0; regarray[12]<=8'd0; + regarray[1]<=8'd0; regarray[5]<=8'd0; regarray[ 9]<=8'd0; regarray[13]<=8'd0; + regarray[2]<=8'd0; regarray[6]<=8'd0; regarray[10]<=8'd0; regarray[14]<=8'd0; + regarray[3]<=8'd0; regarray[7]<=8'd0; regarray[11]<=8'd0; regarray[15]<=8'd0; + end else begin + last_write <= write; + // Data read + case( addr ) + 4'he: dout <= port_A; + 4'hf: dout <= port_B; + default: dout <= regarray[ addr ] & read_mask; + endcase + // Data write + if( write ) begin + regarray[addr] <= din; + if ( addr == 4'hD && wr_edge ) eg_restart <= 1; + end else begin + eg_restart <= 0; + end + end +end + +endmodule diff --git a/rtl/ipcores/jt49/jt49_bus.v b/rtl/ipcores/jt49/jt49_bus.v new file mode 100644 index 0000000..ac48e8e --- /dev/null +++ b/rtl/ipcores/jt49/jt49_bus.v @@ -0,0 +1,105 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 28-Jan-2019 + + Based on sqmusic, by the same author + + */ + +// This is a wrapper with the BDIR/BC1 pins + +module jt49_bus ( // note that input ports are not multiplexed + input rst_n, + input clk, // signal on positive edge + input clk_en /* synthesis direct_enable = 1 */, + // bus control pins of original chip + input bdir, + input bc1, + input [7:0] din, + + input sel, // if sel is low, the clock is divided by 2 + output [7:0] dout, + output [9:0] sound, // combined channel output + output [7:0] A, // linearised channel output + output [7:0] B, + output [7:0] C, + output sample, + + input [7:0] IOA_in, + output [7:0] IOA_out, + output IOA_oe, + + input [7:0] IOB_in, + output [7:0] IOB_out, + output IOB_oe +); + +parameter [2:0] COMP=3'b000; + +reg wr_n, cs_n; +reg [3:0] addr; +reg addr_ok; +reg [7:0] din_latch; + +always @(posedge clk) + if( !rst_n ) begin + wr_n <= 1'b1; + cs_n <= 1'b1; + addr <= 4'd0; + addr_ok <= 1'b1; + end else begin // I/O cannot use clk_en + // addr must be + case( {bdir,bc1} ) + 2'b00: { wr_n, cs_n } <= 2'b11; + 2'b01: { wr_n, cs_n } <= addr_ok ? 2'b10 : 2'b11; + 2'b10: begin + { wr_n, cs_n } <= addr_ok ? 2'b00 : 2'b11; + din_latch <= din; + end + 2'b11: begin + { wr_n, cs_n } <= 2'b11; + addr <= din[3:0]; + addr_ok <= din[7:4] == 4'd0; + end + endcase // {bdir,bc1} + end + +jt49 #(.COMP(COMP)) u_jt49( // note that input ports are not multiplexed + .rst_n ( rst_n ), + .clk ( clk ), // signal on positive edge + .clk_en ( clk_en ), // clock enable on negative edge + .addr ( addr[3:0] ), + .cs_n ( cs_n ), + .wr_n ( wr_n ), // write + .din ( din_latch ), + .sel ( sel ), // if sel is low, the clock is divided by 2 + .dout ( dout ), + .sound ( sound ), // combined channel output + .sample ( sample ), + .A ( A ), // linearised channel output + .B ( B ), + .C ( C ), + .IOA_in ( IOA_in ), + .IOA_out( IOA_out ), + .IOA_oe ( IOA_oe ), + .IOB_in ( IOB_in ), + .IOB_out( IOB_out ), + .IOB_oe ( IOB_oe ) +); + +endmodule // jt49_bus \ No newline at end of file diff --git a/rtl/ipcores/jt49/jt49_cen.v b/rtl/ipcores/jt49/jt49_cen.v new file mode 100644 index 0000000..671eceb --- /dev/null +++ b/rtl/ipcores/jt49/jt49_cen.v @@ -0,0 +1,55 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49_cen( + input clk, + input rst_n, + input cen, // base clock enable signal + input sel, // when low, divide by 2 once more + output reg cen16, + output reg cen256 +); + +reg [9:0] cencnt; +parameter CLKDIV = 3; // use 3 for standalone JT49 or 2 +localparam eg = CLKDIV; //8; + +wire toggle16 = sel ? ~|cencnt[CLKDIV-1:0] : ~|cencnt[CLKDIV:0]; +wire toggle256= sel ? ~|cencnt[eg-2:0] : ~|cencnt[eg-1:0]; + + +always @(posedge clk, negedge rst_n) begin + if(!rst_n) + cencnt <= 10'd0; + else begin + if(cen) cencnt <= cencnt+10'd1; + end +end + +always @(posedge clk) begin + cen16 <= cen & toggle16; + cen256 <= cen & toggle256; +end + + +endmodule // jt49_cen diff --git a/rtl/ipcores/jt49/jt49_div.v b/rtl/ipcores/jt49/jt49_div.v new file mode 100644 index 0000000..ac4564c --- /dev/null +++ b/rtl/ipcores/jt49/jt49_div.v @@ -0,0 +1,52 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + + +module jt49_div #(parameter W=12 )( + (* direct_enable *) input cen, + input clk, // this is the divided down clock from the core + input rst_n, + input [W-1:0] period, + output reg div +); + +reg [W-1:0]count; + +wire [W-1:0] one = { {W-1{1'b0}}, 1'b1}; + +always @(posedge clk, negedge rst_n ) begin + if( !rst_n) begin + count <= one; + div <= 1'b0; + end + else if(cen) begin + if( count>=period ) begin + count <= one; + div <= ~div; + end + else + /*if( period!={W{1'b0}} )*/ count <= count + one ; + end +end + +endmodule diff --git a/rtl/ipcores/jt49/jt49_eg.v b/rtl/ipcores/jt49/jt49_eg.v new file mode 100644 index 0000000..46dd62a --- /dev/null +++ b/rtl/ipcores/jt49/jt49_eg.v @@ -0,0 +1,88 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49_eg( + (* direct_enable *) input cen, + input clk, // this is the divided down clock from the core + input step, + input null_period, + input rst_n, + input restart, + input [3:0] ctrl, + output reg [4:0]env +); + +reg inv, stop; +reg [4:0] gain; + +wire CONT = ctrl[3]; +wire ATT = ctrl[2]; +wire ALT = ctrl[1]; +wire HOLD = ctrl[0]; + +wire will_hold = !CONT || HOLD; + +always @(posedge clk) + if( cen ) env <= inv ? ~gain : gain; + +reg last_step; +wire step_edge = (step && !last_step) || null_period; +wire will_invert = (!CONT&&ATT) || (CONT&&ALT); +reg rst_latch, rst_clr; + +always @(posedge clk) begin + if( restart ) rst_latch <= 1; + else if(rst_clr ) rst_latch <= 0; +end + +always @( posedge clk, negedge rst_n ) + if( !rst_n) begin + gain <= 5'h1F; + inv <= 0; + stop <= 0; + rst_clr <= 0; + end + else if( cen ) begin + last_step <= step; + if( rst_latch ) begin + gain <= 5'h1F; + inv <= ATT; + stop <= 1'b0; + rst_clr <= 1; + end + else begin + rst_clr <= 0; + if (step_edge && !stop) begin + if( gain==5'h00 ) begin + if( will_hold ) + stop <= 1'b1; + else + gain <= gain-5'b1; + if( will_invert ) inv<=~inv; + end + else gain <= gain-5'b1; + end + end + end + +endmodule diff --git a/rtl/ipcores/jt49/jt49_exp.v b/rtl/ipcores/jt49/jt49_exp.v new file mode 100644 index 0000000..25efa38 --- /dev/null +++ b/rtl/ipcores/jt49/jt49_exp.v @@ -0,0 +1,205 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +// Compression vs dynamic range +// 0 -> 43.6dB +// 1 -> 29.1 +// 2 -> 21.8 +// 3 -> 13.4 + +module jt49_exp( + input clk, + input [2:0] comp, // compression + input [4:0] din, + output reg [7:0] dout +); + +reg [7:0] lut[0:159]; + +always @(posedge clk) + dout <= lut[ {comp,din} ]; + +initial begin + lut[0] = 8'd0; + lut[1] = 8'd1; + lut[2] = 8'd1; + lut[3] = 8'd1; + lut[4] = 8'd2; + lut[5] = 8'd2; + lut[6] = 8'd3; + lut[7] = 8'd3; + lut[8] = 8'd4; + lut[9] = 8'd5; + lut[10] = 8'd6; + lut[11] = 8'd7; + lut[12] = 8'd9; + lut[13] = 8'd11; + lut[14] = 8'd13; + lut[15] = 8'd15; + lut[16] = 8'd18; + lut[17] = 8'd22; + lut[18] = 8'd26; + lut[19] = 8'd31; + lut[20] = 8'd37; + lut[21] = 8'd45; + lut[22] = 8'd53; + lut[23] = 8'd63; + lut[24] = 8'd75; + lut[25] = 8'd90; + lut[26] = 8'd107; + lut[27] = 8'd127; + lut[28] = 8'd151; + lut[29] = 8'd180; + lut[30] = 8'd214; + lut[31] = 8'd255; + lut[32] = 8'd0; + lut[33] = 8'd7; + lut[34] = 8'd8; + lut[35] = 8'd10; + lut[36] = 8'd11; + lut[37] = 8'd12; + lut[38] = 8'd14; + lut[39] = 8'd15; + lut[40] = 8'd17; + lut[41] = 8'd20; + lut[42] = 8'd22; + lut[43] = 8'd25; + lut[44] = 8'd28; + lut[45] = 8'd31; + lut[46] = 8'd35; + lut[47] = 8'd40; + lut[48] = 8'd45; + lut[49] = 8'd50; + lut[50] = 8'd56; + lut[51] = 8'd63; + lut[52] = 8'd71; + lut[53] = 8'd80; + lut[54] = 8'd90; + lut[55] = 8'd101; + lut[56] = 8'd113; + lut[57] = 8'd127; + lut[58] = 8'd143; + lut[59] = 8'd160; + lut[60] = 8'd180; + lut[61] = 8'd202; + lut[62] = 8'd227; + lut[63] = 8'd255; + lut[64] = 8'd0; + lut[65] = 8'd18; + lut[66] = 8'd20; + lut[67] = 8'd22; + lut[68] = 8'd24; + lut[69] = 8'd26; + lut[70] = 8'd29; + lut[71] = 8'd31; + lut[72] = 8'd34; + lut[73] = 8'd37; + lut[74] = 8'd41; + lut[75] = 8'd45; + lut[76] = 8'd49; + lut[77] = 8'd53; + lut[78] = 8'd58; + lut[79] = 8'd63; + lut[80] = 8'd69; + lut[81] = 8'd75; + lut[82] = 8'd82; + lut[83] = 8'd90; + lut[84] = 8'd98; + lut[85] = 8'd107; + lut[86] = 8'd116; + lut[87] = 8'd127; + lut[88] = 8'd139; + lut[89] = 8'd151; + lut[90] = 8'd165; + lut[91] = 8'd180; + lut[92] = 8'd196; + lut[93] = 8'd214; + lut[94] = 8'd233; + lut[95] = 8'd255; + lut[96] = 8'd0; + lut[97] = 8'd51; + lut[98] = 8'd54; + lut[99] = 8'd57; + lut[100] = 8'd60; + lut[101] = 8'd63; + lut[102] = 8'd67; + lut[103] = 8'd70; + lut[104] = 8'd74; + lut[105] = 8'd78; + lut[106] = 8'd83; + lut[107] = 8'd87; + lut[108] = 8'd92; + lut[109] = 8'd97; + lut[110] = 8'd103; + lut[111] = 8'd108; + lut[112] = 8'd114; + lut[113] = 8'd120; + lut[114] = 8'd127; + lut[115] = 8'd134; + lut[116] = 8'd141; + lut[117] = 8'd149; + lut[118] = 8'd157; + lut[119] = 8'd166; + lut[120] = 8'd175; + lut[121] = 8'd185; + lut[122] = 8'd195; + lut[123] = 8'd206; + lut[124] = 8'd217; + lut[125] = 8'd229; + lut[126] = 8'd241; + lut[127] = 8'd255; + lut[128] = 8'd0; + lut[129] = 8'd8; + lut[130] = 8'd10; + lut[131] = 8'd12; + lut[132] = 8'd16; + lut[133] = 8'd22; + lut[134] = 8'd29; + lut[135] = 8'd35; + lut[136] = 8'd44; + lut[137] = 8'd50; + lut[138] = 8'd56; + lut[139] = 8'd60; + lut[140] = 8'd64; + lut[141] = 8'd85; + lut[142] = 8'd97; + lut[143] = 8'd103; + lut[144] = 8'd108; + lut[145] = 8'd120; + lut[146] = 8'd127; + lut[147] = 8'd134; + lut[148] = 8'd141; + lut[149] = 8'd149; + lut[150] = 8'd157; + lut[151] = 8'd166; + lut[152] = 8'd175; + lut[153] = 8'd185; + lut[154] = 8'd195; + lut[155] = 8'd206; + lut[156] = 8'd217; + lut[157] = 8'd229; + lut[158] = 8'd241; + lut[159] = 8'd255; + +end +endmodule diff --git a/rtl/ipcores/jt49/jt49_noise.v b/rtl/ipcores/jt49/jt49_noise.v new file mode 100644 index 0000000..ffc1fb9 --- /dev/null +++ b/rtl/ipcores/jt49/jt49_noise.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JT49 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + + +module jt49_noise( + (* direct_enable *) input cen, + input clk, + input rst_n, + input [4:0] period, + output reg noise +); + +reg [5:0]count; +reg [16:0]poly17; +wire poly17_zero = poly17==17'b0; +wire noise_en; +reg last_en; + +wire noise_up = noise_en && !last_en; + +always @(posedge clk ) if(cen) begin + noise <= ~poly17[0]; +end + +always @( posedge clk, negedge rst_n ) + if( !rst_n ) + poly17 <= 17'd0; + else if( cen ) begin + last_en <= noise_en; + if( noise_up ) + poly17 <= { poly17[0] ^ poly17[3] ^ poly17_zero, poly17[16:1] }; + end + +jt49_div #(5) u_div( + .clk ( clk ), + .cen ( cen ), + .rst_n ( rst_n ), + .period ( period ), + .div ( noise_en ) +); + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jtframe_sdram/jtframe_ram1_1slot.v b/rtl/ipcores/jtframe_sdram/jtframe_ram1_1slot.v new file mode 100644 index 0000000..9a39297 --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_ram1_1slot.v @@ -0,0 +1,105 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 1-12-2020 */ + +// SDRAM access multiplexer, 2 -> 1 + +module jtframe_ram1_1slot #(parameter + SDRAMW = 22, + SLOT0_DW = 16, + SLOT0_AW = 8, +/* verilator lint_off WIDTH */ + parameter [SDRAMW-1:0] SLOT1_OFFSET = 0, +/* verilator lint_on WIDTH */ + parameter REF_FILE="sdram_bank3.hex" +)( + input rst, + input clk, + + input [SLOT0_AW-1:0] slot0_addr, + output [SLOT0_DW-1:0] slot0_dout, + input [SLOT0_DW-1:0] slot0_din, + + input [SDRAMW-1:0] slot0_offset, + + input slot0_cs, + output slot0_ok, + input slot0_wen, + input [1:0] slot0_wrmask, + output hold_rst, // signals a busy state so the game is kept in reset + + // SDRAM controller interface + input sdram_ack, + output reg sdram_rd, + output reg sdram_wr, + output [SDRAMW-1:0] sdram_addr, + input data_rdy, + input data_dst, + input [15:0] data_read, + output reg [15:0] data_write, // only 16-bit writes + output reg [ 1:0] sdram_wrmask // each bit is active low +); + +wire req, req_rnw; +reg we; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + we <= 0; + sdram_rd <= 0; + sdram_wr <= 0; + sdram_wrmask <= 0; + end else begin + if( sdram_ack ) begin + sdram_rd <= 0; + sdram_wr <= 0; + end + if( !we || data_rdy ) begin + we <= 0; + // accept a new request + if( req ) begin + we <= 1; + data_write <= hold_rst ? 16'd0 : {(SLOT0_DW==8?2:1){slot0_din}}; + sdram_wrmask<= slot0_wrmask; + sdram_rd <= req_rnw; + sdram_wr <= ~req_rnw; + end + end + end +end + +jtframe_ram_rq #(.SDRAMW(SDRAMW),.AW(SLOT0_AW),.DW(SLOT0_DW)) u_slot0( + .rst ( rst ), + .clk ( clk ), + .addr ( slot0_addr ), + .addr_ok ( slot0_cs ), + .offset ( slot0_offset ), + .wrdata ( slot0_din ), + .wrin ( slot0_wen ), + .req_rnw ( req_rnw ), + .sdram_addr( sdram_addr ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot0_dout ), + .req ( req ), + .data_ok ( slot0_ok ), + .we ( we ), + .erase_bsy ( hold_rst ) +); + +endmodule diff --git a/rtl/ipcores/jtframe_sdram/jtframe_rom.v b/rtl/ipcores/jtframe_sdram/jtframe_rom.v new file mode 100644 index 0000000..2283cfd --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_rom.v @@ -0,0 +1,344 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 6-12-2019 */ + +// 9 slots for SDRAM read-only access +// slot 0 --> maximum priority +// slot 8 --> minimum priority +// Each slot can be used for 8, 16 or 32 bit access +// Small 4 byte cache used for each slot + +module jtframe_rom #(parameter + SLOT0_DW = 8, SLOT1_DW = 8, SLOT2_DW = 8, SLOT3_DW = 8, + SLOT4_DW = 8, SLOT5_DW = 8, SLOT6_DW = 8, SLOT7_DW = 8, SLOT8_DW = 8, + + SLOT0_AW = 8, SLOT1_AW = 8, SLOT2_AW = 8, SLOT3_AW = 8, + SLOT4_AW = 8, SLOT5_AW = 8, SLOT6_AW = 8, SLOT7_AW = 8, SLOT8_AW = 8, + + parameter [21:0] SLOT0_OFFSET = 22'h0, + parameter [21:0] SLOT1_OFFSET = 22'h0, + parameter [21:0] SLOT2_OFFSET = 22'h0, + parameter [21:0] SLOT3_OFFSET = 22'h0, + parameter [21:0] SLOT4_OFFSET = 22'h0, + parameter [21:0] SLOT5_OFFSET = 22'h0, + parameter [21:0] SLOT6_OFFSET = 22'h0, + parameter [21:0] SLOT7_OFFSET = 22'h0, + parameter [21:0] SLOT8_OFFSET = 22'h0 + + // SLOT0_BRAM = 0, + // SLOT1_BRAM = 0 +)( + input rst, + input clk, + + input [SLOT0_AW-1:0] slot0_addr, // 32 kB + input [SLOT1_AW-1:0] slot1_addr, // 160 kB, addressed as 8-bit words + input [SLOT2_AW-1:0] slot2_addr, // 32 kB + input [SLOT3_AW-1:0] slot3_addr, // 64 kB + input [SLOT4_AW-1:0] slot4_addr, // 256 kB + input [SLOT5_AW-1:0] slot5_addr, // 256 kB (16-bit words) + input [SLOT6_AW-1:0] slot6_addr, // 64 kB + input [SLOT7_AW-1:0] slot7_addr, // 32 kB + input [SLOT8_AW-1:0] slot8_addr, // 32 kB + + // output data + output [SLOT0_DW-1:0] slot0_dout, + output [SLOT1_DW-1:0] slot1_dout, + output [SLOT2_DW-1:0] slot2_dout, + output [SLOT3_DW-1:0] slot3_dout, + output [SLOT4_DW-1:0] slot4_dout, + output [SLOT5_DW-1:0] slot5_dout, + output [SLOT6_DW-1:0] slot6_dout, + output [SLOT7_DW-1:0] slot7_dout, + output [SLOT8_DW-1:0] slot8_dout, + + input slot0_cs, + input slot1_cs, + input slot2_cs, + input slot3_cs, + input slot4_cs, + input slot5_cs, + input slot6_cs, + input slot7_cs, + input slot8_cs, + + output slot0_ok, + output slot1_ok, + output slot2_ok, + output slot3_ok, + output slot4_ok, + output slot5_ok, + output slot6_ok, + output slot7_ok, + output slot8_ok, + // SDRAM controller interface + input sdram_ack, + output reg sdram_req, + output reg [21:0] sdram_addr, + input data_dst, + input data_rdy, + input [15:0] data_read, + + // deprecated + input downloading +); + + +reg [ 3:0] rd_state_last; +wire [ 8:0] req, ok; + +reg [ 8:0] data_sel; +wire [21:0] slot0_addr_req, + slot1_addr_req, + slot2_addr_req, + slot3_addr_req, + slot4_addr_req, + slot5_addr_req, + slot6_addr_req, + slot7_addr_req, + slot8_addr_req; + +assign slot0_ok = ok[0]; +assign slot1_ok = ok[1]; +assign slot2_ok = ok[2]; +assign slot3_ok = ok[3]; +assign slot4_ok = ok[4]; +assign slot5_ok = ok[5]; +assign slot6_ok = ok[6]; +assign slot7_ok = ok[7]; +assign slot8_ok = ok[8]; + +wire [21:0] offset0 = SLOT0_OFFSET, + offset1 = SLOT1_OFFSET, + offset2 = SLOT2_OFFSET, + offset3 = SLOT3_OFFSET, + offset4 = SLOT4_OFFSET, + offset5 = SLOT5_OFFSET, + offset6 = SLOT6_OFFSET, + offset7 = SLOT7_OFFSET, + offset8 = SLOT8_OFFSET; + +jtframe_romrq #(.AW(SLOT0_AW),.DW(SLOT0_DW)) u_slot0( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset0 ), + .addr ( slot0_addr ), + .addr_ok ( slot0_cs ), + .sdram_addr( slot0_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot0_dout ), + .req ( req[0] ), + .data_ok ( ok[0] ), + .we ( data_sel[0] ) +); + +jtframe_romrq #(.AW(SLOT1_AW),.DW(SLOT1_DW)) u_slot1( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset1 ), + .addr ( slot1_addr ), + .addr_ok ( slot1_cs ), + .sdram_addr( slot1_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot1_dout ), + .req ( req[1] ), + .data_ok ( ok[1] ), + .we ( data_sel[1] ) +); + +jtframe_romrq #(.AW(SLOT2_AW),.DW(SLOT2_DW)) u_slot2( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset2 ), + .addr ( slot2_addr ), + .addr_ok ( slot2_cs ), + .sdram_addr( slot2_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot2_dout ), + .req ( req[2] ), + .data_ok ( ok[2] ), + .we ( data_sel[2] ) +); + +jtframe_romrq #(.AW(SLOT3_AW),.DW(SLOT3_DW)) u_slot3( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset3 ), + .addr ( slot3_addr ), + .addr_ok ( slot3_cs ), + .sdram_addr( slot3_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot3_dout ), + .req ( req[3] ), + .data_ok ( ok[3] ), + .we ( data_sel[3] ) +); + +jtframe_romrq #(.AW(SLOT4_AW),.DW(SLOT4_DW)) u_slot4( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset4 ), + .addr ( slot4_addr ), + .addr_ok ( slot4_cs ), + .sdram_addr( slot4_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot4_dout ), + .req ( req[4] ), + .data_ok ( ok[4] ), + .we ( data_sel[4] ) +); + +jtframe_romrq #(.AW(SLOT5_AW),.DW(SLOT5_DW)) u_slot5( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset5 ), + .addr ( slot5_addr ), + .addr_ok ( slot5_cs ), + .sdram_addr( slot5_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot5_dout ), + .req ( req[5] ), + .data_ok ( ok[5] ), + .we ( data_sel[5] ) +); + +jtframe_romrq #(.AW(SLOT6_AW),.DW(SLOT6_DW)) u_slot6( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset6 ), + .addr ( slot6_addr ), + .addr_ok ( slot6_cs ), + .sdram_addr( slot6_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot6_dout ), + .req ( req[6] ), + .data_ok ( ok[6] ), + .we ( data_sel[6] ) +); + +jtframe_romrq #(.AW(SLOT7_AW),.DW(SLOT7_DW)) u_slot7( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset7 ), + .addr ( slot7_addr ), + .addr_ok ( slot7_cs ), + .sdram_addr( slot7_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot7_dout ), + .req ( req[7] ), + .data_ok ( ok[7] ), + .we ( data_sel[7] ) +); + + +jtframe_romrq #(.AW(SLOT8_AW),.DW(SLOT8_DW)) u_slot8( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset8 ), + .addr ( slot8_addr ), + .addr_ok ( slot8_cs ), + .sdram_addr( slot8_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot8_dout ), + .req ( req[8] ), + .data_ok ( ok[8] ), + .we ( data_sel[8] ) +); + +wire [8:0] active = ~data_sel & req; + +always @(posedge clk, posedge rst) +if( rst ) begin + sdram_addr <= 22'd0; + sdram_req <= 1'b0; + data_sel <= 9'd0; +end else begin + if( sdram_ack ) sdram_req <= 1'b0; + // accept a new request + if( data_sel==9'd0 || data_rdy ) begin + sdram_req <= |active; + data_sel <= 9'd0; + case( 1'b1 ) + active[0]: begin + sdram_addr <= slot0_addr_req; + data_sel[0] <= 1'b1; + end + active[1]: begin + sdram_addr <= slot1_addr_req; + data_sel[1] <= 1'b1; + end + active[2]: begin + sdram_addr <= slot2_addr_req; + data_sel[2] <= 1'b1; + end + active[3]: begin + sdram_addr <= slot3_addr_req; + data_sel[3] <= 1'b1; + end + active[4]: begin + sdram_addr <= slot4_addr_req; + data_sel[4] <= 1'b1; + end + active[5]: begin + sdram_addr <= slot5_addr_req; + data_sel[5] <= 1'b1; + end + active[6]: begin + sdram_addr <= slot6_addr_req; + data_sel[6] <= 1'b1; + end + active[7]: begin + sdram_addr <= slot7_addr_req; + data_sel[7] <= 1'b1; + end + active[8]: begin + sdram_addr <= slot8_addr_req; + data_sel[8] <= 1'b1; + end + default: ; + endcase + end +end + +endmodule // jtframe_rom \ No newline at end of file diff --git a/rtl/ipcores/jtframe_sdram/jtframe_rom_2slots.v b/rtl/ipcores/jtframe_sdram/jtframe_rom_2slots.v new file mode 100644 index 0000000..8d543a0 --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_rom_2slots.v @@ -0,0 +1,168 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 6-12-2019 */ + +// 2 slots for SDRAM read-only access +// slot 0 --> maximum priority +// slot 1 --> minimum priority +// Each slot can be used for 8, 16 or 32 bit access +// Small 4 byte cache used for each slot + +module jtframe_rom_2slots #(parameter + SDRAMW = 22, + SLOT0_DW = 8, SLOT1_DW = 8, + SLOT0_AW = 8, SLOT1_AW = 8, + + SLOT0_LATCH = 0, + SLOT1_LATCH = 0, + + SLOT0_DOUBLE = 0, + SLOT1_DOUBLE = 0, + + SLOT0_OKLATCH= 1, + SLOT1_OKLATCH= 1, + + parameter [SDRAMW-1:0] SLOT0_OFFSET = 0, + parameter [SDRAMW-1:0] SLOT1_OFFSET = 0, + parameter REF_FILE="sdram_bank3.hex" +)( + input rst, + input clk, + + input [SLOT0_AW-1:0] slot0_addr, + input [SLOT1_AW-1:0] slot1_addr, + + // output data + output [SLOT0_DW-1:0] slot0_dout, + output [SLOT1_DW-1:0] slot1_dout, + + input slot0_cs, + input slot1_cs, + + output slot0_ok, + output slot1_ok, + // SDRAM controller interface + input sdram_ack, + output reg sdram_req, + output reg [SDRAMW-1:0] sdram_addr, + input data_dst, + input data_rdy, + input [15:0] data_read +); + + +reg [ 3:0] ready_cnt; +reg [ 3:0] rd_state_last; +wire [ 1:0] req, ok; + +reg [ 1:0] slot_sel; +wire [SDRAMW-1:0] slot0_addr_req, + slot1_addr_req; + +assign slot0_ok = ok[0]; +assign slot1_ok = ok[1]; + +wire [SDRAMW-1:0] offset0 = SLOT0_OFFSET, + offset1 = SLOT1_OFFSET; + +jtframe_romrq #(.SDRAMW(SDRAMW),.AW(SLOT0_AW),.DW(SLOT0_DW), + .LATCH(SLOT0_LATCH),.DOUBLE(SLOT0_DOUBLE),.OKLATCH(SLOT0_OKLATCH)) +u_slot0( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset0 ), + .addr ( slot0_addr ), + .addr_ok ( slot0_cs ), + .sdram_addr( slot0_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot0_dout ), + .req ( req[0] ), + .data_ok ( ok[0] ), + .we ( slot_sel[0] ) +); + +jtframe_romrq #(.SDRAMW(SDRAMW),.AW(SLOT1_AW),.DW(SLOT1_DW), + .LATCH(SLOT1_LATCH),.DOUBLE(SLOT1_DOUBLE),.OKLATCH(SLOT1_OKLATCH)) +u_slot1( + .rst ( rst ), + .clk ( clk ), + .clr ( 1'b0 ), + .offset ( offset1 ), + .addr ( slot1_addr ), + .addr_ok ( slot1_cs ), + .sdram_addr( slot1_addr_req ), + .din ( data_read ), + .din_ok ( data_rdy ), + .dst ( data_dst ), + .dout ( slot1_dout ), + .req ( req[1] ), + .data_ok ( ok[1] ), + .we ( slot_sel[1] ) +); + +wire [1:0] active = ~slot_sel & req; + +always @(posedge clk, posedge rst) +if( rst ) begin + sdram_addr <= 0; + sdram_req <= 0; + slot_sel <= 0; +end else begin + if( sdram_ack ) sdram_req <= 0; + // accept a new request + if( slot_sel==0 || data_rdy ) begin + sdram_req <= |active; + slot_sel <= 2'd0; + if( active[0] ) begin + sdram_addr <= slot0_addr_req; + slot_sel[0] <= 1; + end else if( active[1] ) begin + sdram_addr <= slot1_addr_req; + slot_sel[1] <= 1; + end + end +end + +`ifdef JTFRAME_SDRAM_CHECK + +reg [15:0] mem[0:4*1024*1024]; + +initial begin + $readmemh( REF_FILE, mem ); +end + +always @( posedge clk ) begin + if( data_rdy ) begin + if( !slot_sel ) begin + $display("ERROR: SDRAM data received but it had not been requested at time %t - %m\n", $time); + $finish; + end else if( { mem[sdram_addr+1], mem[sdram_addr] } !== data_read ) begin + $display("ERROR: Wrong data read at time %t - %m", $time); + $display(" at address %X", sdram_addr ); + $display(" expecting %X_%X - Read %X_%X\n", + mem[sdram_addr+1], mem[sdram_addr], data_read[31:16], data_read[15:0]); + $finish; + end + end +end + +`endif + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jtframe_sdram/jtframe_rom_sync.v b/rtl/ipcores/jtframe_sdram/jtframe_rom_sync.v new file mode 100644 index 0000000..24223ee --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_rom_sync.v @@ -0,0 +1,37 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 27-12-2020 */ + +module jtframe_rom_sync( + input clk, + input rdy_in, + input ack_in, + output rdy_out, + output ack_out +); + +reg last_rdy, last_ack; + +assign rdy_out = rdy_in & last_rdy; +assign ack_out = ack_in & last_ack; + +always @(posedge clk) begin + last_rdy <= rdy_in; + last_ack <= ack_in; +end + +endmodule diff --git a/rtl/ipcores/jtframe_sdram/jtframe_romrq.v b/rtl/ipcores/jtframe_sdram/jtframe_romrq.v new file mode 100644 index 0000000..835676a --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_romrq.v @@ -0,0 +1,271 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 28-2-2019 */ + +// The best use case is with addr_ok going down and up for each addr change +// but it works too with addr_ok permanently high as long as addr input is +// not changed until the data_ok signal is produced. If the requester cannot +// guarantee that, it should toggle addr_ok for each request + +// LATCH LATENCY Timing Requirements +// 0 1 medium +// 1 2 easy + +module jtframe_romrq #(parameter + SDRAMW = 22, // SDRAM width + AW = 18, + DW = 8, + OKLATCH = 1, // Set to 1 to latch the data_ok signal. This implies that + // data_ok will be high for one clock cycle after the input address + // has changed. The requesting module needs to take care of that + // If OKLATCH is zero, data_ok is combinational and it will go to + // zero as soon as the input address changes. This simplifies the + // requesting logic but it is more demanding for timing constraints + DOUBLE = 0, + + LATCH = 0 // dout is latched +)( + input rst, + input clk, + + input clr, // clears the cache + input [SDRAMW-1:0] offset, + + // <-> SDRAM + input [15:0] din, + input din_ok, + input dst, + input we, + output reg req, + output [SDRAMW-1:0] sdram_addr, + + // <-> Consumer + input [AW-1:0] addr, + input addr_ok, // signals that value in addr is valid + output data_ok, // strobe that signals that data is ready + output reg [DW-1:0] dout +); + +reg [AW-1:0] addr_req; + +reg [AW-1:0] cached_addr0, cached_addr1, addr_l; +reg [31:0] cached_data0, cached_data1; +reg [1:0] good; +reg hit0, hit1; +reg dend, double, cache_ok; +wire [AW-1:0] shifted; + +assign sdram_addr = offset + { {SDRAMW-AW{1'b0}}, addr_req>>(DW==8)}; +assign data_ok = OKLATCH ? cache_ok : addr_ok && ( hit0 || hit1 ); + +always @(*) begin + case(DW) + 8: addr_req = {addr[AW-1:2],2'b0}; + 16: addr_req = {addr[AW-1:1],1'b0}; + 32: addr_req = addr; + endcase + // It is important to leave === for simulations, instead of == + // It shouldn't have any implication for synthesis + hit0 = addr_req === cached_addr0 && good[0]; + hit1 = addr_req === cached_addr1 && good[1]; + req = (!(hit0 || hit1) && !we) && addr_ok; +end + +// reg [1:0] ok_sr; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + good <= 'd0; + cached_data0 <= 'd0; + cached_data1 <= 'd0; + cached_addr0 <= 'd0; + cached_addr1 <= 'd0; + cache_ok <= 0; + dend <= 0; + double <= 0; + end else begin + if( clr ) good <= 0; + if( req ) addr_l <= addr_req; + if( we ) begin + if( dst | (double&~dend) ) begin + cached_data1 <= cached_data0; + cached_addr1 <= cached_addr0; + cached_data0[31:16] <= din; + if( double ) + cached_addr0[1] <= ~cached_addr0[1]; + else + cached_addr0 <= addr_l; + good <= { good[0], 1'b1 }; + dend <= 1; + end + if( dend ) begin + cached_data0[31:16] <= din; + cached_data0[15: 0] <= cached_data0[31:16]; + if( !LATCH[0] && !DOUBLE[0] ) cache_ok<= 1; + if( DOUBLE ) double <= ~double; + dend <= 0; + end + end + else begin + cache_ok <= addr_ok && ( hit0 || hit1 ); + double <= 0; + end + end +end + +// data_mux selects one of two cache registers +// but if we are getting fresh data, it selects directly the new data +// this saves one clock cycle at the expense of more LUTs +wire [31:0] data_mux = hit0 ? cached_data0 : cached_data1; +reg [DW-1:0] preout; + +generate + if(DW==8) begin + always @(*) + case( addr[1:0] ) + 2'd0: preout = data_mux[ 7: 0]; + 2'd1: preout = data_mux[15: 8]; + 2'd2: preout = data_mux[23:16]; + 2'd3: preout = data_mux[31:24]; + endcase + end else if(DW==16) begin + always @(*) + case( addr[0] ) + 1'd0: preout = data_mux[15:0]; + 1'd1: preout = data_mux[31:16]; + endcase + end else always @(*) preout = data_mux; +endgenerate + +generate + if( LATCH==0 ) begin : data_latch + always @(*) dout = preout; + end else begin : no_data_latch + always @(posedge clk) dout <= preout; + end +endgenerate + +`ifdef JTFRAME_SDRAM_STATS +jtframe_romrq_stats u_stats( + .clk ( clk ), + .rst ( rst ), + .req ( req ), + .we ( we ), + .din_ok ( din_ok ), + .data_ok( data_ok ) +); +`endif + +`ifdef SIMULATION +`ifndef VERILATOR +`ifndef JTFRAME_SIM_ROMRQ_NOCHECK +reg [AW-1:0] last_addr; +reg waiting, last_req; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + waiting <= 0; + last_req <= 0; + end else begin + last_req <= req; + if( req && !last_req ) begin + if( waiting ) begin + $display("ERROR: %m new request without finishing the previous"); + $finish; + end + last_addr <= addr; + waiting <= 1; + end + if( din_ok && we ) waiting <= 0; + if( waiting && !addr_ok ) begin + $display("ERROR: %m data request interrupted"); + $finish; + end + if( addr != last_addr && addr_ok) begin + if( waiting ) begin + $display("ERROR: %m address changed at time %t",$time); + #40 $finish; + end else waiting <= !hit0 && !hit1; + end + end +end +`endif +`endif +`endif + +endmodule // jtframe_romrq + +`ifdef JTFRAME_SDRAM_STATS +//////////////////////////////////////////////////////////////// +module jtframe_romrq_stats( + input clk, + input rst, + input req, + input we, + input din_ok, + input data_ok +); + +// latency data +integer cur, longest, shortest, total, acc_cnt; +reg cnt_en, last_req, first; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + cur <= 0; + longest <= 0; + shortest <= 10000; + cnt_en <= 0; + last_req <= 0; + acc_cnt <= 0; + total <= 0; + first <= 1; + end else begin + last_req <= req; + if(req && !last_req) begin + cur <= 1; + cnt_en <= 1; + acc_cnt <= acc_cnt+1; + end + if( cnt_en ) begin + cur <= cur+1; + if( (we && din_ok) || data_ok ) begin + if( !first ) begin + if(cur>longest) longest <= cur; + if(cur. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-4-2021 */ + +// SDRAM is set to burst=2 (64 bits) + +module jtframe_sdram64 #( + parameter AW=22, + HF=0, // 1 for HF operation (idle cycles), 0 for LF operation + // HF operation starts at 66.6MHz (1/15ns) + SHIFTED =0, + BA0_LEN =32, // 1=16 bits, 2=32 bits, 4=64 bits + BA1_LEN =32, + BA2_LEN =32, + BA3_LEN =32, + PROG_LEN=64, + + BA0_AUTOPRECH=0, + BA1_AUTOPRECH=0, + BA2_AUTOPRECH=0, + BA3_AUTOPRECH=0, + + MISTER =1, // shorts dqm to address bus 12/11 signals + RFSHCNT=9, // 8192 every 64ms or 1 every 7.8us ~ 8.2 per line (15kHz) + BAPRIO =1 // Bank requests are handled with higher priority to bank 0 + // and lower to to bank 3 +)( + input rst, + input clk, + output init, + + // requests + input [AW-1:0] ba0_addr, + input [AW-1:0] ba1_addr, + input [AW-1:0] ba2_addr, + input [AW-1:0] ba3_addr, + input [3:0] rd, + input [3:0] wr, + input [15:0] din, + input [ 1:0] din_m, // write mask + + // programming + input prog_en, + input [AW-1:0] prog_addr, + input prog_rd, + input prog_wr, + input [15:0] prog_din, + input [ 1:0] prog_din_m, + input [ 1:0] prog_ba, + output reg prog_dst, + output reg prog_dok, + output reg prog_rdy, + output reg prog_ack, + + input rfsh, // triggers a distributed cycle of RFSHCNT refresh commands + // This is meant to be the horizontal blanking of a 15kHz video + // signal. Using HB as rfsh signal also prevents having a bank + // active for longer than tRAS_max (120us) + + output [3:0] ack, + output reg [3:0] dst, + output reg [3:0] dok, + output reg [3:0] rdy, + output reg [15:0] dout, + + // SDRAM interface + // SDRAM_A[12:11] and SDRAM_DQML/H are controlled in a way + // that can be joined together thru an OR operation at a + // higher level. This makes it possible to short the pins + // of the SDRAM, as done in the MiSTer 128MB module + inout [15:0] sdram_dq, // SDRAM Data bus 16 Bits + `ifdef VERILATOR // sdram_dq is used as input-only in Verilator sims + output [15:0] sdram_din, // Data to be stored in SDRAM + `endif + output reg [12:0] sdram_a, // SDRAM Address bus 13 Bits + output sdram_dqml, // SDRAM Low-byte Data Mask + output sdram_dqmh, // SDRAM High-byte Data Mask + output reg [ 1:0] sdram_ba, // SDRAM Bank Address + output sdram_nwe, // SDRAM Write Enable + output sdram_ncas, // SDRAM Column Address Strobe + output sdram_nras, // SDRAM Row Address Strobe + output sdram_ncs, // SDRAM Chip Select + output sdram_cke // SDRAM Chip Select +); + +localparam BURSTLEN=(BA0_LEN>32 || BA1_LEN>32 ||BA2_LEN>32 ||BA3_LEN>32) ? 64 :( + (BA0_LEN>16 || BA1_LEN>16 ||BA2_LEN>16 ||BA3_LEN>16) ? 32 : 16); + +localparam LATCH = HF==1; + +// /CS /RAS /CAS /WE +localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0 + CMD_REFRESH = 4'b0___0____0____1, // 1 + CMD_PRECHARGE = 4'b0___0____1____0, // 2 + CMD_ACTIVE = 4'b0___0____1____1, // 3 + CMD_WRITE = 4'b0___1____0____0, // 4 + CMD_READ = 4'b0___1____0____1, // 5 + CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate + CMD_NOP = 4'b0___1____1____1, // 7 + CMD_INHIBIT = 4'b1___0____0____0; // 8 + +wire [3:0] br, bx0_cmd, bx1_cmd, bx2_cmd, bx3_cmd, rfsh_cmd, + ba_dst, ba_dbusy, ba_dbusy64, ba_rdy, ba_dok, + init_cmd, post_act, next_cmd, dqm_busy, match; +wire all_act, rfshing, rfsh_br, noreq, help; +reg all_dbusy, all_dbusy64; +reg [3:0] bg, cmd; +reg [14:0] prio_lfsr; +wire [12:0] bx0_a, bx1_a, bx2_a, bx3_a, init_a, next_a, rfsh_a, + ba0_row, ba1_row, ba2_row, ba3_row; +wire [ 1:0] next_ba, prio; + +wire [AW-1:0] ba0_addr_l, ba1_addr_l, ba2_addr_l, ba3_addr_l; +wire [3:0] rd_l, wr_l; +wire [4:0] wr_busy, idle; +wire wr_cycle; + +// prog signals +wire pre_dst, pre_dok, pre_ack, pre_rdy; +wire [12:0] pre_a; +wire [ 3:0] pre_cmd; +reg prog_rst, prog_bg, other_rst, rfsh_rst; + +reg rfsh_bg; +reg [ 1:0] dqm; +wire [ 1:0] mask_mux; +wire all_dqm, prog_busy, pre_br; + +assign {sdram_ncs, sdram_nras, sdram_ncas, sdram_nwe } = cmd; +assign {sdram_dqmh, sdram_dqml} = MISTER ? sdram_a[12:11] : dqm; +assign sdram_cke = 1; +assign all_act = |post_act; +assign all_dqm = |dqm_busy; +assign wr_cycle = |wr_busy; + +assign {next_ba, next_cmd, next_a } = + init ? { 2'd0, init_cmd, init_a } : ( + rfshing? { 2'd0, rfsh_cmd, rfsh_a } : ( + prog_en? { prog_ba, pre_cmd, pre_a} : ( + bg[3] ? { 2'd3, bx3_cmd, bx3_a } : ( + bg[2] ? { 2'd2, bx2_cmd, bx2_a } : ( + bg[1] ? { 2'd1, bx1_cmd, bx1_a } : + { 2'd0, bx0_cmd, bx0_a } ))))); + +assign prio = prio_lfsr[1:0]; +assign mask_mux = prog_en ? prog_din_m : din_m; + +`ifndef VERILATOR +reg [15:0] dq_pad; +assign sdram_dq = dq_pad; +`else +assign sdram_din = prog_en ? prog_din : din; +`endif + +always @(negedge clk) begin + prog_rst <= ~prog_en | init | rst; + rfsh_rst <= init | rst; + other_rst <= prog_en | init | rst; +end + +always @(posedge clk) begin + dst <= ba_dst; + rdy <= ba_rdy; + all_dbusy <= |ba_dbusy; + all_dbusy64 <= |ba_dbusy64; + dok <= ba_dok; + dout <= sdram_dq; + cmd <= next_cmd; + + // prog signals + prog_dst <= pre_dst; + prog_dok <= pre_dok; + prog_rdy <= pre_rdy; + prog_ack <= pre_ack; + + sdram_ba <= next_ba; + sdram_a[10:0] <= next_a[10:0]; + +`ifndef VERILATOR + dq_pad <= wr_cycle ? (prog_en ? prog_din : din) : 16'hzzzz; +`endif + if( MISTER ) begin + if( next_cmd==CMD_ACTIVE ) + sdram_a[12:11] <= next_a[12:11]; + else + sdram_a[12:11] <= wr_cycle ? mask_mux : 2'd0; + end else begin + sdram_a[12:11] <= next_a[12:11]; + dqm <= wr_cycle ? mask_mux : 2'd0; + end +end + +always @(posedge clk, posedge rst) begin + if( rst ) begin + prio_lfsr <= 1; + end else begin + prio_lfsr <= { prio_lfsr[0]^prio_lfsr[14], prio_lfsr[14:1] }; + end +end + +jtframe_sdram64_latch #(.LATCH(LATCH),.AW(AW)) u_latch( + .rst ( rst ), + .clk ( clk ), + .ba0_addr ( ba0_addr ), + .ba1_addr ( ba1_addr ), + .ba2_addr ( ba2_addr ), + .ba3_addr ( ba3_addr ), + .ba0_addr_l ( ba0_addr_l), + .ba1_addr_l ( ba1_addr_l), + .ba2_addr_l ( ba2_addr_l), + .ba3_addr_l ( ba3_addr_l), + .ba0_row ( ba0_row ), + .ba1_row ( ba1_row ), + .ba2_row ( ba2_row ), + .ba3_row ( ba3_row ), + .match ( match ), + .prog_en ( prog_en ), + .prog_rd ( prog_rd ), + .prog_wr ( prog_wr ), + .rd ( rd ), + .rd_l ( rd_l ), + .wr ( wr ), + .wr_l ( wr_l ), + .noreq ( noreq ) +); + +jtframe_sdram64_init #(.HF(HF),.BURSTLEN(BURSTLEN)) u_init( + .rst ( rst ), + .clk ( clk ), + + .init ( init ), + .cmd ( init_cmd ), + .sdram_a ( init_a ) +); + +jtframe_sdram64_rfsh #(.HF(HF),.RFSHCNT(RFSHCNT)) u_rfsh( + .rst ( rfsh_rst ), + .clk ( clk ), + + .start ( rfsh ), + .br ( rfsh_br ), + .bg ( rfsh_bg ), + .noreq ( noreq ), + .rfshing ( rfshing ), + .cmd ( rfsh_cmd ), + .help ( help ), + .sdram_a ( rfsh_a ) +); + +jtframe_sdram64_bank #( + .AW ( AW ), + .HF ( HF ), + .SHIFTED ( SHIFTED ), + .BALEN ( PROG_LEN), + .BURSTLEN ( BURSTLEN), + // The programmer always precharges all banks + // at the beginning of the operation + .AUTOPRECH ( 1 ), + .PRECHARGE_ALL( 1 ) +) u_prog( + .rst ( prog_rst ), + .clk ( clk ), + + // requests + .addr ( prog_addr ), + .rd ( prog_rd ), + .wr ( prog_wr ), + + .ack ( pre_ack ), + .dst ( pre_dst ), // data starts + .dbusy ( ), // prog works alone + .all_dbusy ( 1'd0 ), + .idle ( idle[4] ), + + .dbusy64 ( prog_busy ), + .all_dbusy64( 1'd0 ), + + .post_act ( ), + .all_act ( 1'd0 ), + + .dqm_busy ( ), + .all_dqm ( 1'd0 ), + .wr_busy ( wr_busy[4] ), + + .row ( ), + .match ( 1'b0 ), + + .dok ( pre_dok ), + .rdy ( pre_rdy ), + .set_prech ( 1'd0 ), + + // SDRAM interface + .br ( pre_br ), // bus request + .bg ( prog_bg ), // bus grant + + .sdram_a ( pre_a ), + .cmd ( pre_cmd ) +); + +jtframe_sdram64_bank #( + .AW ( AW ), + .HF ( HF ), + .SHIFTED ( SHIFTED ), + .BURSTLEN ( BURSTLEN ), + .BALEN ( BA0_LEN ), + .AUTOPRECH( BA0_AUTOPRECH ) +) u_bank0( + .rst ( other_rst ), + .clk ( clk ), + + // requests + .addr ( ba0_addr_l ), + .rd ( rd_l[0] ), + .wr ( wr_l[0] ), + + .ack ( ack[0] ), + .dst ( ba_dst[0] ), // data starts + .dbusy ( ba_dbusy[0]), + .all_dbusy ( all_dbusy ), + .idle ( idle[0] ), + + .dbusy64 (ba_dbusy64[0]), + .all_dbusy64( all_dbusy64), + .wr_busy ( wr_busy[0] ), + + .post_act ( post_act[0]), + .all_act ( all_act ), + + .dqm_busy ( dqm_busy[0]), + .all_dqm ( all_dqm ), + + .dok ( ba_dok[0] ), + .rdy ( ba_rdy[0] ), + .set_prech ( rfsh_bg ), + + .row ( ba0_row ), + .match ( match[0] ), + + // SDRAM interface + .br ( br[0] ), // bus request + .bg ( bg[0] ), // bus grant + + .sdram_a ( bx0_a ), + .cmd ( bx0_cmd ) +); + +jtframe_sdram64_bank #( + .AW ( AW ), + .HF ( HF ), + .SHIFTED ( SHIFTED ), + .BURSTLEN ( BURSTLEN ), + .BALEN ( BA1_LEN ), + .AUTOPRECH( BA1_AUTOPRECH ) +) u_bank1( + .rst ( other_rst ), + .clk ( clk ), + + // requests + .addr ( ba1_addr_l ), + .rd ( rd_l[1] ), + .wr ( wr_l[1] ), + + .ack ( ack[1] ), + .dst ( ba_dst[1] ), // data starts + .dbusy ( ba_dbusy[1]), + .all_dbusy ( all_dbusy ), + .idle ( idle[1] ), + + .dbusy64 (ba_dbusy64[1]), + .all_dbusy64( all_dbusy64), + .wr_busy ( wr_busy[1] ), + + .post_act ( post_act[1]), + .all_act ( all_act ), + .dok ( ba_dok[1] ), + .rdy ( ba_rdy[1] ), + .set_prech ( rfsh_bg ), + + .dqm_busy ( dqm_busy[1]), + .all_dqm ( all_dqm ), + + .row ( ba1_row ), + .match ( match[1] ), + + // SDRAM interface + .br ( br[1] ), // bus request + .bg ( bg[1] ), // bus grant + + .sdram_a ( bx1_a ), + .cmd ( bx1_cmd ) +); + +jtframe_sdram64_bank #( + .AW ( AW ), + .HF ( HF ), + .SHIFTED ( SHIFTED ), + .BURSTLEN ( BURSTLEN ), + .BALEN ( BA2_LEN ), + .AUTOPRECH( BA2_AUTOPRECH ) +) u_bank2( + .rst ( other_rst ), + .clk ( clk ), + + // requests + .addr ( ba2_addr_l ), + .rd ( rd_l[2] ), + .wr ( wr_l[2] ), + + .ack ( ack[2] ), + .dst ( ba_dst[2] ), // data starts + .dbusy ( ba_dbusy[2]), + .all_dbusy ( all_dbusy ), + .idle ( idle[2] ), + + .dbusy64 (ba_dbusy64[2]), + .all_dbusy64( all_dbusy64), + .wr_busy ( wr_busy[2] ), + + .post_act ( post_act[2]), + .all_act ( all_act ), + .dok ( ba_dok[2] ), + .rdy ( ba_rdy[2] ), + .set_prech ( rfsh_bg ), + + .dqm_busy ( dqm_busy[2]), + .all_dqm ( all_dqm ), + + .row ( ba2_row ), + .match ( match[2] ), + + // SDRAM interface + .br ( br[2] ), // bus request + .bg ( bg[2] ), // bus grant + + .sdram_a ( bx2_a ), + .cmd ( bx2_cmd ) +); + +jtframe_sdram64_bank #( + .AW ( AW ), + .HF ( HF ), + .SHIFTED ( SHIFTED ), + .BURSTLEN ( BURSTLEN ), + .BALEN ( BA3_LEN ), + .AUTOPRECH( BA3_AUTOPRECH ) +) u_bank3( + .rst ( other_rst ), + .clk ( clk ), + + // requests + .addr ( ba3_addr_l ), + .rd ( rd_l[3] ), + .wr ( wr_l[3] ), + + .ack ( ack[3] ), + .dst ( ba_dst[3] ), // data starts + .dbusy ( ba_dbusy[3]), + .all_dbusy ( all_dbusy ), + .wr_busy ( wr_busy[3] ), + .idle ( idle[3] ), + + .dbusy64 (ba_dbusy64[3]), + .all_dbusy64( all_dbusy64), + + .post_act ( post_act[3]), + .all_act ( all_act ), + .dok ( ba_dok[3] ), + .rdy ( ba_rdy[3] ), + .set_prech ( rfsh_bg ), + + .dqm_busy ( dqm_busy[3]), + .all_dqm ( all_dqm ), + + .row ( ba3_row ), + .match ( match[3] ), + + // SDRAM interface + .br ( br[3] ), // bus request + .bg ( bg[3] ), // bus grant + + .sdram_a ( bx3_a ), + .cmd ( bx3_cmd ) +); + +always @(*) begin + rfsh_bg = &idle && (noreq | help) && rfsh_br; + prog_bg = pre_br & !rfshing; + if( rfshing | help ) begin + bg=0; + end else begin + if( BAPRIO ) begin + casez( br ) // Bank requests have priority (eases timing) + 4'b???1: bg=4'b0001; + 4'b??10: bg=4'b0010; + 4'b?100: bg=4'b0100; + 4'b1000: bg=4'b1000; + default: bg=0; + endcase + end else begin // Bank requests are randomized (tougher timing) + case( {br, prio[1:0]} ) + 6'b0000_00: bg=4'b0000; + 6'b0000_01: bg=4'b0000; + 6'b0000_10: bg=4'b0000; + 6'b0000_11: bg=4'b0000; + 6'b0001_00: bg=4'b0001; + 6'b0001_01: bg=4'b0001; + 6'b0001_10: bg=4'b0001; + 6'b0001_11: bg=4'b0001; + 6'b0010_00: bg=4'b0010; + 6'b0010_01: bg=4'b0010; + 6'b0010_10: bg=4'b0010; + 6'b0010_11: bg=4'b0010; + 6'b0011_00: bg=4'b0001; + 6'b0011_01: bg=4'b0010; + 6'b0011_10: bg=4'b0001; + 6'b0011_11: bg=4'b0010; + 6'b0100_00: bg=4'b0100; + 6'b0100_01: bg=4'b0100; + 6'b0100_10: bg=4'b0100; + 6'b0100_11: bg=4'b0100; + 6'b0101_00: bg=4'b0001; + 6'b0101_01: bg=4'b0001; + 6'b0101_10: bg=4'b0100; + 6'b0101_11: bg=4'b0100; + + 6'b0110_00: bg=4'b0010; + 6'b0110_01: bg=4'b0010; + 6'b0110_10: bg=4'b0100; + 6'b0110_11: bg=4'b0100; + + 6'b0111_00: bg=4'b0001; + 6'b0111_01: bg=4'b0010; + 6'b0111_10: bg=4'b0100; + 6'b0111_11: bg=4'b0001; //*0001 + + 6'b1000_00: bg=4'b1000; + 6'b1000_01: bg=4'b1000; + 6'b1000_10: bg=4'b1000; + 6'b1000_11: bg=4'b1000; + + 6'b1001_00: bg=4'b0001; + 6'b1001_01: bg=4'b0001; + 6'b1001_10: bg=4'b1000; + 6'b1001_11: bg=4'b1000; + + 6'b1010_00: bg=4'b0010; + 6'b1010_01: bg=4'b0010; + 6'b1010_10: bg=4'b1000; + 6'b1010_11: bg=4'b1000; + + 6'b1011_00: bg=4'b0001; + 6'b1011_01: bg=4'b0010; //*0010 + 6'b1011_10: bg=4'b0010; + 6'b1011_11: bg=4'b1000; + + 6'b1100_00: bg=4'b1000; + 6'b1100_01: bg=4'b0100; + 6'b1100_10: bg=4'b0100; + 6'b1100_11: bg=4'b1000; + + 6'b1101_00: bg=4'b0001; + 6'b1101_01: bg=4'b0100; //*0100 + 6'b1101_10: bg=4'b0100; + 6'b1101_11: bg=4'b1000; + + 6'b1110_00: bg=4'b1000; //*1000 + 6'b1110_01: bg=4'b0010; + 6'b1110_10: bg=4'b0100; + 6'b1110_11: bg=4'b1000; + + 6'b1111_00: bg=4'b0001; + 6'b1111_01: bg=4'b0010; + 6'b1111_10: bg=4'b0100; + 6'b1111_11: bg=4'b1000; + endcase + end + end +end + +`ifdef SIMULATION +always @(posedge clk) begin + if( (rd!=0 || wr!=0) && init ) begin + $display("\nERROR: SDRAM rd/wr inputs should be zero during initialization (%m)"); + $finish; + end +end +`endif + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jtframe_sdram/jtframe_sdram64_bank.v b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_bank.v new file mode 100644 index 0000000..aa8198b --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_bank.v @@ -0,0 +1,256 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-4-2021 */ + +// SDRAM is set to burst=2 (64 bits) + +module jtframe_sdram64_bank #( + parameter AW=22, + HF=0, // 1 for HF operation (idle cycles), 0 for LF operation + // HF operation starts at 66.6MHz (1/15ns) + SHIFTED =0, + AUTOPRECH =0, + PRECHARGE_ALL=0, + BALEN =64, // 16, 32 or 64 bits + BURSTLEN =64, + READONLY =1 // set to 1 if ALL BANKS can only read + // this will make dbusy64 match dbusy +)( + input rst, + input clk, + + // requests + input [AW-1:0] addr, + input rd, + input wr, + + output ack, + output dst, // data starts + output reg dok, // data ok + output rdy, + input set_prech, + + output dbusy, // DQ bus busy (read values only) + output dbusy64, // DQ bus busy (the full four clock cycles) + output reg dqm_busy, // DQM lines are used + output reg wr_busy, // output access to DQ bus + input all_dbusy, + input all_dbusy64, + input all_dqm, + output idle, + + output reg post_act, // cycles banned for activate (tRRD) + input all_act, + + // row matching + output reg [12:0] row, + input match, + + // SDRAM interface + output reg br, // bus request + input bg, // bus grant + + // SDRAM_A[12:11] and SDRAM_DQML/H are controlled in a way + // that can be joined together thru an OR operation at a + // higher level. This makes it possible to short the pins + // of the SDRAM, as done in the MiSTer 128MB module + output reg [12:0] sdram_a, // SDRAM Address bus 13 Bits + output reg [ 3:0] cmd +); + +localparam ROW=13, + COW= AW==22 ? 9 : 10; // 9 for 32MB SDRAM, 10 for 64MB + +// states +localparam IDLE = 0, + // AUTOPRECH 1+2(1) + PRE_ACT = HF ? 3:2, + ACT = PRE_ACT+1, + PRE_RD = PRE_ACT + (HF ? 3:2), + READ = PRE_RD+1, + DST = READ + (SHIFTED ? 1 : 2) , + DTICKS = BURSTLEN==64 ? 4 : (BURSTLEN==32?2:1), + BUSY = DST+(DTICKS-1), + RDY = DST + (BALEN==16 ? 0 : (BALEN==32? 1 : 3)), + STW = BUSY + 2 + {2'd0,AUTOPRECH[0]}; + +// /CS /RAS /CAS /WE +localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0 + CMD_REFRESH = 4'b0___0____0____1, // 1 + CMD_PRECHARGE = 4'b0___0____1____0, // 2 + CMD_ACTIVE = 4'b0___0____1____1, // 3 + CMD_WRITE = 4'b0___1____0____0, // 4 + CMD_READ = 4'b0___1____0____1, // 5 + CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate + CMD_NOP = 4'b0___1____1____1, // 7 + CMD_INHIBIT = 4'b1___0____0____0; // 8 + +localparam [STW-1:0] ONE = 1; +/* +`ifdef SIMULATION +initial begin + $display("%m\n\tREAD=%2d\n\tDST=%2d\n\tRDY=%2d\n\tSTW=%2d",READ,DST,RDY,STW); +end +`endif +*/ +reg actd, prechd; +wire [ROW-1:0] addr_row; +reg [STW-1:0] st, next_st, rot_st; +reg last_act; +wire rd_wr; + +reg do_prech, do_act, do_read, written; + +// state phases +reg in_busy, in_busy64; + +// SDRAM pins +assign ack = st[READ], + dst = st[DST] | (st[READ] & wr), + dbusy = |{in_busy, do_read}, + dbusy64 = READONLY ? dbusy : |{in_busy64, do_read}, + rdy = (written && !AUTOPRECH) ? st[READ] : st[RDY], + addr_row = AW==22 ? addr[AW-1:AW-ROW] : addr[AW-2:AW-1-ROW], + rd_wr = rd | wr, + idle = st[0]; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + in_busy <= 0; // |st[ (BALEN==16? READ+1 : RDY-2):READ] + in_busy64 <= 0; // |{st[BUSY:READ], do_read} + dok <= 0; // |st[RDY:DST] + dqm_busy <= 0; // |{st[RDY-2:READ]} + end else begin + if(next_st[READ]) in_busy <= 1; + else if( st[(BALEN==16? READ+1 : RDY-2)] || next_st[READ-1:0]!=0 ) in_busy<=0; + + if(next_st[READ]) in_busy64 <= 1; + else if( st[BUSY] || next_st[READ-1:0]!=0 ) in_busy64<=0; + + if(next_st[DST]) dok<=1; + else if( st[RDY] || next_st[DST-1:0]!=0 ) dok <= 0; + + if(next_st[READ]) dqm_busy<=1; + else if(st[RDY-2] || next_st[READ-1:0]!=0) dqm_busy<=0; + + end +end + +always @(*) begin + rot_st = { st[STW-2:0], st[STW-1] }; + next_st = st; + if( st[IDLE] ) begin + if(do_prech) next_st = rot_st; + if(do_act ) next_st = ONE<. + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-4-2021 */ + +module jtframe_sdram64_init #(parameter + HF =1, + BURSTLEN=64 +) ( + input rst, + input clk, + + output reg init, + output reg [3:0] cmd, + output reg [12:0] sdram_a +); + +localparam [13:0] INIT_WAIT = HF ? 14'd10_000 : 14'd5_000; // 100us for 96MHz/48MHz + +// /CS /RAS /CAS /WE +localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0 + CMD_REFRESH = 4'b0___0____0____1, // 1 + CMD_PRECHARGE = 4'b0___0____1____0, // 2 + CMD_ACTIVE = 4'b0___0____1____1, // 3 + CMD_WRITE = 4'b0___1____0____0, // 4 + CMD_READ = 4'b0___1____0____1, // 5 + CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate + CMD_NOP = 4'b0___1____1____1, // 7 + CMD_INHIBIT = 4'b1___0____0____0; // 8 + +// initialization signals +reg [13:0] wait_cnt; +reg [ 2:0] init_st; +reg [ 3:0] init_cmd; + +always @(posedge clk, posedge rst) begin + if( rst ) begin + // initialization loop + init <= 1; + wait_cnt <= INIT_WAIT; // wait for 100us + init_st <= 3'd0; + init_cmd <= CMD_NOP; + // SDRAM pins + cmd <= CMD_NOP; + sdram_a <= 13'd0; + end else if( init ) begin + if( |wait_cnt ) begin + wait_cnt <= wait_cnt-14'd1; + init_cmd <= CMD_NOP; + cmd <= init_cmd; + end else begin + sdram_a <= 13'd0; + if(!init_st[2]) init_st <= init_st+3'd1; + case(init_st) + 3'd0: begin + init_cmd <= CMD_PRECHARGE; + sdram_a[10]<= 1; // all banks + wait_cnt <= 14'd2; + end + 3'd1: begin + init_cmd <= CMD_REFRESH; + wait_cnt <= 14'd11; + end + 3'd2: begin + init_cmd <= CMD_REFRESH; + wait_cnt <= 14'd11; + end + 3'd3: begin + init_cmd <= CMD_LOAD_MODE; + sdram_a <= {10'b00_1_00_010_0,BURSTLEN==64?3'b010:(BURSTLEN==32?3'b001:3'b000)}; // CAS Latency = 2, burst = 1-4 + wait_cnt <= 14'd3; + end + 3'd4: begin + init <= 0; + end + default: begin + cmd <= init_cmd; + init <= 0; + end + endcase + end + end +end + +endmodule \ No newline at end of file diff --git a/rtl/ipcores/jtframe_sdram/jtframe_sdram64_latch.v b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_latch.v new file mode 100644 index 0000000..d1528c4 --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_latch.v @@ -0,0 +1,92 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-4-2021 */ + +module jtframe_sdram64_latch #(parameter LATCH=0, AW=22)( + input rst, + input clk, + input [AW-1:0] ba0_addr, + input [AW-1:0] ba1_addr, + input [AW-1:0] ba2_addr, + input [AW-1:0] ba3_addr, + output reg [AW-1:0] ba0_addr_l, + output reg [AW-1:0] ba1_addr_l, + output reg [AW-1:0] ba2_addr_l, + output reg [AW-1:0] ba3_addr_l, + input [ 12:0] ba0_row, + input [ 12:0] ba1_row, + input [ 12:0] ba2_row, + input [ 12:0] ba3_row, + input [3:0] rd, + input [3:0] wr, + input prog_en, + input prog_rd, + input prog_wr, + output reg [3:0] rd_l, + output reg [3:0] wr_l, + output reg [3:0] match, + output reg noreq +); + +localparam RMSB = AW==22 ? AW-1 : AW-2, + RLSB = RMSB-12; + +wire prog_rq = prog_en &(prog_wr | prog_rd); + +generate + if( LATCH==1 ) begin + always @(posedge clk, posedge rst) begin + if( rst ) begin + ba0_addr_l <= 0; + ba1_addr_l <= 0; + ba2_addr_l <= 0; + ba3_addr_l <= 0; + wr_l <= 0; + rd_l <= 0; + noreq <= 1; + end else begin + ba0_addr_l <= ba0_addr; + ba1_addr_l <= ba1_addr; + ba2_addr_l <= ba2_addr; + ba3_addr_l <= ba3_addr; + match[0] <= ba0_addr[RMSB:RLSB]===ba0_row; + match[1] <= ba1_addr[RMSB:RLSB]===ba1_row; + match[2] <= ba2_addr[RMSB:RLSB]===ba2_row; + match[3] <= ba3_addr[RMSB:RLSB]===ba3_row; + wr_l <= wr; + rd_l <= rd; + noreq <= ~|{wr,rd,prog_rq}; + end + end + end else begin + always @(*) begin + ba0_addr_l = ba0_addr; + ba1_addr_l = ba1_addr; + ba2_addr_l = ba2_addr; + ba3_addr_l = ba3_addr; + match[0] = ba0_addr[RMSB:RLSB]===ba0_row; + match[1] = ba1_addr[RMSB:RLSB]===ba1_row; + match[2] = ba2_addr[RMSB:RLSB]===ba2_row; + match[3] = ba3_addr[RMSB:RLSB]===ba3_row; + wr_l = wr; + rd_l = rd; + noreq = ~|{wr,rd,prog_rq}; + end + end +endgenerate + +endmodule diff --git a/rtl/ipcores/jtframe_sdram/jtframe_sdram64_rfsh.v b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_rfsh.v new file mode 100644 index 0000000..2e448f8 --- /dev/null +++ b/rtl/ipcores/jtframe_sdram/jtframe_sdram64_rfsh.v @@ -0,0 +1,119 @@ +/* This file is part of JTFRAME. + JTFRAME program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + JTFRAME program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 29-4-2021 */ + +module jtframe_sdram64_rfsh #(parameter HF=1, RFSHCNT=9) +( + input rst, + input clk, + + input start, + output reg br, + input bg, + input noreq, + output reg rfshing, + output reg [3:0] cmd, + output reg help, + output [12:0] sdram_a +); + +// Frequency limits before getting a tRFC error +// HF=0 -> 60MHz (16.67ns) +// HF=1 -> 100MHz (10ns) + +localparam STW = 3+7-(HF==1? 0 : 4), + RFRSH= HF?2:1; + +localparam CW=6; +localparam [STW-1:0] ONE=1; + +// /CS /RAS /CAS /WE +localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0 + CMD_REFRESH = 4'b0___0____0____1, // 1 + CMD_PRECHARGE = 4'b0___0____1____0, // 2 + CMD_ACTIVE = 4'b0___0____1____1, // 3 + CMD_WRITE = 4'b0___1____0____0, // 4 + CMD_READ = 4'b0___1____0____1, // 5 + CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate + CMD_NOP = 4'b0___1____1____1, // 7 + CMD_INHIBIT = 4'b1___0____0____0; // 8 + +`ifdef SIMULATION +initial begin + if( RFSHCNT >= (1< 1 and added DJNZ M1_n fix by Mike Johnson +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- 0237 : Changed 8080 I/O address output, added IntE output +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode +-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +use work.all; + +entity T80 is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); +end T80; + +architecture rtl of T80 is + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + XY_State : in std_logic_vector(1 downto 0); + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetWZ : out std_logic_vector(1 downto 0); + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + XYbit_undoc : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + WZ : in std_logic_vector(15 downto 0); + XY_State : in std_logic_vector(1 downto 0); + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0); + DOR : out std_logic_vector(127 downto 0); + DIRSet : in std_logic; + DIR : in std_logic_vector(127 downto 0) + ); + end component; + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + -- Registers + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; + + -- Help Registers + signal WZ : std_logic_vector(15 downto 0); -- MEMPTR register + signal IR : std_logic_vector(7 downto 0); -- Instruction register + signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector + signal RegBusA_r : std_logic_vector(15 downto 0); + + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); + + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal IntE_FF1 : std_logic; + signal IntE_FF2 : std_logic; + signal Halt_FF : std_logic; + signal BusReq_s : std_logic; + signal BusAck : std_logic; + signal ClkEn : std_logic; + signal NMI_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); + + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; + + -- ALU signals + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); + + -- Registered micro code outputs + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); + + -- Micro code outputs + signal MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(3 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Save_ALU : std_logic; + signal PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_i : std_logic; + signal Special_LD : std_logic_vector(2 downto 0); + signal ExchangeDH : std_logic; + signal ExchangeRp : std_logic; + signal ExchangeAF : std_logic; + signal ExchangeRS : std_logic; + signal I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_RXDD : std_logic; + signal I_INRC : std_logic; + signal SetWZ : std_logic_vector(1 downto 0); + signal SetDI : std_logic; + signal SetEI : std_logic; + signal IMode : std_logic_vector(1 downto 0); + signal Halt : std_logic; + signal XYbit_undoc : std_logic; + signal DOR : std_logic_vector(127 downto 0); + +begin + + REG <= IntE_FF2 & IntE_FF1 & IStatus & DOR & std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC when Alternate = '0' + else IntE_FF2 & IntE_FF1 & IStatus & DOR(127 downto 112) & DOR(47 downto 0) & DOR(63 downto 48) & DOR(111 downto 64) & + std_logic_vector(PC) & std_logic_vector(SP) & std_logic_vector(R) & I & Fp & Ap & F & ACC; + + mcode : T80_MCode + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + XY_State => XY_State, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, + Read_To_Acc => Read_To_Acc, + Read_To_Reg => Read_To_Reg, + Set_BusB_To => Set_BusB_To, + Set_BusA_To => Set_BusA_To, + ALU_Op => ALU_Op, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, + Set_Addr_To => Set_Addr_To, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetWZ => SetWZ, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write, + XYbit_undoc => XYbit_undoc); + + alu : T80_ALU + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + Arith16 => Arith16_r, + Z16 => Z16_r, + WZ => WZ, + XY_State=> XY_State, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); + + ClkEn <= CEN and not BusAck; + + T_Res <= '1' when TState = unsigned(TStates) else '0'; + + NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and + ((Set_Addr_To = aXY) or + (MCycle = "001" and IR = "11001011") or + (MCycle = "001" and IR = "00110110")) else '0'; + + Save_Mux <= BusB when ExchangeRp = '1' else + DI_Reg when Save_ALU_r = '0' else + ALU_Q; + + process (RESET_n, CLK_n) + variable n : std_logic_vector(7 downto 0); + variable ioq : std_logic_vector(8 downto 0); + begin + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + WZ <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; + + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; + + Read_To_Reg_r <= "00000"; + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + I_RXDD <= '0'; + + elsif rising_edge(CLK_n) then + + if DIRSet = '1' then + ACC <= DIR( 7 downto 0); + F <= DIR(15 downto 8); + Ap <= DIR(23 downto 16); + Fp <= DIR(31 downto 24); + I <= DIR(39 downto 32); + R <= unsigned(DIR(47 downto 40)); + SP <= unsigned(DIR(63 downto 48)); + PC <= unsigned(DIR(79 downto 64)); + A <= DIR(79 downto 64); + IStatus <= DIR(209 downto 208); + + elsif ClkEn = '1' then + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; + + MCycles <= MCycles_d; + + if IMode /= "11" then + IStatus <= IMode; + end if; + + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; + + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 + + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; + + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; + else + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; + end if; + else + XY_State <= "00"; + XY_Ind <= '0'; + end if; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= WZ; + PC <= unsigned(WZ); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= WZ(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(WZ(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= WZ; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + WZ <= (ACC & DI_Reg) + "1"; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + if SetWZ = "01" then + WZ <= RegBusC + "1"; + end if; + if SetWZ = "10" then + WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + end if; + when aDE => + A <= RegBusC; + if SetWZ = "10" then + WZ(7 downto 0) <= RegBusC(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(WZ) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= WZ(7 downto 0); + if SetWZ = "10" then + WZ(7 downto 0) <= WZ(7 downto 0) + "1"; + WZ(15 downto 8) <= ACC; + end if; + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + if SetWZ = "11" then + WZ <= std_logic_vector(ID16); + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if (TState = 2 and I_BTR = '1' and IR(0) = '1') or (TState = 1 and I_BTR = '1' and IR(0) = '0') then + ioq := ('0' & DI_Reg) + ('0' & std_logic_vector(ID16(7 downto 0))); + F(Flag_N) <= DI_Reg(7); + F(Flag_C) <= ioq(8); + F(Flag_H) <= ioq(8); + ioq := (ioq and ('0' & x"07")) xor ('0'&BusA); + F(Flag_P) <= not (ioq(0) xor ioq(1) xor ioq(2) xor ioq(3) xor ioq(4) xor ioq(5) xor ioq(6) xor ioq(7)); + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + WZ <= std_logic_vector(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + WZ <= (others =>'0'); + WZ(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + WZ <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if MCycle = "011" and TState = 4 and No_BTR = '0' then + if I_BT = '1' or I_BC = '1' then + WZ <= std_logic_vector(PC)-"1"; + end if; + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + WZ(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + WZ(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= I(7); + + if I = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= I(5); + F(Flag_H) <= '0'; + F(Flag_X) <= I(3); + F(Flag_N) <= '0'; + + + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + F(Flag_S) <= R(7); + + if R = x"00" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + + F(Flag_Y) <= R(5); + F(Flag_H) <= '0'; + F(Flag_X) <= R(3); + F(Flag_N) <= '0'; + + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + F(Flag_X) <= DI_Reg(3); + F(Flag_Y) <= DI_Reg(5); + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 and Auto_Wait_t1 = '0' then + -- Keep D0 from M3 for RLD/RRD (Sorgelig) + I_RXDD <= I_RLD or I_RRD; + if I_RXDD='0' then + DO <= BusB; + end if; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if TState = 1 and I_BC = '1' then + n := ALU_Q - ("0000000" & F_Out(Flag_H)); + F(Flag_X) <= n(3); + F(Flag_Y) <= n(1); + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; + when others => + end case; + if XYbit_undoc='1' then + DO <= ALU_Q; + end if; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- BC('), DE('), HL('), IX and IY +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if rising_edge(CLK_n) then + if ClkEn = '1' then + -- Bus A / Write + RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then + RegAddrA_r <= XY_State(1) & "11"; + end if; + + -- Bus B + RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then + RegAddrB_r <= XY_State(1) & "11"; + end if; + + -- Address from register + RegAddrC <= Alternate & Set_Addr_To(1 downto 0); + -- Jump (HL), LD SP,HL + if (JumpXY = '1' or LDSPHL = '1') then + RegAddrC <= Alternate & "10"; + end if; + if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then + RegAddrC <= XY_State(1) & "11"; + end if; + + if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then + IncDecZ <= F_Out(Flag_Z); + end if; + if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then + if ID16 = 0 then + IncDecZ <= '0'; + else + IncDecZ <= '1'; + end if; + end if; + + RegBusA_r <= RegBusA; + end if; + end if; + end process; + + RegAddrA <= + -- 16 bit increment/decrement + Alternate & IncDec_16(1 downto 0) when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else + -- EX HL,DL + Alternate & "10" when ExchangeDH = '1' and TState = 3 else + Alternate & "01" when ExchangeDH = '1' and TState = 4 else + -- Bus A / Write + RegAddrA_r; + + RegAddrB <= + -- EX HL,DL + Alternate & "01" when ExchangeDH = '1' and TState = 3 else + -- Bus B + RegAddrB_r; + + ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else + signed(RegBusA) + 1; + + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegWEH <= '0'; + RegWEL <= '0'; + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => + RegWEH <= not Read_To_Reg_r(0); + RegWEL <= Read_To_Reg_r(0); + when others => + end case; + end if; + + if ExchangeDH = '1' and (TState = 3 or TState = 4) then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + case IncDec_16(1 downto 0) is + when "00" | "01" | "10" => + RegWEH <= '1'; + RegWEL <= '1'; + when others => + end case; + end if; + end process; + + process (Save_Mux, RegBusB, RegBusA_r, ID16, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegDIH <= Save_Mux; + RegDIL <= Save_Mux; + + if ExchangeDH = '1' and TState = 3 then + RegDIH <= RegBusB(15 downto 8); + RegDIL <= RegBusB(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 4 then + RegDIH <= RegBusA_r(15 downto 8); + RegDIL <= RegBusA_r(7 downto 0); + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + RegDIH <= std_logic_vector(ID16(15 downto 8)); + RegDIL <= std_logic_vector(ID16(7 downto 0)); + end if; + end process; + + Regs : T80_Reg + port map( + Clk => CLK_n, + CEN => ClkEn, + WEH => RegWEH, + WEL => RegWEL, + AddrA => RegAddrA, + AddrB => RegAddrB, + AddrC => RegAddrC, + DIH => RegDIH, + DIL => RegDIL, + DOAH => RegBusA(15 downto 8), + DOAL => RegBusA(7 downto 0), + DOBH => RegBusB(15 downto 8), + DOBL => RegBusB(7 downto 0), + DOCH => RegBusC(15 downto 8), + DOCL => RegBusC(7 downto 0), + DOR => DOR, + DIRSet => DIRSet, + DIR => DIR(207 downto 80)); + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if rising_edge(CLK_n) then + if ClkEn = '1' then + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + if IR = x"71" and out0 = '1' then + BusB <= "11111111"; + else + BusB <= "00000000"; + end if; + when others => + BusB <= "--------"; + end case; + + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusA <= "--------"; + end case; + if XYbit_undoc='1' then + BusA <= DI_Reg; + BusB <= DI_Reg; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Generate external control signals +-- +--------------------------------------------------------------------------- + process (RESET_n,CLK_n) + begin + if RESET_n = '0' then + RFSH_n <= '1'; + elsif rising_edge(CLK_n) then + if DIRSet = '0' and CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; + end if; + end if; + end process; + + MC <= std_logic_vector(MCycle); + TS <= std_logic_vector(TState); + DI_Reg <= DI; + HALT_n <= not Halt_FF; + BUSAK_n <= not BusAck; + IntCycle_n <= not IntCycle; + IntE <= IntE_FF1; + IORQ <= IORQ_i; + Stop <= I_DJNZ; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; + begin + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + BusReq_s <= '0'; + NMI_s <= '0'; + elsif rising_edge(CLK_n) then + + if DIRSet = '1' then + IntE_FF2 <= DIR(211); + IntE_FF1 <= DIR(210); + else + if NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + Auto_Wait_t2 <= Auto_Wait_t1; + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + else + Auto_Wait_t1 <= Auto_Wait or IORQ_i; + end if; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if not ( BusReq_s = '1' and BusAck = '1' ) then + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or No_BTR = '1' or (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMI_s <= '0'; + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif IntE_FF1 = '1' and INT_n='0' and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; + end if; + end if; + end if; + end if; + end process; + + Auto_Wait <= '1' when IntCycle = '1' and MCycle = "001" else '0'; +end; diff --git a/rtl/ipcores/t80/T80_ALU.vhd b/rtl/ipcores/t80/T80_ALU.vhd new file mode 100644 index 0000000..a9438ae --- /dev/null +++ b/rtl/ipcores/t80/T80_ALU.vhd @@ -0,0 +1,376 @@ +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- All rights reserved +-- +-- Redistribution and use in source and synthezised 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 synthesized 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 the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- 0240 : Added GB operations +-- 0242 : Cleanup +-- 0247 : Cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_ALU is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + WZ : in std_logic_vector(15 downto 0); + XY_State : in std_logic_vector(1 downto 0); + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); +end T80_ALU; + +architecture rtl of T80_ALU is + + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); + begin + if Sub = '1' then + B_i := not unsigned(B); + else + B_i := unsigned(B); + end if; + + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); + Carry <= Res_i(A'length + 1); + Res <= std_logic_vector(Res_i(A'length downto 1)); + end; + + -- AddSub variables (temporary signals) + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); + + signal BitMask : std_logic_vector(7 downto 0); + +begin + + with IR(5 downto 3) select BitMask <= "00000001" when "000", + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; + + UseCarry <= not ALU_Op(2) and ALU_Op(0); + AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); + AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); + AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); + + -- bug fix - parity flag is just parity for 8080, also overflow for Z80 + process (Carry_v, Carry7_v, Q_v) + begin + if(Mode=2) then + OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor + Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else + OverFlow_v <= Carry_v xor Carry7_v; + end if; + end process; + + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16, WZ, XY_State) + variable Q_t : std_logic_vector(7 downto 0); + variable DAA_Q : unsigned(8 downto 0); + begin + Q_t := "--------"; + F_Out <= F_In; + DAA_Q := "---------"; + case ALU_Op is + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" => + F_Out(Flag_N) <= '0'; + F_Out(Flag_C) <= '0'; + case ALU_OP(2 downto 0) is + when "000" | "001" => -- ADD, ADC + Q_t := Q_v; + F_Out(Flag_C) <= Carry_v; + F_Out(Flag_H) <= HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "010" | "011" | "111" => -- SUB, SBC, CP + Q_t := Q_v; + F_Out(Flag_N) <= '1'; + F_Out(Flag_C) <= not Carry_v; + F_Out(Flag_H) <= not HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "100" => -- AND + Q_t(7 downto 0) := BusA and BusB; + F_Out(Flag_H) <= '1'; + when "101" => -- XOR + Q_t(7 downto 0) := BusA xor BusB; + F_Out(Flag_H) <= '0'; + when others => -- OR "110" + Q_t(7 downto 0) := BusA or BusB; + F_Out(Flag_H) <= '0'; + end case; + if ALU_Op(2 downto 0) = "111" then -- CP + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + else + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + end if; + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + if Z16 = '1' then + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + end if; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + case ALU_Op(2 downto 0) is + when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP + when others => + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + end case; + if Arith16 = '1' then + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + F_Out(Flag_P) <= F_In(Flag_P); + end if; + when "1100" => + -- DAA + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 + end if; + end if; + F_Out(Flag_X) <= DAA_Q(3); + F_Out(Flag_Y) <= DAA_Q(5); + F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8); + Q_t := std_logic_vector(DAA_Q(7 downto 0)); + if DAA_Q(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= DAA_Q(7); + F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor + DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7)); + when "1101" | "1110" => + -- RLD, RRD + Q_t(7 downto 4) := BusA(7 downto 4); + if ALU_Op(0) = '1' then + Q_t(3 downto 0) := BusB(7 downto 4); + else + Q_t(3 downto 0) := BusB(3 downto 0); + end if; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + when "1001" => + -- BIT + Q_t(7 downto 0) := BusB and BitMask; + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + F_Out(Flag_P) <= '1'; + else + F_Out(Flag_Z) <= '0'; + F_Out(Flag_P) <= '0'; + end if; + F_Out(Flag_H) <= '1'; + F_Out(Flag_N) <= '0'; + if IR(2 downto 0) = "110" or XY_State /= "00" then + F_Out(Flag_X) <= WZ(11); + F_Out(Flag_Y) <= WZ(13); + else + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + when "1010" => + -- SET + Q_t(7 downto 0) := BusB or BitMask; + when "1011" => + -- RES + Q_t(7 downto 0) := BusB and not BitMask; + when "1000" => + -- ROT + case IR(5 downto 3) is + when "000" => -- RLC + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := BusA(7); + F_Out(Flag_C) <= BusA(7); + when "010" => -- RL + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(7); + when "001" => -- RRC + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(0); + F_Out(Flag_C) <= BusA(0); + when "011" => -- RR + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(0); + when "100" => -- SLA + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '0'; + F_Out(Flag_C) <= BusA(7); + when "110" => -- SLL (Undocumented) / SWAP + if Mode = 3 then + Q_t(7 downto 4) := BusA(3 downto 0); + Q_t(3 downto 0) := BusA(7 downto 4); + F_Out(Flag_C) <= '0'; + else + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '1'; + F_Out(Flag_C) <= BusA(7); + end if; + when "101" => -- SRA + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(7); + F_Out(Flag_C) <= BusA(0); + when others => -- SRL + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := '0'; + F_Out(Flag_C) <= BusA(0); + end case; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + if ISet = "00" then + F_Out(Flag_P) <= F_In(Flag_P); + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + end if; + when others => + null; + end case; + Q <= Q_t; + end process; +end; diff --git a/rtl/ipcores/t80/T80_MCode.vhd b/rtl/ipcores/t80/T80_MCode.vhd new file mode 100644 index 0000000..f5312bd --- /dev/null +++ b/rtl/ipcores/t80/T80_MCode.vhd @@ -0,0 +1,2035 @@ +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010 +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- All rights reserved +-- +-- Redistribution and use in source and synthezised 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 synthesized 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 the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- 0211 : Fixed IM 1 +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- 0235 : Added IM 2 fix by Mike Johnson +-- 0238 : Added NoRead signal +-- 0238b: Fixed instruction timing for POP and DJNZ +-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes +-- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR +-- 0242 : Fixed I/O instruction timing, cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_MCode is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + XY_State : in std_logic_vector(1 downto 0); + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,CB,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetWZ : out std_logic_vector(1 downto 0); + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + XYbit_undoc : out std_logic + ); +end T80_MCode; + +architecture rtl of T80_MCode is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + function is_cc_true( + F : std_logic_vector(7 downto 0); + cc : bit_vector(2 downto 0) + ) return boolean is + begin + if Mode = 3 then + case cc is + when "000" => return F(Flag_S) = '0'; -- NZ + when "001" => return F(Flag_S) = '1'; -- Z + when "010" => return F(Flag_H) = '0'; -- NC + when "011" => return F(Flag_H) = '1'; -- C + when "100" => return false; + when "101" => return false; + when "110" => return false; + when "111" => return false; + end case; + else + case cc is + when "000" => return F(Flag_Z) = '0'; -- NZ + when "001" => return F(Flag_Z) = '1'; -- Z + when "010" => return F(Flag_C) = '0'; -- NC + when "011" => return F(Flag_C) = '1'; -- C + when "100" => return F(Flag_P) = '0'; -- PO + when "101" => return F(Flag_P) = '1'; -- PE + when "110" => return F(Flag_S) = '0'; -- P + when "111" => return F(Flag_S) = '1'; -- M + end case; + end if; + end; + +begin + + process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); + variable DPair : std_logic_vector(1 downto 0); + variable IRB : bit_vector(7 downto 0); + begin + DDD := IR(5 downto 3); + SSS := IR(2 downto 0); + DPair := IR(5 downto 4); + IRB := to_bitvector(IR); + + MCycles <= "001"; + if MCycle = "001" then + TStates <= "100"; + else + TStates <= "011"; + end if; + Prefix <= "00"; + Inc_PC <= '0'; + Inc_WZ <= '0'; + IncDec_16 <= "0000"; + Read_To_Acc <= '0'; + Read_To_Reg <= '0'; + Set_BusB_To <= "0000"; + Set_BusA_To <= "0000"; + ALU_Op <= "0" & IR(5 downto 3); + Save_ALU <= '0'; + PreserveC <= '0'; + Arith16 <= '0'; + IORQ <= '0'; + Set_Addr_To <= aNone; + Jump <= '0'; + JumpE <= '0'; + JumpXY <= '0'; + Call <= '0'; + RstP <= '0'; + LDZ <= '0'; + LDW <= '0'; + LDSPHL <= '0'; + Special_LD <= "000"; + ExchangeDH <= '0'; + ExchangeRp <= '0'; + ExchangeAF <= '0'; + ExchangeRS <= '0'; + I_DJNZ <= '0'; + I_CPL <= '0'; + I_CCF <= '0'; + I_SCF <= '0'; + I_RETN <= '0'; + I_BT <= '0'; + I_BC <= '0'; + I_BTR <= '0'; + I_RLD <= '0'; + I_RRD <= '0'; + I_INRC <= '0'; + SetDI <= '0'; + SetEI <= '0'; + IMode <= "11"; + Halt <= '0'; + NoRead <= '0'; + Write <= '0'; + XYbit_undoc <= '0'; + SetWZ <= "00"; + + case ISet is + when "00" => + +------------------------------------------------------------------------------ +-- +-- Unprefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is +-- 8 BIT LOAD GROUP + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- LD r,r' + Set_BusB_To(2 downto 0) <= SSS; + ExchangeRp <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" => + -- LD r,n + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" => + -- LD r,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" => + -- LD (HL),r + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110110" => + -- LD (HL),n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00001010" => + -- LD A,(BC) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00011010" => + -- LD A,(DE) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00111010" => + if Mode = 3 then + -- LDD A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end if; + when "00000010" => + -- LD (BC),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + SetWZ <= "10"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00010010" => + -- LD (DE),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + Set_BusB_To <= "0111"; + SetWZ <= "10"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110010" => + if Mode = 3 then + -- LDD (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + SetWZ <= "10"; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + end if; + +-- 16 BIT LOAD GROUP + when "00000001"|"00010001"|"00100001"|"00110001" => + -- LD dd,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1000"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1001"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "00101010" => + if Mode = 3 then + -- LDI A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD HL,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end if; + when "00100010" => + if Mode = 3 then + -- LDI (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD (nn),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "0101"; -- L + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "0100"; -- H + when 5 => + Write <= '1'; + when others => null; + end case; + end if; + when "11111001" => + -- LD SP,HL + TStates <= "110"; + LDSPHL <= '1'; + when "11000101"|"11010101"|"11100101"|"11110101" => + -- PUSH qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "11000001"|"11010001"|"11100001"|"11110001" => + -- POP qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1011"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + IncDec_16 <= "0111"; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "0111"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + +-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + when "11101011" => + if Mode /= 3 then + -- EX DE,HL + ExchangeDH <= '1'; + end if; + when "00001000" => + if Mode = 3 then + -- LD (nn),SP + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "1000"; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "1001"; + when 5 => + Write <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EX AF,AF' + ExchangeAF <= '1'; + end if; + when "11011001" => + if Mode = 3 then + -- RETI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + SetEI <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EXX + ExchangeRS <= '1'; + end if; + when "11100011" => + if Mode /= 3 then + -- EX (SP),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + TStates <= "100"; + Write <= '1'; + when 4 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; + Set_Addr_To <= aSP; + LDW <= '1'; + when 5 => + IncDec_16 <= "1111"; + TStates <= "101"; + Write <= '1'; + when others => null; + end case; + end if; + +-- 8 BIT ARITHMETIC AND LOGICAL GROUP + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- ADD A,r + -- ADC A,r + -- SUB A,r + -- SBC A,r + -- AND A,r + -- OR A,r + -- XOR A,r + -- CP A,r + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- ADD A,(HL) + -- ADC A,(HL) + -- SUB A,(HL) + -- SBC A,(HL) + -- AND A,(HL) + -- OR A,(HL) + -- XOR A,(HL) + -- CP A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + when others => null; + end case; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- ADD A,n + -- ADC A,n + -- SUB A,n + -- SBC A,n + -- AND A,n + -- OR A,n + -- XOR A,n + -- CP A,n + MCycles <= "010"; + if MCycle = "010" then + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + end if; + when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" => + -- INC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + when "00110100" => + -- INC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" => + -- DEC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0010"; + when "00110101" => + -- DEC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + ALU_Op <= "0010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + +-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + when "00100111" => + -- DAA + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + ALU_Op <= "1100"; + Save_ALU <= '1'; + when "00101111" => + -- CPL + I_CPL <= '1'; + when "00111111" => + -- CCF + I_CCF <= '1'; + when "00110111" => + -- SCF + I_SCF <= '1'; + when "00000000" => + if NMICycle = '1' then + -- NMI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + when others => null; + end case; + elsif IntCycle = '1' then + -- INT (IM 2) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + --TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + --TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + else + -- NOP + end if; + when "01110110" => + -- HALT + Halt <= '1'; + when "11110011" => + -- DI + SetDI <= '1'; + when "11111011" => + -- EI + SetEI <= '1'; + +-- 16 BIT ARITHMETIC GROUP + when "00001001"|"00011001"|"00101001"|"00111001" => + -- ADD HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + SetWZ <= "11"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; + when others => + end case; + when "00000011"|"00010011"|"00100011"|"00110011" => + -- INC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when "00001011"|"00011011"|"00101011"|"00111011" => + -- DEC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + +-- ROTATE AND SHIFT GROUP + when "00000111" + -- RLCA + |"00010111" + -- RLA + |"00001111" + -- RRCA + |"00011111" => + -- RRA + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + +-- JUMP GROUP + when "11000011" => + -- JP nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + Jump <= '1'; + LDW <= '1'; + when others => null; + end case; + when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+C),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "01" => + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + when "10" => + -- LD A,($FF00+C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => + end case; + when "11" => + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end case; + else + -- JP cc,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + LDW <= '1'; + Inc_PC <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Jump <= '1'; + end if; + when others => null; + end case; + end if; + when "00011000" => + if Mode /= 2 then + -- JR e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00111000" => + if Mode /= 2 then + -- JR C,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00110000" => + if Mode /= 2 then + -- JR NC,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00101000" => + if Mode /= 2 then + -- JR Z,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00100000" => + if Mode /= 2 then + -- JR NZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "11101001" => + -- JP (HL) + JumpXY <= '1'; + when "00010000" => + if Mode = 3 then + I_DJNZ <= '1'; + elsif Mode < 2 then + -- DJNZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + I_DJNZ <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= "000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + I_DJNZ <= '1'; + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + +-- CALL AND RETURN GROUP + when "11001101" => + -- CALL nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + IncDec_16 <= "1111"; + Inc_PC <= '1'; + TStates <= "100"; + Set_Addr_To <= aSP; + LDW <= '1'; + Set_BusB_To <= "1101"; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => + if IR(5) = '0' or Mode /= 3 then + -- CALL cc,nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + LDW <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + TStates <= "100"; + Set_BusB_To <= "1101"; + else + MCycles <= "011"; + end if; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + end if; + when "11001001" => + -- RET + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + --TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+nn),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "01" => + -- ADD SP,n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + ALU_Op <= "0000"; + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To <= "1000"; + Set_BusB_To <= "0110"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To <= "1001"; + Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + when others => + end case; + when "10" => + -- LD A,($FF00+nn) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "11" => + -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end case; + else + -- RET cc + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; + when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => + -- RST p + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + +-- INPUT AND OUTPUT GROUP + when "11011011" => + if Mode /= 3 then + -- IN A,(n) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + when "11010011" => + if Mode /= 3 then + -- OUT (n),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- MULTIBYTE INSTRUCTIONS +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + + when "11001011" => + if Mode /= 2 then + Prefix <= "01"; + end if; + + when "11101101" => + if Mode < 2 then + Prefix <= "10"; + end if; + + when "11011101"|"11111101" => + if Mode < 2 then + Prefix <= "11"; + end if; + + end case; + + when "01" => + +------------------------------------------------------------------------------ +-- +-- CB prefixed instructions +-- +------------------------------------------------------------------------------ + + Set_BusA_To(2 downto 0) <= IR(2 downto 0); + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" => + -- RLC r + -- RL r + -- RRC r + -- RR r + -- SLA r + -- SRA r + -- SRL r + -- SLL r (Undocumented) / SWAP r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- R/S (IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + + when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" => + -- RLC (HL) + -- RL (HL) + -- RRC (HL) + -- RR (HL) + -- SRA (HL) + -- SRL (HL) + -- SLA (HL) + -- SLL (HL) (Undocumented) / SWAP (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- BIT b,r + if XY_State="00" then + if MCycle = "001" then + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + ALU_Op <= "1001"; + end if; + else + -- BIT b,(IX+d), undocumented + MCycles <= "010"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => null; + end case; + end if; + + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" => + -- BIT b,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => null; + end case; + when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" => + -- SET b,r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- SET b,(IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- SET b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- RES b,r + if XY_State="00" then + if MCycle = "001" then + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + else + -- RES b,(IX+d),Reg, undocumented + MCycles <= "011"; + XYbit_undoc <= '1'; + case to_integer(unsigned(MCycle)) is + when 1 | 7=> + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end if; + + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- RES b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => null; + end case; + end case; + + when others => + +------------------------------------------------------------------------------ +-- +-- ED prefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111" + + + |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111" + | "10100100"|"10100101"|"10100110"|"10100111" + | "10101100"|"10101101"|"10101110"|"10101111" + | "10110100"|"10110101"|"10110110"|"10110111" + | "10111100"|"10111101"|"10111110"|"10111111" + |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => + null; -- NOP, undocumented + when "01111110"|"01111111" => + -- NOP, undocumented + null; +-- 8 BIT LOAD GROUP + when "01010111" => + -- LD A,I + Special_LD <= "100"; + TStates <= "101"; + when "01011111" => + -- LD A,R + Special_LD <= "101"; + TStates <= "101"; + when "01000111" => + -- LD I,A + Special_LD <= "110"; + TStates <= "101"; + when "01001111" => + -- LD R,A + Special_LD <= "111"; + TStates <= "101"; +-- 16 BIT LOAD GROUP + when "01001011"|"01011011"|"01101011"|"01111011" => + -- LD dd,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1000"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '1'; + end if; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1001"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "01000011"|"01010011"|"01100011"|"01110011" => + -- LD (nn),dd + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1000"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1001"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 5 => + Write <= '1'; + when others => null; + end case; + when "10100000" | "10101000" | "10110000" | "10111000" => + -- LDI, LDD, LDIR, LDDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0000"; + Set_Addr_To <= aDE; + if IR(3) = '0' then + IncDec_16 <= "0110"; -- IX + else + IncDec_16 <= "1110"; + end if; + when 3 => + I_BT <= '1'; + TStates <= "101"; + Write <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0101"; -- DE + else + IncDec_16 <= "1101"; + end if; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100001" | "10101001" | "10110001" | "10111001" => + -- CPI, CPD, CPIR, CPDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0111"; + Save_ALU <= '1'; + PreserveC <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + when 3 => + NoRead <= '1'; + I_BC <= '1'; + TStates <= "101"; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" => + -- NEG + Alu_OP <= "0010"; + Set_BusB_To <= "0111"; + Set_BusA_To <= "1010"; + Read_To_Acc <= '1'; + Save_ALU <= '1'; + when "01000110"|"01001110"|"01100110"|"01101110" => + -- IM 0 + IMode <= "00"; + when "01010110"|"01110110" => + -- IM 1 + IMode <= "01"; + when "01011110"|"01110111" => + -- IM 2 + IMode <= "10"; +-- 16 bit arithmetic + when "01001010"|"01011010"|"01101010"|"01111010" => + -- ADC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0001"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + SetWZ <= "11"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01000010"|"01010010"|"01100010"|"01110010" => + -- SBC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + SetWZ <= "11"; + when 3 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01101111" => + -- RLD -- Read in M2, not M3! fixed by Sorgelig + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1101"; + Save_ALU <= '1'; + when 3 => + TStates <= "100"; + I_RLD <= '1'; + NoRead <= '1'; + Set_Addr_To <= aXY; + when 4 => + Write <= '1'; + when others => + end case; + when "01100111" => + -- RRD -- Read in M2, not M3! fixed by Sorgelig + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1110"; + Save_ALU <= '1'; + when 3 => + TStates <= "100"; + I_RRD <= '1'; + NoRead <= '1'; + Set_Addr_To <= aXY; + when 4 => + Write <= '1'; + when others => + end case; + when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => + -- RETI/RETN + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + LDW <= '1'; + I_RETN <= '1'; + when others => null; + end case; + when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" => + -- IN r,(C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + SetWZ <= "01"; + when 2 => + IORQ <= '1'; + if IR(5 downto 3) /= "110" then + Read_To_Reg <= '1'; + Set_BusA_To(2 downto 0) <= IR(5 downto 3); + end if; + I_INRC <= '1'; + when others => + end case; + when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" => + -- OUT (C),r + -- OUT (C),0 + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + SetWZ <= "01"; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + if IR(5 downto 3) = "110" then + Set_BusB_To(3) <= '1'; + end if; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "10100010" | "10101010" | "10110010" | "10111010" => + -- INI, IND, INIR, INDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aBC; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + SetWZ <= "11"; + IncDec_16(3) <= IR(3); + when 2 => + IORQ <= '1'; + Set_BusB_To <= "0110"; + Set_Addr_To <= aXY; + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100011" | "10101011" | "10110011" | "10111011" => + -- OUTI, OUTD, OTIR, OTDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aXY; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + Set_BusB_To <= "0110"; + Set_Addr_To <= aBC; + SetWZ <= "11"; + IncDec_16(3) <= IR(3); + when 3 => + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + IORQ <= '1'; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + end case; + + end case; + + if Mode = 1 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "011"; + end if; + end if; + + if Mode = 3 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "100"; + end if; + end if; + + if Mode < 2 then + if MCycle = "110" then + Inc_PC <= '1'; + if Mode = 1 then + Set_Addr_To <= aXY; + TStates <= "100"; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + end if; + if IRB = "00110110" or IRB = "11001011" then + Set_Addr_To <= aNone; + end if; + end if; + if MCycle = "111" then + if Mode = 0 then + TStates <= "101"; + end if; + if ISet /= "01" then + Set_Addr_To <= aXY; + end if; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + if IRB = "00110110" or ISet = "01" then + -- LD (HL),n + Inc_PC <= '1'; + else + NoRead <= '1'; + end if; + end if; + end if; + + end process; + +end; diff --git a/rtl/ipcores/t80/T80_Reg.vhd b/rtl/ipcores/t80/T80_Reg.vhd new file mode 100644 index 0000000..e7e8645 --- /dev/null +++ b/rtl/ipcores/t80/T80_Reg.vhd @@ -0,0 +1,152 @@ +-------------------------------------------------------------------------------- +-- **** +-- T80(c) core. Attempt to finish all undocumented features and provide +-- accurate timings. +-- Version 350. +-- Copyright (c) 2018 Sorgelig +-- Test passed: ZEXDOC, ZEXALL, Z80Full(*), Z80memptr +-- (*) Currently only SCF and CCF instructions aren't passed X/Y flags check as +-- correct implementation is still unclear. +-- +-- **** +-- T80(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 started tidyup +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- T80 Registers, technology independent +-- +-- Version : 0244 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised 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 synthesized 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 the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t51/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : Initial release +-- +-- 0244 : Changed to single register file +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_Reg is + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0); + DOR : out std_logic_vector(127 downto 0); + DIRSet : in std_logic; + DIR : in std_logic_vector(127 downto 0) + ); +end T80_Reg; + +architecture rtl of T80_Reg is + + type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); + +begin + + process (Clk) + begin + if rising_edge(Clk) then + if DIRSet = '1' then + RegsL(0) <= DIR( 7 downto 0); + RegsH(0) <= DIR( 15 downto 8); + + RegsL(1) <= DIR( 23 downto 16); + RegsH(1) <= DIR( 31 downto 24); + + RegsL(2) <= DIR( 39 downto 32); + RegsH(2) <= DIR( 47 downto 40); + + RegsL(3) <= DIR( 55 downto 48); + RegsH(3) <= DIR( 63 downto 56); + + RegsL(4) <= DIR( 71 downto 64); + RegsH(4) <= DIR( 79 downto 72); + + RegsL(5) <= DIR( 87 downto 80); + RegsH(5) <= DIR( 95 downto 88); + + RegsL(6) <= DIR(103 downto 96); + RegsH(6) <= DIR(111 downto 104); + + RegsL(7) <= DIR(119 downto 112); + RegsH(7) <= DIR(127 downto 120); + elsif CEN = '1' then + if WEH = '1' then + RegsH(to_integer(unsigned(AddrA))) <= DIH; + end if; + if WEL = '1' then + RegsL(to_integer(unsigned(AddrA))) <= DIL; + end if; + end if; + end if; + end process; + + DOAH <= RegsH(to_integer(unsigned(AddrA))); + DOAL <= RegsL(to_integer(unsigned(AddrA))); + DOBH <= RegsH(to_integer(unsigned(AddrB))); + DOBL <= RegsL(to_integer(unsigned(AddrB))); + DOCH <= RegsH(to_integer(unsigned(AddrC))); + DOCL <= RegsL(to_integer(unsigned(AddrC))); + DOR <= RegsH(7) & RegsL(7) & RegsH(6) & RegsL(6) & RegsH(5) & RegsL(5) & RegsH(4) & RegsL(4) & RegsH(3) & RegsL(3) & RegsH(2) & RegsL(2) & RegsH(1) & RegsL(1) & RegsH(0) & RegsL(0); + +end; diff --git a/rtl/ipcores/t80/T80pa.vhd b/rtl/ipcores/t80/T80pa.vhd new file mode 100644 index 0000000..436dc4d --- /dev/null +++ b/rtl/ipcores/t80/T80pa.vhd @@ -0,0 +1,259 @@ +-- +-- Z80 compatible microprocessor core, preudo-asynchronous top level (by Sorgelig) +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised 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 synthesized 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 the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- File history : +-- +-- v1.0: convert to preudo-asynchronous model with original Z80 timings. +-- +-- v2.0: rewritten for more precise timings. +-- support for both CEN_n and CEN_p set to 1. Effective clock will be CLK/2. +-- +-- v2.1: Output Address 0 during non-bus MCycle (fix ZX contention) +-- +-- v2.2: Interrupt acknowledge cycle has been corrected +-- WAIT_n is broken in T80.vhd. Simulate correct WAIT_n locally. +-- +-- v2.3: Output last used Address during non-bus MCycle seems more correct. +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80pa is + generic( + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + RESET_n : in std_logic; + CLK : in std_logic; + CEN_p : in std_logic := '1'; + CEN_n : in std_logic := '1'; + WAIT_n : in std_logic := '1'; + INT_n : in std_logic := '1'; + NMI_n : in std_logic := '1'; + BUSRQ_n : in std_logic := '1'; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); +end T80pa; + +architecture rtl of T80pa is + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); + end component; + signal IntCycle_n : std_logic; + signal IntCycleD_n : std_logic_vector(1 downto 0); + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal BUSAK : std_logic; + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + signal CEN_pol : std_logic; + signal A_int : std_logic_vector(15 downto 0); + signal A_last : std_logic_vector(15 downto 0); + signal CEN : std_logic; +begin + + A <= A_int when NoRead = '0' or Write = '1' else A_last; + CEN <= CEN_p and not CEN_pol; + BUSAK_n <= BUSAK; + + u0 : T80 + generic map( + Mode => Mode, + IOWait => 1 + ) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => '1', + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK, + CLK_n => CLK, + A => A_int, + DInst => DI, -- valid at beginning of T3 + DI => DI_Reg, -- latched at middle of T3 + DO => DO, + REG => REG, + MC => MCycle, + TS => TState, + OUT0 => OUT0, + IntCycle_n => IntCycle_n, + DIRSet => DIRSet, + DIR => DIR + ); + + process(CLK) + begin + if rising_edge(CLK) then + if RESET_n = '0' then + WR_n <= '1'; + RD_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + CEN_pol <= '0'; + elsif CEN_p = '1' and CEN_pol = '0' then + CEN_pol <= '1'; + if MCycle = "001" then + if TState = "010" then + IORQ_n <= '1'; + MREQ_n <= '1'; + RD_n <= '1'; + end if; + else + if TState = "001" and IORQ = '1' then + WR_n <= not Write; + RD_n <= Write; + IORQ_n <= '0'; + end if; + end if; + elsif CEN_n = '1' and CEN_pol = '1' then + if TState = "010" then + CEN_pol <= not WAIT_n; + else + CEN_pol <= '0'; + end if; + if TState = "011" and BUSAK = '1' then + DI_Reg <= DI; + end if; + if MCycle = "001" then + if TState = "001" then + IntCycleD_n <= IntCycleD_n(0) & IntCycle_n; + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycleD_n(1); + A_last <= A_int; + end if; + if TState = "011" then + IntCycleD_n <= "11"; + RD_n <= '1'; + MREQ_n <= '0'; + end if; + if TState = "100" then + MREQ_n <= '1'; + end if; + else + if NoRead = '0' and IORQ = '0' then + if TState = "001" then + RD_n <= Write; + MREQ_n <= '0'; + A_last <= A_int; + end if; + end if; + if TState = "010" then + WR_n <= not Write; + end if; + if TState = "011" then + WR_n <= '1'; + RD_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + end if; + end if; + end if; + end if; + end process; +end; diff --git a/rtl/ipcores/t80/T80s.vhd b/rtl/ipcores/t80/T80s.vhd new file mode 100644 index 0000000..a2d8c44 --- /dev/null +++ b/rtl/ipcores/t80/T80s.vhd @@ -0,0 +1,236 @@ +-- +-- Z80 compatible microprocessor core, synchronous top level +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised 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 synthesized 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 the author nor the names of other 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 AUTHOR 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. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0210 : Fixed read with wait +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use IEEE.STD_LOGIC_UNSIGNED.all; + +entity T80s is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + T2Write : integer := 1; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + CLK : in std_logic; + CEN : in std_logic := '1'; + WAIT_n : in std_logic := '1'; + INT_n : in std_logic := '1'; + NMI_n : in std_logic := '1'; + BUSRQ_n : in std_logic := '1'; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + OUT0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T80s; + +architecture rtl of T80s is + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 0 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic; + out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 + REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + + DIRSet : in std_logic := '0'; + DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A + ); + end component; + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + OUT0 => OUT0, + IntCycle_n => IntCycle_n + ); + + process (RESET_n, CLK) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif rising_edge(CLK) then + if CEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = 1 then + if TState = 1 or (TState = 2 and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycle_n; + end if; + if TState = 3 then + MREQ_n <= '0'; + end if; + else + if (TState = 1 or (TState = 2 and Wait_n = '0')) and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if T2Write = 0 then + if TState = 2 and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + else + if (TState = 1 or (TState = 2 and Wait_n = '0')) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + end if; + if TState = 2 and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; +end; diff --git a/rtl/ipcores/vlm5030_gl/vlm5030_gl.qip b/rtl/ipcores/vlm5030_gl/vlm5030_gl.qip new file mode 100644 index 0000000..0086063 --- /dev/null +++ b/rtl/ipcores/vlm5030_gl/vlm5030_gl.qip @@ -0,0 +1,3 @@ +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) vlm5030_gl.vhd] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) vlm5030_pack.vhd] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) vlm5030_subcircuits.vhd] diff --git a/rtl/ipcores/vlm5030_gl/vlm5030_gl.vhd b/rtl/ipcores/vlm5030_gl/vlm5030_gl.vhd new file mode 100644 index 0000000..996b98e --- /dev/null +++ b/rtl/ipcores/vlm5030_gl/vlm5030_gl.vhd @@ -0,0 +1,2304 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- +------------------------------------------------------------------------------- +-- +-- Sanyo VLM5030 speech snythesizer +-- +-- Gate-level recreation extracted from the die image at +-- https://siliconpr0n.org/archive/doku.php?id=ogoun:vlm5030 +-- +------------------------------------------------------------------------------- +-- +-- +-------,_,-------+ +-- GND -- | 1 40 | <- RST +-- TST1 -> | 2 39 | -> TST4 +-- OSC2 ck | 3 _ 38 | <- TST3 +-- OSC1 ck | 4 (_) 37 | -> TST2 +-- D0 -> | 5 36 | -> DAO +-- D1 -> | 6 35 | <- VREF +-- D2 -> | 7 34 | -> MTE +-- D3 -> | 8 V 33 | -> /ME +-- D4 -> | 9 L 32 | <- VCU +-- D5 -> | 10 M 31 | <- START +-- D6 -> | 11 5 30 | -> BSY +-- D7 -> | 12 0 29 | -- Vdd +-- A0 <- | 13 3 28 | -> A15 +-- A1 <- | 14 0 27 | -> A14 +-- A2 <- | 15 26 | -> A13 +-- A3 <- | 16 _ 25 | -> A12 +-- A4 <- | 17 (_) 24 | -> A11 +-- A5 <- | 18 23 | -> A10 +-- A6 <- | 19 22 | -> A9 +-- A7 <- | 20 21 | -> A8 +-- +-----------------+ +-- +-- Clocking +-- ======== +-- +-- This model requires overclocking of OSC1/OSC2 by 2x or higher. +-- Violating this requirement results in undefined behaviour. +-- +-- i_clk is supplied with a free-running clock at >= 2x OSC frequency. +-- +-- i_oscen acts as clock enable for i_clk to define the 3.58 MHz clock +-- at OSC1/OSC2 of a real chip. +-- +-- +-- Test pins +-- ========= +-- +-- i_tst1 must be tied to '0' for mission mode operation. +-- Other unused test pins can be left unconnected: +-- * i_vref +-- * o_tst2 +-- * i_tst3 +-- * o_tst4 +-- +-- +-- Audio output +-- ============ +-- +-- The VLM5030 internally generates 12 bit signed PCM audio with ~8136 Hz +-- sample rate. +-- +-- During /ME=1 this PCM data is available at A[13:12], A[9:0]. +-- Note that A[9] has to be inverted externally if A[9:0] is to be used as a +-- standard signed vector. +-- +-- Typical applications use audio from the DAO pin. It is fed by a combination +-- of a 5 bit parallel DAC (tapping A[9:5]) and overlaid with a PWM signal +-- (controlled by A[4:2]). Bits A[1:0] are not used for DAO generation +-- +-- DAO characteristics +-- ------------------- +-- +-- DAO is an overlay of the 8136 Hz PCM data with high frequency PWM. +-- The PWM overlay periodically increases the DAO output voltage to the next +-- higher value with a duty cycle controlled by A[4:2]. +-- +-- ^ new PCM value new PCM value +-- | . PWM overlay . +-- | .+---+ +---+ +---+ +---+ +---+ +-+ +-- | ++ +------+ +------+ +------+ +------+ +------+ + +-- | | | +-- | | +-- +-- |---+ +-- +------------------------------------------------------------------> +-- +-- When fed through an external low-pass filter, this PWM overlay augments +-- the discreete PCM DAC voltages with fractional levels. +-- +-- PWM period approx. 24.581 us, 40.682 kHz +-- PWM | high | low +-- -----+--------+-------- +-- 7 | 20.112 | 4.470 +-- 6 | 17.318 | 7.263 +-- 5 | 13.966 | 10.615 +-- 4 | 11.173 | 13.408 +-- 3 | 7.821 | 16.760 +-- 2 | 4.670 | 19.553 +-- 1 | 1.676 | 22.905 +-- 0 | 0.000 | 24.581 +-- +-- Direct PCM output +-- ----------------- +-- +-- This model outputs signed 10 bit audio at o_audio in addition to DAO. +-- o_audio is equivalent to A[9:0] during /ME=1 with corrected sign bit. +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity vlm5030_gl is + + port ( + i_clk : in std_logic; + i_oscen : in std_logic; + i_rst : in std_logic; + i_start : in std_logic; + i_vcu : in std_logic; + i_vref : in std_logic := '1'; + i_tst1 : in std_logic; + o_tst2 : out std_logic; + i_tst3 : in std_logic := '1'; + o_tst4 : out std_logic; + i_d : in std_logic_vector( 7 downto 0); + o_a : out std_logic_vector(15 downto 0); + o_me_l : out std_logic; + o_mte : out std_logic; + o_bsy : out std_logic; + + -- o_dao: unsigned audio, sample rate ~8136Hz, PWM ~40.682 kHz + o_dao : out std_logic_vector( 5 downto 0); + + -- o_audio: signed audio, sample rate ~8136Hz + o_audio : out std_logic_vector(9 downto 0) + ); + +end; + +use work.vlm5030_pack.all; + +architecture gl of vlm5030_gl is + + signal osc : t_clk; + signal clk2 : t_clk := z_clk; + signal nclk2 : t_clk; + + signal rst : std_logic; + + + signal dq : std_logic_vector(7 downto 0); + signal maskdq53 : std_logic; + + signal starttst : std_logic; + signal tststopclk2, tstend2ID, tstend2IE, + tstenID2A, tstenIE2A, tstenctrl2A, + tstenIE2DAC : std_logic; + + signal clk2divq : std_logic_vector(10 downto 0) := (others => '0'); + signal c2d0, c2d1, c2d2, + c2d3, c2d4, c2d5, + c2d6, c2d7, c2d8, + c2d9, c2d10 : t_clk; + signal c2d5fin : t_clk; + signal c2d7fin, nc2d7fin : t_clk; + signal c2d9fin, nc2d9fin : t_clk; + signal clk2gd5 : t_clk; + signal nc2d1, nc2d6, + nc2d8, nc2d10 : t_clk; + signal c2d3gated : t_clk; + + + signal fsromevalout : std_logic; + signal fsromdo : std_logic_vector(13 downto 0); + signal fsromnorhigh, + fsromnorlow : std_logic; + -- + signal clk2ctrl : t_clk; + signal ncen1, cen3 : std_logic; + signal eaoen : std_logic; + signal xromdo7nq : std_logic := '0'; + signal xromdo7q : std_logic; + signal xromdo : std_logic_vector(36 downto 0); + signal yromdo : std_logic_vector( 4 downto 0); + signal c2d3gate : std_logic; + + + signal cntdn0 : std_logic; + + + signal dinalq : std_logic_vector(7 downto 0) := (others => '0'); + signal aq : std_logic_vector(o_a'range); + + + signal startrise : std_logic; + signal clkcntdn : t_clk; + signal ncntdnload : std_logic; + signal ncntdn : std_logic; + + signal eavcu : std_logic; + signal ealatchh : std_logic; + signal neaload : std_logic; + signal eainc : std_logic; + signal clrdinal : std_logic; + signal clkdin : std_logic; + signal nvcufinal : std_logic; + signal vcufinal12 : std_logic; + signal nbsy : std_logic; + signal me : std_logic; + signal rflatchwen : std_logic; + signal asshift2 : std_logic; + signal updtpitch : std_logic; + signal enrf2ID : std_logic; + signal clkksa : t_clk; + signal ensum2ID : std_logic; + + + signal clk2ena, clk2enb : t_clk; + + signal rstdel : std_logic; + + + signal ksa : std_logic_vector(4 downto 0); + signal nkdo : std_logic_vector(9 downto 0); + + + signal rfdo : std_logic_vector(nkdo'range); + signal rfdo97zero : std_logic; + + + signal nID : std_logic_vector(9 downto 0); + + signal assum : std_logic_vector(nID'range); + + signal nIE : std_logic_vector(11 downto 0); + + signal idlat : std_logic_vector(7 downto 0); + signal idlatall1 : std_logic; + signal enIDlinv2ID : std_logic; + signal enIDl2IE : std_logic; + signal enIDlinv2IE : std_logic; + + + signal pitchoverflow : std_logic; + signal enpitchlat : t_clk; + + + signal enmem02ID : std_logic; + signal nmem0do, + mem0do : std_logic_vector(nID'range); + signal enmem12IE : std_logic; + signal mem1do2IE : std_logic_vector(nIE'range); + signal enmem22IE : std_logic; + signal mem2do2IE : std_logic_vector(nIE'range); + + signal ieregdrv, + ieregdrv4IE : std_logic_vector(nIE'range); + signal ieregload : t_clk; + + signal enieregfa2IE : std_logic; + + signal c2d10xr9 : t_clk; + signal enIE2A : std_logic; + signal ieaddrreg : std_logic_vector(nIE'range); + + signal pitchmod : std_logic; + + signal random : std_logic; + + signal pwmsr : std_logic; + +begin + + -- MSB K-slice address bit + -- logic exists that generates it but output is not used (patched wiring) + ksa(4) <= '0'; + + -- main clock, corresponds to oscillator output + osc <= (base => i_clk, + val => i_clk, + rise => i_oscen, + fall => '0'); + + clk2ena <= clk2 or (cen3 nor tstenctrl2A) or ncen1; + clk2enb <= clk2 or (cen3 nor tstenctrl2A) or ncen1 or (fsromdo(6) nor tstenctrl2A); + + + + ----------------------------------------------------------------------------- + -- RST / POR generation + -- + rstdel_block : block + signal porcnt : unsigned(7 downto 0) := (others => '1'); + signal npor : std_logic := '0'; + signal del : std_logic_vector(1 downto 0) := (others => '0'); + begin + por_p : process (osc) + begin + if rising_edge(osc) then + if porcnt > 0 then + porcnt <= porcnt - 1; + end if; + if porcnt = 0 then -- TODO: measure POR hold time + npor <= '1'; + end if; + end if; + end process; + + o_tst4 <= not npor; + + rst <= '1' when npor = '0' and i_tst3 = '1' else i_rst; + + rstdel_p : process (clk2) + begin + if rising_edge(clk2) then + del <= del(0) & rst; + end if; + end process; + -- + rstdel <= del(1); + end block; + + + + ----------------------------------------------------------------------------- + -- DQ registers + -- + dq_block : block + signal rstq : std_logic := '0'; + signal rstclk : t_clk; + signal ldq : std_logic_vector(dq'range); + signal maskdq53m, maskdq53s : std_logic := '1'; + + begin + rstclk_p : process (osc.base) + begin + if rising_edge(osc.base) then + rstq <= rst; + end if; + end process; + -- + rstclk <= (base => osc.base, + val => rstq, + rise => not rstq and rst, + fall => rstq and not rst); + + dq_p : process (rstclk) + begin + if falling_edge(rstclk) then + ldq <= i_d; + end if; + end process; + + maskqm_p : process(startrise, enpitchlat) + begin + if startrise = '1' then + maskdq53m <= '1'; + elsif rising_edge(enpitchlat) then + maskdq53m <= rfdo97zero; + end if; + end process; + maskqs_p : process(startrise, enpitchlat) + begin + if startrise = '1' then + maskdq53s <= '1'; + elsif falling_edge(enpitchlat) then + maskdq53s <= maskdq53m; + end if; + end process; + maskdq53 <= maskdq53s; + + dqmask_p : process(maskdq53, ldq) + begin + dq <= ldq; + if maskdq53 = '1' then + dq(5 downto 3) <= (others => '0'); + end if; + end process; + + end block; + + + + ----------------------------------------------------------------------------- + -- TST logic + -- + -- + -- TST1 VREF VCU START Function + -- 0 X X X Mission mode + -- 1 0 1 1 Clock stopped + -- 1 1 1 0 D to ID + -- 1 1 0 0 D to IE + -- 1 1 1 1 ID to A + -- 1 1 0 1 IE to A + -- 1 0 0 1 CTRL to A + -- 1 0 X 0 IE to DAC, forces D to IE + -- VCU controls pwmsel + -- + tst_block : block + signal ntst1, nstart, nvcu : std_logic; + signal ntst1vref : std_logic; + begin + ntst1 <= not i_tst1; + nstart <= not i_start; + nvcu <= not i_vcu; + + starttst <= nstart nor i_tst1; + + ntst1vref <= i_tst1 nand i_vref; + + tststopclk2 <= not( ntst1 or i_vref or nvcu or nstart ); + tstend2ID <= not( ntst1vref or nvcu or i_start ); + tstend2IE <= not( ntst1vref or i_vcu or i_start ) or tstenIE2DAC; + tstenID2A <= not( ntst1vref or nvcu or nstart ); + tstenIE2A <= not( ntst1vref or i_vcu or nstart ); + tstenctrl2A <= not( ntst1 or i_vref or i_vcu or nstart ); + tstenIE2DAC <= not( ntst1 or i_vref or i_start ); + end block; + + + + ----------------------------------------------------------------------------- + -- CLK2 generation + -- + clk2_block : block + begin + + clk2.base <= osc.base; + + process (osc) + begin + if rising_edge(osc) then + if tststopclk2 = '1' then + clk2.val <= '0'; + + else + clk2.val <= not clk2.val; + end if; + end if; + end process; + + clk2.rise <= '0' when tststopclk2 = '1' else + osc.rise when clk2 = '0' else + '0'; + clk2.fall <= '0' when tststopclk2 = '1' else + osc.rise when clk2 = '1' else + '0'; + + nclk2 <= not clk2; + + end block; + + + + ----------------------------------------------------------------------------- + -- CLK2 divider + -- + clk2div_block : block + signal c2qnor : std_logic; + signal feedback : std_logic; + + -- edge detection for val that will change to preval on the rising refclk edge + function rising_edge_detect(refclk : t_clk; val, preval : std_logic) return t_clk is + begin + return (base => refclk.base, + val => val, + rise => refclk.rise and not val and preval, + fall => refclk.rise and val and not preval); + end; + + begin + -- the 10 bit shift register chain for CLK2DIV + process (clk2) + begin + if rising_edge(clk2) then + clk2divq <= clk2divq(9 downto 0) & feedback; + end if; + end process; + + c2qnor <= norf(clk2divq(9 downto 0)); + + -- feedback signal for the CLK2DIV shifter + feedback <= '0' when rstdel = '1' else c2qnor; + + c2d0 <= rising_edge_detect(refclk => clk2, val => clk2divq( 0), preval => feedback); + c2d1 <= rising_edge_detect(refclk => clk2, val => clk2divq( 1), preval => clk2divq(0)); + c2d2 <= rising_edge_detect(refclk => clk2, val => clk2divq( 2), preval => clk2divq(1)); + c2d3 <= rising_edge_detect(refclk => clk2, val => clk2divq( 3), preval => clk2divq(2)); + c2d4 <= rising_edge_detect(refclk => clk2, val => clk2divq( 4), preval => clk2divq(3)); + c2d5 <= rising_edge_detect(refclk => clk2, val => clk2divq( 5), preval => clk2divq(4)); + c2d6 <= rising_edge_detect(refclk => clk2, val => clk2divq( 6), preval => clk2divq(5)); + c2d7 <= rising_edge_detect(refclk => clk2, val => clk2divq( 7), preval => clk2divq(6)); + c2d8 <= rising_edge_detect(refclk => clk2, val => clk2divq( 8), preval => clk2divq(7)); + c2d9 <= rising_edge_detect(refclk => clk2, val => clk2divq( 9), preval => clk2divq(8)); + c2d10 <= rising_edge_detect(refclk => clk2, val => clk2divq(10), preval => clk2divq(9)); + + + -- SR-latches + c2d5fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d5, + o_q => c2d5fin + ); + c2d7fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d7, + o_q => c2d7fin + ); + nc2d7fin <= not c2d7fin; + + c2d9fin_b : entity work.vlm5030_srlatchclk + port map ( + i_clk => osc, + i_res => c2d0, + i_set => c2d9, + o_q => c2d9fin + ); + nc2d9fin <= not c2d9fin; + + clk2gd5 <= c2d0 nor (c2d5 and nclk2); + nc2d1 <= not c2d1; + c2d3gated <= (not c2d3) nor c2d3gate; + nc2d6 <= not c2d6; + nc2d8 <= not c2d8; + nc2d10 <= not c2d10; + end block; + + + + ----------------------------------------------------------------------------- + -- FSROM + -- + fsrom_block : block + signal fsroma : std_logic_vector(5 downto 0); + begin + + agen_block : block + begin + process (clk2ena) + begin + if rising_edge(clk2ena) then + if (fsromnorlow nand nvcufinal) = '0' then + -- shift chain + fsroma <= fsroma(4 downto 0) & (fsroma(0) xor fsroma(5)); + else + -- reset chain + fsroma <= (3 => not rstdel, + others => '0'); + end if; + + end if; + end process; + + fsromevalout <= not( (fsromdo( 9) and (xromdo(0) or xromdo(4))) + or (fsromdo(10) and (xromdo(1) or xromdo(4))) + or (fsromdo(11) and (xromdo(6) or xromdo(3) or xromdo(0))) + or (fsromdo(12) and (xromdo(5) or xromdo(2))) + or (fsromdo(13) and xromdo(5)) + or (fsromdo( 8) and (xromdo(7) or xromdo(1))) ); + end block; + + rom_block : block + alias a : std_logic_vector(fsroma'range) is fsroma; + signal na : std_logic_vector(a'range); + signal ndq : std_logic_vector(5 downto 3); + + -- NOTE: vectors for norf must be range 0 to N! + signal wl : std_logic_vector(0 to 17); + + begin + na <= not a; + ndq <= not dq(5 downto 3); + + ------------------------------------------------------------------------- + -- FSROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + wl <= a(5)&na(5) & na(4)&a(4) & a(3)&na(3) & na(2)&a(2) & a(1)&na(1) & na(0)&a(0) & dq(3)&ndq(3) & ndq(4)&dq(4) & dq(5)&ndq(5); + + -- wl(0) wl(17) + -- a(5) ndq(5) + -- | | + fsromdo <= (-- | | + 00 => norf(wl, "100110011001000000"), + 01 => norf(wl, "011010010110001010"), + 02 => norf(wl, "101001010101010110"), + 03 => norf(wl, "011001011001100100"), + 04 => norf(wl, "011010010101001001"), + 05 => norf(wl, "011010011001010101"), + 06 => norf(wl, "010110011001000000"), + -- + 07 => norf(wl, "101010011001000000"), + 08 => norf(wl, "011001100110000000"), + 09 => norf(wl, "101001100110000000"), + 10 => norf(wl, "100101100110000000"), + 11 => norf(wl, "100110100110000000"), + 12 => norf(wl, "100110010110000000"), + 13 => norf(wl, "100110011010000000"), + others => '1'); + -- + ------------------------------------------------------------------------- + + fsromnorhigh <= norf(fsromdo(13 downto 8)); + fsromnorlow <= norf(fsromdo( 5 downto 0)); + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- Sequencer ROM + -- + seqrom_block : block + signal gseqroma : std_logic_vector(4 downto 0); + begin + + agen_block : block + signal ncen3 : std_logic; + signal nclk2ctrlcen3, nclk2ctrlncen3 : std_logic; + signal seqroma : std_logic_vector(4 downto 0) := "11110"; + + begin + ncen1 <= tstenctrl2A nor c2d10; + + clk2ctrl <= clk2 or ncen1; + + ncen3 <= rstdel nor xromdo(7); + cen3 <= not ncen3; + + nclk2ctrlcen3 <= cen3 nor clk2ctrl; + nclk2ctrlncen3 <= ncen3 nor clk2ctrl; + + + process (clk2ctrl) + begin + if rising_edge(clk2ctrl) then + seqroma(0) <= rstdel nor not (cen3 or xromdo(36) or not (seqroma(4) xor not seqroma(1))); + + if cen3 = '0' then + seqroma(1) <= not seqroma(0); + seqroma(2) <= seqroma(1); + seqroma(3) <= seqroma(2); + seqroma(4) <= seqroma(3); + end if; + if ncen3 = '0' then + seqroma(4 downto 1) <= (others => '1'); + end if; + + xromdo7nq <= xromdo(7); -- unclear circuit extraction + end if; + + end process; + + xromdo7q <= not xromdo7nq; + + gseqroma <= seqroma(4 downto 1) & not seqroma(0); + + eaoen <= i_tst1 nor xromdo7nq; + + end block; + + rom_block : block + alias a0 : std_logic is gseqroma(0); + alias a1 : std_logic is gseqroma(1); + alias a2 : std_logic is gseqroma(2); + alias a3 : std_logic is gseqroma(3); + alias a4 : std_logic is gseqroma(4); + alias xa5 : std_logic is nc2d9fin.val; + alias xa6 : std_logic is c2d9fin.val; + signal na : std_logic_vector(gseqroma'range); + alias na0 : std_logic is na(0); + alias na1 : std_logic is na(1); + alias na2 : std_logic is na(2); + alias na3 : std_logic is na(3); + alias na4 : std_logic is na(4); + + signal ny : std_logic_vector(yromdo'range); + + -- NOTE: vectors for norf must be range 0 to N! + signal xwl : std_logic_vector(0 to 11); + signal ywl : std_logic_vector(0 to 35); + + begin + na <= not gseqroma; + + ------------------------------------------------------------------------- + -- XROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + xwl <= na0 & a0 & a1 & na1 & na2 & a2 & a3 & na3 & na4 & a4 & xa5 & xa6; + + -- xwl(0) xwl(11) + -- na0 xa6 + -- | | + xromdo <= (-- | | + 00 => norf(xwl, "100110100100"), + 01 => norf(xwl, "010110010100"), + 02 => norf(xwl, "011010011000"), + 03 => norf(xwl, "011001011000"), + 04 => norf(xwl, "011001101000"), + 05 => norf(xwl, "011001100100"), + 06 => norf(xwl, "101001100100"), + 07 => norf(xwl, "100101100100"), + -- + 08 => norf(xwl, "100110100100"), + 09 => norf(xwl, "011010100100"), + 10 => norf(xwl, "101001101000"), + 11 => norf(xwl, "011001010100"), + 12 => norf(xwl, "011001101010"), + 13 => norf(xwl, "011010011010"), + 14 => norf(xwl, "100110100110"), + -- + 15 => norf(xwl, "101001000110"), + 16 => norf(xwl, "011001100101"), + 17 => norf(xwl, "011001011001"), + 18 => norf(xwl, "010110010101"), + 19 => norf(xwl, "010001010100"), + 20 => norf(xwl, "010101000000"), + 21 => norf(xwl, "011001100010"), + -- + 22 => norf(xwl, "000110000110"), + 23 => norf(xwl, "011001001001"), + 24 => norf(xwl, "010110011000"), + 25 => norf(xwl, "101000101000"), + 26 => norf(xwl, "010101011000"), + 27 => norf(xwl, "011000011010"), + 28 => norf(xwl, "100101101001"), + -- + 29 => norf(xwl, "000110000100"), + 30 => norf(xwl, "011010011000"), + 31 => norf(xwl, "001010101000"), + 32 => norf(xwl, "010101010000"), + 33 => norf(xwl, "100101101010"), + 34 => norf(xwl, "101001010100"), + 35 => norf(xwl, "101010011000"), + 36 => norf(xwl, "100110011000"), + others => '1'); + -- + ------------------------------------------------------------------------- + + + ------------------------------------------------------------------------- + -- YROM data out + -- + x_to_ywl : for idx in ywl'range generate + ywl(idx) <= xromdo(idx); + end generate; + + -- The sequence of the word lines must match the ROM bitmap below: + -- Leftmost word line is x0, rightmost word line is x35 + -- + -- ywl(0) ywl(35) + -- x0 x35 + -- | | + ny <= (-- | | + 04 => norf(ywl, "000000000100000000011000110000010001"), + 03 => norf(ywl, "000000000000111111111000100010000000"), + 02 => norf(ywl, "000000001001000000000111011010000000"), + 01 => norf(ywl, "000000000000000000000000000111111000"), + 00 => norf(ywl, "000000000000000000000000100000000111"), + others => '1'); + + c2d3gate <= norf(xromdo(7 downto 0)); + + yromdo <= not ny; + -- + ------------------------------------------------------------------------- + + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- COUNT DOWN + -- + cntdown_block : block + signal cntq : unsigned(7 downto 3) := (others => '0'); + begin + process (clkcntdn) + begin + if rising_edge(clkcntdn) then + if ncntdnload = '0' then + cntq(7 downto 4) <= unsigned(dinalq(7 downto 4)); + cntq(3) <= '1'; + + else + if ncntdn = '0' then + cntq <= cntq - 1; + end if; + + end if; + end if; + end process; + + cntdn0 <= '1' when cntq = 0 else '0'; + + end block; + + + + ----------------------------------------------------------------------------- + -- DIN ALIGNMENT + -- + din_block : block + signal dinlat : std_logic_vector(i_d'range) := (others => '0'); + signal ndincom : std_logic; + + signal latchhq, latchh : std_logic_vector(15 downto 8); + + begin + process (osc.base) + begin + if rising_edge(osc.base) then + if clkdin = '0' then + dinlat <= i_d; + end if; + end if; + end process; + + ndincom <= norf(dinlat and xromdo(7 downto 0)); + + process (clrdinal, c2d3gated) + begin + if clrdinal = '1' then + dinalq <= (others => '0'); + elsif rising_edge(c2d3gated) then + dinalq <= not ndincom & dinalq(7 downto 1); + end if; + end process; + + process (osc.base) + begin + if rising_edge(osc.base) then + if ealatchh = '1' then + latchhq <= dinalq; + end if; + end if; + end process; + + latchh(8) <= dinalq(0) when eavcu = '1' else + latchhq(8); + latchh(15 downto 9) <= (others => '0') when eavcu = '1' else + latchhq(15 downto 9); + + process (clk2ena) + begin + if rising_edge(clk2ena) then + if neaload = '0' then + -- parallel load + aq( 0) <= eavcu nor (not dinalq(0)); + aq( 7 downto 1) <= dinalq(7 downto 1); + aq(15 downto 8) <= latchh; + else + if eainc = '1' then + -- toggle/ripple + aq <= std_logic_vector(unsigned(aq) + 1); + end if; + end if; + end if; + end process; + + end block; + + + + ----------------------------------------------------------------------------- + -- Random data source + -- + random_block : block + signal lfsr : std_logic_vector(9 downto 0) := (others => '0'); + signal all0 : std_logic; + signal feedback : std_logic; + begin + + all0 <= norf(lfsr(lfsr'high-1 downto 0)); + + feedback <= (lfsr(9) xor lfsr(2)) nor all0; + + process (clk2ena) + begin + if rising_edge(clk2ena) then + lfsr <= lfsr(8 downto 0) & (rstdel nor feedback); + end if; + end process; + + random <= lfsr(9); + + end block; + + + + ----------------------------------------------------------------------------- + -- START control logic + -- + start_block : block + alias vcu : std_logic is i_vcu; + signal nvcu : std_logic; + + signal startq : std_logic_vector(2 downto 0); + alias startq0 : std_logic is startq(0); + alias startq1 : std_logic is startq(1); + alias startq2 : std_logic is startq(2); + signal startriseq : std_logic; + signal startriseqvcu : std_logic; + + signal ffsset : std_logic; + signal ffsloop : std_logic; + signal ffs1q, ffs2q, + ffs3q, ffs4q : std_logic := '1'; + signal ffs1nq, ffs2nq, + ffs3nq, ffs4nq : std_logic; + signal ffs5q : std_logic := '0'; + signal ffs5nq : std_logic; + signal vcumode : std_logic; + alias nvcumode : std_logic is ffs1q; + + signal vcufinal : std_logic; + signal vcufinal1q, + vcufinal2q : std_logic; + signal nvcufinal12 : std_logic; + + signal xromdo7nqdel : std_logic; + + signal msff1q, msff2q, + pmsff3q : std_logic := '1'; + signal msff1nq, msff2nq, + pmsff3nq : std_logic; + signal msffset : std_logic; + + signal n001x, n002x, n003x, n004x, n005x, n006x, + n007x, n008x, n009x, n014x, n015x, + n016x, n017x : std_logic; + signal n012x : t_clk; + + signal busy1q, + busy2q : std_logic; + signal setbusy1 : std_logic; + + begin + nvcu <= not vcu; + vcumode <= not nvcumode; + + vcufinal <= not nvcufinal; + + process (rstdel, clk2ena) + begin + if rstdel = '1' then + startq <= (others => '0'); + startriseq <= '1'; + + elsif rising_edge(clk2ena) then + startq <= startq(1 downto 0) & starttst; + startriseq <= startrise nand vcu; + + end if; + end process; + + startrise <= (not startq1) nor startq2; + startriseqvcu <= not startriseq; + + + ffsset <= rstdel or n005x; + process (ffsset, clk2ena) + begin + if ffsset = '1' then + ffs1q <= '1'; + ffs1q <= '1'; + ffs4q <= '1'; + ffs5q <= '0'; + elsif rising_edge(clk2ena) then + ffs1q <= (ffs1nq and ffsloop) nor (nvcu and startrise); -- async set + ffs2q <= (ffs2nq and ffsloop) nor ( vcu and startrise); -- async set + ffs4q <= (ffs4q nor startrise) nor (startq1 nor ffs3nq); -- async set + ffs5q <= ffs5nq nand ffsloop; -- async clr + + end if; + end process; + process (clk2ena) + begin + if rising_edge(clk2ena) then + ffs3q <= ffs1nq; -- no async set/clr + end if; + end process; + ffs1nq <= not ffs1q; + ffs2nq <= not ffs2q; + ffs3nq <= not ffs3q; + ffs4nq <= not ffs4q; + ffs5nq <= not ffs5q; + -- + ffsloop <= ffs1q or (not ffs3q) or (not fsromdo(6)); + + + process (vcufinal, clk2enb) + begin + if vcufinal = '1' then + vcufinal1q <= '1'; + vcufinal2q <= '1'; + + elsif rising_edge(clk2enb) then + vcufinal1q <= not vcufinal1q; + + if vcufinal1q = '1' then + vcufinal2q <= not vcufinal2q; + end if; + end if; + + end process; + + vcufinal12 <= (not vcufinal1q) nor (not vcufinal2q); + nvcufinal12 <= not vcufinal12; + nvcufinal <= rstdel nor (nvcumode nor (not ffs4q)); + + eavcu <= ffs2nq xor (ffs3q nor nvcumode); + + neaload <= (nvcumode or (ffs3q and (ffs2nq or (not fsromdo(6)) or nvcufinal12))); + + xromdo7nqdel_b : entity work.vlm5030_delay_inv + generic map ( + -- delay by ~558ns = 2 clocks + g_numclks => 2 + ) + port map ( + i_clk => osc, + i_in => xromdo7q, + o_out => xromdo7nqdel + ); + + clkdin <= (xromdo7nq and xromdo7nqdel and (vcumode or startriseqvcu)) nor ffs4nq; + + ealatchh <= startriseqvcu or (fsromdo(7) and ffs3q and vcufinal12); + + + msffset <= rstdel or startrise; + -- + process (msffset, c2d0) + begin + if msffset = '1' then + msff1q <= '1'; + elsif rising_edge(c2d0) then + msff1q <= n008x nor (pmsff3nq and xromdo(7)); + end if; + end process; + msff1nq <= not msff1q; + -- + process (msffset, c2d6) + begin + if msffset = '1' then + msff2q <= '1'; + elsif rising_edge(c2d6) then + msff2q <= msff2nq nor (xromdo(1) and n007x and pmsff3nq); + end if; + end process; + msff2nq <= not msff2q; + -- + process (c2d6) + begin + if rising_edge(c2d6) then + pmsff3q <= (n007x and xromdo(0)) nor (pmsff3nq and msff1q); + end if; + end process; + pmsff3nq <= not pmsff3q; + + + n001x <= not( (not fsromdo(7)) or nvcufinal12 or ffs2nq or ffs3nq ); + n002x <= not( dq(0) or vcufinal2q or vcufinal1q ); + n003x <= not( n002x or dq(1) or n004x ); + n004x <= vcufinal1q nor (not dq(0)); + n005x <= not( msff2q or n006x or nc2d6 ); + n006x <= n009x nand cntdn0; + n007x <= not( n003x or ffs5nq or (fsromdo(13) nand dinalq(7)) ); + n008x <= not( msff1q or rstdel or (not n006x) ); + n009x <= not( nvcufinal12 or (not fsromdo(6)) or (not xromdo(7)) ); + n012x <= not( nc2d10 or n003x or fsromevalout or ffs5nq ); + n014x <= n001x nor not( n003x or ffs5nq or fsromnorhigh ); + n015x <= not( dq(1) or n004x or (not ( vcufinal2q or (not vcufinal1q) or dq(0)) ) ); + n016x <= (not fsromdo(6)) nor (not( dq(1) or n017x or (dq(0) and vcufinal1q) )); + n017x <= not( dq(0) or (not vcufinal12) or (not vcufinal1q) ); + + ncntdn <= not( msff1nq and n009x and (not cntdn0) ); + + ncntdnload <= xromdo(5) nand pmsff3nq; + clkcntdn <= (c2d0 and msff1nq) or (c2d6 and (xromdo(5) and pmsff3nq)); + + clrdinal <= msff1nq or n012x; + + eainc <= n014x nor msff1nq; + + + setbusy1 <= startq1 nor startriseqvcu; + process (setbusy1, clk2ctrl) + begin + if setbusy1 = '1' then + busy1q <= '1'; + elsif rising_edge(clk2ctrl) then + busy1q <= startriseqvcu nor (not busy1q); + end if; + end process; + + process (ffsset, clk2ctrl) + begin + if ffsset = '1' then + busy2q <= '1'; + elsif rising_edge(clk2ctrl) then + busy2q <= vcumode nor (not busy2q); + end if; + end process; + + nbsy <= (not busy1q) nor (not busy2q); + + me <= not( ffs4q or i_start or xromdo7nq ); + + rflatchwen <= not( fsromevalout or n003x or nc2d6 ); + + asshift2 <= not( vcufinal2q or dq(1) or dq(0) ); + + updtpitch <= not( n015x or (not fsromdo(6)) or (not xromdo(11)) ); + + enrf2ID <= (not( n016x and (tstend2ID nor ffs5nq) )) nor nc2d8; + + clkksa <= n012x; + + ensum2ID <= not( ffs5nq or tstend2ID or ((n016x nor nc2d8) nor c2d4) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- K-Factor ROM + -- + krom_block : block + signal ka : std_logic_vector(4 downto 0); + begin + + agen_block : block + signal nfsrdo6 : std_logic; + signal ksaq : std_logic_vector(3 downto 0); + begin + + ka <= dinalq(7 downto 3); + + process (fsromdo(6), clkksa) + variable toggle : std_logic_vector(ksaq'high+1 downto 0); + begin + if fsromdo(6) = '1' then + ksaq <= "1011"; + + elsif rising_edge(clkksa) then + toggle(0) := '1'; + for idx in 0 to ksaq'high loop + if toggle(idx) = '1' then + ksaq(idx) <= not ksaq(idx); + end if; + + toggle(idx+1) := ksaq(idx) nor (not toggle(idx)); + end loop; + + end if; + end process; + + nfsrdo6 <= not fsromdo(6); + + ksa(3 downto 0) <= ( + 0 => ((not ksaq(0)) and nfsrdo6) nor (nfsrdo6 nor yromdo(3)), + 1 => ((not ksaq(1)) and nfsrdo6) nor (nfsrdo6 nor yromdo(2)), + 2 => ((not ksaq(2)) and nfsrdo6) nor (nfsrdo6 nor yromdo(1)), + 3 => ((not ksaq(3)) and nfsrdo6) nor (fsromdo(6) and (yromdo(0) xor (xromdo(10) nor xromdo(11)))) + ); + + end block; + + rom_block : block + signal kslice0, kslice1, kslice2, kslice3, kslice4, kslice5 : std_logic_vector(9 downto 0); + + -- NOTE: vectors for norf must be range 0 to N! + signal wl : std_logic_vector(0 to 31); + signal wl_slice : std_logic_vector(0 to 5); + + alias kaodd : std_logic is dinalq(2); + signal nkaodd : std_logic; + alias ksa0 : std_logic is ksa(0); + signal nksa0 : std_logic; + signal range_s0s1s2, range_s3s4 : std_logic; + + signal kout : std_logic_vector(nkdo'range); + begin + + process (ka) + begin + wl <= (others => '0'); + wl(to_integer(unsigned(ka))) <= '1'; + end process; + + --------------------------------------------------------------------------- + -- KROM data out + -- + -- The sequence of the word lines must match the ROM bitmaps below + + -- wl(0) wl(31) + -- | | + kslice0 <= (-- | | + 00 => orf(wl, "11110111110000101101000111000101"), + 01 => orf(wl, "00000001001010110101010111101111"), + 02 => orf(wl, "00110111010011001110111111000001"), + 03 => orf(wl, "10110010011100000001101111010010"), + 04 => orf(wl, "10011011100000000001011111001011"), + 05 => orf(wl, "11011100000000000100111111000110"), + 06 => orf(wl, "11100000000000000110101010010100"), + 07 => orf(wl, "00000000000000001000110011100111"), + 08 => orf(wl, "00000000000000001111000011111000"), + 09 => orf(wl, "11111111111111110000000011111111"), + others => '0'); + + kslice1 <= ( + 00 => orf(wl, "00000100101110101100000110000011"), + 01 => orf(wl, "01011010100100111100111110001111"), + 02 => orf(wl, "11110001110111001101001110110111"), + 03 => orf(wl, "10001010111000000000011110011100"), + 04 => orf(wl, "01010011000000001110111110001000"), + 05 => orf(wl, "10011100000000001010000001111010"), + 06 => orf(wl, "11100000000000001100101010101100"), + 07 => orf(wl, "00000000000000000000110011001111"), + 08 => orf(wl, "00000000000000001111000011110000"), + 09 => orf(wl, "11111111111111110000000011111111"), + others => '0'); + + kslice2 <= ( + 00 => orf(wl, "11101010111101111111011110101011"), + 01 => orf(wl, "10111111010110001000010100101010"), + 02 => orf(wl, "11000100101011001110000001000100"), + 03 => orf(wl, "11111101000100101101101110100000"), + 04 => orf(wl, "10101001111101001110100000110101"), + 05 => orf(wl, "10011011010110001111001010010011"), + 06 => orf(wl, "11010010011000001111110011011010"), + 07 => orf(wl, "11100011100000001111111100011100"), + 08 => orf(wl, "11111100000000001111111111100000"), + 09 => orf(wl, "11111111111111111000000000000000"), + others => '0'); + + kslice3 <= ( + 00 => orf(wl, "10100100000001100111000110101010"), + 01 => orf(wl, "11001001010100100000001010010010"), + 02 => orf(wl, "11110001100110110101011001111100"), + 03 => orf(wl, "11111110000111000110010010101010"), + 04 => orf(wl, "11111111111000000111100011001100"), + 05 => orf(wl, "11111111111111111000000011110000"), + 06 => orf(wl, "11111111111111111111111100000000"), + others => '0'); + + kslice4 <= ( + 03 => orf(wl, "10101010100000000000000000000000"), + 04 => orf(wl, "11001100110101010111111111111111"), + 05 => orf(wl, "10001111000110011010101010000000"), + 06 => orf(wl, "11110000000111100011001100101010"), + 07 => orf(wl, "10000000000111111100001111001100"), + 08 => orf(wl, "11111111111000000000001111110000"), + 09 => orf(wl, "11111111111111111111110000000000"), + others => '0'); + + kslice5 <= ( + 06 => not ka(1), + 07 => not ka(2), + 08 => not ka(3), + 09 => not ka(4), + others => '0'); + -- + --------------------------------------------------------------------------- + + ------------------------------------------------------------------------- + -- Output mux + -- + range_s0s1s2 <= norf(ksa(3 downto 1)); + range_s3s4 <= ksa(2) nor (ksa(3) nand ksa(1)); + nkaodd <= not kaodd; + nksa0 <= not ksa0; + + -- NOTE: Each bitline forms a distributed complex gate: (enable) AND (OR'ed wl-transistors) + -- Bitlines from each slice are then NORed together to the data lines. + -- + -- 1. Wordlines are OR'ed on each bitline by the transistors + -- 2. The enable lines gate the effect of the bitline: + -- - enabled: can pull data line to 0 if result of OR is 1 + -- - not enabled: data line remains 1 + -- 3. Bitline result is visible as a NOR on the data line if enabled + -- + -- This model pre-calculates the bitlines above using OR and NORs + -- their results (enabled by the slice wls) onto the data lines. + -- + -- --> kout represents the data lines + + wl_slice <= (range_s0s1s2 and nksa0 and nkaodd) & -- enable kslice0 + (range_s0s1s2 and nksa0 and kaodd) & -- enable kslice1 + (range_s0s1s2 and ksa0 ) & -- enable kslice2 + (range_s3s4 and nksa0 ) & -- enable kslice3 + (range_s3s4 and ksa0 ) & -- enable kslice4 + (range_s0s1s2 nor range_s3s4 ) ; -- enable kslice5 + kout_gen : for idx in kout'range generate + kout(idx) <= norf(wl_slice, + kslice0(idx) & + kslice1(idx) & + kslice2(idx) & + kslice3(idx) & + kslice4(idx) & + kslice5(idx)); + end generate; + -- data lines are subsequently inverted by the INVBUFs + nkdo <= not kout; + + end block; + end block; + + + + ----------------------------------------------------------------------------- + -- Register file + -- + -- Memory map + -- + -- 9 8 7 6 5 4 3 2 1 0 + -- ksa[3..0] +---------------------+ + -- 11 | Pitch |XXXXXX| + -- +---------------------+ + -- 10 |XXXXXX| Energy | + -- +---------------------+ + -- 9 | K10 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 8 | K9 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 7 | K8 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 6 | K7 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 5 | K6 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 4 | K5 |XXXXXXXXXXXXXX| + -- +---------------------+ + -- 3 | K4 |XXXXXXXXXXXX| + -- +---------------------+ + -- 2 | K3 |XXXXXXXXXXXX| + -- +---------------------+ + -- 1 | K2 | + -- +---------------------+ + -- 0 | K1 | + -- +---------------------+ + -- + -- + regfile_block : block + signal rf0, rf1 : std_logic_vector(9 downto 0) := (others => '0'); + signal rf2, rf3 : std_logic_vector(9 downto 6) := (others => '0'); + signal rf4, rf5, + rf6, rf7, + rf8, rf9 : std_logic_vector(9 downto 7) := (others => '0'); + signal rf10 : std_logic_vector(6 downto 0) := (others => '0'); + signal rf11 : std_logic_vector(9 downto 3) := (others => '0'); + signal a : natural; + signal al : std_logic_vector(0 to 11); + signal nrfdo : std_logic_vector(rfdo'range); + + begin + a <= to_integer(unsigned(ksa)); + + process (osc.base) + begin + if rising_edge(osc.base) then + if rflatchwen = '1' then + case a is + when 0 => rf0 <= nkdo; + when 1 => rf1 <= nkdo; + when 2 => rf2 <= nkdo( rf2'range); + when 3 => rf3 <= nkdo( rf3'range); + when 4 => rf4 <= nkdo( rf4'range); + when 5 => rf5 <= nkdo( rf5'range); + when 6 => rf6 <= nkdo( rf6'range); + when 7 => rf7 <= nkdo( rf7'range); + when 8 => rf8 <= nkdo( rf8'range); + when 9 => rf9 <= nkdo( rf9'range); + when 10 => rf10 <= nkdo(rf10'range); + when 11 => rf11 <= nkdo(rf11'range); + when others => null; + end case; + end if; + end if; + end process; + + process (a) + begin + al <= (others => '0'); + if a <= al'high then + al(a) <= '1'; + end if; + end process; + + -- unimplemented bits read as '0' + -- they're coded with '1' here because the norif function inverts the vec operand + nrfdo(0) <= norif(al, rf0(0) & rf1(0) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(0) & '1' ); + nrfdo(1) <= norif(al, rf0(1) & rf1(1) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(1) & '1' ); + nrfdo(2) <= norif(al, rf0(2) & rf1(2) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(2) & '1' ); + nrfdo(3) <= norif(al, rf0(3) & rf1(3) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(3) & rf11(3) ); + nrfdo(4) <= norif(al, rf0(4) & rf1(4) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(4) & rf11(4) ); + nrfdo(5) <= norif(al, rf0(5) & rf1(5) & '1' & '1' & '1' & '1' & '1' & '1' & '1' & '1' & rf10(5) & rf11(5) ); + nrfdo(6) <= norif(al, rf0(6) & rf1(6) & rf2(6) & rf3(6) & '1' & '1' & '1' & '1' & '1' & '1' & rf10(6) & rf11(6) ); + nrfdo(7) <= norif(al, rf0(7) & rf1(7) & rf2(7) & rf3(7) & rf4(7) & rf5(7) & rf6(7) & rf7(7) & rf8(7) & rf9(7) & '1' & rf11(7) ); + nrfdo(8) <= norif(al, rf0(8) & rf1(8) & rf2(8) & rf3(8) & rf4(8) & rf5(8) & rf6(8) & rf7(8) & rf8(8) & rf9(8) & '1' & rf11(8) ); + nrfdo(9) <= norif(al, rf0(9) & rf1(9) & rf2(9) & rf3(9) & rf4(9) & rf5(9) & rf6(9) & rf7(9) & rf8(9) & rf9(9) & '1' & rf11(9) ); + -- register file ouputs are subsequently inverted by the INVBUFs + rfdo <= not nrfdo; + + rfdo97zero <= norf(rfdo(9 downto 7)); + + end block; + + + + ----------------------------------------------------------------------------- + -- ADDSHIFT + -- + addshift_block : block + signal nIDlat, port_nID, + port_rf : std_logic_vector(nID'range); + signal sumlat : std_logic_vector(nID'high+2 downto 0); + signal cin, sum : std_logic_vector(nID'high+1 downto 0); + signal idpos : std_logic; + begin + + idpos <= not( (dq(6) and updtpitch) nor c2d5fin); + + cin(0) <= not idpos; + + -- + -- Generate adder/shifter slices + -- + addshift_slice : for idx in nID'high downto 0 generate + + -- nID bus latch cell + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d1 = '1' then + nIDlat(idx) <= nID(idx); + end if; + end if; + end process; + + -- adder port: nID bus + port_nID(idx) <= not nIDlat(idx) when idpos = '1' else nIDlat(idx); + -- adder port: registerfile or shift + port_rf(idx) <= rfdo(idx) when c2d5fin = '0' else + sumlat(idx+1) when asshift2 = '0' else + sumlat(idx+2); + -- xor3 cell + sum(idx) <= port_nID(idx) xor port_rf(idx) xor cin(idx); + -- carry cell + cin(idx+1) <= (port_nID(idx) and port_rf(idx)) or ((port_nID(idx) or port_rf(idx)) and cin(idx)); + + -- sum latch cell + -- note: sumlat[0] is omitted on the die + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d4 = '1' then + sumlat(idx) <= sum(idx); + end if; + end if; + end process; + end generate; + + -- extra cells + sum(nID'high+1) <= cin(nID'high+1) xor port_nID(nID'high) xor port_rf(nID'high); + process (osc.base) + begin + if rising_edge(osc.base) then + if c2d4 = '1' then + sumlat(nID'high+1) <= sum(nID'high+1); + end if; + end if; + end process; + sumlat(nID'high+2) <= sumlat(nID'high+1); + + assum <= sum(nID'range); + + end block; + + + + ----------------------------------------------------------------------------- + -- Pitch incrementer + -- + pitchinc_block : block + signal pitchlat, + pitchreg : std_logic_vector(9 downto 3) := (others => '0'); + signal toggle : std_logic_vector(pitchreg'high+1 downto pitchreg'low); + begin + + enpitchlat <= not (c2d4 nand updtpitch); + + process (osc.base) + begin + if rising_edge(osc.base) then + if enpitchlat = '1' then + pitchlat <= nID(pitchlat'range); + end if; + end if; + end process; + + process (rstdel, clk2ena) + begin + if rstdel = '1' then + pitchreg <= (others => '0'); + + elsif rising_edge(clk2ena) then + if pitchoverflow = '1' then + -- load + pitchreg <= pitchlat; + else + -- toggle reg + for idx in pitchreg'range loop + if toggle(idx) = '1' then + pitchreg(idx) <= not pitchreg(idx); + end if; + end loop; + end if; + + end if; + end process; + + toggle(3) <= '1'; + gen_toggle: for idx in 4 to toggle'high generate + toggle(idx) <= (not pitchreg(idx-1)) nor (not toggle(idx-1)); + end generate; + + pitchoverflow <= toggle(toggle'high); + + end block; + + + pitchmod <= not( (not(dq(6) xor dq(7))) or tstend2ID or nc2d1 ); + + + + ----------------------------------------------------------------------------- + -- nID bus + -- + nID_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= tstend2ID & enrf2ID & ensum2ID & updtpitch & enIDlinv2ID & enmem02ID ; + -- | | | | | | | + nID(0) <= norf(wl, i_d(0) & rfdo(0) & assum(0) & '0' & not idlat(0) & nmem0do(0) ); + nID(1) <= norf(wl, i_d(1) & rfdo(1) & assum(1) & '0' & not idlat(1) & nmem0do(1) ); + nID(2) <= norf(wl, i_d(2) & rfdo(2) & assum(2) & '0' & not idlat(2) & nmem0do(2) ); + nID(3) <= norf(wl, i_d(3) & rfdo(3) & assum(3) & '0' & not idlat(3) & nmem0do(3) ); + nID(4) <= norf(wl, i_d(4) & rfdo(4) & assum(4) & '0' & not idlat(4) & nmem0do(4) ); + nID(5) <= norf(wl, i_d(5) & rfdo(5) & assum(5) & '0' & not idlat(5) & nmem0do(5) ); + nID(6) <= norf(wl, i_d(6) & rfdo(6) & assum(6) & pitchmod & not idlat(6) & nmem0do(6) ); + nID(7) <= norf(wl, i_d(7) & rfdo(7) & assum(7) & '0' & not idlat(7) & nmem0do(7) ); + nID(8) <= norf(wl, i_d(0) & rfdo(8) & assum(8) & '0' & '0' & nmem0do(8) ); + nID(9) <= norf(wl, i_d(1) & rfdo(9) & assum(9) & '0' & '0' & nmem0do(9) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- ID Latch + -- + idlat_block : block + signal idlaten : std_logic; + signal n : std_logic; + begin + + idlaten <= not( (not fsromdo(6)) or (not xromdo(10)) or nc2d8 ); + enIDlinv2ID <= not( (not xromdo(10)) or tstend2ID or nc2d1 ); + + n <= xromdo7q or tstend2IE or c2d7fin; + enIDlinv2IE <= (not( (maskdq53 and random) or ((not maskdq53) and pitchoverflow) )) nor n; + enIDl2IE <= not( n or random or idlatall1 or (not maskdq53) ); + + process (osc.base) + begin + if rising_edge(osc.base) then + if idlaten = '1' then + idlat <= nID(7 downto 0); + end if; + end if; + end process; + + idlatall1 <= norf(not idlat); + + end block; + + + + ----------------------------------------------------------------------------- + -- Memories + -- + mem_block : block + signal swapa : unsigned(3 downto 0); + signal a : natural; + + signal clkmem0, clkmem1, clkmem2 : std_logic; + + type t_mem0 is array(0 to 9) of std_logic_vector(nID'range); + signal mem0 : t_mem0 := (others => (others => '0')); + type t_mem1 is array(0 to 9) of std_logic_vector(nIE'range); + signal mem1 : t_mem1 := (others => (others => '0')); + type t_mem2 is array(0 to 8) of std_logic_vector(nIE'range); + signal mem2 : t_mem2 := (others => (others => '0')); + begin + + yswap_gen : for idx in 3 downto 0 generate + swapa(idx) <= yromdo(3-idx); + end generate; + a <= to_integer(swapa); + + -- + -- MEM0 + -- + clkmem0 <= not( xromdo(7) or (not fsromdo(6)) or (xromdo7q and yromdo(4)) or nc2d8 ); + enmem02ID <= not( tstend2ID or (xromdo7q and yromdo(4)) or nc2d1 ); + + mem0_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem0 = '1' then + if a <= t_mem0'high then + mem0(a) <= nID; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + nmem0do <= not mem0(a) when a <= t_mem0'high else (others => '1'); + mem0do <= not nmem0do; + + + -- + -- MEM1 + -- + clkmem1 <= yromdo(4) nor nc2d10; + enmem12IE <= not( yromdo(4) or tstend2IE or c2d7fin ); + + mem1_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem1 = '1' then + if a <= t_mem1'high then + mem1(a) <= nIE; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + mem1do2IE <= not mem1(a) when a <= t_mem1'high else (others => '1'); + + + -- + -- MEM2 + -- + clkmem2 <= yromdo(4) and c2d10; + enmem22IE <= not( tstend2IE or (not xromdo(7)) or nc2d10 ); + + mem2_p : process (osc.base) + begin + if rising_edge(osc.base) then + if clkmem2 = '1' then + if a <= t_mem2'high then + mem2(a) <= nIE; + end if; + end if; + end if; + end process; + + -- the latches provide inverted Q on output, enabled by a + mem2do2IE <= not mem2(a) when a <= t_mem2'high else (others => '1'); + + + end block; + + + ----------------------------------------------------------------------------- + -- Arithmetic block + -- + arithmetic_block : block + signal memxdo : std_logic_vector(nIE'range); + signal wl : std_logic_vector(0 to 1); + constant num_slices : natural := nIE'high+2; -- 13 slices + + type r_row is record + line1 : std_logic; + line2 : std_logic; + line3 : std_logic; + line4in : std_logic_vector(num_slices-1+1 downto 0); + lxor : std_logic_vector(num_slices-1 downto 0); + sum : std_logic_vector(num_slices-1 downto 0); + carry : std_logic_vector(num_slices-1 downto 0); + rowcarry1, rowcarry2 : std_logic; + end record; + signal row0, row1, row2, row3, row4 : r_row; + + -- map the slice index to the memxdo index + function map_slice_memxdo_f (slice : natural) return natural is + begin + if slice <= 9 then + -- slices 0 to 9 are supplied by memxdo(9) downto (0) + return 9-slice; + elsif slice = 10 then + -- slice 10 is supplied by memxdo(11) + return 11; + elsif slice = 11 then + -- slice 11 is supplied by memxdo(10) + return 10; + else + -- invalid slice + return 100; + end if; + end; + -- + function line1_f(odd_prev : std_logic; + even : std_logic) return std_logic is + begin + return not (odd_prev xor (not even)); + end; + -- + function line2_f(odd_prev : std_logic; + even : std_logic; + odd : std_logic) return std_logic is + begin + return ( + (not odd_prev) + and (not even) + and odd + ) or ( + odd_prev + and even + and (not odd) + ); + end; + -- + function xor_f (line4_upper : std_logic; + line1 : std_logic; + line2 : std_logic; + line3 : std_logic; + line4_lower : std_logic) return std_logic is + begin + return line3 xor not((line4_upper and line2) or (line4_lower and line1)); + end; + -- + function sum_f (porta : std_logic; + portb : std_logic; + carry : std_logic) return std_logic is + begin + return porta xor portb xor carry; + end; + -- + function carry_f (porta : std_logic; + portb : std_logic; + carry : std_logic) return std_logic is + begin + return ( + carry and (porta or portb) + ) or ( + porta and portb + ); + end; + -- + function map_slice_ie_f (slice : natural) return natural is + begin + return map_slice_memxdo_f(slice); + end; + + signal oeq, oenq : std_logic; + signal memlatmuxq : std_logic_vector(nIE'range); + type r_memlatmux is record + sum : std_logic_vector(nIE'range); + carry : std_logic_vector(nIE'range); + end record; + signal memlatmux : r_memlatmux; + + type r_iereg is record + q : std_logic_vector(nIE'range); + portb : std_logic_vector(nIE'range); + cout : std_logic_vector(nIE'high+1 downto 0); + sum : std_logic_vector(nIE'range); + end record; + signal iereg : r_iereg; + + begin + + wl <= yromdo(4) & not yromdo(4); + memxdo_gen : for idx in memxdo'range generate + memxdo(idx) <= norf(wl, mem1do2IE(idx) & mem2do2IE(idx)); + end generate; + + + -- + -- Row 0 + -- + row0.line1 <= line1_f(odd_prev => '1', + even => mem0do(0)); + row0.line2 <= (not mem0do(0)) nor mem0do(1); -- line2_f with odd_prev='1' + row0.line3 <= mem0do(1); + row0.line4in(0) <= row0.line4in(1); -- metal short between upper and lower line4 + -- preset with 0 to replicate unimplemented left half of MUXI + row0.line4in(13) <= '0'; + -- + row0_gen_low : for slice in 0 to 11 generate + row0.line4in(slice+1) <= not memxdo(map_slice_memxdo_f(slice)); + row0.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row0.line1, + line2 => row0.line2, + line3 => row0.line3, + line4_lower => row0.line4in(slice)); + row0.sum(slice) <= sum_f(porta => row0.lxor(slice), + portb => '0', + carry => '0'); + row0.carry(slice) <= '0'; + end generate; + + -- rowcarry is built based on slice 11 + row0.rowcarry1 <= not( (row0.line1 and row0.line4in(12)) or (row0.line3 or (not row0.sum(11))) ); + row0.rowcarry2 <= row0.rowcarry1; + + -- + -- Row 1 + -- + row1.line1 <= line1_f(odd_prev => mem0do(1), + even => mem0do(2)); + row1.line2 <= line2_f(odd_prev => mem0do(1), + even => mem0do(2), + odd => mem0do(3)); + row1.line3 <= mem0do(3); + row1.line4in <= (others => '0'); + -- slices 0 and 1 + row1_gen_0_1 : for slice in 0 to 1 generate + row1.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(slice)); + row1.sum(slice) <= not row1.lxor(slice); + row1.carry(slice) <= '0' when slice = 0 else + row1.lxor(slice); + end generate; + -- slice 2 has special carry calculation + row1.lxor(2) <= xor_f(line4_upper => row0.line4in(2+1), + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(2)); + row1.sum(2) <= sum_f(porta => row1.lxor(2), + portb => row0.sum(2-2), + carry => '0'); -- just XOR lxor with sum-2 + row1.carry(2) <= (not row1.lxor(2)) nand row0.sum(2-2); -- special operator in slice 2 + -- slices 3 to 12 + row1_gen_upper : for slice in 3 to num_slices-1 generate + row1.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row1.line1, + line2 => row1.line2, + line3 => row1.line3, + line4_lower => row0.line4in(slice)); + row1.sum(slice) <= sum_f(porta => row1.lxor(slice), + portb => row0.sum(slice-2), + carry => '0'); -- just XOR lxor with sum-2 + row1.carry(slice) <= carry_f(porta => row1.lxor(slice), + portb => row0.sum(slice-2), + carry => '0'); -- just AND lxor with sum-2 + end generate; + + -- rowcarry chain + row1.rowcarry1 <= carry_f(porta => not row1.line3, + portb => row1.sum(12), + carry => row0.rowcarry2); + row1.rowcarry2 <= carry_f(porta => row1.carry(12), + portb => row1.sum(11), + carry => row1.rowcarry1); + + + -- + -- Row 2 + -- + row2.line1 <= line1_f(odd_prev => mem0do(3), + even => mem0do(4)); + row2.line2 <= line2_f(odd_prev => mem0do(3), + even => mem0do(4), + odd => mem0do(5)); + row2.line3 <= mem0do(5); + row2.line4in <= (others => '0'); + -- slices 0 and 1 + row2_gen_0_1 : for slice in 0 to 1 generate + row2.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row2.line1, + line2 => row2.line2, + line3 => row2.line3, + line4_lower => row0.line4in(slice)); + row2.sum(slice) <= not row2.lxor(slice); + row2.carry(slice) <= '0' when slice = 0 else + row2.lxor(slice); + end generate; + -- slices 2 to 12 + row2_gen_upper : for slice in 2 to num_slices-1 generate + row2.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row2.line1, + line2 => row2.line2, + line3 => row2.line3, + line4_lower => row0.line4in(slice)); + row2.sum(slice) <= sum_f(porta => row2.lxor(slice), + portb => row1.sum(slice-2), + carry => row1.carry(slice-1)); + row2.carry(slice) <= carry_f(porta => row2.lxor(slice), + portb => row1.sum(slice-2), + carry => row1.carry(slice-1)); + end generate; + + -- rowcarry chain + row2.rowcarry1 <= carry_f(porta => not row2.line3, + portb => row2.sum(12), + carry => row1.rowcarry2); + row2.rowcarry2 <= carry_f(porta => row2.carry(12), + portb => row2.sum(11), + carry => row2.rowcarry1); + + -- + -- Row 3 + -- + row3.line1 <= line1_f(odd_prev => mem0do(5), + even => mem0do(6)); + row3.line2 <= line2_f(odd_prev => mem0do(5), + even => mem0do(6), + odd => mem0do(7)); + row3.line3 <= mem0do(7); + row3.line4in <= (others => '0'); + -- slices 0 and 1 + row3_gen_0_1 : for slice in 0 to 1 generate + row3.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row3.line1, + line2 => row3.line2, + line3 => row3.line3, + line4_lower => row0.line4in(slice)); + row3.sum(slice) <= not row3.lxor(slice); + row3.carry(slice) <= '0' when slice = 0 else + row3.lxor(slice); + end generate; + -- slices 2 to 12 + row3_gen_upper : for slice in 2 to num_slices-1 generate + row3.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row3.line1, + line2 => row3.line2, + line3 => row3.line3, + line4_lower => row0.line4in(slice)); + row3.sum(slice) <= sum_f(porta => row3.lxor(slice), + portb => row2.sum(slice-2), + carry => row2.carry(slice-1)); + row3.carry(slice) <= carry_f(porta => row3.lxor(slice), + portb => row2.sum(slice-2), + carry => row2.carry(slice-1)); + end generate; + + -- rowcarry chain + row3.rowcarry1 <= carry_f(porta => not row3.line3, + portb => row3.sum(12), + carry => row2.rowcarry2); + row3.rowcarry2 <= carry_f(porta => row3.carry(12), + portb => row3.sum(11), + carry => row3.rowcarry1); + + -- + -- Row 4 + -- + row4.line1 <= line1_f(odd_prev => mem0do(7), + even => mem0do(8)); + row4.line2 <= line2_f(odd_prev => mem0do(7), + even => mem0do(8), + odd => mem0do(9)); + row4.line3 <= mem0do(9); + row4.line4in <= (others => '0'); + -- slices 0 and 1 + row4_gen_0_1 : for slice in 0 to 1 generate + row4.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), + line1 => row4.line1, + line2 => row4.line2, + line3 => row4.line3, + line4_lower => row0.line4in(slice)); + row4.sum(slice) <= not row4.lxor(slice); + row4.carry(slice) <= '0' when slice = 0 else + row4.lxor(slice); + end generate; + -- slices 2 to 12 + row4_gen_upper : for slice in 2 to num_slices-1 generate + row4.lxor(slice) <= xor_f(line4_upper => row0.line4in(slice+1), -- slice 12 expects 0 + line1 => row4.line1, + line2 => row4.line2, + line3 => row4.line3, + line4_lower => row0.line4in(slice)); + row4.sum(slice) <= sum_f(porta => row4.lxor(slice), + portb => row3.sum(slice-2), + carry => row3.carry(slice-1)); + row4.carry(slice) <= carry_f(porta => row4.lxor(slice), + portb => row3.sum(slice-2), + carry => row3.carry(slice-1)); + end generate; + + -- rowcarry chain + row4.rowcarry1 <= carry_f(porta => not row4.line3, + portb => row4.sum(12), + carry => row3.rowcarry2); + row4.rowcarry2 <= row4.rowcarry1; + + + -- + -- MEMLATMUX + -- + memlatmux_p : process (c2d7fin) + begin + if rising_edge(c2d7fin) then + memlatmuxq <= not ieregdrv; + end if; + end process; + -- + gen_memlatmux : for slice in 0 to memlatmuxq'high generate + memlatmux.sum(slice) <= row4.carry(slice+1) when c2d7fin = '0' else + memlatmuxq(slice) when yromdo(4) = '0' else -- OEQ /c2d7fin nor yromdo(4) = '1' + not memlatmuxq(slice); -- OEnQ /c2d7fin nor /yromdo(4) = '1' + memlatmux.carry(slice) <= row4.sum(slice); + end generate; + + + -- + -- IEREG level + -- + + -- represents MUX on output of ROWCARRY chain + iereg.cout(iereg.cout'high) <= not yromdo(4) when c2d7fin = '1' else + row4.rowcarry2; + iereg_gen : for slice in 0 to nIE'high generate + + -- IEREG + iereg_p : process (ieregload) + begin + if falling_edge(ieregload) then + iereg.q(slice) <= nIE(map_slice_ie_f(slice)); + end if; + end process; + + iereg.portb(slice) <= not iereg.q(slice) when c2d7fin = '1' else + memlatmux.carry(slice); + iereg.cout(slice) <= carry_f(porta => memlatmux.sum(slice), + portb => iereg.portb(slice), + carry => iereg.cout(slice+1)); + iereg.sum(slice) <= sum_f(porta => memlatmux.sum(slice), + portb => iereg.portb(slice), + carry => iereg.cout(slice+1)); + end generate; + + ieregdrv <= iereg.sum when ( ((not iereg.cout(0)) xor (not iereg.cout(1))) nand c2d7fin ) = '1' else + (others => '1') when not( iereg.cout(1) or (not iereg.cout(0)) or nc2d7fin ) = '1' else + (others => '0') when not( (not iereg.cout(1)) or iereg.cout(0) or nc2d7fin ) = '1' else + (others => 'X'); -- invalid + iregdrv_gen : for slice in 0 to nIE'high generate + ieregdrv4IE(slice) <= ieregdrv(map_slice_ie_f(slice)); + end generate; + + ieregload <= ( (c2d10 and yromdo(4)) or ( c2d6 and (xromdo7q nand yromdo(4) ) ) ); + enieregfa2IE <= not( tstend2IE or xromdo(7) or nc2d10 ); + + + -- + -- nIE distribution to ABUS and DAC + -- + c2d10xr9 <= c2d10 and xromdo(9); + enIE2A <= i_tst1 nor xromdo7q; + + ieaddr_p : process (c2d10xr9) + begin + if falling_edge(c2d10xr9) then + ieaddrreg <= not nIE; + end if; + end process; + + end block; + + + ----------------------------------------------------------------------------- + -- nIE bus + -- + nIE_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= enIDlinv2IE & enIDl2IE & enmem12IE & enmem22IE & enieregfa2IE & tstend2IE; + -- | | | | | | | + nIE( 0) <= norf(wl, '0' & '1' & mem1do2IE( 0) & mem2do2IE( 0) & ieregdrv4IE( 0) & i_d(0) ); + nIE( 1) <= norf(wl, not idlat(0) & idlat(0) & mem1do2IE( 1) & mem2do2IE( 1) & ieregdrv4IE( 1) & i_d(1) ); + nIE( 2) <= norf(wl, not idlat(1) & idlat(1) & mem1do2IE( 2) & mem2do2IE( 2) & ieregdrv4IE( 2) & i_d(2) ); + nIE( 3) <= norf(wl, not idlat(2) & idlat(2) & mem1do2IE( 3) & mem2do2IE( 3) & ieregdrv4IE( 3) & i_d(3) ); + nIE( 4) <= norf(wl, not idlat(3) & idlat(3) & mem1do2IE( 4) & mem2do2IE( 4) & ieregdrv4IE( 4) & i_d(4) ); + nIE( 5) <= norf(wl, not idlat(4) & idlat(4) & mem1do2IE( 5) & mem2do2IE( 5) & ieregdrv4IE( 5) & i_d(5) ); + nIE( 6) <= norf(wl, not idlat(5) & idlat(5) & mem1do2IE( 6) & mem2do2IE( 6) & ieregdrv4IE( 6) & i_d(6) ); + nIE( 7) <= norf(wl, not idlat(6) & idlat(6) & mem1do2IE( 7) & mem2do2IE( 7) & ieregdrv4IE( 7) & i_d(7) ); + nIE( 8) <= norf(wl, not idlat(7) & idlat(7) & mem1do2IE( 8) & mem2do2IE( 8) & ieregdrv4IE( 8) & i_d(0) ); + nIE( 9) <= norf(wl, '0' & '1' & mem1do2IE( 9) & mem2do2IE( 9) & ieregdrv4IE( 9) & i_d(1) ); + nIE(10) <= norf(wl, '0' & '1' & mem1do2IE(10) & mem2do2IE(10) & ieregdrv4IE(10) & i_d(2) ); + nIE(11) <= norf(wl, '0' & '1' & mem1do2IE(11) & mem2do2IE(11) & ieregdrv4IE(11) & i_d(3) ); + + end block; + + + + ----------------------------------------------------------------------------- + -- DAC block + -- + dac_block : block + signal pwmsel : std_logic; + begin + + pwm_block : block + signal pwm0, pwm1, pwm2 : std_logic; + + signal nc2d10xr9del : std_logic; + signal nclk2gd5hi, + nclk2gd5lo : std_logic; + + signal pwmreg1toggle, + pwmreg2toggle : std_logic; + signal pwmreg0, pwmreg1, + pwmreg2 : std_logic; + + signal pwmcomm, + pwmcommdel, + pwmcommand : std_logic; + signal pwmcomp : std_logic; + + begin + + pwm2 <= ieaddrreg(4) when tstenIE2DAC = '0' else nIE(4); + pwm1 <= ieaddrreg(3) when tstenIE2DAC = '0' else nIE(3); + pwm0 <= ieaddrreg(2) when tstenIE2DAC = '0' else nIE(2); + + nc2d10xr9del_b : entity work.vlm5030_delay_inv + generic map ( + -- delay by ~1.1us = 4 osc clocks + g_numclks => 4 + ) + port map ( + i_clk => osc, + i_in => c2d10xr9.val, + o_out => nc2d10xr9del + ); + nclk2gd5hi <= nc2d10xr9del nor clk2gd5; + nclk2gd5lo <= (not nc2d10xr9del) nor clk2gd5; + + pwmreg1toggle <= pwmreg0; + pwmreg2toggle <= (not pwmreg1) nor (not pwmreg0); + + process (clk2gd5) + begin + if rising_edge(clk2gd5) then + if nc2d10xr9del = '0' then + -- clear + pwmreg0 <= '0'; + pwmreg1 <= '0'; + pwmreg2 <= '0'; + + else + pwmreg0 <= not pwmreg0; + if pwmreg1toggle = '1' then + pwmreg1 <= not pwmreg1; + end if; + if pwmreg2toggle = '1' then + pwmreg2 <= not pwmreg2; + end if; + end if; + end if; + + end process; + + pwmcomm <= norf(pwmreg0 & pwmreg1 & pwmreg2); + pwmcommdel_b : entity work.vlm5030_delay + generic map ( + -- delay by ~1.1us = 4 osc clocks + g_numclks => 4 + ) + port map ( + i_clk => osc, + i_in => pwmcomm, + o_out => pwmcommdel + ); + pwmcommand <= pwmcomm and pwmcommdel; + + pwmcomp <= norif(pwm2 & pwm1 & pwm0, pwmreg2 & pwmreg1 & pwmreg0); + + pwmsr_b : entity work.vlm5030_srlatch + port map ( + i_clk => osc.base, + i_res => pwmcomp, + i_set => pwmcommand, + o_q => pwmsr + ); + pwmsel <= not i_vcu when tstenIE2DAC = '1' else + not pwmsr; + + end block; + + dacrom_block : block + signal ndac : std_logic_vector(4 downto 0); + signal dacval, dacpwm : signed(o_dao'high+1 downto 0); + begin + + ndac <= not ieaddrreg(9 downto 5) when tstenIE2DAC = '0' else + not nIE(9 downto 5); + + -- The R-ladder between GND and VREF has 34 segments. + -- * the lowest setting (-16 & pwmsel=1) generates 33 over 1 + -- * the highest setting (15 & pwmsel=0) generates 1 over 33 + -- TODO: check absolute resistance value of segments + + -- dacval is range 1 to 32 + dacval <= RESIZE(signed(not ndac), dacval'length) + 16+1; + -- dacpwm is range 1 to 33 + dacpwm <= dacval when pwmsel = '1' else dacval + 1; + + o_dao <= std_logic_vector(dacpwm(o_dao'range)); + -- TST2 not modelled + o_tst2 <= '0'; + + end block; + + end block; + + + + ----------------------------------------------------------------------------- + -- Address bus block + -- + abus_block : block + signal wl : std_logic_vector(0 to 5); + begin + + wl <= eaoen & enIE2A & tstenID2A & tstenIE2A & tstenctrl2A & tstenIE2DAC; + -- | | | | | | | + o_a( 0) <= not norf(wl, aq( 0) & ieaddrreg(0) & not nID(0) & not nIE( 0) & '0' & '0' ); + o_a( 1) <= not norf(wl, aq( 1) & ieaddrreg(1) & not nID(1) & not nIE( 1) & '0' & '0' ); + o_a( 2) <= not norf(wl, aq( 2) & ieaddrreg(2) & not nID(2) & not nIE( 2) & '0' & '0' ); + o_a( 3) <= not norf(wl, aq( 3) & ieaddrreg(3) & not nID(3) & not nIE( 3) & '0' & '0' ); + o_a( 4) <= not norf(wl, aq( 4) & ieaddrreg(4) & not nID(4) & not nIE( 4) & '0' & '0' ); + o_a( 5) <= not norf(wl, aq( 5) & ieaddrreg(5) & not nID(5) & not nIE( 5) & '0' & '0' ); + o_a( 6) <= not norf(wl, aq( 6) & ieaddrreg(6) & not nID(6) & not nIE( 6) & '0' & '0' ); + o_a( 7) <= not norf(wl, aq( 7) & ieaddrreg(7) & not nID(7) & not nIE( 7) & '0' & '0' ); + o_a( 8) <= not norf(wl, aq( 8) & ieaddrreg(8) & not nID(8) & not nIE( 8) & '0' & '0' ); + o_a( 9) <= not norf(wl, aq( 9) & not ieaddrreg(9) & not nID(9) & not nIE( 9) & '0' & '0' ); + o_a(10) <= not norf(wl, aq(10) & pitchoverflow & '0' & '0' & c2d0.val & pwmsr ); + o_a(11) <= not norf(wl, aq(11) & random & '0' & '0' & xromdo7nq & '0' ); + o_a(12) <= not norf(wl, aq(12) & ieaddrreg(10) & '0' & not nIE(10) & fsromdo(13) & '0' ); + o_a(13) <= not norf(wl, aq(13) & ieaddrreg(11) & '0' & not nIE(11) & vcufinal12 & '0' ); + o_a(14) <= not norf(wl, aq(14) & '0' & '0' & '0' & cntdn0 & '0' ); + o_a(15) <= not norf(wl, aq(15) & '0' & '0' & '0' & '0' & '0' ); + + end block; + + + o_audio <= ieaddrreg(9 downto 0); + + o_bsy <= not nbsy; + + o_me_l <= not me; + + mte_delay_b : entity work.vlm5030_delay + generic map ( + -- delay for ~6us ==> 21 osc clocks + g_numclks => 21 + ) + port map ( + i_clk => osc, + i_in => xromdo(35), + o_out => o_mte + ); + +end; diff --git a/rtl/ipcores/vlm5030_gl/vlm5030_pack.vhd b/rtl/ipcores/vlm5030_gl/vlm5030_pack.vhd new file mode 100644 index 0000000..fdf0771 --- /dev/null +++ b/rtl/ipcores/vlm5030_gl/vlm5030_pack.vhd @@ -0,0 +1,217 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- + + +library ieee; +use ieee.std_logic_1164.all; + +package vlm5030_pack is + + ----------------------------------------------------------------------------- + -- Verctorized NOR and OR functions + ----------------------------------------------------------------------------- + function norf(i : std_logic_vector) return std_logic; + function norf(wl, vec : std_logic_vector) return std_logic; + function norif(wl, vec : std_logic_vector) return std_logic; + function orf(wl, vec : std_logic_vector) return std_logic; + + ----------------------------------------------------------------------------- + -- Transparent handling of clock enables + -- + -- Basic type def + type t_clk is record + base : std_logic; + val : std_logic; + rise : std_logic; + fall : std_logic; + end record; + constant z_clk : t_clk := ( + base => '0', + val => '0', + rise => '0', + fall => '0'); + + -- Overloaded functions for synchronous process template + function rising_edge(signal clk : t_clk) return boolean; + function falling_edge(signal clk : t_clk) return boolean; + + -- Overloaded functions for boolean arithmetic on clocks + function "not" (clk : t_clk) return t_clk; + -- + function "and" (clk1, clk2 : t_clk) return t_clk; + function "and" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "and" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "nand" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "nand" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "or" (clk1, clk2 : t_clk) return t_clk; + function "or" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "or" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "nor" (clk1, clk2 : t_clk) return t_clk; + function "nor" (clk1 : t_clk; op2 : std_logic) return t_clk; + function "nor" (op1 : std_logic; clk2 : t_clk) return std_logic; + -- + function "=" (clk1 : t_clk; op2 : std_logic) return boolean; + +end; + +package body vlm5030_pack is + + function norf(i : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in i'range loop + lorf := lorf or i(idx); + end loop; + return not lorf; + end; + + function norf(wl, vec : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in wl'range loop + lorf := lorf or (wl(idx) and vec(idx)); + end loop; + return not lorf; + end; + + function norif(wl, vec : std_logic_vector) return std_logic is + variable lorf : std_logic; + begin + lorf := '0'; + for idx in wl'range loop + lorf := lorf or (wl(idx) and not vec(idx)); + end loop; + return not lorf; + end; + + function orf(wl, vec : std_logic_vector) return std_logic is + begin + return not norf(wl, vec); + end; + + ----------------------------------------------------------------------------- + + function rising_edge(signal clk : t_clk) return boolean is + begin + return rising_edge(clk.base) and clk.rise = '1'; + end; + + function falling_edge(signal clk : t_clk) return boolean is + begin + return rising_edge(clk.base) and clk.fall = '1'; + end; + + function "not" (clk : t_clk) return t_clk is + begin + return (base => clk.base, + val => not clk.val, + rise => clk.fall, + fall => clk.rise); + end; + + function "and" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val and clk2.val, + rise => (clk1.rise and clk2.val and not clk2.fall) or + (clk2.rise and clk1.val and not clk1.fall), + fall => (clk1.fall and clk2.val) or + (clk2.fall and clk1.val)); + end; + + function "and" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val and op2, + rise => clk1.rise and op2, + fall => clk1.fall and op2); + end; + + function "and" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 and clk2.val; + end; + + function "nand" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nand op2, + rise => clk1.fall and op2, + fall => clk1.rise and op2); + end; + + function "nand" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 nand clk2.val; + end; + + function "or" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val or clk2.val, + rise => (clk1.rise and not clk2.val) or + (clk2.rise and not clk1.val), + fall => (clk1.fall and not clk2.val and not clk2.rise) or + (clk2.fall and not clk1.val and not clk1.rise)); + end; + + function "or" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val or op2, + rise => clk1.rise and not op2, + fall => clk1.fall and not op2); + end; + + function "or" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 or clk2.val; + end; + + function "nor" (clk1, clk2 : t_clk) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nor clk2.val, + rise => (clk1.fall and not clk2.val and not clk2.rise) or + (clk2.fall and not clk1.val and not clk1.rise), + fall => (clk1.rise and not clk2.val) or + (clk2.rise and not clk1.val)); + end; + + function "nor" (clk1 : t_clk; op2 : std_logic) return t_clk is + begin + return (base => clk1.base, + val => clk1.val nor op2, + rise => clk1.fall and not op2, + fall => clk1.rise and not op2); + end; + + function "nor" (op1 : std_logic; clk2 : t_clk) return std_logic is + begin + return op1 nor clk2.val; + end; + + function "=" (clk1 : t_clk; op2 : std_logic) return boolean is + begin + return clk1.val = op2; + end; + +end; diff --git a/rtl/ipcores/vlm5030_gl/vlm5030_subcircuits.vhd b/rtl/ipcores/vlm5030_gl/vlm5030_subcircuits.vhd new file mode 100644 index 0000000..2dda760 --- /dev/null +++ b/rtl/ipcores/vlm5030_gl/vlm5030_subcircuits.vhd @@ -0,0 +1,204 @@ +---------------------------------------------------------------------- +-- VLM5030 +-- www.fpgaarcade.com +-- All rights reserved. +-- +-- admin@fpgaarcade.com +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, You can obtain one at https://mozilla.org/MPL/2.0/. +---------------------------------------------------------------------- +-- +-- Copyright (c) 2021, Arnim Laeuger arnim.laeuger@gmx.net +-- All rights reserved. +-- + + +------------------------------------------------------------------------------- +-- SR-latch, synchronous to common clock +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity vlm5030_srlatch is + + port ( + i_clk : in std_logic; + i_res : in std_logic; + i_set : in std_logic; + o_q : out std_logic + ); + +end; + +architecture rtl of vlm5030_srlatch is + signal q : std_logic := '0'; +begin + + process (i_clk) + begin + if rising_edge(i_clk) then + if i_res = '1' then + q <= '0'; + elsif i_set = '1' then + q <= '1'; + end if; + end if; + end process; + + o_q <= q; + +end; + + +------------------------------------------------------------------------------- +-- SR-latch, synchronous to common clock, t_clk version +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +use work.vlm5030_pack.t_clk; +use work.vlm5030_pack.rising_edge; + +entity vlm5030_srlatchclk is + + port ( + i_clk : in t_clk; + i_res : in t_clk; + i_set : in t_clk; + o_q : out t_clk + ); + +end; + +architecture rtl of vlm5030_srlatchclk is + signal q : std_logic := '0'; +begin + + process (i_clk) + begin + if rising_edge(i_clk) then + if i_res.val = '1' then + q <= '0'; + elsif i_set.val = '1' then + q <= '1'; + end if; + end if; + end process; + + o_q <= (base => i_clk.base, + val => q, + rise => not q and i_set.val, + fall => q and i_res.val); + +end; + + +------------------------------------------------------------------------------- +-- vlm5030_delay +-- +-- Delay input signal by the specified number of clocks. +-- +-- NOTE: This is inertial delay. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.vlm5030_pack.all; + +entity vlm5030_delay is + + generic ( + g_numclks : integer := 3 + ); + port ( + i_clk : in t_clk; + i_in : in std_logic; + o_out : out std_logic + ); + +end; + +architecture rtl of vlm5030_delay is +begin + + delay_p : process (i_clk) + variable cnt : natural := 0; + variable inq : std_logic := '0'; + begin + if rising_edge(i_clk) then + if i_in /= inq then + cnt := g_numclks-2; + inq := i_in; + else + if cnt > 0 then + cnt := cnt - 1; + else + o_out <= i_in; + end if; + end if; + end if; + end process; + +end; + + +------------------------------------------------------------------------------- +-- vlm5030_delay_inv +-- +-- Invert input signal and delay falling edge of input. +-- The input's rising edge is not delayed. +-- +-- NOTE: This is inertial delay. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use work.vlm5030_pack.all; + +entity vlm5030_delay_inv is + + generic ( + g_numclks : integer := 3 + ); + port ( + i_clk : in t_clk; + i_in : in std_logic; + o_out : out std_logic + ); + +end; + +architecture rtl of vlm5030_delay_inv is + signal outq : std_logic; +begin + + delay_p : process (i_clk) + variable cnt : natural := 0; + variable inq : std_logic := '0'; + begin + if rising_edge(i_clk) then + if i_in /= inq then + cnt := g_numclks-2; + inq := i_in; + if i_in = '1' then + outq <= '1'; + end if; + else + if cnt > 0 then + cnt := cnt - 1; + else + outq <= i_in; + end if; + end if; + end if; + end process; + + o_out <= '0' when i_in = '1' else not outq; + +end; diff --git a/rtl/ipcores/vollut.txt b/rtl/ipcores/vollut.txt new file mode 100644 index 0000000..76b6e56 --- /dev/null +++ b/rtl/ipcores/vollut.txt @@ -0,0 +1 @@ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 06 07 08 0A 0B 0C 0D 0F 10 11 12 00 02 04 06 09 0B 0E 10 14 16 18 1A 1C 1E 21 22 00 02 06 08 0C 0F 12 15 1A 1D 20 23 27 2A 2C 2F 00 04 08 0B 10 14 18 1C 22 26 2A 2E 33 36 3A 3E 00 04 08 0C 12 16 1B 1F 28 2C 30 34 3A 3E 43 47 00 04 0A 0E 15 1A 1E 23 2C 31 36 3A 42 46 4B 50 00 05 0A 0F 17 1C 21 26 30 35 3A 40 47 4C 52 56 00 06 0C 12 1A 20 26 2C 38 3E 44 4A 52 58 5E 64 00 06 0C 12 1C 22 28 2E 3A 40 47 4D 56 5C 62 68 00 06 0D 13 1D 23 2A 30 3D 44 4A 50 5A 60 67 6D 00 06 0E 14 1E 24 2C 32 40 46 4D 54 5D 64 6B 71 00 06 0E 15 1F 26 2E 34 42 49 50 57 62 68 70 76 00 07 0E 16 20 27 2E 36 44 4B 52 5A 64 6B 72 7A 00 07 0F 16 21 28 30 37 46 4D 55 5C 67 6E 76 7D 00 07 10 16 22 29 31 38 48 4E 56 5E 69 70 78 80 \ No newline at end of file diff --git a/rtl/pll.qip b/rtl/pll.qip new file mode 100644 index 0000000..eb0e99c --- /dev/null +++ b/rtl/pll.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] +set_global_assignment -entity "pll" -library "pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll" -library "pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll" -library "pll" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_NAME "cGxs" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_NAME "cGxsXzAwMDI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::SW50ZWdlci1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::ZmFsc2U=::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::NA==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::NA==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::NzMuNzI4::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::MTQ2::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::OTk=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NzMuNzI4::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MTQ2::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::OTk=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::ZGVncmVlcw==::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::LTYwLjA=::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::NTcuMjcyNzI=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MTQ2::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MTI2::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::NDguMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MTQ2::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MTUz::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::NzMuNzM3MzczIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::NzMuNzM3MzczIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MTEyNDkgcHM=::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::NTcuOTM2NTA3IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::NDcuNzEyNDE4IE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTIgSGkgRGl2aWRlLEMtQ291bnRlci0yIExvdyBEaXZpZGUsQy1Db3VudGVyLTIgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0yIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTIgSW5wdXQgU291cmNlLEMtQ291bnRlci0yIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTMgSGkgRGl2aWRlLEMtQ291bnRlci0zIExvdyBEaXZpZGUsQy1Db3VudGVyLTMgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0zIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTMgSW5wdXQgU291cmNlLEMtQ291bnRlci0zIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTMgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NzMsNzMsNSw0LGZhbHNlLGZhbHNlLGZhbHNlLHRydWUsNiw1LDEsMCxwaF9tdXhfY2xrLGZhbHNlLHRydWUsNiw1LDEwLDEscGhfbXV4X2NsayxmYWxzZSx0cnVlLDcsNywxLDAscGhfbXV4X2NsayxmYWxzZSxmYWxzZSw5LDgsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwxLDIwLDEyMDAwLDgxMS4xMTExMTEgTUh6LDEsbm9uZSxnbGIsbV9jbnQscGhfbXV4X2Nsayx0cnVl::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"] +set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002.qip"] + +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" diff --git a/rtl/pll.v b/rtl/pll.v new file mode 100644 index 0000000..353c702 --- /dev/null +++ b/rtl/pll.v @@ -0,0 +1,259 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll.v + +// Generated using ACDS version 17.0 595 + +`timescale 1 ps / 1 ps +module pll ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + output wire outclk_1, // outclk1.clk + output wire outclk_2, // outclk2.clk + output wire outclk_3, // outclk3.clk + output wire locked // locked.export + ); + + pll_0002 pll_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .outclk_1 (outclk_1), // outclk1.clk + .outclk_2 (outclk_2), // outclk2.clk + .outclk_3 (outclk_3), // outclk3.clk + .locked (locked) // locked.export + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll.vo +// RELATED_FILES: pll.v, pll_0002.v diff --git a/rtl/pll/pll_0002.qip b/rtl/pll/pll_0002.qip new file mode 100644 index 0000000..aec45eb --- /dev/null +++ b/rtl/pll/pll_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" + +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/rtl/pll/pll_0002.v b/rtl/pll/pll_0002.v new file mode 100644 index 0000000..c99cc8d --- /dev/null +++ b/rtl/pll/pll_0002.v @@ -0,0 +1,96 @@ +`timescale 1ns/10ps +module pll_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'outclk1' + output wire outclk_1, + + // interface 'outclk2' + output wire outclk_2, + + // interface 'outclk3' + output wire outclk_3, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("false"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(4), + .output_clock_frequency0("73.737373 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("73.737373 MHz"), + .phase_shift1("11249 ps"), + .duty_cycle1(50), + .output_clock_frequency2("57.936507 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("47.712418 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_3, outclk_2, outclk_1, outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/rtl/pll/pll_0002_q13.qip b/rtl/pll/pll_0002_q13.qip new file mode 100644 index 0000000..9f8ded1 --- /dev/null +++ b/rtl/pll/pll_0002_q13.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/alsa.sv b/sys/alsa.sv new file mode 100644 index 0000000..9034389 --- /dev/null +++ b/sys/alsa.sv @@ -0,0 +1,157 @@ +//============================================================================ +// +// ALSA sound support for MiSTer +// (c)2019,2020 Alexey Melnikov +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module alsa +#( + parameter CLK_RATE = 24576000 +) +( + input reset, + input clk, + + output reg [31:3] ram_address, + input [63:0] ram_data, + output reg ram_req = 0, + input ram_ready, + + input spi_ss, + input spi_sck, + input spi_mosi, + output spi_miso, + + output reg [15:0] pcm_l, + output reg [15:0] pcm_r +); + +reg [60:0] buf_info; +reg [6:0] spicnt = 0; +always @(posedge spi_sck, posedge spi_ss) begin + reg [95:0] spi_data; + + if(spi_ss) spicnt <= 0; + else begin + spi_data[{spicnt[6:3],~spicnt[2:0]}] <= spi_mosi; + if(&spicnt) buf_info <= {spi_data[82:67],spi_data[50:35],spi_data[31:3]}; + spicnt <= spicnt + 1'd1; + end +end + +assign spi_miso = spi_out[{spicnt[4:3],~spicnt[2:0]}]; + +reg [31:0] spi_out = 0; +always @(posedge clk) if(spi_ss) spi_out <= {buf_rptr, hurryup, 8'h00}; + + +reg [31:3] buf_addr; +reg [18:3] buf_len; +reg [18:3] buf_wptr = 0; + +always @(posedge clk) begin + reg [60:0] data1,data2; + + data1 <= buf_info; + data2 <= data1; + if(data2 == data1) {buf_wptr,buf_len,buf_addr} <= data2; +end + +reg [2:0] hurryup = 0; +reg [18:3] buf_rptr = 0; + +always @(posedge clk) begin + reg [18:3] len = 0; + reg [1:0] ready = 0; + reg [63:0] readdata; + reg got_first = 0; + reg [7:0] ce_cnt = 0; + reg [1:0] state = 0; + + if(reset) begin + ready <= 0; + ce_cnt <= 0; + state <= 0; + got_first <= 0; + len <= 0; + end + else begin + + //ramp up + if(len[18:14] && (hurryup < 1)) hurryup <= 1; + if(len[18:16] && (hurryup < 2)) hurryup <= 2; + if(len[18:17] && (hurryup < 4)) hurryup <= 4; + + //ramp down + if(!len[18:15] && (hurryup > 2)) hurryup <= 2; + if(!len[18:13] && (hurryup > 1)) hurryup <= 1; + if(!len[18:10]) hurryup <= 0; + + if(ce_sample && ~&ce_cnt) ce_cnt <= ce_cnt + 1'd1; + + case(state) + 0: if(!ce_sample) begin + if(ready) begin + if(ce_cnt) begin + {readdata[31:0],pcm_r,pcm_l} <= readdata; + ready <= ready - 1'd1; + ce_cnt <= ce_cnt - 1'd1; + end + end + else if(buf_rptr != buf_wptr) begin + if(~got_first) begin + buf_rptr <= buf_wptr; + got_first <= 1; + end + else begin + ram_address <= buf_addr + buf_rptr; + ram_req <= ~ram_req; + buf_rptr <= buf_rptr + 1'd1; + len <= (buf_wptr < buf_rptr) ? (buf_len + buf_wptr - buf_rptr) : (buf_wptr - buf_rptr); + state <= 1; + end + end + else begin + len <= 0; + ce_cnt <= 0; + hurryup <= 0; + end + end + 1: if(ram_ready) begin + ready <= 2; + readdata <= ram_data; + if(buf_rptr >= buf_len) buf_rptr <= buf_rptr - buf_len; + state <= 0; + end + endcase + end +end + +reg ce_sample; +always @(posedge clk) begin + reg [31:0] acc = 0; + + ce_sample <= 0; + acc <= acc + 48000 + {hurryup,6'd0}; + if(acc >= CLK_RATE) begin + acc <= acc - CLK_RATE; + ce_sample <= 1; + end +end + +endmodule diff --git a/sys/arcade_video.v b/sys/arcade_video.v new file mode 100644 index 0000000..8388fda --- /dev/null +++ b/sys/arcade_video.v @@ -0,0 +1,329 @@ +//============================================================================ +// +// Copyright (C) 2017-2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +////////////////////////////////////////////////////////// +// DW: +// 6 : 2R 2G 2B +// 8 : 3R 3G 2B +// 9 : 3R 3G 3B +// 12 : 4R 4G 4B +// 24 : 8R 8G 8B + +module arcade_video #(parameter WIDTH=320, DW=8, GAMMA=1) +( + input clk_video, + input ce_pix, + + input[DW-1:0] RGB_in, + input HBlank, + input VBlank, + input HSync, + input VSync, + + output CLK_VIDEO, + output CE_PIXEL, + output [7:0] VGA_R, + output [7:0] VGA_G, + output [7:0] VGA_B, + output VGA_HS, + output VGA_VS, + output VGA_DE, + output [1:0] VGA_SL, + + input [2:0] fx, + input forced_scandoubler, + inout [21:0] gamma_bus +); + +assign CLK_VIDEO = clk_video; + +wire hs_fix,vs_fix; +sync_fix sync_v(CLK_VIDEO, HSync, hs_fix); +sync_fix sync_h(CLK_VIDEO, VSync, vs_fix); + +reg [DW-1:0] RGB_fix; + +reg CE,HS,VS,HBL,VBL; +always @(posedge CLK_VIDEO) begin + reg old_ce; + old_ce <= ce_pix; + CE <= 0; + if(~old_ce & ce_pix) begin + CE <= 1; + HS <= hs_fix; + if(~HS & hs_fix) VS <= vs_fix; + + RGB_fix <= RGB_in; + HBL <= HBlank; + if(HBL & ~HBlank) VBL <= VBlank; + end +end + +wire [7:0] R,G,B; + +generate + if(DW == 6) begin + assign R = {RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4],RGB_fix[5:4]}; + assign G = {RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2],RGB_fix[3:2]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; + end + else if(DW == 8) begin + assign R = {RGB_fix[7:5],RGB_fix[7:5],RGB_fix[7:6]}; + assign G = {RGB_fix[4:2],RGB_fix[4:2],RGB_fix[4:3]}; + assign B = {RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0],RGB_fix[1:0]}; + end + else if(DW == 9) begin + assign R = {RGB_fix[8:6],RGB_fix[8:6],RGB_fix[8:7]}; + assign G = {RGB_fix[5:3],RGB_fix[5:3],RGB_fix[5:4]}; + assign B = {RGB_fix[2:0],RGB_fix[2:0],RGB_fix[2:1]}; + end + else if(DW == 12) begin + assign R = {RGB_fix[11:8],RGB_fix[11:8]}; + assign G = {RGB_fix[7:4],RGB_fix[7:4]}; + assign B = {RGB_fix[3:0],RGB_fix[3:0]}; + end + else if(DW == 18) begin + assign R = {RGB_fix[17:12],RGB_fix[17:16]}; + assign G = {RGB_fix[11: 6],RGB_fix[11:10]}; + assign B = {RGB_fix[ 5: 0],RGB_fix[ 5: 4]}; + end + else begin // 24 + assign R = RGB_fix[23:16]; + assign G = RGB_fix[15:8]; + assign B = RGB_fix[7:0]; + end +endgenerate + +assign VGA_SL = sl[1:0]; +wire [2:0] sl = fx ? fx - 1'd1 : 3'd0; +wire scandoubler = fx || forced_scandoubler; + +video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer +( + .CLK_VIDEO(CLK_VIDEO), + .ce_pix(CE), + .CE_PIXEL(CE_PIXEL), + + .scandoubler(scandoubler), + .hq2x(fx==1), + .gamma_bus(gamma_bus), + + .R((DW!=24) ? R[7:4] : R), + .G((DW!=24) ? G[7:4] : G), + .B((DW!=24) ? B[7:4] : B), + + .HSync (HS), + .VSync (VS), + .HBlank(HBL), + .VBlank(VBL), + + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B), + .VGA_VS(VGA_VS), + .VGA_HS(VGA_HS), + .VGA_DE(VGA_DE) +); + +endmodule + +//============================================================================ +// +// Screen +90/-90 deg. rotation +// Copyright (C) 2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module screen_rotate +( + input CLK_VIDEO, + input CE_PIXEL, + + input [7:0] VGA_R, + input [7:0] VGA_G, + input [7:0] VGA_B, + input VGA_HS, + input VGA_VS, + input VGA_DE, + + input rotate_ccw, + input no_rotate, + input flip, + output video_rotated, + + output FB_EN, + output [4:0] FB_FORMAT, + output reg [11:0] FB_WIDTH, + output reg [11:0] FB_HEIGHT, + output [31:0] FB_BASE, + output [13:0] FB_STRIDE, + input FB_VBL, + input FB_LL, + + output DDRAM_CLK, + input DDRAM_BUSY, + output [7:0] DDRAM_BURSTCNT, + output [28:0] DDRAM_ADDR, + output [63:0] DDRAM_DIN, + output [7:0] DDRAM_BE, + output DDRAM_WE, + output DDRAM_RD +); + +parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB + +reg do_flip; + +assign DDRAM_CLK = CLK_VIDEO; +assign DDRAM_BURSTCNT = 1; +assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]}; +assign DDRAM_BE = ram_addr[2] ? 8'hF0 : 8'h0F; +assign DDRAM_DIN = {ram_data,ram_data}; +assign DDRAM_WE = ram_wr; +assign DDRAM_RD = 0; + +assign FB_EN = fb_en[2]; +assign FB_FORMAT = 5'b00110; +assign FB_BASE = {MEM_BASE,o_fb,23'd0}; +assign FB_STRIDE = stride; + +function [1:0] buf_next; + input [1:0] a,b; + begin + buf_next = 1; + if ((a==0 && b==1) || (a==1 && b==0)) buf_next = 2; + if ((a==1 && b==2) || (a==2 && b==1)) buf_next = 0; + end +endfunction + +assign video_rotated = ~no_rotate; + +always @(posedge CLK_VIDEO) begin + do_flip <= no_rotate && flip; + if( do_flip ) begin + FB_WIDTH <= hsz; + FB_HEIGHT <= vsz; + end else begin + FB_WIDTH <= vsz; + FB_HEIGHT <= hsz; + end +end + +reg [1:0] i_fb,o_fb; +always @(posedge CLK_VIDEO) begin + reg old_vbl,old_vs; + old_vbl <= FB_VBL; + old_vs <= VGA_VS; + + if(FB_LL) begin + if(~old_vbl & FB_VBL) o_fb<={1'b0,~i_fb[0]}; + if(~old_vs & VGA_VS) i_fb<={1'b0,~i_fb[0]}; + end + else begin + if(~old_vbl & FB_VBL) o_fb<=buf_next(o_fb,i_fb); + if(~old_vs & VGA_VS) i_fb<=buf_next(i_fb,o_fb); + end +end + +initial begin + fb_en = 0; +end + +reg [2:0] fb_en = 0; +reg [11:0] hsz = 320, vsz = 240; +reg [11:0] bwidth; +reg [22:0] bufsize; +always @(posedge CLK_VIDEO) begin + reg [11:0] hcnt = 0, vcnt = 0; + reg old_vs, old_de; + + if(CE_PIXEL) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + hcnt <= hcnt + 1'd1; + if(~old_de & VGA_DE) begin + hcnt <= 1; + vcnt <= vcnt + 1'd1; + end + if(old_de & ~VGA_DE) begin + hsz <= hcnt; + if( do_flip ) bwidth <= hcnt + 2'd3; + end + if(~old_vs & VGA_VS) begin + vsz <= vcnt; + if( !do_flip ) bwidth <= vcnt + 2'd3; + vcnt <= 0; + fb_en <= {fb_en[1:0], ~no_rotate | flip}; + end + if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride; + end +end + +wire [13:0] stride = {bwidth[11:2], 4'd0}; + +reg [22:0] ram_addr, next_addr; +reg [31:0] ram_data; +reg ram_wr; +always @(posedge CLK_VIDEO) begin + reg [13:0] hcnt = 0; + reg old_vs, old_de; + + ram_wr <= 0; + if(CE_PIXEL && FB_EN) begin + old_vs <= VGA_VS; + old_de <= VGA_DE; + + if(~old_vs & VGA_VS) begin + next_addr <= + do_flip ? bufsize-3'd4 : + rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00}; + hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00}; + end + if(VGA_DE) begin + ram_wr <= 1; + ram_data <= {8'd0,VGA_B,VGA_G,VGA_R}; + ram_addr <= next_addr; + next_addr <= + do_flip ? next_addr-3'd4 : + rotate_ccw ? (next_addr - stride) : (next_addr + stride); + end + if(old_de & ~VGA_DE & ~do_flip) begin + next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt; + hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4); + end + end +end + +endmodule diff --git a/sys/ascal.vhd b/sys/ascal.vhd new file mode 100644 index 0000000..7ac95a6 --- /dev/null +++ b/sys/ascal.vhd @@ -0,0 +1,2927 @@ +-------------------------------------------------------------------------------- +-- AVALON SCALER +-------------------------------------------------------------------------------- +-- TEMLIB 2018 - 2020 +-------------------------------------------------------------------------------- +-- This code can be freely distributed and used for any purpose, but, if you +-- find any bug, or want to suggest an enhancement, you ought to send a mail +-- to info@temlib.org. +-------------------------------------------------------------------------------- + +-- Features +-- - Arbitrary output video format +-- - Autodetect input image size or fixed window +-- - Progressive and interlaced input +-- - Interpolation +-- Upscaling : Nearest, Bilinear, Sharp Bilinear, Bicubic, Polyphase +-- Downscaling : Nearest, Bilinear +-- - Avalon bus interface with 128 or 64 bits DATA +-- - Optional triple buffering +-- - Support for external low lag syntonization + +-------------------------------------------- +-- Downscaling +-- - Horizontal and vertical up-/down-scaling are independant. +-- - Downscaling, H and/or V, supports only nearest-neighbour and bilinear +-- filtering. +-- - For interlaced video, when the vertical size is lower than a deinterlaced +-- frame size (2x half-frame), the scaler processes only half-frames +-- and upscales (when the output size is between 1x an 2x) or downscales (size +-- below 1x) them. + +-------------------------------------------- +-- 5 clock domains +-- i_xxx : Input video +-- o_xxx : Output video +-- avl_xxx : Avalon memory bus +-- poly_xxx : Polyphase filters memory +-- pal_xxx : Framebuffer mode 8bpp palette. + +-------------------------------------------- +-- O_FB_FORMAT : Framebuffer format +-- [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp +-- [3] : 0=16bits 565 1=16bits 1555 +-- [4] : 0=RGB 1=BGR (for 16/24/32 modes) +-- [5] : TBD + +-------------------------------------------- +-- Image header. When HEADER = TRUE +-- Header Address = RAMBASE +-- Image Address = RAMBASE + HEADER_SIZE + +-- Header (Bytes. Big Endian.) +-- 0 : Type = 1 +-- 1 : Pixel format +-- 0 : 16 bits/pixel, RGB : RRRRRGGGGGGBBBBB +-- 1 : 24 bits/pixel, RGB +-- 2 : 32 bits/pixel, RGB0 + +-- 3:2 : Header size : Offset to start of picture (= N_BURST). 12 bits +-- 5:4 : Attributes +-- b0 ; Interlaced +-- b1 : Field number +-- b2 : Horizontal downscaled +-- b3 : Vertical downscaled +-- b4 : Triple buffered +-- b7-5 : Frame counter +-- 7:6 : Image width. Pixels. 12 bits +-- 9:8 : Image height. Pixels. 12 bits +-- 11:10 : Line length. Bytes. +-- 13:12 : Output width. Pixels. 12 bits +-- 15:14 : Output height. Pixels. 12 bits +-------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +-- MODE[2:0] +-- 000 : Nearest +-- 001 : Bilinear +-- 010 : Sharp Bilinear +-- 011 : Bicubic +-- 100 : Polyphase +-- 101 : TBD +-- 110 : TBD +-- 111 : TBD + +-- MODE[3] +-- 0 : Direct. Single framebuffer. +-- 1 : Triple buffering + +-- MODE[4] : TBD + +-- MASK : Enable / Disable selected interpoler +-- 0:Nearest 1:Bilinear 2:SharpBilinear 3:Bicubic 4:Polyphase +-- RAMBASE : RAM base address for framebuffer +-- RAMSIZE : RAM allocated for one framebuffer (needs x3 if triple-buffering) +-- Must be a power of two +-- INTER : True=Autodetect interlaced video False=Force progressive scan +-- HEADER : True=Add image properties header +-- PALETTE : Enable palette for framebuffer 8bpp mode +-- PALETTE2 : Enable palette for framebuffer 8bpp mode supplied by core +-- DOWNSCALE : True=Support downscaling False=Downscaling disabled +-- BYTESWAP : Little/Big endian byte swap +-- FRAC : Fractional bits, subpixel resolution +-- OHRES : Max. output horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- IHRES : Max. input horizontal resolution. Must be a power of two. +-- (Used for sizing line buffers) +-- N_DW : Avalon data bus width. 64 or 128 bits +-- N_AW : Avalon address bus width +-- N_BURST : Burst size in bytes. Power of two. + +ENTITY ascal IS + GENERIC ( + MASK : unsigned(7 DOWNTO 0) :=x"FF"; + RAMBASE : unsigned(31 DOWNTO 0); + RAMSIZE : unsigned(31 DOWNTO 0) := x"0080_0000"; -- =8MB + INTER : boolean := true; + HEADER : boolean := true; + DOWNSCALE : boolean := true; + BYTESWAP : boolean := true; + PALETTE : boolean := true; + PALETTE2 : boolean := true; + ADAPTIVE : boolean := true; + DOWNSCALE_NN : boolean := false; + FRAC : natural RANGE 4 TO 8 :=4; + OHRES : natural RANGE 1 TO 4096 :=2048; + IHRES : natural RANGE 1 TO 2048 :=2048; + N_DW : natural RANGE 64 TO 128 := 128; + N_AW : natural RANGE 8 TO 32 := 32; + N_BURST : natural := 256 -- 256 bytes per burst + ); + PORT ( + ------------------------------------ + -- Input video + i_r : IN unsigned(7 DOWNTO 0); + i_g : IN unsigned(7 DOWNTO 0); + i_b : IN unsigned(7 DOWNTO 0); + i_hs : IN std_logic; -- H sync + i_vs : IN std_logic; -- V sync + i_fl : IN std_logic; -- Interlaced field + i_de : IN std_logic; -- Display Enable + i_ce : IN std_logic; -- Clock Enable + i_clk : IN std_logic; -- Input clock + + ------------------------------------ + -- Output video + o_r : OUT unsigned(7 DOWNTO 0); + o_g : OUT unsigned(7 DOWNTO 0); + o_b : OUT unsigned(7 DOWNTO 0); + o_hs : OUT std_logic; -- H sync + o_vs : OUT std_logic; -- V sync + o_de : OUT std_logic; -- Display Enable + o_vbl : OUT std_logic; -- V blank + o_brd : OUT std_logic; -- border enable + o_ce : IN std_logic; -- Clock Enable + o_clk : IN std_logic; -- Output clock + + -- Border colour R G B + o_border : IN unsigned(23 DOWNTO 0) := x"000000"; + + ------------------------------------ + -- Framebuffer mode + o_fb_ena : IN std_logic :='0'; -- Enable Framebuffer Mode + o_fb_hsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_vsize : IN natural RANGE 0 TO 4095 :=0; + o_fb_format : IN unsigned(5 DOWNTO 0) :="000100"; + o_fb_base : IN unsigned(31 DOWNTO 0) :=x"0000_0000"; + o_fb_stride : IN unsigned(13 DOWNTO 0) :=(OTHERS =>'0'); + + -- Framebuffer palette in 8bpp mode + pal1_clk : IN std_logic :='0'; + pal1_dw : IN unsigned(47 DOWNTO 0) :=x"000000000000"; -- R1 G1 B1 R0 G0 B0 + pal1_dr : OUT unsigned(47 DOWNTO 0) :=x"000000000000"; + pal1_a : IN unsigned(6 DOWNTO 0) :="0000000"; -- Colour index/2 + pal1_wr : IN std_logic :='0'; + + pal_n : IN std_logic :='0'; + + pal2_clk : IN std_logic :='0'; + pal2_dw : IN unsigned(23 DOWNTO 0) :=x"000000"; -- R G B + pal2_dr : OUT unsigned(23 DOWNTO 0) :=x"000000"; + pal2_a : IN unsigned(7 DOWNTO 0) :="00000000"; -- Colour index + pal2_wr : IN std_logic :='0'; + + ------------------------------------ + -- Low lag PLL tuning + o_lltune : OUT unsigned(15 DOWNTO 0); + + ------------------------------------ + -- Input video parameters + iauto : IN std_logic :='1'; -- 1=Autodetect image size 0=Choose window + himin : IN natural RANGE 0 TO 4095 :=0; -- MIN < MAX, MIN >=0, MAX < DISP + himax : IN natural RANGE 0 TO 4095 :=0; + vimin : IN natural RANGE 0 TO 4095 :=0; + vimax : IN natural RANGE 0 TO 4095 :=0; + + -- Detected input image size + i_hdmax : OUT natural RANGE 0 TO 4095; + i_vdmax : OUT natural RANGE 0 TO 4095; + + -- Output video parameters + run : IN std_logic :='1'; -- 1=Enable output image. 0=No image + freeze : IN std_logic :='0'; -- 1=Disable framebuffer writes + mode : IN unsigned(4 DOWNTO 0); + -- SYNC |_________________________/"""""""""\_______| + -- DE |""""""""""""""""""\________________________| + -- RGB | <#IMAGE#> ^HDISP | + -- ^HMIN ^HMAX ^HSSTART ^HSEND ^HTOTAL + htotal : IN natural RANGE 0 TO 4095; + hsstart : IN natural RANGE 0 TO 4095; + hsend : IN natural RANGE 0 TO 4095; + hdisp : IN natural RANGE 0 TO 4095; + hmin : IN natural RANGE 0 TO 4095; + hmax : IN natural RANGE 0 TO 4095; -- 0 <= hmin < hmax < hdisp + vtotal : IN natural RANGE 0 TO 4095; + vsstart : IN natural RANGE 0 TO 4095; + vsend : IN natural RANGE 0 TO 4095; + vdisp : IN natural RANGE 0 TO 4095; + vmin : IN natural RANGE 0 TO 4095; + vmax : IN natural RANGE 0 TO 4095; -- 0 <= vmin < vmax < vdisp + vrr : IN std_logic := '0'; + vrrmax : IN natural RANGE 0 TO 4095 := 0; + swblack : IN std_logic := '0'; -- will output 3 black frame on every resolution switch + + -- Scaler format. 00=16bpp 565, 01=24bpp 10=32bpp + format : IN unsigned(1 DOWNTO 0) :="01"; + + ------------------------------------ + -- Polyphase filter coefficients + -- Order : + -- [Horizontal] [Vertical] [Horizontal2] [Vertical2] + -- [0]...[2**FRAC-1] + -- [-1][0][1][2] + poly_clk : IN std_logic; + poly_dw : IN unsigned(9 DOWNTO 0); + poly_a : IN unsigned(FRAC+3 DOWNTO 0); + poly_wr : IN std_logic; + + ------------------------------------ + -- Avalon + avl_clk : IN std_logic; -- Avalon clock + avl_waitrequest : IN std_logic; + avl_readdata : IN std_logic_vector(N_DW-1 DOWNTO 0); + avl_readdatavalid : IN std_logic; + avl_burstcount : OUT std_logic_vector(7 DOWNTO 0); + avl_writedata : OUT std_logic_vector(N_DW-1 DOWNTO 0); + avl_address : OUT std_logic_vector(N_AW-1 DOWNTO 0); + avl_write : OUT std_logic; + avl_read : OUT std_logic; + avl_byteenable : OUT std_logic_vector(N_DW/8-1 DOWNTO 0); + + ------------------------------------ + reset_na : IN std_logic + ); + +BEGIN + ASSERT N_DW=64 OR N_DW=128 REPORT "DW" SEVERITY failure; + +END ENTITY ascal; + +--############################################################################## + +ARCHITECTURE rtl OF ascal IS + + CONSTANT MASK_NEAREST : natural :=0; + CONSTANT MASK_BILINEAR : natural :=1; + CONSTANT MASK_SHARP_BILINEAR : natural :=2; + CONSTANT MASK_BICUBIC : natural :=3; + CONSTANT MASK_POLY : natural :=4; + + ---------------------------------------------------------- + FUNCTION ilog2 (CONSTANT v : natural) RETURN natural IS + VARIABLE r : natural := 1; + VARIABLE n : natural := 0; + BEGIN + WHILE v>r LOOP + n:=n+1; + r:=r*2; + END LOOP; + RETURN n; + END FUNCTION ilog2; + FUNCTION to_std_logic (a : boolean) RETURN std_logic IS + BEGIN + IF a THEN RETURN '1'; + ELSE RETURN '0'; + END IF; + END FUNCTION to_std_logic; + + ---------------------------------------------------------- + CONSTANT NB_BURST : natural :=ilog2(N_BURST); + CONSTANT NB_LA : natural :=ilog2(N_DW/8); -- Low address bits + CONSTANT BLEN : natural :=N_BURST / N_DW * 8; -- Burst length + + ---------------------------------------------------------- + TYPE arr_dw IS ARRAY (natural RANGE <>) OF unsigned(N_DW-1 DOWNTO 0); + + TYPE type_pix IS RECORD + r,g,b : unsigned(7 DOWNTO 0); -- 0.8 + END RECORD; + TYPE arr_pix IS ARRAY (natural RANGE <>) OF type_pix; + TYPE arr_pixq IS ARRAY(natural RANGE <>) OF arr_pix(0 TO 3); + ATTRIBUTE ramstyle : string; + + SUBTYPE uint12 IS natural RANGE 0 TO 4095; + SUBTYPE uint13 IS natural RANGE 0 TO 8191; + + TYPE arr_uv48 IS ARRAY (natural RANGE <>) OF unsigned(47 DOWNTO 0); + TYPE arr_uv24 IS ARRAY (natural RANGE <>) OF unsigned(23 DOWNTO 0); + TYPE arr_uv40 IS ARRAY (natural RANGE <>) OF unsigned(39 DOWNTO 0); + TYPE arr_int9 IS ARRAY (natural RANGE <>) OF integer RANGE -256 TO 255; + TYPE arr_uint12 IS ARRAY (natural RANGE <>) OF uint12; + TYPE arr_frac IS ARRAY (natural RANGE <>) OF unsigned(11 DOWNTO 0); + TYPE arr_div IS ARRAY (natural RANGE <>) OF unsigned(20 DOWNTO 0); + + ---------------------------------------------------------- + -- Input image + SIGNAL i_pvs,i_pfl,i_pde,i_pce : std_logic; + SIGNAL i_ppix : type_pix; + SIGNAL i_freeze : std_logic; + SIGNAL i_count : unsigned(2 DOWNTO 0); + SIGNAL i_hsize,i_hmin,i_hmax,i_hcpt : uint12; + SIGNAL i_hrsize,i_vrsize : uint12; + SIGNAL i_himax,i_vimax : uint12; + SIGNAL i_vsize,i_vmaxmin,i_vmin,i_vmax,i_vcpt : uint12; + SIGNAL i_iauto : std_logic; + SIGNAL i_mode : unsigned(4 DOWNTO 0); + SIGNAL i_format : unsigned(1 DOWNTO 0); + SIGNAL i_ven,i_sof : std_logic; + SIGNAL i_wr : std_logic; + SIGNAL i_divstart,i_divrun : std_logic; + SIGNAL i_de_pre,i_vs_pre,i_fl_pre : std_logic; + SIGNAL i_de_delay : natural RANGE 0 TO 31; + SIGNAL i_intercnt : natural RANGE 0 TO 3; + SIGNAL i_inter,i_half,i_flm : std_logic; + SIGNAL i_write,i_wreq,i_alt,i_line,i_wline,i_wline_mem : std_logic; + SIGNAL i_walt,i_walt_mem,i_wreq_mem : std_logic; + SIGNAL i_wdelay : natural RANGE 0 TO 7; + SIGNAL i_push,i_pushend,i_pushend2 : std_logic; + SIGNAL i_eol : std_logic; + SIGNAL i_pushhead,i_pushhead2,i_pushhead3 : std_logic; + SIGNAL i_hburst,i_hbcpt : natural RANGE 0 TO 31; + SIGNAL i_shift : unsigned(0 TO 119) := (OTHERS =>'0'); + SIGNAL i_head : unsigned(127 DOWNTO 0); + SIGNAL i_acpt : natural RANGE 0 TO 15; + SIGNAL i_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF i_dpram : SIGNAL IS "no_rw_check"; + SIGNAL i_endframe0,i_endframe1,i_vss : std_logic; + SIGNAL i_wad : natural RANGE 0 TO BLEN*2-1; + SIGNAL i_dw : unsigned(N_DW-1 DOWNTO 0); + SIGNAL i_adrs,i_adrsi,i_wadrs,i_wadrs_mem : unsigned(31 DOWNTO 0); + SIGNAL i_reset_na : std_logic; + SIGNAL i_hnp,i_vnp : std_logic; + SIGNAL i_mem : arr_pix(0 TO IHRES-1); -- Downscale line buffer + ATTRIBUTE ramstyle OF i_mem : SIGNAL IS "no_rw_check"; + SIGNAL i_ohsize,i_ovsize : uint12; + SIGNAL i_vdivi : unsigned(12 DOWNTO 0); + SIGNAL i_vdivr : unsigned(24 DOWNTO 0); + SIGNAL i_div : unsigned(16 DOWNTO 0); + SIGNAL i_dir : unsigned(11 DOWNTO 0); + SIGNAL i_h_frac,i_v_frac : unsigned(11 DOWNTO 0); + SIGNAL i_hacc,i_vacc : uint13; + SIGNAL i_hdown,i_vdown : std_logic; + SIGNAL i_divcpt : natural RANGE 0 TO 36; + SIGNAL i_lwad,i_lrad : natural RANGE 0 TO OHRES-1; + SIGNAL i_lwr,i_bil : std_logic; + SIGNAL i_ldw,i_ldrm : type_pix; + SIGNAL i_hpixp,i_hpix0,i_hpix1,i_hpix2,i_hpix3,i_hpix4 : type_pix; + SIGNAL i_hpix,i_pix : type_pix; + SIGNAL i_hnp1,i_hnp2,i_hnp3,i_hnp4 : std_logic; + SIGNAL i_ven1,i_ven2,i_ven3,i_ven4,i_ven5,i_ven6 : std_logic; + + ---------------------------------------------------------- + -- Avalon + TYPE type_avl_state IS (sIDLE,sWRITE,sREAD); + SIGNAL avl_state : type_avl_state; + SIGNAL avl_write_i,avl_write_sync,avl_write_sync2 : std_logic; + SIGNAL avl_read_i,avl_read_sync,avl_read_sync2 : std_logic; + SIGNAL avl_read_pulse,avl_write_pulse : std_logic; + SIGNAL avl_read_sr,avl_write_sr,avl_read_clr,avl_write_clr : std_logic; + SIGNAL avl_rad,avl_rad_c,avl_wad : natural RANGE 0 TO 2*BLEN-1; + SIGNAL avl_walt,avl_wline,avl_rline : std_logic; + SIGNAL avl_dw,avl_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL avl_wr : std_logic; + SIGNAL avl_readdataack,avl_readack : std_logic; + SIGNAL avl_radrs,avl_wadrs : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset0,avl_o_offset0 : unsigned(31 DOWNTO 0); + SIGNAL avl_i_offset1,avl_o_offset1 : unsigned(31 DOWNTO 0); + SIGNAL avl_reset_na : std_logic; + SIGNAL avl_o_vs_sync,avl_o_vs : std_logic; + SIGNAL avl_fb_ena : std_logic; + + FUNCTION buf_next(a,b : natural RANGE 0 TO 2; freeze : std_logic := '0') RETURN natural IS + BEGIN + IF (freeze='1') THEN RETURN a; END IF; + IF (a=0 AND b=1) OR (a=1 AND b=0) THEN RETURN 2; END IF; + IF (a=1 AND b=2) OR (a=2 AND b=1) THEN RETURN 0; END IF; + RETURN 1; + END FUNCTION; + FUNCTION buf_offset(b : natural RANGE 0 TO 2; + base : unsigned(31 DOWNTO 0); + size : unsigned(31 DOWNTO 0)) RETURN unsigned IS + BEGIN + IF b=1 THEN RETURN base+size; END IF; + IF b=2 THEN RETURN base+(size(30 DOWNTO 0) & '0'); END IF; + RETURN base; + END FUNCTION; + + ---------------------------------------------------------- + -- Output + SIGNAL o_run : std_logic; + SIGNAL o_freeze : std_logic; + SIGNAL o_mode,o_hmode,o_vmode : unsigned(4 DOWNTO 0); + SIGNAL o_format : unsigned(5 DOWNTO 0); + SIGNAL o_fb_pal_dr : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr2 : unsigned(23 DOWNTO 0); + SIGNAL o_fb_pal_dr_x2 : unsigned(47 DOWNTO 0); + SIGNAL pal_idx: unsigned(7 DOWNTO 0); + SIGNAL pal_idx_lsb: std_logic; + SIGNAL pal1_mem : arr_uv48(0 TO 127); + SIGNAL pal2_mem : arr_uv24(0 TO 255); + ATTRIBUTE ramstyle of pal1_mem : signal is "no_rw_check"; + ATTRIBUTE ramstyle of pal2_mem : signal is "no_rw_check"; + SIGNAL o_htotal,o_hsstart,o_hsend : uint12; + SIGNAL o_hmin,o_hmax,o_hdisp,o_v_hmin_adj : uint12; + SIGNAL o_hsize,o_vsize : uint12; + SIGNAL o_vtotal,o_vsstart,o_vsend : uint12; + SIGNAL o_vrr,o_isync,o_isync2 : std_logic; + SIGNAL o_vrr_sync,o_vrr_sync2 : boolean; + SIGNAL o_vrr_min,o_vrr_min2 : boolean; + SIGNAL o_vrr_max,o_vrr_max2 : boolean; + SIGNAL o_vcpt_sync,o_vcpt_sync2, o_vrrmax : uint12; + SIGNAL o_sync, o_sync_max : boolean; + SIGNAL o_vmin,o_vmax,o_vdisp : uint12; + SIGNAL o_divcpt : natural RANGE 0 TO 36; + SIGNAL o_iendframe0,o_iendframe02,o_iendframe1,o_iendframe12 : std_logic; + SIGNAL o_bufup0,o_bufup1,o_inter : std_logic; + SIGNAL o_ibuf0,o_ibuf1,o_obuf0,o_obuf1 : natural RANGE 0 TO 2; + TYPE enum_o_state IS (sDISP,sHSYNC,sREAD,sWAITREAD); + SIGNAL o_state : enum_o_state; + TYPE enum_o_copy IS (sWAIT,sSHIFT,sCOPY); + SIGNAL o_copy : enum_o_copy; + SIGNAL o_pshift : natural RANGE 0 TO 15; + SIGNAL o_readack,o_readack_sync,o_readack_sync2 : std_logic; + SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic; + SIGNAL o_copyv : unsigned(0 TO 14); + SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address + SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1; + SIGNAL o_stride : unsigned(13 DOWNTO 0); + SIGNAL o_adrsa,o_adrsb,o_rline : std_logic; + SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1; + SIGNAL o_adturn : std_logic; + SIGNAL o_dr : unsigned(N_DW-1 DOWNTO 0); + SIGNAL o_shift : unsigned(0 TO N_DW+15); + SIGNAL o_sh,o_sh1,o_sh2,o_sh3,o_sh4 : std_logic; + SIGNAL o_reset_na : std_logic; + SIGNAL o_dpram : arr_dw(0 TO BLEN*2-1); + ATTRIBUTE ramstyle OF o_dpram : SIGNAL IS "no_rw_check"; + SIGNAL o_line0,o_line1,o_line2,o_line3 : arr_pix(0 TO OHRES-1); + ATTRIBUTE ramstyle OF o_line0 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line1 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line2 : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_line3 : SIGNAL IS "no_rw_check"; + SIGNAL o_wadl,o_radl0,o_radl1,o_radl2,o_radl3 : natural RANGE 0 TO OHRES-1; + SIGNAL o_ldw,o_ldr0,o_ldr1,o_ldr2,o_ldr3 : type_pix; + SIGNAL o_wr : unsigned(3 DOWNTO 0); + SIGNAL o_hcpt,o_vcpt,o_vcpt_pre,o_vcpt_pre2,o_vcpt_pre3,o_vcpt2 : uint12; + SIGNAL o_ihsize,o_ihsizem,o_ivsize : uint12; + SIGNAL o_ihsize_temp, o_ihsize_temp2 : natural RANGE 0 TO 32767; + + SIGNAL o_vfrac : unsigned(11 DOWNTO 0); + SIGNAL o_hfrac : arr_frac(0 TO 9); + ATTRIBUTE ramstyle OF o_hfrac : SIGNAL IS "logic"; -- avoid blockram shift register + + SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1; + SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 11); + SIGNAL o_hsp,o_vss : std_logic; + SIGNAL o_vcarrym,o_prim : boolean; + SIGNAL o_read,o_read_pre : std_logic; + SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; + SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31; + SIGNAL o_fload : natural RANGE 0 TO 3; + SIGNAL o_acpt,o_acpt1,o_acpt2,o_acpt3,o_acpt4 : natural RANGE 0 TO 15; -- Alternance pixels FIFO + SIGNAL o_dshi : natural RANGE 0 TO 3; + SIGNAL o_first,o_last,o_last1,o_last2 : std_logic; + SIGNAL o_lastt1,o_lastt2,o_lastt3,o_lastt4 : std_logic; + SIGNAL o_alt,o_altx : unsigned(3 DOWNTO 0); + SIGNAL o_hdown,o_vdown : std_logic; + SIGNAL o_primv,o_lastv,o_bibv : unsigned(0 TO 2); + TYPE arr_uint4 IS ARRAY (natural RANGE <>) OF natural RANGE 0 TO 15; + SIGNAL o_off : arr_uint4(0 TO 2); + SIGNAL o_bibu : std_logic :='0'; + SIGNAL o_dcptv : arr_uint12(1 TO 14); + SIGNAL o_dcpt : uint12; + SIGNAL o_hpixs,o_hpix0,o_hpix1,o_hpix2,o_hpix3 : type_pix; + SIGNAL o_hpixq : arr_pixq(2 TO 8); + ATTRIBUTE ramstyle OF o_hpixq : SIGNAL IS "logic"; -- avoid blockram shift register + SIGNAL o_vpixq, o_vpixq_pre : arr_pix(0 TO 3); + SIGNAL o_vpix_outer : arr_pix(0 TO 2); + SIGNAL o_vpix_inner : arr_pix(0 TO 6); + + + SIGNAL o_vpe : std_logic; + SIGNAL o_div : arr_div(0 TO 2); --uint12; + SIGNAL o_dir : arr_frac(0 TO 2); + ATTRIBUTE ramstyle OF o_div, o_dir : SIGNAL IS "logic"; -- avoid blockram shift register + SIGNAL o_vdivi : unsigned(12 DOWNTO 0); + SIGNAL o_vdivr : unsigned(24 DOWNTO 0); + SIGNAL o_divstart : std_logic; + SIGNAL o_divrun : std_logic; + SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); + SIGNAL o_vacptl : unsigned(1 DOWNTO 0); + signal o_newres : integer range 0 to 3; + + ----------------------------------------------------------------------------- + FUNCTION shift_ishift(shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN shift(24 TO 119) & pix.r & pix.g & pix.b; + WHEN "10" => -- 32bpp + RETURN shift(32 TO 119) & pix.r & pix.g & pix.b & x"00"; + WHEN OTHERS => -- 16bpp 565 + RETURN shift(16 TO 119) & + pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END CASE; + END FUNCTION; + + FUNCTION shift_ipack( i_dw : unsigned(N_DW-1 DOWNTO 0); + acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO 119); + pix : type_pix; + format : unsigned(1 DOWNTO 0)) RETURN unsigned IS + VARIABLE dw : unsigned(N_DW-1 DOWNTO 0); + BEGIN + dw:=i_dw; + CASE format IS + WHEN "01" => -- 24bpp + IF N_DW=128 THEN + IF acpt=5 THEN dw:=shift(0 TO 119) & pix.r; + ELSIF acpt=10 THEN dw:=shift(8 TO 119) & pix.r & pix.g; + ELSIF acpt=15 THEN dw:=shift(16 TO 119) & pix.r & pix.g & pix.b; + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=2 THEN dw:=shift(72 TO 119) & pix.r & pix.g; + ELSIF (acpt MOD 8)=5 THEN dw:=shift(64 TO 119) & pix.r; + ELSIF (acpt MOD 8)=7 THEN dw:=shift(80 TO 119) & pix.r & pix.g & pix.b; + END IF; + END IF; + WHEN "10" => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=3) OR (N_DW=64 AND (acpt MOD 8)=7) THEN + dw:=shift(128-N_DW+24 TO 119) & pix.r & pix.g & pix.b & x"00"; + END IF; + WHEN OTHERS => -- 16bpp 565 + IF (N_DW=128 AND (acpt MOD 8)=7) OR (N_DW=64 AND (acpt MOD 4)=3) THEN + dw:=shift(128-N_DW+8 TO 119) & pix.g(4 DOWNTO 2) & pix.r(7 DOWNTO 3) & + pix.b(7 DOWNTO 3) & pix.g(7 DOWNTO 5); + END IF; + END CASE; + RETURN dw; + END FUNCTION; + + FUNCTION shift_inext (acpt : natural RANGE 0 TO 15; + format : unsigned(1 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format IS + WHEN "01" => -- 24bpp + RETURN (N_DW=128 AND (acpt=5 OR acpt=10 OR acpt=15)) OR + (N_DW=64 AND ((acpt MOD 8)=2 OR (acpt MOD 8)=5 OR (acpt MOD 8)=7)); + WHEN "10" => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=3)) OR + (N_DW=64 AND ((acpt MOD 2)=1)); + WHEN OTHERS => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=7)) OR + (N_DW=64 AND ((acpt MOD 4)=3)); + END CASE; + END FUNCTION; + + FUNCTION shift_opack(acpt : natural RANGE 0 TO 15; + shift : unsigned(0 TO N_DW+15); + dr : unsigned(N_DW-1 DOWNTO 0); + format : unsigned(5 DOWNTO 0)) RETURN unsigned IS + VARIABLE shift_v : unsigned(0 TO N_DW+15); + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + IF (N_DW=128 AND acpt=0) OR (N_DW=64 AND (acpt MOD 8)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(8 TO N_DW+15) & dr(7 DOWNTO 0); + END IF; + + WHEN "100" => -- 16bpp + IF (N_DW=128 AND (acpt MOD 8)=0) OR (N_DW=64 AND (acpt MOD 4)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(16 TO N_DW+15) & dr(15 DOWNTO 0); + END IF; + + WHEN "101" => -- 24bpp + IF N_DW=128 THEN + IF acpt=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF acpt=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSIF acpt=10 THEN + shift_v:=shift(24 TO 39) & dr; + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + ELSE -- N_DW=64 + IF (acpt MOD 8)=0 THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSIF (acpt MOD 8)=2 THEN + shift_v:=shift(24 TO 39) & dr; + ELSIF (acpt MOD 8)=5 THEN + shift_v:=shift(24 TO 31) & dr & dr(7 DOWNTO 0); + ELSE + shift_v:=shift(24 TO N_DW+15) & dr(23 DOWNTO 0); + END IF; + END IF; + WHEN OTHERS => -- 32bpp + IF (N_DW=128 AND (acpt MOD 4)=0) OR (N_DW=64 AND (acpt MOD 2)=0) THEN + shift_v:=dr & dr(15 DOWNTO 0); + ELSE + shift_v:=shift(32 TO N_DW+15) & dr(31 DOWNTO 0); + END IF; + END CASE; + RETURN shift_v; + END FUNCTION; + + FUNCTION shift_onext (acpt : natural RANGE 0 TO 15; + format : unsigned(5 DOWNTO 0)) RETURN boolean IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bpp + RETURN (N_DW=128 AND acpt=0) OR + (N_DW=64 AND ((acpt MOD 8)=0)); + WHEN "100" => -- 16bpp + RETURN (N_DW=128 AND ((acpt MOD 8)=0)) OR + (N_DW=64 AND ((acpt MOD 4)=0)); + WHEN "101" => -- 24bpp + RETURN (N_DW=128 AND (acpt=0 OR acpt=5 OR acpt=10)) OR + (N_DW=64 AND ((acpt MOD 8)=0 OR (acpt MOD 8)=2 OR (acpt MOD 8)=5)); + WHEN OTHERS => -- 32bpp + RETURN (N_DW=128 AND ((acpt MOD 4)=0)) OR + (N_DW=64 AND ((acpt MOD 2)=0)); + END CASE; + END FUNCTION; + + FUNCTION shift_opix (shift : unsigned(0 TO N_DW+15); + format : unsigned(5 DOWNTO 0)) RETURN type_pix IS + BEGIN + CASE format(3 DOWNTO 0) IS + WHEN "0100" => -- 16bpp 565 + RETURN (b=>shift(8 TO 12) & shift(8 TO 10), + g=>shift(13 TO 15) & shift(0 TO 2) & shift(13 TO 14), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "1100" => -- 16bpp 1555 + RETURN (b=>shift(9 TO 13) & shift(9 TO 11), + g=>shift(14 TO 15) & shift(0 TO 2) & shift(14 TO 15) & shift(0), + r=>shift(3 TO 7) & shift(3 TO 5)); + WHEN "0101" | "0110" => -- 24bpp / 32bpp + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + WHEN OTHERS => + RETURN (r=>shift(0 TO 7),g=>shift(8 TO 15),b=>shift(16 TO 23)); + + END CASE; + END FUNCTION; + + FUNCTION pixoffset(adrs : unsigned(31 DOWNTO 0); + format : unsigned (5 DOWNTO 0)) RETURN natural IS + BEGIN + CASE format(2 DOWNTO 0) IS + WHEN "011" => -- 8bbp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 0)); + WHEN "100" => -- 16bpp 565 + RETURN to_integer(adrs(NB_LA-1 DOWNTO 1)); + WHEN OTHERS => -- 32bpp + RETURN to_integer(adrs(NB_LA-1 DOWNTO 2)); + END CASE; + END FUNCTION; + + FUNCTION swap(d : unsigned(N_DW-1 DOWNTO 0)) RETURN unsigned IS + VARIABLE e : unsigned(N_DW-1 DOWNTO 0); + BEGIN + IF BYTESWAP THEN + FOR i IN 0 TO N_DW/8-1 LOOP + e(i*8+7 DOWNTO i*8):=d(N_DW-i*8-1 DOWNTO N_DW-i*8-8); + END LOOP; + RETURN e; + ELSE + RETURN d; + END IF; + END FUNCTION swap; + + ----------------------------------------------------------------------------- + FUNCTION altx (a : unsigned(1 DOWNTO 0)) RETURN unsigned IS + BEGIN + CASE a IS + WHEN "00" => RETURN "0001"; + WHEN "01" => RETURN "0010"; + WHEN "10" => RETURN "0100"; + WHEN OTHERS => RETURN "1000"; + END CASE; + END FUNCTION; + + ----------------------------------------------------------------------------- + FUNCTION bound(a : unsigned; + s : natural) RETURN unsigned IS + BEGIN + IF a(a'left)='1' THEN + RETURN x"00"; + ELSIF a(a'left DOWNTO s)/=0 THEN + RETURN x"FF"; + ELSE + RETURN a(s-1 DOWNTO s-8); + END IF; + END FUNCTION bound; + + ----------------------------------------------------------------------------- + -- Nearest + FUNCTION near_frac(f : unsigned) RETURN unsigned IS + VARIABLE x : unsigned(FRAC-1 DOWNTO 0); + BEGIN + x:=(OTHERS =>f(f'left)); + RETURN x; + END FUNCTION; + + SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; + + ----------------------------------------------------------------------------- + -- Nearest + Bilinear + Sharp Bilinear + FUNCTION bil_frac(f : unsigned) RETURN unsigned IS + BEGIN + RETURN f(f'left DOWNTO f'left+1-FRAC); + END FUNCTION; + + TYPE type_bil_t IS RECORD + r,g,b : unsigned(8+FRAC DOWNTO 0); + END RECORD; + + FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + fp:=('0' & f) + (Z & f(FRAC-1)); + fn:=('1' & Z) - fp; + u:=p(2).r * fp + p(1).r * fn; + x.r:=u; + u:=p(2).g * fp + p(1).g * fn; + x.g:=u; + u:=p(2).b * fp + p(1).b * fn; + x.b:=u; + RETURN x; + END FUNCTION; + + FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + IF f(FRAC-1)='0' THEN + x.r := '0' & p(1).r & Z; + x.g := '0' & p(1).g & Z; + x.b := '0' & p(1).b & Z; + ELSE + x.r := '0' & p(2).r & Z; + x.g := '0' & p(2).g & Z; + x.b := '0' & p(2).b & Z; + END IF; + RETURN x; + END FUNCTION; + + SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; + SIGNAL o_h_near_t,o_v_near_t : type_bil_t; + SIGNAL i_h_bil_t : type_bil_t; + + ----------------------------------------------------------------------------- + -- Sharp Bilinear + -- <0.5 : x*x*x*4 + -- >0.5 : 1 - (1-x)*(1-x)*(1-x)*4 + + TYPE type_sbil_tt IS RECORD + f : unsigned(FRAC-1 DOWNTO 0); + s : unsigned(FRAC-1 DOWNTO 0); + END RECORD; + + SIGNAL o_h_sbil_t,o_v_sbil_t : type_sbil_tt; + + FUNCTION sbil_frac1(f : unsigned(11 DOWNTO 0)) RETURN type_sbil_tt IS + VARIABLE u : unsigned(FRAC-1 DOWNTO 0); + VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); + VARIABLE x : type_sbil_tt; + BEGIN + IF f(11)='0' THEN + u:=f(11 DOWNTO 12-FRAC); + ELSE + u:=NOT f(11 DOWNTO 12-FRAC); + END IF; + v:=u*u; + x.f:=u; + x.s:=v(2*FRAC-2 DOWNTO FRAC-1); + RETURN x; + END FUNCTION; + + FUNCTION sbil_frac2(f : unsigned(11 DOWNTO 0); + t : type_sbil_tt) RETURN unsigned IS + VARIABLE v : unsigned(2*FRAC-1 DOWNTO 0); + BEGIN + v:=t.f*t.s; + IF f(11)='0' THEN + RETURN v(2*FRAC-2 DOWNTO FRAC-1); + ELSE + RETURN NOT v(2*FRAC-2 DOWNTO FRAC-1); + END IF; + END FUNCTION; + + ----------------------------------------------------------------------------- + -- Bicubic + TYPE type_bic_abcd IS RECORD + a : unsigned(7 DOWNTO 0); -- 0.8 + b : signed(8 DOWNTO 0); -- 0.9 + c : signed(11 DOWNTO 0); -- 3.9 + d : signed(10 DOWNTO 0); -- 2.9 + xx : signed(8 DOWNTO 0); -- X.X 1.8 + END RECORD; + TYPE type_bic_pix_abcd IS RECORD + r,g,b : type_bic_abcd; + END RECORD; + TYPE type_bic_tt1 IS RECORD -- Intermediate result + r_bx,g_bx,b_bx : signed(8 DOWNTO 0); -- B.X 1.8 + r_cxx,g_cxx,b_cxx : signed(11 DOWNTO 0); -- C.XX 3.9 + r_dxx,g_dxx,b_dxx : signed(10 DOWNTO 0); -- D.XX 2.9 + END RECORD; + TYPE type_bic_tt2 IS RECORD -- Intermediate result + r_abxcxx,g_abxcxx,b_abxcxx : signed(9 DOWNTO 0); -- A + B.X + C.XX 2.8 + r_dxxx,g_dxxx,b_dxxx : signed(9 DOWNTO 0); -- D.X.X.X 2.8 + END RECORD; + + ---------------------------------------------------------- + -- Y = A + B.X + C.X.X + D.X.X.X = A + X.(B + X.(C + X.D)) + -- A = Y(0) 0 .. 1 unsigned + -- B = Y(1)/2 - Y(-1)/2 -1/2 .. +1/2 signed + -- C = Y(-1) - 5*Y(0)/2 + 2*Y(1) - Y(2)/2 -3 .. +3 signed + -- D = -Y(-1)/2 + 3*Y(0)/2 - 3*Y(1)/2 + Y(2)/2 -2 .. +2 signed + + FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); + pm,p0,p1,p2 : unsigned(7 DOWNTO 0)) RETURN type_bic_abcd IS + VARIABLE xx : signed(2*FRAC+1 DOWNTO 0); -- 2.(2*FRAC) + BEGIN + xx := signed('0' & f(11 DOWNTO 12-FRAC)) * + signed('0' & f(11 DOWNTO 12-FRAC)); -- 2.(2*FRAC) + RETURN type_bic_abcd'( + a=>p0,-- 0.8 + b=>signed(('0' & p1) - ('0' & pm)), -- 0.9 + c=>signed(("000" & pm & '0') - ("00" & p0 & "00") - ("0000" & p0) + + ("00" & p1 & "00") - ("0000" & p2)), -- 3.9 + d=>signed(("00" & p0 & '0') - ("00" & p1 & '0') - ("000" & p1) + + ("000" & p0) + ("000" & p2) - ("000" & pm)), -- 2.9 + xx=>xx(2*FRAC DOWNTO 2*FRAC-8)); -- 1.8 + END FUNCTION; + FUNCTION bic_calc0(f : unsigned(11 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bic_pix_abcd IS + BEGIN + RETURN type_bic_pix_abcd'( r=>bic_calc0(f,p(0).r,p(1).r,p(2).r,p(3).r), + g=>bic_calc0(f,p(0).g,p(1).g,p(2).g,p(3).g), + b=>bic_calc0(f,p(0).b,p(1).b,p(2).b,p(3).b)); + END FUNCTION; + + ---------------------------------------------------------- + -- Calc : B.X, C.XX, D.XX + FUNCTION bic_calc1(f : unsigned(11 DOWNTO 0); + abcd : type_bic_pix_abcd) RETURN type_bic_tt1 IS + VARIABLE t : type_bic_tt1; + VARIABLE bx : signed(9+FRAC DOWNTO 0); -- 1.(FRAC+9) + VARIABLE cxx : signed(20 DOWNTO 0); -- 4.17 + VARIABLE dxx : signed(19 DOWNTO 0); -- 3.17 + BEGIN + bx := abcd.r.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.r_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.r.c * abcd.r.xx; -- 3.9 * 1.8 = 4.17 + t.r_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.r.d * abcd.r.xx; -- 2.9 * 1.8 = 3.17 + t.r_dxx:=dxx(18 DOWNTO 8); -- 2.9 + bx := abcd.g.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.g_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.g.c * abcd.g.xx; -- 3.9 * 1.8 = 4.17 + t.g_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.g.d * abcd.g.xx; -- 2.9 * 1.8 = 3.17 + t.g_dxx:=dxx(18 DOWNTO 8); -- 2.9 + bx := abcd.b.b * signed('0' & f(11 DOWNTO 12-FRAC)); -- 1.(FRAC+9) + t.b_bx:=bx(9+FRAC DOWNTO 9+FRAC-8); -- 1.8 + cxx:= abcd.b.c * abcd.b.xx; -- 3.9 * 1.8 = 4.17 + t.b_cxx:=cxx(19 DOWNTO 8); -- 3.9 + dxx:= abcd.b.d * abcd.b.xx; -- 2.9 * 1.8 = 3.17 + t.b_dxx:=dxx(18 DOWNTO 8); -- 2.9 + RETURN t; + END FUNCTION; + + ---------------------------------------------------------- + -- Calc A + BX + CXX , X.DXX + FUNCTION bic_calc2(f : unsigned(11 DOWNTO 0); + t : type_bic_tt1; + abcd : type_bic_pix_abcd) RETURN type_bic_tt2 IS + VARIABLE u : type_bic_tt2; + VARIABLE x : signed(11+FRAC DOWNTO 0); -- 3.(9+FRAC) + BEGIN + u.r_abxcxx:=(t.r_bx(8) & t.r_bx) + ("00" & signed(abcd.r.a)) + t.r_cxx(10 DOWNTO 1); -- 2.8 + u.g_abxcxx:=(t.g_bx(8) & t.g_bx) + ("00" & signed(abcd.g.a)) + t.g_cxx(10 DOWNTO 1); -- 2.8 + u.b_abxcxx:=(t.b_bx(8) & t.b_bx) + ("00" & signed(abcd.b.a)) + t.b_cxx(10 DOWNTO 1); -- 2.8 + + x:=t.r_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.r_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + x:=t.g_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.g_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + x:=t.b_dxx * signed('0' & f(11 DOWNTO 12-FRAC)); --2.9 * 1.FRAC =3.(9+FRAC) + u.b_dxxx:=x(10+FRAC DOWNTO 9+FRAC-8); -- 2.8 + RETURN u; + END FUNCTION; + + ---------------------------------------------------------- + -- Calc (A + BX + CXX) + (DXXX) + FUNCTION bic_calc3(f : unsigned(11 DOWNTO 0); + t : type_bic_tt2; + abcd : type_bic_pix_abcd) RETURN type_pix IS + VARIABLE x : type_pix; + VARIABLE v : signed(9 DOWNTO 0); -- 2.8 + BEGIN + v:=t.r_abxcxx + t.r_dxxx; + x.r:=bound(unsigned(v),8); + v:=t.g_abxcxx + t.g_dxxx; + x.g:=bound(unsigned(v),8); + v:=t.b_abxcxx + t.b_dxxx; + x.b:=bound(unsigned(v),8); + RETURN x; + END FUNCTION; + + ----------------------------------------------------------------------------- + SIGNAL o_h_bic_pix,o_v_bic_pix : type_pix; + SIGNAL o_h_bic_abcd1,o_h_bic_abcd2 : type_bic_pix_abcd; + SIGNAL o_v_bic_abcd1,o_v_bic_abcd2 : type_bic_pix_abcd; + SIGNAL o_h_bic_tt1,o_v_bic_tt1 : type_bic_tt1; + SIGNAL o_h_bic_tt2,o_v_bic_tt2 : type_bic_tt2; + + ----------------------------------------------------------------------------- + -- Polyphase + -- 2.7 + TYPE poly_phase_t IS RECORD + t0, t1, t2, t3 : signed(9 DOWNTO 0); + END RECORD; + + -- 4.14 + TYPE poly_phase_interp_t IS RECORD + t0, t1, t2, t3 : signed(17 DOWNTO 0); + END RECORD; + + -- 5.22 + TYPE type_poly_t IS RECORD + r0,r1,b0,b1,g0,g1 : signed(26 DOWNTO 0); + END RECORD; + + SIGNAL o_h_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_v_poly_mem : arr_uv40(0 TO 2**FRAC-1); + SIGNAL o_a_poly_mem : arr_uv40(0 TO 2**FRAC-1); + ATTRIBUTE ramstyle OF o_h_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_v_poly_mem : SIGNAL IS "no_rw_check"; + ATTRIBUTE ramstyle OF o_a_poly_mem : SIGNAL IS "no_rw_check"; + SIGNAL o_a_poly_addr, o_v_poly_addr : integer RANGE 0 TO 2**FRAC-1; + SIGNAL o_h_poly_phase_a,o_h_poly_phase_a2,o_h_poly_phase_a3, o_h_poly_phase_a4, o_h_poly_phase_a5 : poly_phase_t; + SIGNAL o_v_poly_phase_a,o_v_poly_phase_a2,o_v_poly_phase_a3, o_v_poly_phase_a4, o_v_poly_phase_a5 : poly_phase_t; + SIGNAL o_poly_phase_a, o_poly_phase_a2, o_poly_phase_a3 : poly_phase_t; + SIGNAL o_poly_phase_b,o_poly_phase_b2,o_poly_phase_b3 : poly_phase_t; + SIGNAL o_v_poly_phase, o_v_poly_phase2, o_h_poly_phase, o_poly_phase, o_poly_phase1 : poly_phase_interp_t; + SIGNAL o_v_poly_pix, o_h_poly_pix, o_h_lum_pix, o_v_lum_pix : type_pix; + SIGNAL o_poly_lum, o_poly_lum1 : unsigned(7 DOWNTO 0); + SIGNAL o_poly_lerp_ta, o_poly_lerp_tb : signed(9 DOWNTO 0); + SIGNAL o_h_poly_t,o_h_poly_t2,o_v_poly_t : type_poly_t; + + SIGNAL o_v_poly_adaptive, o_h_poly_adaptive, o_v_poly_use_adaptive, o_h_poly_use_adaptive : std_logic; + SIGNAL poly_wr_mode : std_logic_vector(2 DOWNTO 0); + SIGNAL poly_tdw : unsigned(39 DOWNTO 0); + SIGNAL poly_a2 : unsigned(FRAC-1 DOWNTO 0); + + FUNCTION poly_unpack(a : unsigned(39 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + v.t0 := signed(a(39 DOWNTO 30)); + v.t1 := signed(a(29 DOWNTO 20)); + v.t2 := signed(a(19 DOWNTO 10)); + v.t3 := signed(a( 9 DOWNTO 0)); + RETURN v; + END FUNCTION; + + -- 6 DSP 18*18 + 18*18 + FUNCTION poly_calc(fi : poly_phase_interp_t; + p : arr_pix(0 TO 3)) RETURN type_poly_t IS + VARIABLE t : type_poly_t; + BEGIN + -- 3.15 * 1.8 = 4.23 + t.r0:=(fi.t0 * signed('0' & p(0).r) + + fi.t1 * signed('0' & p(1).r)); + t.r1:=(fi.t2 * signed('0' & p(2).r) + + fi.t3 * signed('0' & p(3).r)); + t.g0:=(fi.t0 * signed('0' & p(0).g) + + fi.t1 * signed('0' & p(1).g)); + t.g1:=(fi.t2 * signed('0' & p(2).g) + + fi.t3 * signed('0' & p(3).g)); + t.b0:=(fi.t0 * signed('0' & p(0).b) + + fi.t1 * signed('0' & p(1).b)); + t.b1:=(fi.t2 * signed('0' & p(2).b) + + fi.t3 * signed('0' & p(3).b)); + RETURN t; + END FUNCTION; + + FUNCTION poly_final(t : type_poly_t) RETURN type_pix IS + VARIABLE p : type_pix; + BEGIN + p.r:=bound(unsigned(t.r0(26 DOWNTO 8)+t.r1(26 DOWNTO 8)),15); + p.g:=bound(unsigned(t.g0(26 DOWNTO 8)+t.g1(26 DOWNTO 8)),15); + p.b:=bound(unsigned(t.b0(26 DOWNTO 8)+t.b1(26 DOWNTO 8)),15); + RETURN p; + END FUNCTION; + + -- 4 DSP 18*18 + 18*18 + FUNCTION poly_lerp(a : poly_phase_t; + b : poly_phase_t; + ta : SIGNED(9 DOWNTO 0); + tb : SIGNED(9 DOWNTO 0)) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + VARIABLE t0,t1,t2,t3 : signed(19 DOWNTO 0); + BEGIN + -- 2.8 * 2.8 = 4.16 + t0 := (a.t0 * ta) + (b.t0 * tb); + t1 := (a.t1 * ta) + (b.t1 * tb); + t2 := (a.t2 * ta) + (b.t2 * tb); + t3 := (a.t3 * ta) + (b.t3 * tb); + + -- 4.16 -> 3.15 + v.t0 := t0(18 DOWNTO 1); + v.t1 := t1(18 DOWNTO 1); + v.t2 := t2(18 DOWNTO 1); + v.t3 := t3(18 DOWNTO 1); + + RETURN v; + END FUNCTION; + + FUNCTION poly_cvt(a : poly_phase_t) RETURN poly_phase_interp_t IS + VARIABLE v : poly_phase_interp_t; + BEGIN + v.t0 := resize(signed( a.t0 & "0000000" ), v.t0'length); + v.t1 := resize(signed( a.t1 & "0000000" ), v.t1'length); + v.t2 := resize(signed( a.t2 & "0000000" ), v.t2'length); + v.t3 := resize(signed( a.t3 & "0000000" ), v.t3'length); + RETURN v; + END FUNCTION; + + -- Nearest neighbor polyphase ceoffs + FUNCTION poly_nn(frac : unsigned(FRAC-1 DOWNTO 0)) RETURN poly_phase_t IS + VARIABLE v : poly_phase_t; + BEGIN + IF frac(frac'left)='0' THEN + v := (t1=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + ELSE + v := (t2=>to_signed(256, 10), OTHERS=>to_signed(0, 10)); + END IF; + RETURN v; + END FUNCTION; + + + FUNCTION poly_lum(p : type_pix) RETURN unsigned IS + VARIABLE v : UNSIGNED(7 DOWNTO 0); + BEGIN + -- 0.375 R + 0.5 G + 0.125 B + --v := ("00" & p.r(7 DOWNTO 2)) + ("000" & p.r(7 DOWNTO 3)) + ("0" & p.g(7 DOWNTO 1)) + ("000" & p.b(7 DOWNTO 3)); + + -- 0.25 R + 0.5 G + 0.25 B + -- v := ( ("00" & p.r(7 DOWNTO 2)) + ("0" & p.g(7 DOWNTO 1)) + ("00" & p.b(7 DOWNTO 2)) ); + + -- Just OR them all together + --v := (p.r OR p.g OR p.b); + + -- Maximum + IF p.r > p.g THEN + v := p.r; + ELSE + v := p.g; + END IF; + + IF p.b > v THEN + v := p.b; + END IF; + + -- 100% + -- v := "1111111"; + + RETURN v; + END FUNCTION; +BEGIN + + ----------------------------------------------------------------------------- + i_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(i_clk); + o_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(o_clk); + avl_reset_na<='0' WHEN reset_na='0' ELSE '1' WHEN rising_edge(avl_clk); + + ----------------------------------------------------------------------------- + -- Input pixels FIFO and shreg + InAT:PROCESS(i_clk,i_reset_na) IS + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + VARIABLE frac_v : unsigned(FRAC-1 DOWNTO 0); + VARIABLE div_v : unsigned(16 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + VARIABLE bil_t_v : type_bil_t; + BEGIN + IF i_reset_na='0' THEN + i_write<='0'; + + ELSIF rising_edge(i_clk) THEN + i_push<='0'; + i_pushhead<='0'; + i_eol<='0'; -- End Of Line + i_freeze <=freeze; -- + i_iauto<=iauto; -- + i_wreq<='0'; + i_wr<='0'; + + ------------------------------------------------------ + i_head(127 DOWNTO 120)<=x"01"; -- Header type + i_head(119 DOWNTO 112)<="000000" & i_format; -- Header format + i_head(111 DOWNTO 96)<="0000" & to_unsigned(N_BURST,12); -- Header size + i_head(95 DOWNTO 80)<=x"0000"; -- Attributes. TBD + i_head(80)<=i_inter; + i_head(81)<=i_flm; + i_head(82)<=i_hdown; + i_head(83)<=i_vdown; + i_head(84)<=i_mode(3); + i_head(87 DOWNTO 85)<=i_count; + i_head(79 DOWNTO 64)<="0000" & to_unsigned(i_hrsize,12); -- Image width + i_head(63 DOWNTO 48)<="0000" & to_unsigned(i_vrsize,12); -- Image height + i_head(47 DOWNTO 32)<= to_unsigned(N_BURST * i_hburst,16); -- Line Length. Bytes + i_head(31 DOWNTO 16)<="0000" & to_unsigned(i_ohsize,12); + i_head(15 DOWNTO 0) <="0000" & to_unsigned(i_ovsize,12); + + ------------------------------------------------------ + i_ppix<=(i_r,i_g,i_b); + i_pvs<=i_vs; + i_pfl<=i_fl; + i_pde<=i_de; + i_pce<=i_ce; + + ------------------------------------------------------ + IF i_pce='1' THEN + ---------------------------------------------------- + i_vs_pre<=i_pvs; + i_de_pre<=i_pde; + i_fl_pre<=i_pfl; + + ---------------------------------------------------- + -- Detect interlaced video + IF NOT INTER THEN + i_intercnt<=0; + ELSIF i_pfl/=i_fl_pre THEN + i_intercnt<=3; + ELSIF i_pvs='1' AND i_vs_pre='0' AND i_intercnt>0 THEN + i_intercnt<=i_intercnt-1; + END IF; + i_inter<=to_std_logic(i_intercnt>0); + + ---------------------------------------------------- + IF i_pvs='1' AND i_vs_pre='0' THEN + i_sof<='1'; + END IF; + + IF i_pde='1' AND i_de_pre='0' THEN + i_flm<=i_pfl; + END IF; + + IF i_pde='1' AND i_sof='1' THEN + i_sof<='0'; + i_vcpt<=0; + IF i_inter='1' AND i_flm='0' AND i_half='0' AND INTER THEN + i_line<='1'; + i_adrsi<=to_unsigned(N_BURST * i_hburst,32) + + to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + ELSE + i_line<='0'; + i_adrsi<=to_unsigned(N_BURST * to_integer( + unsigned'("00") & to_std_logic(HEADER)),32); + END IF; + END IF; + + i_ven<=to_std_logic(i_hcpt>=i_hmin AND i_hcpt<=i_hmax AND + i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + -- Detects end of frame for triple buffering. + i_endframe0<=i_vs AND (NOT i_inter OR i_flm); + i_endframe1<=i_vs AND (NOT i_inter OR NOT i_flm); + + i_vss<=to_std_logic(i_vcpt>=i_vmin AND i_vcpt<=i_vmax); + + ---------------------------------------------------- + IF i_pde='1' AND i_de_pre='0' THEN + i_vimax<=i_vcpt; + i_hcpt<=0; + ELSE + i_hcpt<=(i_hcpt+1) MOD 4096; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_himax<=i_hcpt; + END IF; + + IF i_iauto='1' THEN + -- Auto-size + i_hmin<=0; + i_hmax<=i_himax; + i_vmin<=0; + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vmax<=i_vimax; + END IF; + ELSE + -- Forced image + i_hmin<=himin; -- + i_hmax<=himax; -- + i_vmin<=vimin; -- + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vmax<=vimax; -- + END IF; + END IF; + + IF i_pvs='1' AND i_vs_pre='0' AND (i_inter='0' OR i_pfl='0') THEN + i_vdmax<=i_vimax; + END IF; + i_hdmax<=i_himax; + + IF i_format="00" OR i_format="11" THEN -- 16bpp + i_hburst<=(i_hrsize*2 + N_BURST - 1) / N_BURST; + ELSIF i_format="01" THEN -- 24bpp + i_hburst<=(i_hrsize*3 + N_BURST - 1) / N_BURST; + ELSE -- 32bpp + i_hburst<=(i_hrsize*4 + N_BURST - 1) / N_BURST; + END IF; + ---------------------------------------------------- + i_mode<=mode; -- + i_format<=format; -- + + -- Downscaling : Nearest or bilinear + i_bil<=to_std_logic(i_mode(2 DOWNTO 0)/="000" AND NOT DOWNSCALE_NN); + + i_hdown<=to_std_logic(i_hsize>i_ohsize AND DOWNSCALE); --H downscale + i_vdown<=to_std_logic(i_vsize>i_ovsize AND DOWNSCALE); --V downscale + + ---------------------------------------------------- + i_hsize <=(4096+i_hmax-i_hmin+1) MOD 4096; + i_vmaxmin<=(4096+i_vmax-i_vmin+1) MOD 4096; + + IF i_inter='0' THEN + -- Non interlaced + i_vsize<=i_vmaxmin; + i_half <='0'; + ELSIF i_ovsize<2*i_vmaxmin THEN + -- Interlaced, but downscaling, use only half frames + i_vsize<=i_vmaxmin; + i_half <='1'; + ELSE + -- Interlaced : Double image height + i_vsize<=2*i_vmaxmin; + i_half <='0'; + END IF; + + i_ohsize<=o_hsize; -- + i_ovsize<=o_vsize; -- + + ---------------------------------------------------- + -- Downscaling vertical + i_divstart<='0'; + IF i_de_delay=16 THEN + IF (i_vacc + 2*i_ovsize) < 2*i_vsize THEN + i_vacc<=(i_vacc + 2*i_ovsize) MOD 8192; + i_vnp<='0'; + ELSE + i_vacc<=(i_vacc + 2*i_ovsize - 2*i_vsize + 8192) MOD 8192; + i_vnp<='1'; + END IF; + i_divstart<='1'; + + IF i_vcpt=i_vmin THEN + i_vacc<=(i_vsize - i_ovsize + 8192) MOD 8192; + i_vnp<='1'; -- + END IF; + END IF; + + IF i_vdown='0' THEN + i_vnp<='1'; + END IF; + + -- Downscaling horizontal + IF i_ven='1' THEN + IF i_hacc + 2*i_ohsize < 2*i_hsize THEN + i_hacc<=(i_hacc + 2*i_ohsize) MOD 8192; + i_hnp<='0'; -- Skip. pix. + ELSE + i_hacc<=(i_hacc + 2*i_ohsize - 2*i_hsize + 8192) MOD 8192; + i_hnp<='1'; + END IF; + END IF; + IF i_hdown='0' THEN + i_hnp<='1'; + END IF; + + ---------------------------------------------------- + -- Downscaling interpolation + i_hpixp<=i_ppix; + i_hpix0<=i_hpixp; + i_hpix1<=i_hpix0; + i_hpix2<=i_hpix1; + i_hpix3<=i_hpix2; + i_hpix4<=i_hpix3; + + i_hnp1<=i_hnp; i_hnp2<=i_hnp1; i_hnp3<=i_hnp2; i_hnp4<=i_hnp3; + i_ven1<=i_ven; i_ven2<=i_ven1; i_ven3<=i_ven2; i_ven4<=i_ven3; + i_ven5<=i_ven4; i_ven6<=i_ven5; + + -- C1 : DIV 1. Pipelined 4 bits non-restoring divider + dir_v:=x"000"; + div_v:=to_unsigned(i_hacc * 16,17); + + div_v:=div_v-to_unsigned(i_hsize*16,17); + dir_v(11):=NOT div_v(16); + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*8,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*8,17); + END IF; + dir_v(10):=NOT div_v(16); + i_div<=div_v; + i_dir<=dir_v; + + -- C2 : DIV 2. + div_v:=i_div; + dir_v:=i_dir; + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*4,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*4,17); + END IF; + dir_v(9):=NOT div_v(16); + + IF div_v(16)='0' THEN + div_v:=div_v-to_unsigned(i_hsize*2,17); + ELSE + div_v:=div_v+to_unsigned(i_hsize*2,17); + END IF; + dir_v(8):=NOT div_v(16); + i_h_frac<=dir_v; + + -- C4 : Horizontal Bilinear + IF i_bil='0' THEN + frac_v:=near_frac(i_h_frac); + i_h_bil_t<=near_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + ELSE + frac_v:=bil_frac(i_h_frac); + i_h_bil_t<=bil_calc(frac_v,(i_hpix2,i_hpix2,i_hpix3,i_hpix3)); + END IF; + + i_hpix.r<=bound(i_h_bil_t.r,8+FRAC); + i_hpix.g<=bound(i_h_bil_t.g,8+FRAC); + i_hpix.b<=bound(i_h_bil_t.b,8+FRAC); + + IF i_hdown='0' THEN + i_hpix<=i_hpix4; + END IF; + + -- C5 : Vertical Bilinear + IF i_bil='0' THEN + frac_v:=near_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=near_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + ELSE + frac_v:=bil_frac(i_v_frac(11 DOWNTO 0)); + bil_t_v:=bil_calc(frac_v,(i_hpix,i_hpix,i_ldrm,i_ldrm)); + END IF; + + i_pix.r<=bound(bil_t_v.r,8+FRAC); + i_pix.g<=bound(bil_t_v.g,8+FRAC); + i_pix.b<=bound(bil_t_v.b,8+FRAC); + + IF i_vdown='0' THEN + i_pix<=i_hpix; + END IF; + + ---------------------------------------------------- + -- VNP : Vert. downscaling line enable + -- HNP : Horiz. downscaling pix. enable + -- VEN : Enable pixel within displayed window + + IF (i_hnp4='1' AND i_ven6='1') OR i_pushend='1' THEN + i_shift<=shift_ishift(i_shift,i_pix,i_format); + i_dw<=shift_ipack(i_dw,i_acpt,i_shift,i_pix,i_format); + + IF shift_inext(i_acpt,i_format) AND i_vnp='1' THEN + i_push<='1'; + i_pushend<='0'; + END IF; + i_acpt<=(i_acpt+1) MOD 16; + END IF; + + IF i_ven6='1' AND i_ven5='0' AND i_vnp='1' THEN + i_pushend<='1'; + END IF; + i_pushend2<=i_pushend; + + IF i_pushend2='1' AND i_pushend='0' THEN + i_eol<='1'; + END IF; + + IF i_pde='0' AND i_de_pre='1' THEN + i_de_delay<=0; + ELSIF i_de_delay<18 THEN + i_de_delay<=i_de_delay+1; + END IF; + + IF i_de_delay=16 THEN + i_lwad<=0; + i_lrad<=0; + i_vcpt<=i_vcpt+1; + i_hacc<=(i_hsize - i_ohsize + 8192) MOD 8192; + i_hbcpt<=0; + END IF; + IF i_de_delay=17 THEN + i_acpt<=0; + i_wad<=2*BLEN-1; + END IF; + + IF i_pvs='0' AND i_vs_pre='1' THEN + -- Push header + i_pushhead<=to_std_logic(HEADER); + END IF; + + END IF; -- IF i_pce='1' + + ------------------------------------------------------ + -- Push pixels to downscaling line buffer + i_lwr<=i_hnp4 AND i_ven5 AND i_pce; + IF i_lwr='1' THEN + i_lwad<=(i_lwad+1) MOD OHRES; + END IF; + i_ldw<=i_hpix; + + IF i_hnp3='1' AND i_ven4='1' AND i_pce='1' THEN + i_lrad<=(i_lrad+1) MOD OHRES; + END IF; + + ------------------------------------------------------ + -- Write image properties header + i_pushhead2<=i_pushhead; i_pushhead3<=i_pushhead2; + + IF i_pushhead='1' AND i_freeze='0' THEN + i_dw<=i_head(127 DOWNTO 128-N_DW); + i_count<=i_count+1; + i_wr<='1'; + i_wad<=0; + IF N_DW=128 THEN + i_alt<='0'; + i_wreq<=NOT i_freeze; + i_adrs<=(OTHERS =>'0'); + END IF; + END IF; + + IF i_pushhead2='1' AND i_freeze='0' AND N_DW=64 THEN + i_dw<=i_head(N_DW-1 DOWNTO 0); + i_wr<='1'; + i_wad<=1; + i_wreq<=NOT i_freeze; + i_alt<='0'; + i_adrs<=(OTHERS =>'0'); + END IF; + IF i_pushhead3='1' THEN + i_wad<=BLEN-1; + END IF; + + ------------------------------------------------------ + -- Push pixels to DPRAM + IF i_push='1' AND i_freeze='0' THEN + i_wr<='1'; + i_wad<=(i_wad+1) MOD (BLEN*2); + IF (i_wad+1) MOD BLEN=BLEN-1 AND i_hbcpt 12 + IDividers:PROCESS (i_clk,i_reset_na) IS + BEGIN + IF i_reset_na='0' THEN +--pragma synthesis_off + i_v_frac<=x"000"; +--pragma synthesis_on + NULL; + ELSIF rising_edge(i_clk) THEN + i_vdivi<=to_unsigned(2*i_vsize,13); + i_vdivr<=to_unsigned(i_vacc*4096,25); + + ------------------------------------------------------ + IF i_divstart='1' THEN + i_divcpt<=0; + i_divrun<='1'; + + ELSIF i_divrun='1' THEN + ---------------------------------------------------- + IF i_divcpt=6 THEN + i_divrun<='0'; + i_v_frac<=i_vdivr(4 DOWNTO 0) & NOT i_vdivr(24) & "000000"; + ELSE + i_divcpt<=i_divcpt+1; + END IF; + + IF i_vdivr(24)='0' THEN + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) - i_vdivi; + ELSE + i_vdivr(24 DOWNTO 12)<=i_vdivr(23 DOWNTO 11) + i_vdivi; + END IF; + i_vdivr(11 DOWNTO 0)<=i_vdivr(10 DOWNTO 0) & NOT i_vdivr(24); + + ---------------------------------------------------- + END IF; + END IF; + END PROCESS IDividers; + + ----------------------------------------------------------------------------- + -- DPRAM Input. Double buffer for RAM bursts. + PROCESS (i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_wr='1' THEN + i_dpram(i_wad)<=i_dw; + END IF; + END IF; + END PROCESS; + + avl_dr<=i_dpram(avl_rad_c) WHEN rising_edge(avl_clk); + + -- Line buffer for downscaling with interpolation + DownLine:IF DOWNSCALE GENERATE + ILBUF:PROCESS(i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_lwr='1' THEN + i_mem(i_lwad MOD IHRES)<=i_ldw; + END IF; + IF i_pce='1' THEN + i_ldrm<=i_mem(i_lrad MOD IHRES); + END IF; + END IF; + END PROCESS ILBUF; + END GENERATE DownLine; + + ----------------------------------------------------------------------------- + -- AVALON interface + Avaloir:PROCESS(avl_clk,avl_reset_na) IS + VARIABLE adr_v : unsigned(31 DOWNTO 0); + BEGIN + IF avl_reset_na='0' THEN + avl_state<=sIDLE; + avl_write_sr<='0'; + avl_read_sr<='0'; + avl_readdataack<='0'; + avl_readack<='0'; + + ELSIF rising_edge(avl_clk) THEN + ---------------------------------- + avl_write_sync<=i_write; -- + avl_write_sync2<=avl_write_sync; + avl_write_pulse<=avl_write_sync XOR avl_write_sync2; + IF avl_write_pulse='1' THEN + avl_wadrs <=i_wadrs AND (RAMSIZE - 1); -- + avl_wline <=i_wline; -- + avl_walt <=i_walt; -- + END IF; + + ---------------------------------- + avl_read_sync<=o_read; -- + avl_read_sync2<=avl_read_sync; + avl_read_pulse<=avl_read_sync XOR avl_read_sync2; + avl_radrs <=o_adrs; -- + avl_rline <=o_rline; -- + + -------------------------------------------- + avl_o_vs_sync<=o_vsv(0); -- + avl_o_vs<=avl_o_vs_sync; + + avl_fb_ena<=o_fb_ena; -- + IF avl_fb_ena='0' THEN + IF HEADER THEN + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE) + N_BURST; -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE) + N_BURST; -- + ELSE + avl_o_offset0<=buf_offset(o_obuf0,RAMBASE,RAMSIZE); -- + avl_o_offset1<=buf_offset(o_obuf1,RAMBASE,RAMSIZE); -- + END IF; + ELSIF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + -- Copy framebuffer base address at VS falling edge + avl_o_offset0<=o_fb_base; -- + avl_o_offset1<=o_fb_base; -- + END IF; + + avl_i_offset0<=buf_offset(o_ibuf0,RAMBASE,RAMSIZE); -- + avl_i_offset1<=buf_offset(o_ibuf1,RAMBASE,RAMSIZE); -- + + -------------------------------------------- + avl_dw<=swap(unsigned(avl_readdata)); + avl_read_i<='0'; + avl_write_i<='0'; + + avl_write_sr<=(avl_write_sr OR avl_write_pulse) AND NOT avl_write_clr; + avl_read_sr <=(avl_read_sr OR avl_read_pulse) AND NOT avl_read_clr; + avl_write_clr<='0'; + avl_read_clr <='0'; + + avl_rad<=avl_rad_c; + + -------------------------------------------- + CASE avl_state IS + WHEN sIDLE => + IF avl_write_sr='1' THEN + avl_state<=sWRITE; + avl_write_clr<='1'; + IF avl_walt='0' THEN + avl_rad<=0; + ELSE + avl_rad<=BLEN; + END IF; + IF avl_wline='0' THEN + avl_address<=std_logic_vector( + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset0(N_AW+NB_LA-1 DOWNTO NB_LA)); + ELSE + avl_address<=std_logic_vector( + avl_wadrs(N_AW+NB_LA-1 DOWNTO NB_LA) + + avl_i_offset1(N_AW+NB_LA-1 DOWNTO NB_LA)); + END IF; + ELSIF avl_read_sr='1' THEN + avl_state<=sREAD; + avl_read_clr<='1'; + END IF; + + WHEN sWRITE => + avl_write_i<='1'; + IF avl_write_i='1' AND avl_waitrequest='0' THEN + IF (avl_rad MOD BLEN)=BLEN-1 THEN + avl_write_i<='0'; + avl_state<=sIDLE; + END IF; + END IF; + + WHEN sREAD => + IF avl_rline='0' THEN + adr_v:=avl_radrs + avl_o_offset0; + ELSE + adr_v:=avl_radrs + avl_o_offset1; + END IF; + avl_address<=std_logic_vector(adr_v(N_AW+NB_LA-1 DOWNTO NB_LA)); + + avl_read_i<='1'; + IF avl_read_i='1' AND avl_waitrequest='0' THEN + avl_state<=sIDLE; + avl_read_i<='0'; + avl_readack<=NOT avl_readack; + END IF; + END CASE; + + -------------------------------------------- + -- Pipelined data read + avl_wr<='0'; + IF avl_readdatavalid='1' THEN + avl_wr<='1'; + avl_wad<=(avl_wad+1) MOD (2*BLEN); + IF (avl_wad MOD BLEN)=BLEN-2 THEN + avl_readdataack<=NOT avl_readdataack; + END IF; + END IF; + + IF avl_o_vs_sync='0' AND avl_o_vs='1' THEN + avl_wad<=2*BLEN-1; + END IF; + + -------------------------------------------- + END IF; + END PROCESS Avaloir; + + avl_read<=avl_read_i; + avl_write<=avl_write_i; + avl_writedata<=std_logic_vector(swap(avl_dr)); + avl_burstcount<=std_logic_vector(to_unsigned(BLEN,8)); + avl_byteenable<=(OTHERS =>'1'); + + avl_rad_c<=(avl_rad+1) MOD (2*BLEN) + WHEN avl_write_i='1' AND avl_waitrequest='0' ELSE avl_rad; + + ----------------------------------------------------------------------------- + -- DPRAM Output. Double buffer for RAM bursts. + PROCESS (avl_clk) IS + BEGIN + IF rising_edge(avl_clk) THEN + IF avl_wr='1' THEN + o_dpram(avl_wad)<=avl_dw; + END IF; + END IF; + END PROCESS; + + o_dr<=o_dpram(o_ad3) WHEN rising_edge(o_clk); + + ----------------------------------------------------------------------------- + -- Output Vertical Divider + -- Vfrac = Vacc / Vsize + ODivider:PROCESS (o_clk,o_reset_na) IS + BEGIN + IF o_reset_na='0' THEN +--pragma synthesis_off + o_vfrac<=x"000"; +--pragma synthesis_on + ELSIF rising_edge(o_clk) THEN + o_vdivi<=to_unsigned(2*o_vsize,13); + o_vdivr<=to_unsigned(o_vacc*4096,25); + ------------------------------------------------------ + IF o_divstart='1' THEN + o_divcpt<=0; + o_divrun<='1'; + + ELSIF o_divrun='1' THEN + ---------------------------------------------------- + IF o_divcpt=12 THEN + o_divrun<='0'; + o_vfrac<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); + ELSE + o_divcpt<=o_divcpt+1; + END IF; + + IF o_vdivr(24)='0' THEN + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) - o_vdivi; + ELSE + o_vdivr(24 DOWNTO 12)<=o_vdivr(23 DOWNTO 11) + o_vdivi; + END IF; + o_vdivr(11 DOWNTO 0)<=o_vdivr(10 DOWNTO 0) & NOT o_vdivr(24); + ---------------------------------------------------- + END IF; + END IF; + END PROCESS ODivider; + + ----------------------------------------------------------------------------- + Scalaire:PROCESS (o_clk,o_reset_na) IS + VARIABLE lev_inc_v,lev_dec_v : std_logic; + VARIABLE prim_v,last_v,bib_v : std_logic; + VARIABLE shift_v : unsigned(0 TO N_DW+15); + VARIABLE hpix_v : type_pix; + VARIABLE hcarry_v,vcarry_v : boolean; + VARIABLE dif_v : natural RANGE 0 TO 8*OHRES-1; + VARIABLE off_v : natural RANGE 0 TO 15; + BEGIN + IF o_reset_na='0' THEN + o_copy<=sWAIT; + o_state<=sDISP; + o_read_pre<='0'; + o_readlev<=0; + o_copylev<=0; + o_hsp<='0'; + + ELSIF rising_edge(o_clk) THEN + ------------------------------------------------------ + o_mode <=mode; -- ? + o_format <="0001" & format; -- ? + + o_run <=run; -- ? + + o_htotal <=htotal; -- ? + o_hsstart<=hsstart; -- ? + o_hsend <=hsend; -- ? + o_hdisp <=hdisp; -- ? + o_hmin <=hmin; -- ? + o_hmax <=hmax; -- ? + + o_vtotal <=vtotal; -- ? + o_vsstart<=vsstart; -- ? + o_vsend <=vsend; -- ? + o_vdisp <=vdisp; -- ? + o_vmin <=vmin; -- ? + o_vmax <=vmax; -- ? + + o_hsize <=o_hmax - o_hmin + 1; + o_vsize <=o_vmax - o_vmin + 1; + + o_vrr <=vrr; + o_vrrmax <= vrrmax; + + -------------------------------------------- + -- Triple buffering. + -- For intelaced video, half frames are updated independently + -- Input : Toggle buffer at end of input frame + o_isync <= '0'; + o_isync2 <= o_isync; + o_freeze <= freeze; + o_inter <=i_inter; -- + o_iendframe0<=i_endframe0; -- + o_iendframe02<=o_iendframe0; + IF o_iendframe0='1' AND o_iendframe02='0' THEN + o_ibuf0<=buf_next(o_ibuf0,o_obuf0,o_freeze); + o_bufup0<='1'; + o_isync <= '1'; + END IF; + o_iendframe1<=i_endframe1; -- + o_iendframe12<=o_iendframe1; + IF o_iendframe1='1' AND o_iendframe12='0' THEN + o_ibuf1<=buf_next(o_ibuf1,o_obuf1,o_freeze); + o_bufup1<='1'; + o_isync <= '1'; + END IF; + + -- Output : Change framebuffer, and image properties, at VS falling edge + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup0='1' THEN + o_obuf0<=buf_next(o_obuf0,o_ibuf0,o_freeze); + o_bufup0<='0'; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND o_bufup1='1' THEN + o_obuf1<=buf_next(o_obuf1,o_ibuf1,o_freeze); + o_bufup1<='0'; + o_ihsize<=i_hrsize; -- + o_ivsize<=i_vrsize; -- + o_hdown<=i_hdown; -- + o_vdown<=i_vdown; -- + + IF (o_newres > 0) then + o_newres <= o_newres- 1; + END IF; + END IF; + + IF (swblack = '1' and o_fb_ena = '0' and (o_ihsize /= i_hrsize or o_ivsize /= i_vrsize)) then + o_newres <= 3; + END IF; + + -- Simultaneous change of input and output framebuffers + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe0='1' AND o_iendframe02='0' THEN + o_bufup0<='0'; + o_obuf0<=o_ibuf0; + END IF; + IF o_vsv(1)='1' AND o_vsv(0)='0' AND + o_iendframe1='1' AND o_iendframe12='0' THEN + o_bufup1<='0'; + o_obuf1<=o_ibuf1; + END IF; + + -- Non-interlaced, use same buffer for even and odd lines + IF o_inter='0' THEN + o_ibuf1<=o_ibuf0; + o_obuf1<=o_obuf0; + END IF; + + -- Triple buffer disabled + IF o_mode(3)='0' THEN + o_obuf0<=0; + o_obuf1<=0; + o_ibuf0<=0; + o_ibuf1<=0; + END IF; + + -- Framebuffer mode. + IF o_fb_ena='1' THEN + o_ihsize<=o_fb_hsize; + o_ivsize<=o_fb_vsize; + o_format<=o_fb_format; + o_hdown<='0'; + o_vdown<='0'; + END IF; + + -- 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp + CASE o_format(2 DOWNTO 0) IS + WHEN "011" => o_ihsize_temp <= o_ihsize; + WHEN "100" => o_ihsize_temp <= o_ihsize * 2; + WHEN "110" => o_ihsize_temp <= o_ihsize * 4; + WHEN OTHERS => o_ihsize_temp <= o_ihsize * 3; + END CASE; + + o_ihsize_temp2 <= (o_ihsize_temp + N_BURST - 1); + o_hburst <= o_ihsize_temp2 / N_BURST; + + IF o_fb_ena='1' AND o_fb_stride /= 0 THEN + o_stride<=o_fb_stride; + ELSE + o_stride<=to_unsigned(o_ihsize_temp2,14); + o_stride(NB_BURST-1 DOWNTO 0)<=(OTHERS =>'0'); + END IF; + ------------------------------------------------------ + o_hmode<=o_mode; + IF o_hdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_hmode(2 DOWNTO 0)<="000"; + END IF; + + o_vmode<=o_mode; + IF o_vdown='1' AND DOWNSCALE THEN + -- Force nearest if downscaling : Downscaled framebuffer + o_vmode(2 DOWNTO 0)<="000"; + END IF; + + ------------------------------------------------------ + -- End DRAM READ + o_readack_sync<=avl_readack; -- + o_readack_sync2<=o_readack_sync; + o_readack<=o_readack_sync XOR o_readack_sync2; + + o_readdataack_sync<=avl_readdataack; -- + o_readdataack_sync2<=o_readdataack_sync; + o_readdataack<=o_readdataack_sync XOR o_readdataack_sync2; + + ------------------------------------------------------ + lev_inc_v:='0'; + lev_dec_v:='0'; + + -- acpt : Pixel position within current data word + -- dcpt : Destination image position + + -- Force preload 2 lines at top of screen + IF o_hsv(0)='1' AND o_hsv(1)='0' THEN + IF o_vcpt_pre3=o_vmin THEN + o_fload<=2; + o_bibu<='0'; + END IF; + o_hsp<='1'; + END IF; + + o_vpe<=to_std_logic(o_vcpt_pre=o_vmin); + o_divstart<='0'; + o_adrsa<='0'; + o_adrsb<=o_adrsa; + + o_vacc_ini<=(o_vsize - o_ivsize + 8192) MOD 8192; + o_hacc_ini<=(o_hsize + o_ihsize + 8192) MOD 8192; + + --Alternate phase + --o_vacc_ini<=o_ivsize; + --o_hacc_ini<=(2*o_hsize - o_ihsize + 8192) MOD 8192; + + CASE o_state IS + -------------------------------------------------- + WHEN sDISP => + IF o_hsp='1' THEN + o_state<=sHSYNC; + o_hsp<='0'; + END IF; + o_prim<=true; + o_vcarrym<=false; + + -------------------------------------------------- + WHEN sHSYNC => + dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF o_prim THEN + IF dif_v>=8192 THEN + o_vacc <=o_vacc_next; + ELSE + o_vacc <=dif_v; + END IF; + END IF; + IF dif_v>=8192 THEN + o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; + vcarry_v:=false; + ELSE + o_vacc_next<=dif_v; + vcarry_v:=true; + END IF; + + IF o_vcpt_pre2=o_vmin THEN + o_vacc <=o_vacc_ini; + o_vacc_next<=o_vacc_ini + 2*o_ivsize; + o_vacpt <=x"001"; + o_vacptl<="01"; + vcarry_v:=false; + END IF; + + IF vcarry_v THEN + o_vacpt<=o_vacpt+1; + END IF; + IF vcarry_v AND o_prim THEN + o_vacptl<=o_vacptl+1; + END IF; + o_vcarrym <= o_vcarrym OR vcarry_v; + o_prim <= false; + o_hbcpt<=0; -- Clear burst counter on line + o_divstart<=to_std_logic(NOT vcarry_v); + IF NOT vcarry_v OR o_fload>0 THEN + IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN + o_state<=sREAD; + ELSE + o_state<=sDISP; + END IF; + END IF; + + WHEN sREAD => + -- Read a block + IF o_readlev<2 AND o_adrsb='1' THEN + lev_inc_v:='1'; + o_read_pre<=NOT o_read_pre; + o_state <=sWAITREAD; + o_bibu<=NOT o_bibu; + END IF; + prim_v:=to_std_logic(o_hbcpt=0); + last_v:=to_std_logic(o_hbcpt=o_hburst-1); + bib_v :=o_bibu; + off_v :=pixoffset(o_adrs + o_fb_base(NB_LA-1 DOWNTO 0),o_fb_format); + IF o_fb_ena='0' THEN + off_v:=0; + END IF; + o_adrsa<='1'; + + WHEN sWAITREAD => + IF o_readack='1' THEN + o_hbcpt<=o_hbcpt+1; + IF o_hbcpt=1 THEN + o_fload<=o_fload-1; + END IF; + END IF; + END IF; + + -------------------------------------------------- + END CASE; + + o_read<=o_read_pre AND o_run; + o_rline<=o_vacpt(0); -- Even/Odd line for interlaced video + + o_adrs_pre<=to_integer(o_vacpt) * to_integer(o_stride); + IF o_adrsa='1' THEN + IF o_fload=2 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32); + o_alt<="1111"; + ELSIF o_fload=1 THEN + o_adrs<=to_unsigned(o_hbcpt * N_BURST,32) + o_stride; + o_alt<="0100"; + ELSE + o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32); + o_alt<=altx(o_vacptl + 1); + END IF; + END IF; + + ------------------------------------------------------ + -- Copy from buffered memory to pixel lines + o_sh<='0'; + CASE o_copy IS + WHEN sWAIT => + o_copyv(0)<='0'; + IF o_copylev>0 AND o_copyv(0)='0' THEN + o_copy<=sCOPY; + IF o_off(0)>0 AND o_primv(0)='1' THEN + o_copy<=sSHIFT; + END IF; + o_altx<=o_alt; + END IF; + o_adturn<='0'; + o_pshift<=o_off(0) -1; + IF o_primv(0)='1' THEN + -- First memcopy of a horizontal line, carriage return ! + o_ihsizem<=o_ihsize + o_off(0) - 2; + o_hacc <=o_hacc_ini; + o_hacc_next<=o_hacc_ini + 2*o_ihsize; + o_hacpt <=x"000"; + o_dcpt<=0; + o_dshi<=2; + o_acpt<=0; + o_first<='1'; + o_last<='0'; + END IF; + + IF o_bibv(0)='0' THEN + o_ad<=0; + ELSE + o_ad<=BLEN; + END IF; + + WHEN sSHIFT => + o_hacpt<=o_hacpt+1; + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + o_pshift<=o_pshift-1; + IF o_pshift=0 THEN + o_copy<=sCOPY; + END IF; + + WHEN sCOPY => + -- dshi : Force shift first two or three pixels of each line + IF o_dshi=0 THEN + dif_v:=(o_hacc_next - 2*o_hsize + (8*OHRES)) MOD (8*OHRES); + IF dif_v>=4*OHRES THEN + o_hacc<=o_hacc_next; + o_hacc_next<=o_hacc_next + 2*o_ihsize; + hcarry_v:=false; + ELSE + o_hacc<=dif_v; + o_hacc_next<=(dif_v + 2*o_ihsize + (4*OHRES)) MOD (4*OHRES); + hcarry_v:=true; + END IF; + o_dcpt<=(o_dcpt+1) MOD 4096; + ELSE + o_dshi<=o_dshi-1; + hcarry_v:=false; + END IF; + IF o_dshi<=1 THEN + o_copyv(0)<='1'; + END IF; + IF hcarry_v THEN + o_hacpt<=o_hacpt+1; + o_last <=to_std_logic(o_hacpt>=o_ihsizem); + END IF; + + IF hcarry_v OR o_dshi>0 THEN + o_sh<='1'; + o_acpt<=(o_acpt+1) MOD 16; + + -- Shift two more pixels to the right before ending line. + o_last1<=o_last; + o_last2<=o_last1; + + IF shift_onext(o_acpt,o_format) THEN + o_ad<=(o_ad+1) MOD (2*BLEN); + END IF; + + IF o_adturn='1' AND (shift_onext((o_acpt+1) MOD 16,o_format)) AND + (((o_ad MOD BLEN=0) AND o_lastv(0)='0') OR o_last2='1') THEN + o_copy<=sWAIT; + lev_dec_v:='1'; + END IF; + + IF o_ad MOD BLEN=4 THEN + o_adturn<='1'; + END IF; + END IF; + END CASE; + + o_acpt1<=o_acpt; o_acpt2<=o_acpt1; o_acpt3<=o_acpt2; o_acpt4<=o_acpt3; + o_ad1<=o_ad; o_ad2<=o_ad1; o_ad3<=o_ad2; + o_sh1<=o_sh; o_sh2<=o_sh1; o_sh3<=o_sh2; o_sh4<=o_sh3; + o_lastt1<=o_last; o_lastt2<=o_lastt1; + o_lastt3<=o_lastt2; o_lastt4<=o_lastt3; + + ------------------------------------------------------ + IF o_sh3='1' THEN + shift_v:=shift_opack(o_acpt4,o_shift,o_dr,o_format); + o_shift<=shift_v; + o_hpixs<=shift_opix(shift_v,o_format); + END IF; + + IF o_sh4='1' THEN + hpix_v:=o_hpixs; + IF o_format(4)='1' THEN -- Swap B <-> R + hpix_v:=(r=>o_hpixs.b,g=>o_hpixs.g,b=>o_hpixs.r); + END IF; + IF o_format(2 DOWNTO 0)="011" THEN + -- 8bpp indexed colour mode + hpix_v:=(r=>o_fb_pal_dr(23 DOWNTO 16),g=>o_fb_pal_dr(15 DOWNTO 8), + b=>o_fb_pal_dr(7 DOWNTO 0)); + END IF; + IF (o_newres > 0) then + hpix_v := (others => (others => '0')); + END IF; + o_hpix0<=hpix_v; + o_hpix1<=o_hpix0; + o_hpix2<=o_hpix1; + o_hpix3<=o_hpix2; + + IF o_first='1' THEN + -- Left edge. Duplicate first pixel + o_hpix1<=hpix_v; + o_hpix2<=hpix_v; + o_first<='0'; + END IF; + IF o_lastt4='1' THEN + -- Right edge. Keep last pixel. + o_hpix0<=o_hpix0; + END IF; + END IF; + + ------------------------------------------------------ + -- lev_inc : read start + -- lev_dec : end of copy + -- READLEV : Number of ongoing Avalon Reads + IF lev_dec_v='0' AND lev_inc_v='1' THEN + o_readlev<=o_readlev+1; + ELSIF lev_dec_v='1' AND lev_inc_v='0' THEN + o_readlev<=o_readlev-1; + END IF; + + -- COPYLEV : Number of ongoing copies to line buffers + IF lev_dec_v='1' AND o_readdataack='0' THEN + o_copylev<=o_copylev-1; + ELSIF lev_dec_v='0' AND o_readdataack='1' THEN + o_copylev<=o_copylev+1; + END IF; + + -- FIFOs + IF lev_dec_v='1' THEN + o_primv(0 TO 1)<=o_primv(1 TO 2); -- First buffer of line + o_lastv(0 TO 1)<=o_lastv(1 TO 2); -- Last buffer of line + o_bibv (0 TO 1)<=o_bibv (1 TO 2); -- Double buffer select + o_off (0 TO 1)<=o_off (1 TO 2); -- Start offset + END IF; + + IF lev_inc_v='1' THEN + IF o_readlev=0 OR (o_readlev=1 AND lev_dec_v='1') THEN + o_primv(0)<=prim_v; + o_lastv(0)<=last_v; + o_bibv (0)<=bib_v; + o_off (0)<=off_v; + ELSIF (o_readlev=1 AND lev_dec_v='0') OR + (o_readlev=2 AND lev_dec_v='1') THEN + o_primv(1)<=prim_v; + o_lastv(1)<=last_v; + o_bibv (1)<=bib_v; + o_off (1)<=off_v; + END IF; + o_primv(2)<=prim_v; + o_lastv(2)<=last_v; + o_bibv (2)<=bib_v; + o_off (2)<=off_v; + END IF; + + ------------------------------------------------------ + END IF; + END PROCESS Scalaire; + + -- Fetch polyphase coefficients + PolyFetch:PROCESS (o_clk) IS + VARIABLE hfrac3_v, vfrac_v : unsigned(FRAC-1 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + hfrac3_v:=o_hfrac(3)(11 DOWNTO 12-FRAC); + vfrac_v:=o_vfrac(11 DOWNTO 12-FRAC); + + o_v_poly_use_adaptive <= to_std_logic((o_vmode(2 DOWNTO 0)/="000") AND (o_v_poly_adaptive = '1')); + o_h_poly_use_adaptive <= to_std_logic((o_hmode(2 DOWNTO 0)/="000") AND (o_h_poly_adaptive = '1')); + o_v_poly_addr<=to_integer(o_vfrac(11 DOWNTO 12-FRAC)); + + -- C3 / HC3 / VC4 + IF o_vmode(2 DOWNTO 0)/="000" THEN + o_v_poly_phase_a<=poly_unpack(o_v_poly_mem(o_v_poly_addr)); + ELSE + o_v_poly_phase_a<=poly_nn(vfrac_v); + END IF; + + IF o_hmode(2 DOWNTO 0)/="000" THEN + o_h_poly_phase_a<=poly_unpack(o_h_poly_mem(to_integer(hfrac3_v))); + ELSE + o_h_poly_phase_a<=poly_nn(hfrac3_v); + END IF; + + IF o_v_poly_use_adaptive='1' THEN + o_poly_lum<=poly_lum(o_v_lum_pix); + o_a_poly_addr<=o_v_poly_addr; + ELSIF o_h_poly_use_adaptive='1' THEN + o_poly_lum<=poly_lum(o_h_lum_pix); + o_a_poly_addr<=to_integer(hfrac3_v); + END IF; + + -- C4 / HC4 / VC5 + o_poly_phase_b<=poly_unpack(o_a_poly_mem(o_a_poly_addr)); + + IF o_v_poly_use_adaptive='1' THEN + o_poly_phase_a<=o_v_poly_phase_a; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_poly_phase_a<=o_h_poly_phase_a; + END IF; + + o_h_poly_phase_a2<=o_h_poly_phase_a; + o_v_poly_phase_a2<=o_v_poly_phase_a; + o_poly_lum1<=o_poly_lum; + + -- C5 / HC5 / VC6 + o_poly_lerp_ta<=signed(to_unsigned(256,10) - resize(o_poly_lum1,10)); + o_poly_lerp_tb<=signed(resize(o_poly_lum1,10)); + + o_poly_phase_b2<=o_poly_phase_b; + o_poly_phase_a2<=o_poly_phase_a; + + o_h_poly_phase_a3<=o_h_poly_phase_a2; + o_v_poly_phase_a3<=o_v_poly_phase_a2; + + -- C6 / HC6 / VC7 + o_poly_phase<=poly_lerp(o_poly_phase_a2, o_poly_phase_b2, o_poly_lerp_ta, o_poly_lerp_tb); + o_h_poly_phase_a4<=o_h_poly_phase_a3; + o_v_poly_phase_a4<=o_v_poly_phase_a3; + + -- C7 / HC7 / VC8 + o_h_poly_phase_a5<=o_h_poly_phase_a4; + o_v_poly_phase_a5<=o_v_poly_phase_a4; + o_poly_phase1<=o_poly_phase; + + -- C8 / HC8 / VC9 + o_v_poly_phase<=poly_cvt(o_v_poly_phase_a5); + o_h_poly_phase<=poly_cvt(o_h_poly_phase_a5); + + IF o_v_poly_use_adaptive = '1' THEN + o_v_poly_phase<=o_poly_phase1; + ELSIF o_h_poly_use_adaptive = '1' THEN + o_h_poly_phase<=o_poly_phase1; + END IF; + + END IF; + END PROCESS PolyFetch; + + + -- Framebuffer palette + GenPal1:IF PALETTE GENERATE + Tempera1:PROCESS(pal1_clk) IS + BEGIN + IF rising_edge(pal1_clk) THEN + IF pal1_wr='1' THEN + pal1_mem(to_integer(pal1_a))<=pal1_dw; + END IF; + pal1_dr<=pal1_mem(to_integer(pal1_a)); + END IF; + END PROCESS; + + pal_idx <= shift_opack(o_acpt4,o_shift,o_dr,o_format)(0 TO 7); + pal_idx_lsb <= pal_idx(0) WHEN rising_edge(o_clk); + o_fb_pal_dr_x2 <= pal1_mem(to_integer(pal_idx(7 DOWNTO 1))) WHEN rising_edge(o_clk); + END GENERATE GenPal1; + + GenPal2:IF PALETTE and PALETTE2 GENERATE + Tempera2:PROCESS(pal2_clk) IS + BEGIN + IF rising_edge(pal2_clk) THEN + IF pal2_wr='1' THEN + pal2_mem(to_integer(pal2_a))<=pal2_dw; + END IF; + pal2_dr<=pal2_mem(to_integer(pal2_a)); + END IF; + END PROCESS; + + o_fb_pal_dr2 <= pal2_mem(to_integer(pal_idx(7 DOWNTO 0))) WHEN rising_edge(o_clk); + o_fb_pal_dr <= o_fb_pal_dr2 when pal_n = '1' else o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal2; + + GenPal1not2:IF PALETTE and not PALETTE2 GENERATE + o_fb_pal_dr <= o_fb_pal_dr_x2(47 DOWNTO 24) WHEN pal_idx_lsb = '1' ELSE o_fb_pal_dr_x2(23 DOWNTO 0); + END GENERATE GenPal1not2; + + GenNoPal:IF NOT PALETTE GENERATE + o_fb_pal_dr<=x"000000"; + END GENERATE GenNoPal; + + ----------------------------------------------------------------------------- + -- Polyphase ROMs + Polikarpov:PROCESS(poly_clk) IS + BEGIN + IF rising_edge(poly_clk) THEN + IF poly_wr='1' THEN + poly_tdw(9+10*(3-to_integer(poly_a(1 DOWNTO 0))) DOWNTO + 10*(3-to_integer(poly_a(1 DOWNTO 0))))<=poly_dw; + END IF; + + poly_wr_mode(0)<=poly_wr AND NOT poly_a(FRAC+2); + poly_wr_mode(1)<=poly_wr AND poly_a(FRAC+2); + poly_wr_mode(2)<=poly_wr AND poly_a(FRAC+3) AND to_std_logic(ADAPTIVE); + poly_a2<=poly_a(FRAC+1 DOWNTO 2); + + CASE poly_wr_mode IS + WHEN "001" => -- horiz + o_h_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='0'; + WHEN "010" => -- vert + o_v_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='0'; + WHEN "101" => -- horiz adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_h_poly_adaptive<='1'; + WHEN "110" => -- vert adaptive + o_a_poly_mem(to_integer(poly_a2))<=poly_tdw; + o_v_poly_adaptive<='1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + END PROCESS Polikarpov; + + ----------------------------------------------------------------------------- + -- Horizontal Scaler + HSCAL:PROCESS(o_clk) IS + VARIABLE div_v : unsigned(20 DOWNTO 0); + VARIABLE dir_v : unsigned(11 DOWNTO 0); + BEGIN + IF rising_edge(o_clk) THEN + -- Pipeline signals + ----------------------------------- + -- Pipelined 8 bits non-restoring divider. Cycle 1 + dir_v:=x"000"; + div_v:=to_unsigned(o_hacc * 256,21); + + div_v:=div_v-to_unsigned(o_hsize*256,21); + dir_v(11):=NOT div_v(20); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*128,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*128,21); + END IF; + dir_v(10):=NOT div_v(20); + + o_div(0)<=div_v; + o_dir(0)<=dir_v; + + -- Cycle 2 + div_v:=o_div(0); + dir_v:=o_dir(0); + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*64,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*64,21); + END IF; + dir_v( 9):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*32,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*32,21); + END IF; + dir_v( 8):=NOT div_v(20); + + o_div(1)<=div_v; + o_dir(1)<=dir_v; + + -- Cycle 3 + div_v:=o_div(1); + dir_v:=o_dir(1); + IF FRAC>4 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*16,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*16,21); + END IF; + dir_v(7):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*8,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*8,21); + END IF; + dir_v(6):=NOT div_v(20); + END IF; + o_div(2)<=div_v; + o_dir(2)<=dir_v; + + div_v:=o_div(2); + dir_v:=o_dir(2); + IF FRAC>6 THEN + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*4,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*4,21); + END IF; + dir_v(5):=NOT div_v(20); + + IF div_v(20)='0' THEN + div_v:=div_v-to_unsigned(o_hsize*2,21); + ELSE + div_v:=div_v+to_unsigned(o_hsize*2,21); + END IF; + dir_v(4):=NOT div_v(20); + END IF; + + ----------------------------------- + o_hfrac(1)<=dir_v; + o_hfrac(2 TO 9) <= o_hfrac(1 TO 8); + + o_copyv(1 TO 14)<=o_copyv(0 TO 13); + + o_dcptv(1)<=o_dcpt; + IF o_dcptv(1)>=o_hsize THEN + o_copyv(2)<='0'; + END IF; + o_dcptv(2)<=o_dcptv(1) MOD OHRES; + o_dcptv(3 TO 14)<=o_dcptv(2 TO 13); + + -- C2 + o_hpixq(2)<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); + o_hpixq(3 TO 8)<=o_hpixq(2 TO 7); + + -- BILINEAR / SHARP BILINEAR --------------- + -- C7 : Pre-calc Sharp Bilinear + o_h_sbil_t<=sbil_frac1(o_hfrac(6)); + + -- C8 : Select + o_h_bil_frac<=(OTHERS =>'0'); + IF o_hmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_h_bil_frac<=bil_frac(o_hfrac(7)); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_h_bil_frac<=sbil_frac2(o_hfrac(7),o_h_sbil_t); + END IF; + END IF; + + -- C9 : Opposite frac + o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq(8)); + + -- C10 : Bilinear / Sharp Bilinear + o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC); + o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC); + o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC); + + -- BICUBIC ------------------------------------------- + -- C8 : Bicubic coefficients A,B,C,D + -- C8 : Bicubic calc T1 = X.D + C + o_h_bic_abcd1<=bic_calc0(o_hfrac(7),o_hpixq(6)); + o_h_bic_tt1<=bic_calc1(o_hfrac(7), + bic_calc0(o_hfrac(7),o_hpixq(6))); + + -- C9 : Bicubic calc T2 = X.T1 + B + o_h_bic_abcd2<=o_h_bic_abcd1; + o_h_bic_tt2<=bic_calc2(o_hfrac(8),o_h_bic_tt1,o_h_bic_abcd1); + + -- C10 : Bicubic final Y = X.T2 + A + o_h_bic_pix<=bic_calc3(o_hfrac(9),o_h_bic_tt2,o_h_bic_abcd2); + + -- POLYPHASE ----------------------------------------- + -- C2 + IF o_hfrac(2)(o_hfrac(2)'left)='0' THEN + o_h_lum_pix<=o_hpix2; + ELSE + o_h_lum_pix<=o_hpix1; + END IF; + + -- C3-C8 in PolyFetch + + -- C9 : Apply Polyphase + o_h_poly_t<=poly_calc(o_h_poly_phase,o_hpixq(8)); + + -- C10 : Sum and bound + o_h_poly_pix<=poly_final(o_h_poly_t); + + -- C11 : Select interpoler ---------------------------- + o_wadl<=o_dcptv(14); + o_wr<=o_altx AND (o_copyv(14) & o_copyv(14) & o_copyv(14) & o_copyv(14)); + o_ldw<=(x"00",x"00",x"00"); + + CASE o_hmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_ldw<=o_h_bil_pix; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_ldw<=o_h_bic_pix; + END IF; + WHEN OTHERS => -- PolyPhase + IF MASK(MASK_POLY)='1' THEN + o_ldw<=o_h_poly_pix; + END IF; + END CASE; + ------------------------------------------------------ + END IF; + END PROCESS HSCAL; + + ----------------------------------------------------------------------------- + -- Line buffers 4 x OHRES x (R+G+B) + OLBUF:PROCESS(o_clk) IS + BEGIN + IF rising_edge(o_clk) THEN + -- WRITES + IF o_wr(0)='1' THEN o_line0(o_wadl)<=o_ldw; END IF; + IF o_wr(1)='1' THEN o_line1(o_wadl)<=o_ldw; END IF; + IF o_wr(2)='1' THEN o_line2(o_wadl)<=o_ldw; END IF; + IF o_wr(3)='1' THEN o_line3(o_wadl)<=o_ldw; END IF; + + -- READS + o_ldr0<=o_line0(o_radl0); + o_ldr1<=o_line1(o_radl1); + o_ldr2<=o_line2(o_radl2); + o_ldr3<=o_line3(o_radl3); + END IF; + END PROCESS OLBUF; + + ----------------------------------------------------------------------------- + -- Output video sweep + OSWEEP:PROCESS(o_clk) IS + BEGIN + IF rising_edge(o_clk) THEN + + IF o_ce='1' THEN + -- Output pixels count + IF o_hcpt+1=o_vtotal THEN + o_vcpt_pre3<=0; + ELSIF o_vrr_sync2 THEN + o_vcpt_pre3<=o_vsstart; + o_sync<=false; + ELSE + o_vcpt_pre3<=(o_vcpt_pre3+1) MOD 4096; + END IF; + + o_vcpt_pre2<=o_vcpt_pre3; + o_vcpt_pre<=o_vcpt_pre2; + o_vcpt<=o_vcpt_pre; + END IF; + + o_end(0)<=to_std_logic(o_vcpt>=o_vdisp); + o_dev(0)<=to_std_logic(o_hcpt=o_hmin AND o_hcpt<=o_hmax AND + o_vcpt>=o_vmin AND o_vcpt<=o_vmax); + o_hsv(0)<=to_std_logic(o_hcpt>=o_hsstart AND o_hcpt=o_hsstart) OR + (o_vcpt>o_vsstart AND o_vcpt=o_vmin AND o_vcpt_pre2<=o_vmax); + o_hsv(1 TO 11)<=o_hsv(0 TO 10); + o_vsv(1 TO 11)<=o_vsv(0 TO 10); + o_dev(1 TO 11)<=o_dev(0 TO 10); + o_pev(1 TO 11)<=o_pev(0 TO 10); + o_end(1 TO 11)<=o_end(0 TO 10); + + IF o_run='0' THEN + o_hsv(2)<='0'; + o_vsv(2)<='0'; + o_dev(2)<='0'; + o_pev(2)<='0'; + o_end(2)<='0'; + END IF; + END IF; + + o_vcpt_sync2<=o_vcpt_sync; + o_vrr_min<=(o_vcpt_sync2=o_vdisp AND o_vcpt2 o_radl1<=r2_v; + WHEN "11" => o_radl2<=r2_v; + WHEN "00" => o_radl3<=r2_v; + WHEN OTHERS => o_radl0<=r2_v; + END CASE; + ELSE + CASE o_vacptl IS + WHEN "10" => o_radl2<=r2_v; + WHEN "11" => o_radl3<=r2_v; + WHEN "00" => o_radl0<=r2_v; + WHEN OTHERS => o_radl1<=r2_v; + END CASE; + END IF; + + -- CYCLE 2 ----------------------------------------- + -- Lines reordering + CASE o_vacptl IS + WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); + WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); + WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); + WHEN OTHERS => pixq_v:=(o_ldr3,o_ldr0,o_ldr1,o_ldr2); + END CASE; + + IF fracnn_v = '0' THEN + o_vpix_outer<=(pixq_v(0), pixq_v(2), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(1); + ELSE + o_vpix_outer<=(pixq_v(0), pixq_v(1), pixq_v(3)); + o_vpix_inner(0)<=pixq_v(2); + END IF; + + -- CYCLE 3-7 + o_vpix_inner(1 TO 5)<=o_vpix_inner(0 TO 4); + + -- CYCLE 8 + IF to_integer(o_vacpt)>o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_inner(5), o_vpix_inner(5)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_outer(1), o_vpix_outer(1)); + END IF; + ELSIF to_integer(o_vacpt)=o_ivsize THEN + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(1)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_inner(5)); + END IF; + ELSE + IF fracnn_v = '0' THEN + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_inner(5), o_vpix_outer(1), o_vpix_outer(2)); + ELSE + o_vpixq_pre<=(o_vpix_outer(0), o_vpix_outer(1), o_vpix_inner(5), o_vpix_outer(2)); + END IF; + END IF; + + -- CYCLE 9 + o_vpixq<=o_vpixq_pre; + + -- BILINEAR / SHARP BILINEAR ----------------------- + -- C8 : Pre-calc Sharp Bilinear + o_v_sbil_t<=sbil_frac1(o_vfrac); + + -- C9 : Select + o_v_bil_frac<=(OTHERS =>'0'); + IF o_vmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_v_bil_frac<=bil_frac(o_vfrac); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); + END IF; + END IF; + + -- C10 : + o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq); + + -- C11 : Nearest / Bilinear / Sharp Bilinear + o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC); + o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC); + o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC); + + -- BICUBIC ----------------------------------------- + -- C9 : Bicubic coefficients A,B,C,D + -- C9 : Bicubic calc T1 = X.D + C + o_v_bic_abcd1<=bic_calc0(o_vfrac,o_vpixq); + o_v_bic_tt1<=bic_calc1(o_vfrac,bic_calc0(o_vfrac,o_vpixq)); + + -- C10 : Bicubic calc T2 = X.T1 + B + o_v_bic_abcd2<=o_v_bic_abcd1; + o_v_bic_tt2<=bic_calc2(o_vfrac,o_v_bic_tt1,o_v_bic_abcd1); + + -- C11 : Bicubic final Y = X.T2 + A + o_v_bic_pix<=bic_calc3(o_vfrac,o_v_bic_tt2,o_v_bic_abcd2); + + -- POLYPHASE --------------------------------------- + -- C3 : Setup luminance + o_v_lum_pix<=o_vpix_inner(0); + + -- C4-C9 in PolyFetch + + -- C10 : Apply polyphase + o_v_poly_t<=poly_calc(o_v_poly_phase,o_vpixq); + + -- C11 : Bound + o_v_poly_pix<=poly_final(o_v_poly_t); + + -- CYCLE 12 ----------------------------------------- + o_hs<=o_hsv(11); + o_vs<=o_vsv(11); + o_de<=o_dev(11); + o_vbl<=o_end(11); + o_r<=x"00"; + o_g<=x"00"; + o_b<=x"00"; + o_brd<= not o_pev(11); + + CASE o_vmode(2 DOWNTO 0) IS + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR + MASK(MASK_SHARP_BILINEAR)='1' THEN + o_r<=o_v_bil_pix.r; + o_g<=o_v_bil_pix.g; + o_b<=o_v_bil_pix.b; + END IF; + WHEN "011" => -- BiCubic + IF MASK(MASK_BICUBIC)='1' THEN + o_r<=o_v_bic_pix.r; + o_g<=o_v_bic_pix.g; + o_b<=o_v_bic_pix.b; + END IF; + + WHEN OTHERS => -- Polyphase + IF MASK(MASK_POLY)='1' THEN + o_r<=o_v_poly_pix.r; + o_g<=o_v_poly_pix.g; + o_b<=o_v_poly_pix.b; + END IF; + END CASE; + + IF o_pev(11)='0' THEN + o_r<=o_border(23 DOWNTO 16); -- Copy border colour + o_g<=o_border(15 DOWNTO 8); + o_b<=o_border(7 DOWNTO 0); + END IF; + + ---------------------------------------------------- + END IF; + END IF; + END PROCESS VSCAL; + + ----------------------------------------------------------------------------- + -- Low Lag syntoniser interface + o_lltune<=(0 => i_vss, + 1 => i_pde, + 2 => i_inter, + 3 => i_flm, + 4 => o_vss, + 5 => i_pce, + 6 => i_clk, + 7 => o_clk, + OTHERS =>'0'); + + ---------------------------------------------------------------------------- +END ARCHITECTURE rtl; diff --git a/sys/audio_out.v b/sys/audio_out.v new file mode 100644 index 0000000..0f748e0 --- /dev/null +++ b/sys/audio_out.v @@ -0,0 +1,296 @@ + +module audio_out +#( + parameter CLK_RATE = 24576000 +) +( + input reset, + input clk, + + //0 - 48KHz, 1 - 96KHz + input sample_rate, + + input [31:0] flt_rate, + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [4:0] att, + input [1:0] mix, + + input is_signed, + input [15:0] core_l, + input [15:0] core_r, + + input [15:0] alsa_l, + input [15:0] alsa_r, + + // I2S + output i2s_bclk, + output i2s_lrclk, + output i2s_data, + + // SPDIF + output spdif, + + // Sigma-Delta DAC + output dac_l, + output dac_r +); + +localparam AUDIO_RATE = 48000; +localparam AUDIO_DW = 16; + +localparam CE_RATE = AUDIO_RATE*AUDIO_DW*8; +localparam FILTER_DIV = (CE_RATE/(AUDIO_RATE*32))-1; + +wire [31:0] real_ce = sample_rate ? {CE_RATE[30:0],1'b0} : CE_RATE[31:0]; + +reg mclk_ce; +always @(posedge clk) begin + reg [31:0] cnt; + + mclk_ce = 0; + cnt = cnt + real_ce; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + mclk_ce = 1; + end +end + +reg i2s_ce; +always @(posedge clk) begin + reg div; + i2s_ce <= 0; + if(mclk_ce) begin + div <= ~div; + i2s_ce <= div; + end +end + +i2s i2s +( + .reset(reset), + + .clk(clk), + .ce(i2s_ce), + + .sclk(i2s_bclk), + .lrclk(i2s_lrclk), + .sdata(i2s_data), + + .left_chan(al), + .right_chan(ar) +); + +spdif toslink +( + .rst_i(reset), + + .clk_i(clk), + .bit_out_en_i(mclk_ce), + + .sample_i({ar,al}), + .spdif_o(spdif) +); + +sigma_delta_dac #(15) sd_l +( + .CLK(clk), + .RESET(reset), + .DACin({~al[15], al[14:0]}), + .DACout(dac_l) +); + +sigma_delta_dac #(15) sd_r +( + .CLK(clk), + .RESET(reset), + .DACin({~ar[15], ar[14:0]}), + .DACout(dac_r) +); + +reg sample_ce; +always @(posedge clk) begin + reg [8:0] div = 0; + reg [1:0] add = 0; + + div <= div + add; + if(!div) begin + div <= 2'd1 << sample_rate; + add <= 2'd1 << sample_rate; + end + + sample_ce <= !div; +end + +reg flt_ce; +always @(posedge clk) begin + reg [31:0] cnt = 0; + + flt_ce = 0; + cnt = cnt + {flt_rate[30:0],1'b0}; + if(cnt >= CLK_RATE) begin + cnt = cnt - CLK_RATE; + flt_ce = 1; + end +end + +reg [15:0] cl,cr; +always @(posedge clk) begin + reg [15:0] cl1,cl2; + reg [15:0] cr1,cr2; + + cl1 <= core_l; cl2 <= cl1; + if(cl2 == cl1) cl <= cl2; + + cr1 <= core_r; cr2 <= cr1; + if(cr2 == cr1) cr <= cr2; +end + +reg a_en1 = 0, a_en2 = 0; +always @(posedge clk, posedge reset) begin + reg [1:0] dly1 = 0; + reg [14:0] dly2 = 0; + + if(reset) begin + dly1 <= 0; + dly2 <= 0; + a_en1 <= 0; + a_en2 <= 0; + end + else begin + if(flt_ce) begin + if(~&dly1) dly1 <= dly1 + 1'd1; + else a_en1 <= 1; + end + + if(sample_ce) begin + if(!dly2[13+sample_rate]) dly2 <= dly2 + 1'd1; + else a_en2 <= 1; + end + end +end + +wire [15:0] acl, acr; +IIR_filter #(.use_params(0)) IIR_filter +( + .clk(clk), + .reset(reset), + + .ce(flt_ce & a_en1), + .sample_ce(sample_ce), + + .cx(cx), + .cx0(cx0), + .cx1(cx1), + .cx2(cx2), + .cy0(cy0), + .cy1(cy1), + .cy2(cy2), + + .input_l({~is_signed ^ cl[15], cl[14:0]}), + .input_r({~is_signed ^ cr[15], cr[14:0]}), + .output_l(acl), + .output_r(acr) +); + +wire [15:0] adl; +DC_blocker dcb_l +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acl), + .dout(adl) +); + +wire [15:0] adr; +DC_blocker dcb_r +( + .clk(clk), + .ce(sample_ce), + .sample_rate(sample_rate), + .mute(~a_en2), + .din(acr), + .dout(adr) +); + +wire [15:0] al, audio_l_pre; +aud_mix_top audmix_l +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adl), + .pre_in(audio_r_pre), + .linux_audio(alsa_l), + + .pre_out(audio_l_pre), + .out(al) +); + +wire [15:0] ar, audio_r_pre; +aud_mix_top audmix_r +( + .clk(clk), + .ce(sample_ce), + .att(att), + .mix(mix), + + .core_audio(adr), + .pre_in(audio_l_pre), + .linux_audio(alsa_r), + + .pre_out(audio_r_pre), + .out(ar) +); + +endmodule + +module aud_mix_top +( + input clk, + input ce, + + input [4:0] att, + input [1:0] mix, + + input [15:0] core_audio, + input [15:0] linux_audio, + input [15:0] pre_in, + + output reg [15:0] pre_out = 0, + output reg [15:0] out = 0 +); + +reg signed [16:0] a1, a2, a3, a4; +always @(posedge clk) if (ce) begin + + a1 <= {core_audio[15],core_audio}; + a2 <= a1 + {linux_audio[15],linux_audio}; + + pre_out <= a2[16:1]; + + case(mix) + 0: a3 <= a2; + 1: a3 <= $signed(a2) - $signed(a2[16:3]) + $signed(pre_in[15:2]); + 2: a3 <= $signed(a2) - $signed(a2[16:2]) + $signed(pre_in[15:1]); + 3: a3 <= {a2[16],a2[16:1]} + {pre_in[15],pre_in}; + endcase + + if(att[4]) a4 <= 0; + else a4 <= a3 >>> att[3:0]; + + //clamping + out <= ^a4[16:15] ? {a4[16],{15{a4[15]}}} : a4[15:0]; +end + +endmodule diff --git a/sys/build_id.tcl b/sys/build_id.tcl new file mode 100644 index 0000000..bb2dc67 --- /dev/null +++ b/sys/build_id.tcl @@ -0,0 +1,73 @@ + +# Build TimeStamp Verilog Module +# Jeff Wiencrot - 8/1/2011 +# Sorgelig - 02/11/2019 +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate "`define BUILD_DATE \"[clock format [ clock seconds ] -format %y%m%d]\"" + + # Create a Verilog file for output + set outputFileName "build_id.v" + + set fileData "" + if { [file exists $outputFileName]} { + set outputFile [open $outputFileName "r"] + set fileData [read $outputFile] + close $outputFile + } + + if {$buildDate ne $fileData} { + set outputFile [open $outputFileName "w"] + puts -nonewline $outputFile $buildDate + close $outputFile + # Send confirmation message to the Messages window + post_message "Generated: [pwd]/$outputFileName: $buildDate" + } +} + +# Build CDF file +# Sorgelig - 17/2/2018 +proc generateCDF {revision device outpath} { + + set outputFileName "jtag.cdf" + set outputFile [open $outputFileName "w"] + + puts $outputFile "JedecChain;" + puts $outputFile " FileRevision(JESD32A);" + puts $outputFile " DefaultMfr(6E);" + puts $outputFile "" + puts $outputFile " P ActionCode(Ign)" + puts $outputFile " Device PartName(SOCVHPS) MfrSpec(OpMask(0));" + puts $outputFile " P ActionCode(Cfg)" + puts $outputFile " Device PartName($device) Path(\"$outpath/\") File(\"$revision.sof\") MfrSpec(OpMask(1));" + puts $outputFile "ChainEnd;" + puts $outputFile "" + puts $outputFile "AlteraBegin;" + puts $outputFile " ChainType(JTAG);" + puts $outputFile "AlteraEnd;" +} + +set project_name [lindex $quartus(args) 1] +set revision [lindex $quartus(args) 2] + +if {[project_exists $project_name]} { + if {[string equal "" $revision]} { + project_open $project_name -revision [get_current_revision $project_name] + } else { + project_open $project_name -revision $revision + } +} else { + post_message -type error "Project $project_name does not exist" + exit +} + +set device [get_global_assignment -name DEVICE] +set outpath [get_global_assignment -name PROJECT_OUTPUT_DIRECTORY] + +if [is_project_open] { + project_close +} + +generateBuildID_Verilog +generateCDF $revision $device $outpath diff --git a/sys/ddr_svc.sv b/sys/ddr_svc.sv new file mode 100644 index 0000000..abcd4fa --- /dev/null +++ b/sys/ddr_svc.sv @@ -0,0 +1,108 @@ +// +// Copyright (c) 2020 Alexey Melnikov +// +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ------------------------------------------ +// + +// 16-bit version + +module ddr_svc +( + input clk, + + input ram_waitrequest, + output [7:0] ram_burstcnt, + output [28:0] ram_addr, + input [63:0] ram_readdata, + input ram_read_ready, + output reg ram_read, + output [63:0] ram_writedata, + output [7:0] ram_byteenable, + output reg ram_write, + + output [7:0] ram_bcnt, + + input [31:3] ch0_addr, + input [7:0] ch0_burst, + output [63:0] ch0_data, + input ch0_req, + output ch0_ready, + + input [31:3] ch1_addr, + input [7:0] ch1_burst, + output [63:0] ch1_data, + input ch1_req, + output ch1_ready +); + +assign ram_burstcnt = ram_burst; +assign ram_byteenable = 8'hFF; +assign ram_addr = ram_address; +assign ram_writedata = 0; + +assign ch0_data = ram_q[0]; +assign ch1_data = ram_q[1]; +assign ch0_ready = ready[0]; +assign ch1_ready = ready[1]; + +reg [7:0] ram_burst; +reg [63:0] ram_q[2]; +reg [31:3] ram_address; +reg [1:0] ack = 0; +reg [1:0] ready; +reg state = 0; +reg ch = 0; + +always @(posedge clk) begin + ready <= 0; + + if(!ram_waitrequest) begin + ram_read <= 0; + ram_write <= 0; + + case(state) + 0: if(ch0_req != ack[0]) begin + ack[0] <= ch0_req; + ram_address <= ch0_addr; + ram_burst <= ch0_burst; + ram_read <= 1; + ch <= 0; + ram_bcnt <= 8'hFF; + state <= 1; + end + else if(ch1_req != ack[1]) begin + ack[1] <= ch1_req; + ram_address <= ch1_addr; + ram_burst <= ch1_burst; + ram_read <= 1; + ch <= 1; + ram_bcnt <= 8'hFF; + state <= 1; + end + 1: begin + if(ram_read_ready) begin + ram_bcnt <= ram_bcnt + 1'd1; + ram_q[ch] <= ram_readdata; + ready[ch] <= 1; + if ((ram_bcnt+2'd2) == ram_burst) state <= 0; + end + end + endcase + end +end + +endmodule diff --git a/sys/f2sdram_safe_terminator.sv b/sys/f2sdram_safe_terminator.sv new file mode 100644 index 0000000..07085d7 --- /dev/null +++ b/sys/f2sdram_safe_terminator.sv @@ -0,0 +1,250 @@ +// ============================================================================ +// +// f2sdram_safe_terminator for MiSTer platform +// +// ============================================================================ +// Copyright (c) 2021 bellwood420 +// +// Background: +// +// Terminating a transaction of burst writing(/reading) in its midstream +// seems to cause an illegal state to f2sdram interface. +// +// Forced reset request that occurs when loading other core is inevitable. +// +// So if it happens exactly within the transaction period, +// unexpected issues with accessing to f2sdram interface will be caused +// in next loaded core. +// +// It seems that only way to reset broken f2sdram interface is to reset +// whole SDRAM Controller Subsystem from HPS via permodrst register +// in Reset Manager. +// But it cannot be done safely while Linux is running. +// It is usually done when cold or warm reset is issued in HPS. +// +// Main_MiSTer is issuing reset for FPGA <> HPS bridges +// via brgmodrst register in Reset Manager when loading rbf. +// But it has no effect on f2sdram interface. +// f2sdram interface seems to belong to SDRAM Controller Subsystem +// rather than FPGA-to-HPS bridge. +// +// Main_MiSTer is also trying to issuing reset for f2sdram ports +// via fpgaportrst register in SDRAM Controller Subsystem when loading rbf. +// But according to the Intel's document, fpgaportrst register can be +// used to stretch the port reset. +// It seems that it cannot be used to assert the port reset. +// +// According to the Intel's document, there seems to be a reset port on +// Avalon-MM slave interface, but it cannot be found in Qsys generated HDL. +// +// To conclude, the only thing FPGA can do is not to break the transaction. +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +// Purpose: +// To prevent the issue, this module completes ongoing transaction +// on behalf of user logic, when reset is asserted. +// +// Usage: +// Insert this module into the bus line between +// f2sdram (Avalon-MM slave) and user logic (Avalon-MM master). +// +// Notice: +// Asynchronous reset request is not supported. +// Please feed reset request synchronized to clock. +// +module f2sdram_safe_terminator #( + parameter DATA_WIDTH = 64, + parameter BURSTCOUNT_WIDTH = 8 +) ( + // clk should be the same as one provided to f2sdram port + // clk should not be stop when reset is asserted + input clk, + // rst_req_sync should be synchronized to clk + // Asynchronous reset request is not supported + input rst_req_sync, + + // Master port: connecting to Alavon-MM slave(f2sdram) + input waitrequest_master, + output [BURSTCOUNT_WIDTH-1:0] burstcount_master, + output [ADDRESS_WITDH-1:0] address_master, + input [DATA_WIDTH-1:0] readdata_master, + input readdatavalid_master, + output read_master, + output [DATA_WIDTH-1:0] writedata_master, + output [BYTEENABLE_WIDTH-1:0] byteenable_master, + output write_master, + + // Slave port: connecting to Alavon-MM master(user logic) + output waitrequest_slave, + input [BURSTCOUNT_WIDTH-1:0] burstcount_slave, + input [ADDRESS_WITDH-1:0] address_slave, + output [DATA_WIDTH-1:0] readdata_slave, + output readdatavalid_slave, + input read_slave, + input [DATA_WIDTH-1:0] writedata_slave, + input [BYTEENABLE_WIDTH-1:0] byteenable_slave, + input write_slave +); + +localparam BYTEENABLE_WIDTH = DATA_WIDTH/8; +localparam ADDRESS_WITDH = 32-$clog2(BYTEENABLE_WIDTH); + +/* +* Capture init reset deaseert +*/ +reg init_reset_deasserted = 1'b0; + +always_ff @(posedge clk) begin + if (!rst_req_sync) begin + init_reset_deasserted <= 1'b1; + end +end + +/* +* Lock stage +*/ +reg lock_stage = 1'b0; + +always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + lock_stage <= 1'b1; + end + end + else begin + // Reset deassert + lock_stage <= 1'b0; + end +end + +/* +* Write burst transaction observer +*/ +reg state_write = 1'b0; +wire next_state_write; + +wire burst_write_start = !state_write && next_state_write; +wire valid_write_data = state_write && !waitrequest_master; +wire burst_write_end = state_write && (write_burstcounter == write_burstcount_latch - 1'd1); +wire valid_non_burst_write = !state_write && write_slave && (burstcount_slave == 1) && !waitrequest_master; + +reg [BURSTCOUNT_WIDTH-1:0] write_burstcounter = 0; +reg [BURSTCOUNT_WIDTH-1:0] write_burstcount_latch = 0; +reg [ADDRESS_WITDH-1:0] write_address_latch = 0; + +always_ff @(posedge clk) begin + state_write <= next_state_write; + + if (burst_write_start) begin + write_burstcounter <= waitrequest_master ? 1'd0 : 1'd1; + write_burstcount_latch <= burstcount_slave; + write_address_latch <= address_slave; + end + else if (valid_write_data) begin + write_burstcounter <= write_burstcounter + 1'd1; + end +end + +always_comb begin + if (!state_write) begin + if (valid_non_burst_write) + next_state_write = 1'b0; + else if (write_slave) + next_state_write = 1'b1; + else + next_state_write = 1'b0; + end + else begin + if (burst_write_end) + next_state_write = 1'b0; + else + next_state_write = 1'b1; + end +end + +reg [BURSTCOUNT_WIDTH-1:0] write_terminate_counter = 0; +reg [BURSTCOUNT_WIDTH-1:0] burstcount_latch = 0; +reg [ADDRESS_WITDH-1:0] address_latch = 0; + +reg terminating = 0; +reg read_terminating = 0; +reg write_terminating = 0; + +wire on_write_transaction = state_write && next_state_write; +wire on_start_write_transaction = !state_write && next_state_write; + +always_ff @(posedge clk) begin + if (rst_req_sync) begin + // Reset assert + if (init_reset_deasserted) begin + if (!lock_stage) begin + // Even not knowing reading is in progress or not, + // if it is in progress, it will finish at some point, and no need to do anything. + // Assume that reading is in progress when we are not on write transaction. + burstcount_latch <= burstcount_slave; + address_latch <= address_slave; + terminating <= 1; + + if (on_write_transaction) begin + write_terminating <= 1; + burstcount_latch <= write_burstcount_latch; + address_latch <= write_address_latch; + write_terminate_counter <= waitrequest_master ? write_burstcounter : write_burstcounter + 1'd1; + end + else if (on_start_write_transaction) begin + if (!valid_non_burst_write) begin + write_terminating <= 1; + write_terminate_counter <= waitrequest_master ? 1'd0 : 1'd1; + end + end + else if (read_slave && waitrequest_master) begin + // Need to keep read signal, burstcount and address until waitrequest_master deasserted + read_terminating <= 1; + end + end + else if (!waitrequest_master) begin + read_terminating <= 0; + end + end + end + else begin + // Reset deassert + if (!write_terminating) terminating <= 0; + read_terminating <= 0; + end + + if (write_terminating) begin + // Continue write transaction until the end + if (!waitrequest_master) write_terminate_counter <= write_terminate_counter + 1'd1; + if (write_terminate_counter == burstcount_latch - 1'd1) write_terminating <= 0; + end +end + +/* +* Bus mux depending on the stage. +*/ +always_comb begin + if (terminating) begin + burstcount_master = burstcount_latch; + address_master = address_latch; + read_master = read_terminating; + write_master = write_terminating; + byteenable_master = 0; + end + else begin + burstcount_master = burstcount_slave; + address_master = address_slave; + read_master = read_slave; + byteenable_master = byteenable_slave; + write_master = write_slave; + end +end + +// Just passing master <-> slave +assign writedata_master = writedata_slave; +assign readdata_slave = readdata_master; +assign readdatavalid_slave = readdatavalid_master; +assign waitrequest_slave = waitrequest_master; + +endmodule diff --git a/sys/gamma_corr.sv b/sys/gamma_corr.sv new file mode 100644 index 0000000..321b83f --- /dev/null +++ b/sys/gamma_corr.sv @@ -0,0 +1,124 @@ +module gamma_corr +( + input clk_sys, + input clk_vid, + input ce_pix, + input gamma_en, + input gamma_wr, + input [9:0] gamma_wr_addr, + input [7:0] gamma_value, + input HSync, + input VSync, + input HBlank, + input VBlank, + input [23:0] RGB_in, + output reg HSync_out, + output reg VSync_out, + output reg HBlank_out, + output reg VBlank_out, + output reg [23:0] RGB_out +); + +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve[768]; + +always @(posedge clk_sys) if (gamma_wr) gamma_curve[gamma_wr_addr] <= gamma_value; +always @(posedge clk_vid) gamma <= gamma_curve[gamma_index]; + +reg [9:0] gamma_index; +reg [7:0] gamma; + +always @(posedge clk_vid) begin + reg [7:0] R_in, G_in, B_in; + reg [7:0] R_gamma, G_gamma; + reg hs,vs,hb,vb; + reg [1:0] ctr = 0; + reg old_ce; + + old_ce <= ce_pix; + if(~old_ce & ce_pix) begin + {R_in,G_in,B_in} <= RGB_in; + hs <= HSync; vs <= VSync; + hb <= HBlank; vb <= VBlank; + + RGB_out <= gamma_en ? {R_gamma,G_gamma,gamma} : {R_in,G_in,B_in}; + HSync_out <= hs; VSync_out <= vs; + HBlank_out <= hb; VBlank_out <= vb; + + ctr <= 1; + gamma_index <= {2'b00,RGB_in[23:16]}; + end + + if (|ctr) ctr <= ctr + 1'd1; + + case(ctr) + 1: begin gamma_index <= {2'b01,G_in}; end + 2: begin R_gamma <= gamma; gamma_index <= {2'b10,B_in}; end + 3: begin G_gamma <= gamma; end + endcase +end + +endmodule + +module gamma_fast +( + input clk_vid, + input ce_pix, + + inout [21:0] gamma_bus, + + input HSync, + input VSync, + input HBlank, + input VBlank, + input DE, + input [23:0] RGB_in, + + output reg HSync_out, + output reg VSync_out, + output reg HBlank_out, + output reg VBlank_out, + output reg DE_out, + output reg [23:0] RGB_out +); + +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_r[256]; +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_g[256]; +(* ramstyle="no_rw_check" *) reg [7:0] gamma_curve_b[256]; + +assign gamma_bus[21] = 1; +wire clk_sys = gamma_bus[20]; +wire gamma_en = gamma_bus[19]; +wire gamma_wr = gamma_bus[18]; +wire [9:0] gamma_wr_addr = gamma_bus[17:8]; +wire [7:0] gamma_value = gamma_bus[7:0]; + +always @(posedge clk_sys) if (gamma_wr) begin + case(gamma_wr_addr[9:8]) + 0: gamma_curve_r[gamma_wr_addr[7:0]] <= gamma_value; + 1: gamma_curve_g[gamma_wr_addr[7:0]] <= gamma_value; + 2: gamma_curve_b[gamma_wr_addr[7:0]] <= gamma_value; + endcase +end + +reg [7:0] gamma_index_r,gamma_index_g,gamma_index_b; + +always @(posedge clk_vid) begin + reg [7:0] R_in, G_in, B_in; + reg [7:0] R_gamma, G_gamma; + reg hs,vs,hb,vb,de; + + if(ce_pix) begin + {gamma_index_r,gamma_index_g,gamma_index_b} <= RGB_in; + hs <= HSync; vs <= VSync; + hb <= HBlank; vb <= VBlank; + de <= DE; + + RGB_out <= gamma_en ? {gamma_curve_r[gamma_index_r],gamma_curve_g[gamma_index_g],gamma_curve_b[gamma_index_b]} + : {gamma_index_r,gamma_index_g,gamma_index_b}; + HSync_out <= hs; VSync_out <= vs; + HBlank_out <= hb; VBlank_out <= vb; + DE_out <= de; + end +end + +endmodule diff --git a/sys/hps_io.sv b/sys/hps_io.sv new file mode 100644 index 0000000..4fac671 --- /dev/null +++ b/sys/hps_io.sv @@ -0,0 +1,1039 @@ +// +// hps_io.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2017-2020 Alexey Melnikov +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// +// altera message_off 10665 + +// +// Use buffer to access SD card. It's time-critical part. +// +// WIDE=1 for 16 bit file I/O +// VDNUM 1..10 +// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384 +// +module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0) +( + input clk_sys, + inout [48:0] HPS_BUS, + + // buttons up to 32 + output reg [31:0] joystick_0, + output reg [31:0] joystick_1, + output reg [31:0] joystick_2, + output reg [31:0] joystick_3, + output reg [31:0] joystick_4, + output reg [31:0] joystick_5, + + // analog -127..+127, Y: [15:8], X: [7:0] + output reg [15:0] joystick_l_analog_0, + output reg [15:0] joystick_l_analog_1, + output reg [15:0] joystick_l_analog_2, + output reg [15:0] joystick_l_analog_3, + output reg [15:0] joystick_l_analog_4, + output reg [15:0] joystick_l_analog_5, + + output reg [15:0] joystick_r_analog_0, + output reg [15:0] joystick_r_analog_1, + output reg [15:0] joystick_r_analog_2, + output reg [15:0] joystick_r_analog_3, + output reg [15:0] joystick_r_analog_4, + output reg [15:0] joystick_r_analog_5, + + input [15:0] joystick_0_rumble, // 15:8 - 'large' rumble motor magnitude, 7:0 'small' rumble motor magnitude + input [15:0] joystick_1_rumble, + input [15:0] joystick_2_rumble, + input [15:0] joystick_3_rumble, + input [15:0] joystick_4_rumble, + input [15:0] joystick_5_rumble, + + // paddle 0..255 + output reg [7:0] paddle_0, + output reg [7:0] paddle_1, + output reg [7:0] paddle_2, + output reg [7:0] paddle_3, + output reg [7:0] paddle_4, + output reg [7:0] paddle_5, + + // spinner [7:0] -128..+127, [8] - toggle with every update + output reg [8:0] spinner_0, + output reg [8:0] spinner_1, + output reg [8:0] spinner_2, + output reg [8:0] spinner_3, + output reg [8:0] spinner_4, + output reg [8:0] spinner_5, + + // ps2 keyboard emulation + output ps2_kbd_clk_out, + output ps2_kbd_data_out, + input ps2_kbd_clk_in, + input ps2_kbd_data_in, + + input [2:0] ps2_kbd_led_status, + input [2:0] ps2_kbd_led_use, + + output ps2_mouse_clk_out, + output ps2_mouse_data_out, + input ps2_mouse_clk_in, + input ps2_mouse_data_in, + + // ps2 alternative interface. + + // [8] - extended, [9] - pressed, [10] - toggles with every press/release + output reg [10:0] ps2_key = 0, + + // [24] - toggles with every event + output reg [24:0] ps2_mouse = 0, + output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements + + output [1:0] buttons, + output forced_scandoubler, + output direct_video, + input video_rotated, + + //toggle to force notify of video mode change + input new_vmode, + + inout [21:0] gamma_bus, + + output reg [127:0] status, + input [127:0] status_in, + input status_set, + input [15:0] status_menumask, + + input info_req, + input [7:0] info, + + // SD config + output reg [VD:0] img_mounted, // signaling that new image has been mounted + output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted + output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted + + // SD block level access + input [31:0] sd_lba[VDNUM], + input [5:0] sd_blk_cnt[VDNUM], // number of blocks-1, total size ((sd_blk_cnt+1)*(1<<(BLKSZ+7))) must be <= 16384! + input [VD:0] sd_rd, + input [VD:0] sd_wr, + output reg [VD:0] sd_ack, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [AW:0] sd_buff_addr, + output reg [DW:0] sd_buff_dout, + input [DW:0] sd_buff_din[VDNUM], + output reg sd_buff_wr, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [15:0] ioctl_index, // menu index used to upload the file + output reg ioctl_wr, + output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2 + output reg [DW:0] ioctl_dout, + output reg ioctl_upload = 0, // signal indicating an active upload + input ioctl_upload_req, // request to save (must be supported on HPS side for specific core) + input [7:0] ioctl_upload_index, + input [DW:0] ioctl_din, + output reg ioctl_rd, + output reg [31:0] ioctl_file_ext, + input ioctl_wait, + + // [15]: 0 - unset, 1 - set. [1:0]: 0 - none, 1 - 32MB, 2 - 64MB, 3 - 128MB + // [14]: debug mode: [8]: 1 - phase up, 0 - phase down. [7:0]: amount of shift. + output reg [15:0] sdram_sz, + + // RTC MSM6242B layout + output reg [64:0] RTC, + + // Seconds since 1970-01-01 00:00:00 + output reg [32:0] TIMESTAMP, + + // UART flags + output reg [7:0] uart_mode, + output reg [31:0] uart_speed, + + // for core-specific extensions + inout [35:0] EXT_BUS +); + +assign EXT_BUS[31:16] = HPS_BUS[31:16]; +assign EXT_BUS[35:33] = HPS_BUS[35:33]; + +localparam DW = (WIDE) ? 15 : 7; +localparam AW = (WIDE) ? 12 : 13; +localparam VD = VDNUM-1; + +wire io_strobe= HPS_BUS[33]; +wire io_enable= HPS_BUS[34]; +wire fp_enable= HPS_BUS[35]; +wire io_wide = (WIDE) ? 1'b1 : 1'b0; +wire [15:0] io_din = HPS_BUS[31:16]; +reg [15:0] io_dout; + +assign HPS_BUS[37] = ioctl_wait; +assign HPS_BUS[36] = clk_sys; +assign HPS_BUS[32] = io_wide; +assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : fp_enable ? fp_dout : io_dout; + +reg [15:0] cfg; +assign buttons = cfg[1:0]; +//cfg[2] - vga_scaler handled in sys_top +//cfg[3] - csync handled in sys_top +assign forced_scandoubler = cfg[4]; +//cfg[5] - ypbpr handled in sys_top +assign direct_video = cfg[10]; + +reg [3:0] sdn; +reg [3:0] sd_rrb = 0; +always_comb begin + int n, i; + + sdn = 0; + for(i = VDNUM - 1; i >= 0; i = i - 1) begin + n = i + sd_rrb; + if(n >= VDNUM) n = n - VDNUM; + if(sd_wr[n] | sd_rd[n]) sdn = n[3:0]; + end +end + +///////////////////////////////////////////////////////// + +wire [15:0] vc_dout; +video_calc video_calc +( + .clk_100(HPS_BUS[43]), + .clk_vid(HPS_BUS[42]), + .clk_sys(clk_sys), + .ce_pix(HPS_BUS[41]), + .de(HPS_BUS[40]), + .hs(HPS_BUS[39]), + .vs(HPS_BUS[38]), + .vs_hdmi(HPS_BUS[44]), + .f1(HPS_BUS[45]), + .new_vmode(new_vmode), + .video_rotated(video_rotated), + + .par_num(byte_cnt[4:0]), + .dout(vc_dout) +); + +///////////////////////////////////////////////////////// + +localparam STRLEN = $size(CONF_STR)>>3; +localparam MAX_W = $clog2((64 > (STRLEN+2)) ? 64 : (STRLEN+2))-1; + +wire [7:0] conf_byte; +generate + if(CONF_STR_BRAM) begin + confstr_rom #(CONF_STR, STRLEN) confstr_rom(.*, .conf_addr(byte_cnt - 1'd1)); + end + else begin + assign conf_byte = CONF_STR[{(STRLEN - byte_cnt),3'b000} +:8]; + end +endgenerate + +assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value}; +reg gamma_en; +reg gamma_wr; +reg [9:0] gamma_wr_addr; +reg [7:0] gamma_value; + +reg [31:0] ps2_key_raw = 0; +wire pressed = (ps2_key_raw[15:8] != 8'hf0); +wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0)); + +reg [MAX_W:0] byte_cnt; +reg [3:0] sdn_ack; +wire [15:0] disk = 16'd1 << io_din[11:8]; + +always@(posedge clk_sys) begin : uio_block + reg [15:0] cmd; + reg [2:0] b_wr; + reg [3:0] stick_idx; + reg [3:0] pdsp_idx; + reg ps2skip = 0; + reg [3:0] stflg = 0; + reg[127:0] status_req; + reg old_status_set = 0; + reg old_upload_req = 0; + reg upload_req = 0; + reg old_info = 0; + reg [7:0] info_n = 0; + reg [15:0] tmp1; + reg [7:0] tmp2; + reg [3:0] sdn_r; + + old_status_set <= status_set; + if(~old_status_set & status_set) begin + stflg <= stflg + 1'd1; + status_req <= status_in; + end + + old_upload_req <= ioctl_upload_req; + if(~old_upload_req & ioctl_upload_req) upload_req <= 1; + + old_info <= info_req; + if(~old_info & info_req) info_n <= info; + + sd_buff_wr <= b_wr[0]; + if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; + b_wr <= (b_wr<<1); + + if(PS2DIV) {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; + + gamma_wr <= 0; + + if(~io_enable) begin + if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24]; + if(cmd == 5 && !ps2skip) begin + ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]}; + if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed + if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released + if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed + end + if(cmd == 'h22) RTC[64] <= ~RTC[64]; + if(cmd == 'h24) TIMESTAMP[32] <= ~TIMESTAMP[32]; + cmd <= 0; + byte_cnt <= 0; + sd_ack <= 0; + io_dout <= 0; + ps2skip <= 0; + img_mounted <= 0; + end + else if(io_strobe) begin + + io_dout <= 0; + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + if(byte_cnt == 0) begin + cmd <= io_din; + + casex(io_din) + 'h16: begin io_dout <= {1'b1, sd_blk_cnt[sdn], BLKSZ[2:0], sdn, sd_wr[sdn], sd_rd[sdn]}; sdn_r <= sdn; end + 'h0X17, + 'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end + 'h29: io_dout <= {4'hA, stflg}; +`ifdef MISTER_DISABLE_ADAPTIVE + 'h2B: io_dout <= {HPS_BUS[48:46],4'b0110}; +`else + 'h2B: io_dout <= {HPS_BUS[48:46],4'b0111}; +`endif + 'h2F: io_dout <= 1; + 'h32: io_dout <= gamma_bus[21]; + 'h36: begin io_dout <= info_n; info_n <= 0; end + 'h39: io_dout <= 1; + 'h3C: if(upload_req) begin io_dout <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end + 'h3E: io_dout <= 1; // shadow mask + 'h003F: io_dout <= joystick_0_rumble; + 'h013F: io_dout <= joystick_1_rumble; + 'h023F: io_dout <= joystick_2_rumble; + 'h033F: io_dout <= joystick_3_rumble; + 'h043F: io_dout <= joystick_4_rumble; + 'h053F: io_dout <= joystick_5_rumble; + endcase + + sd_buff_addr <= 0; + if(io_din == 5) ps2_key_raw <= 0; + end else begin + + casex(cmd) + // buttons and switches + 'h01: cfg <= io_din; + 'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din; + 'h03: if(byte_cnt==1) joystick_1[15:0] <= io_din; else joystick_1[31:16] <= io_din; + 'h10: if(byte_cnt==1) joystick_2[15:0] <= io_din; else joystick_2[31:16] <= io_din; + 'h11: if(byte_cnt==1) joystick_3[15:0] <= io_din; else joystick_3[31:16] <= io_din; + 'h12: if(byte_cnt==1) joystick_4[15:0] <= io_din; else joystick_4[31:16] <= io_din; + 'h13: if(byte_cnt==1) joystick_5[15:0] <= io_din; else joystick_5[31:16] <= io_din; + + // store incoming ps2 mouse bytes + 'h04: begin + if(PS2DIV) begin + mouse_data <= io_din[7:0]; + mouse_we <= 1; + end + if(&io_din[15:8]) ps2skip <= 1; + if(~&io_din[15:8] && ~ps2skip && !byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: ps2_mouse[7:0] <= io_din[7:0]; + 2: ps2_mouse[15:8] <= io_din[7:0]; + 3: ps2_mouse[23:16] <= io_din[7:0]; + endcase + case(byte_cnt[1:0]) + 1: ps2_mouse_ext[7:0] <= {io_din[14], io_din[14:8]}; + 2: ps2_mouse_ext[11:8] <= io_din[11:8]; + 3: ps2_mouse_ext[15:12]<= io_din[11:8]; + endcase + end + end + + // store incoming ps2 keyboard bytes + 'h05: begin + if(&io_din[15:8]) ps2skip <= 1; + if(~&io_din[15:8] & ~ps2skip) ps2_key_raw[31:0] <= {ps2_key_raw[23:0], io_din[7:0]}; + if(PS2DIV) begin + kbd_data <= io_din[7:0]; + kbd_we <= 1; + end + end + + // reading config string, returning a byte from string + 'h14: if(byte_cnt <= STRLEN) io_dout[7:0] <= conf_byte; + + // reading sd card status + 'h16: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: sd_rrb <= (sd_rrb == VD) ? 4'd0 : (sd_rrb + 1'd1); + 2: io_dout <= sd_lba[sdn_r][15:0]; + 3: io_dout <= sd_lba[sdn_r][31:16]; + endcase + end + + // send sector IO -> FPGA + // flag that download begins + 'h0X17: begin + sd_buff_dout <= io_din[DW:0]; + b_wr <= 1; + end + + // reading sd card write data + 'h0X18: begin + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + io_dout <= sd_buff_din[sdn_ack]; + end + + // joystick left analog + 'h1a: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_l_analog_0 <= io_din; + 1: joystick_l_analog_1 <= io_din; + 2: joystick_l_analog_2 <= io_din; + 3: joystick_l_analog_3 <= io_din; + 4: joystick_l_analog_4 <= io_din; + 5: joystick_l_analog_5 <= io_din; + 15: case(pdsp_idx) + 0: paddle_0 <= io_din[7:0]; + 1: paddle_1 <= io_din[7:0]; + 2: paddle_2 <= io_din[7:0]; + 3: paddle_3 <= io_din[7:0]; + 4: paddle_4 <= io_din[7:0]; + 5: paddle_5 <= io_din[7:0]; + 8: spinner_0 <= {~spinner_0[8],io_din[7:0]}; + 9: spinner_1 <= {~spinner_1[8],io_din[7:0]}; + 10: spinner_2 <= {~spinner_2[8],io_din[7:0]}; + 11: spinner_3 <= {~spinner_3[8],io_din[7:0]}; + 12: spinner_4 <= {~spinner_4[8],io_din[7:0]}; + 13: spinner_5 <= {~spinner_5[8],io_din[7:0]}; + endcase + endcase + endcase + end + + // joystick right analog + 'h3d: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: stick_idx <= io_din[3:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_r_analog_0 <= io_din; + 1: joystick_r_analog_1 <= io_din; + 2: joystick_r_analog_2 <= io_din; + 3: joystick_r_analog_3 <= io_din; + 4: joystick_r_analog_4 <= io_din; + 5: joystick_r_analog_5 <= io_din; + endcase + endcase + end + + // notify image selection + 'h1c: begin + img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; + img_readonly <= io_din[7]; + end + + // send image info + 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; + + // status, 128bit version + 'h1e: if(!byte_cnt[MAX_W:4]) begin + case(byte_cnt[3:0]) + 1: status[15:00] <= io_din; + 2: status[31:16] <= io_din; + 3: status[47:32] <= io_din; + 4: status[63:48] <= io_din; + 5: status[79:64] <= io_din; + 6: status[95:80] <= io_din; + 7: status[111:96] <= io_din; + 8: status[127:112] <= io_din; + endcase + end + + // reading keyboard LED status + 'h1f: io_dout <= {|PS2WE, 2'b01, ps2_kbd_led_status[2], ps2_kbd_led_use[2], ps2_kbd_led_status[1], ps2_kbd_led_use[1], ps2_kbd_led_status[0], ps2_kbd_led_use[0]}; + + // reading ps2 keyboard/mouse control + 'h21: if(PS2DIV) begin + if(byte_cnt == 1) begin + io_dout <= kbd_data_host; + kbd_rd <= 1; + end + else + if(byte_cnt == 2) begin + io_dout <= mouse_data_host; + mouse_rd <= 1; + end + end + + //RTC + 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //Video res. + 'h23: if(!byte_cnt[MAX_W:5]) io_dout <= vc_dout; + + //RTC + 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //status set + 'h29: if(!byte_cnt[MAX_W:4]) begin + case(byte_cnt[3:0]) + 1: io_dout <= status_req[15:00]; + 2: io_dout <= status_req[31:16]; + 3: io_dout <= status_req[47:32]; + 4: io_dout <= status_req[63:48]; + 5: io_dout <= status_req[79:64]; + 6: io_dout <= status_req[95:80]; + 7: io_dout <= status_req[111:96]; + 8: io_dout <= status_req[127:112]; + endcase + end + + //menu mask + 'h2E: if(byte_cnt == 1) io_dout <= status_menumask; + + //sdram size set + 'h31: if(byte_cnt == 1) sdram_sz <= io_din; + + // Gamma + 'h32: gamma_en <= io_din[0]; + 'h33: begin + gamma_wr_addr <= {(byte_cnt[1:0]-1'b1),io_din[15:8]}; + {gamma_wr, gamma_value} <= {1'b1,io_din[7:0]}; + if (byte_cnt[1:0] == 3) byte_cnt <= 1; + end + + // UART + 'h3b: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: tmp2 <= io_din[7:0]; + 2: tmp1 <= io_din; + 3: {uart_speed, uart_mode} <= {io_din, tmp1, tmp2}; + endcase + end + endcase + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +generate + if(PS2DIV) begin + reg clk_ps2; + always @(posedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end + end + + reg [7:0] kbd_data; + reg kbd_we; + wire [8:0] kbd_data_host; + reg kbd_rd; + + ps2_device keyboard + ( + .clk_sys(clk_sys), + + .wdata(kbd_data), + .we(kbd_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_kbd_clk_out), + .ps2_dat_out(ps2_kbd_data_out), + + .ps2_clk_in(ps2_kbd_clk_in || !PS2WE), + .ps2_dat_in(ps2_kbd_data_in || !PS2WE), + + .rdata(kbd_data_host), + .rd(kbd_rd) + ); + + reg [7:0] mouse_data; + reg mouse_we; + wire [8:0] mouse_data_host; + reg mouse_rd; + + ps2_device mouse + ( + .clk_sys(clk_sys), + + .wdata(mouse_data), + .we(mouse_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_mouse_clk_out), + .ps2_dat_out(ps2_mouse_data_out), + + .ps2_clk_in(ps2_mouse_clk_in || !PS2WE), + .ps2_dat_in(ps2_mouse_data_in || !PS2WE), + + .rdata(mouse_data_host), + .rd(mouse_rd) + ); + end + else begin + assign ps2_kbd_clk_out = 0; + assign ps2_kbd_data_out = 0; + assign ps2_mouse_clk_out = 0; + assign ps2_mouse_data_out = 0; + end +endgenerate + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam FIO_FILE_TX = 8'h53; +localparam FIO_FILE_TX_DAT = 8'h54; +localparam FIO_FILE_INDEX = 8'h55; +localparam FIO_FILE_INFO = 8'h56; + +reg [15:0] fp_dout; +always@(posedge clk_sys) begin : fio_block + reg [15:0] cmd; + reg [2:0] cnt; + reg has_cmd; + reg [26:0] addr; + reg wr; + + ioctl_rd <= 0; + ioctl_wr <= wr; + wr <= 0; + + if(~fp_enable) has_cmd <= 0; + else begin + if(io_strobe) begin + + if(!has_cmd) begin + cmd <= io_din; + has_cmd <= 1; + cnt <= 0; + end else begin + + case(cmd) + FIO_FILE_INFO: + if(~cnt[1]) begin + case(cnt) + 0: ioctl_file_ext[31:16] <= io_din; + 1: ioctl_file_ext[15:00] <= io_din; + endcase + cnt <= cnt + 1'd1; + end + + FIO_FILE_INDEX: + begin + ioctl_index <= io_din[15:0]; + end + + FIO_FILE_TX: + begin + cnt <= cnt + 1'd1; + case(cnt) + 0: if(io_din[7:0] == 8'hAA) begin + ioctl_addr <= 0; + ioctl_upload <= 1; + ioctl_rd <= 1; + end + else if(io_din[7:0]) begin + addr <= 0; + ioctl_download <= 1; + end + else begin + if(ioctl_download) ioctl_addr <= addr; + ioctl_download <= 0; + ioctl_upload <= 0; + end + + 1: begin + ioctl_addr[15:0] <= io_din; + addr[15:0] <= io_din; + end + + 2: begin + ioctl_addr[26:16] <= io_din[10:0]; + addr[26:16] <= io_din[10:0]; + end + endcase + end + + FIO_FILE_TX_DAT: + if(ioctl_download) begin + ioctl_addr <= addr; + ioctl_dout <= io_din[DW:0]; + wr <= 1; + addr <= addr + (WIDE ? 2'd2 : 2'd1); + end + else begin + ioctl_addr <= ioctl_addr + (WIDE ? 2'd2 : 2'd1); + fp_dout <= ioctl_din; + ioctl_rd <= 1; + end + endcase + end + end + end +end + +endmodule + +////////////////////////////////////////////////////////////////////////////////// + + +module ps2_device #(parameter PS2_FIFO_BITS=5) +( + input clk_sys, + + input [7:0] wdata, + input we, + + input ps2_clk, + output reg ps2_clk_out, + output reg ps2_dat_out, + output reg tx_empty, + + input ps2_clk_in, + input ps2_dat_in, + + output [8:0] rdata, + input rd +); + + +(* ramstyle = "logic" *) reg [7:0] fifo[1<= 1)&&(tx_state < 9)) begin + ps2_dat_out <= tx_byte[0]; // data bits + tx_byte[6:0] <= tx_byte[7:1]; // shift down + if(tx_byte[0]) + parity <= !parity; + end + + // transmission of parity + if(tx_state == 9) ps2_dat_out <= parity; + + // transmission of stop bit + if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1 + + // advance state machine + if(tx_state < 11) tx_state <= tx_state + 1'd1; + else tx_state <= 0; + end + end + end + + if(~old_clk & ps2_clk) ps2_clk_out <= 1; + if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2)); + +end + +endmodule + + +///////////////// calc video parameters ////////////////// +module video_calc +( + input clk_100, + input clk_vid, + input clk_sys, + + input ce_pix, + input de, + input hs, + input vs, + input vs_hdmi, + input f1, + input new_vmode, + input video_rotated, + + input [4:0] par_num, + output reg [15:0] dout +); + +always @(posedge clk_sys) begin + case(par_num) + 1: dout <= {video_rotated, |vid_int, vid_nres}; + 2: dout <= vid_hcnt[15:0]; + 3: dout <= vid_hcnt[31:16]; + 4: dout <= vid_vcnt[15:0]; + 5: dout <= vid_vcnt[31:16]; + 6: dout <= vid_htime[15:0]; + 7: dout <= vid_htime[31:16]; + 8: dout <= vid_vtime[15:0]; + 9: dout <= vid_vtime[31:16]; + 10: dout <= vid_pix[15:0]; + 11: dout <= vid_pix[31:16]; + 12: dout <= vid_vtime_hdmi[15:0]; + 13: dout <= vid_vtime_hdmi[31:16]; + 14: dout <= vid_ccnt[15:0]; + 15: dout <= vid_ccnt[31:16]; + 16: dout <= vid_pixrep; + 17: dout <= vid_de_h; + 18: dout <= vid_de_v; + default dout <= 0; + endcase +end + +reg [31:0] vid_hcnt = 0; +reg [31:0] vid_vcnt = 0; +reg [31:0] vid_ccnt = 0; +reg [7:0] vid_nres = 0; +reg [1:0] vid_int = 0; +reg [7:0] vid_pixrep; +reg [15:0] vid_de_h; +reg [7:0] vid_de_v; + +always @(posedge clk_vid) begin + integer hcnt; + integer vcnt; + integer ccnt; + reg [7:0] pcnt; + reg [7:0] de_v; + reg [15:0] de_h; + reg old_vs = 0, old_hs = 0, old_hs_vclk = 0, old_de = 0, old_de_vclk = 0, old_de1 = 0, old_vmode = 0; + reg [3:0] resto = 0; + reg calch = 0; + + if(calch & de) ccnt <= ccnt + 1; + pcnt <= pcnt + 1'd1; + + old_hs_vclk <= hs; + de_h <= de_h + 1'd1; + if(old_hs_vclk & ~hs) de_h <= 1; + + old_de_vclk <= de; + if(calch & ~old_de_vclk & de) vid_de_h <= de_h; + + if(ce_pix) begin + old_vs <= vs; + old_hs <= hs; + old_de <= de; + old_de1 <= old_de; + pcnt <= 1; + + if(~vs & ~old_de & de) vcnt <= vcnt + 1; + if(calch & de) hcnt <= hcnt + 1; + if(old_de & ~de) calch <= 0; + if(~old_de1 & old_de) vid_pixrep <= pcnt; + if(old_hs & ~hs) de_v <= de_v + 1'd1; + if(calch & ~old_de & de) vid_de_v <= de_v; + + if(old_vs & ~vs) begin + vid_int <= {vid_int[0],f1}; + if(~f1) begin + if(hcnt && vcnt) begin + old_vmode <= new_vmode; + + //report new resolution after timeout + if(resto) resto <= resto + 1'd1; + if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) resto <= 1; + if(&resto) vid_nres <= vid_nres + 1'd1; + vid_hcnt <= hcnt; + vid_vcnt <= vcnt; + vid_ccnt <= ccnt; + end + vcnt <= 0; + hcnt <= 0; + ccnt <= 0; + calch <= 1; + de_v <= 0; + end + end + end +end + +reg [31:0] vid_htime = 0; +reg [31:0] vid_vtime = 0; +reg [31:0] vid_pix = 0; + +always @(posedge clk_100) begin + integer vtime, htime, hcnt; + reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2; + reg calch = 0; + + old_vs <= vs; + old_hs <= hs; + + old_vs2 <= old_vs; + old_hs2 <= old_hs; + + vtime <= vtime + 1'd1; + htime <= htime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_pix <= hcnt; + vid_vtime <= vtime; + vtime <= 0; + hcnt <= 0; + end + + if(old_vs2 & ~old_vs) calch <= 1; + + if(~old_hs2 & old_hs) begin + vid_htime <= htime; + htime <= 0; + end + + old_de <= de; + old_de2 <= old_de; + + if(calch & old_de) hcnt <= hcnt + 1; + if(old_de2 & ~old_de) calch <= 0; +end + +reg [31:0] vid_vtime_hdmi; +always @(posedge clk_100) begin + integer vtime; + reg old_vs, old_vs2; + + old_vs <= vs_hdmi; + old_vs2 <= old_vs; + + vtime <= vtime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_vtime_hdmi <= vtime; + vtime <= 0; + end +end + +endmodule + +module confstr_rom #(parameter CONF_STR, STRLEN) +( + input clk_sys, + input [$clog2(STRLEN+1)-1:0] conf_addr, + output reg [7:0] conf_byte +); + +wire [7:0] rom[STRLEN]; +initial for(int i = 0; i < STRLEN; i++) rom[i] = CONF_STR[((STRLEN-i)*8)-1 -:8]; +always @ (posedge clk_sys) conf_byte <= rom[conf_addr]; + +endmodule diff --git a/sys/hq2x.sv b/sys/hq2x.sv new file mode 100644 index 0000000..f5fcc71 --- /dev/null +++ b/sys/hq2x.sv @@ -0,0 +1,371 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017,2018 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// altera message_off 10030 + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + + input ce_in, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + + input ce_out, + input [1:0] read_y, + input hblank, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = $clog2(LENGTH)-1; +localparam DWIDTH = HALF_DEPTH ? 11 : 23; +localparam DWIDTH1 = DWIDTH+1; + +(* romstyle = "MLAB" *) reg [5:0] hqTable[256]; +initial begin + hqTable = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 + }; +end + +wire [5:0] hqrule = hqTable[nextpatt]; + +reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2; +reg [23:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] cyc; + +reg curbuf; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (cyc == 0) ? Prev0 : (cyc == 1) ? Curr0 : (cyc == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (cyc == 0) ? Prev1 : (cyc == 1) ? Next0 : (cyc == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [23:0] X = (cyc == 0) ? A : (cyc == 1) ? Prev1 : (cyc == 2) ? Next1 : G; +wire [23:0] blend_result_pre; +Blend blender(clk, ce_in, disable_hq2x ? 6'd0 : hqrule, Curr0, X, B, D, F, H, blend_result_pre); + +wire [DWIDTH:0] Curr20tmp; +wire [23:0] Curr20 = HALF_DEPTH ? h2rgb(Curr20tmp) : Curr20tmp; +wire [DWIDTH:0] Curr21tmp; +wire [23:0] Curr21 = HALF_DEPTH ? h2rgb(Curr21tmp) : Curr21tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [23:0] h2rgb; + input [11:0] v; +begin + h2rgb = mono ? {v[7:0], v[7:0], v[7:0]} : {v[11:8],v[11:8],v[7:4],v[7:4],v[3:0],v[3:0]}; +end +endfunction + +function [11:0] rgb2h; + input [23:0] v; +begin + rgb2h = mono ? {4'b0000, v[23:20], v[19:16]} : {v[23:20], v[15:12], v[7:4]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(offs), + .rdbuf0(prevbuf), + .rdbuf1(curbuf), + .q0(Curr20tmp), + .q1(Curr21tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [AWIDTH+1:0] read_x; +reg [AWIDTH+1:0] wrout_addr; +reg wrout_en; +reg [DWIDTH1*4-1:0] wrdata, wrdata_pre; +wire [DWIDTH1*4-1:0] outpixel_x4; +reg [DWIDTH1*2-1:0] outpixel_x2; + +assign outpixel = read_x[0] ? outpixel_x2[DWIDTH1*2-1:DWIDTH1] : outpixel_x2[DWIDTH:0]; + +hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH+1), .DWIDTH(DWIDTH1*4-1)) hq2x_out +( + .clock(clk), + + .rdaddress({read_x[AWIDTH+1:1],read_y[1]}), + .q(outpixel_x4), + + .data(wrdata), + .wraddress(wrout_addr), + .wren(wrout_en) +); + +always @(posedge clk) begin + if(ce_out) begin + if(read_x[0]) outpixel_x2 <= read_y[0] ? outpixel_x4[DWIDTH1*4-1:DWIDTH1*2] : outpixel_x4[DWIDTH1*2-1:0]; + if(~hblank & ~&read_x) read_x <= read_x + 1'd1; + if(hblank) read_x <= 0; + end +end + +wire [DWIDTH:0] blend_result = HALF_DEPTH ? rgb2h(blend_result_pre) : blend_result_pre[DWIDTH:0]; + +reg [AWIDTH:0] offs; +always @(posedge clk) begin + reg old_reset_line; + reg old_reset_frame; + reg [3:0] wrdata_finished; + reg [AWIDTH+1:0] waddr; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_in) begin + + // blend_result has been delayed by 4 cycles + case(cyc) + 0: wrdata[DWIDTH:0] <= blend_result; + 1: wrdata[DWIDTH1+DWIDTH:DWIDTH1] <= blend_result; + 2: wrdata[DWIDTH1*3+DWIDTH:DWIDTH1*3] <= blend_result; + 3: wrdata[DWIDTH1*2+DWIDTH:DWIDTH1*2] <= blend_result; + endcase + + wrdata_finished <= wrdata_finished << 1; + if(wrdata_finished[3]) begin + wrout_en <= 1; + wrout_addr <= waddr; + end + + if(~&offs) begin + if (cyc == 1) begin + Prev2 <= Curr20; + Curr2 <= Curr21; + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + + if(cyc==3) begin + offs <= offs + 1'd1; + waddr <= {offs, curbuf}; + wrdata_finished[0] <= 1; + end + end + + pattern <= new_pattern; + if(cyc==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + cyc <= cyc + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + cyc <= 0; + curbuf <= ~curbuf; + prevbuf <= curbuf; + {Prev0, Prev1, Prev2, Curr0, Curr1, Curr2, Next0, Next1, Next2} <= '0; + if(old_reset_frame & ~reset_frame) begin + curbuf <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf0, rdbuf1, + output[DWIDTH:0] q0,q1, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + +localparam AWIDTH = $clog2(LENGTH)-1; +wire [DWIDTH:0] out[2]; +assign q0 = out[rdbuf0]; +assign q1 = out[rdbuf1]; + +hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); +hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + +endmodule + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output reg [DWIDTH:0] q +); + +reg [DWIDTH:0] ram[0:NUMWORDS-1]; + +always_ff@(posedge clock) begin + if(wren) ram[wraddress] <= data; + q <= ram[rdaddress]; +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [23:0] rgb1, + input [23:0] rgb2, + output result +); + + wire [7:0] r = rgb1[7:1] - rgb2[7:1]; + wire [7:0] g = rgb1[15:9] - rgb2[15:9]; + wire [7:0] b = rgb1[23:17] - rgb2[23:17]; + wire [8:0] t = $signed(r) + $signed(b); + wire [9:0] y = $signed(t) + $signed({g[7], g}); + wire [8:0] u = $signed(r) - $signed(b); + wire [9:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-96..96) + wire y_inside = (y < 10'h60 || y >= 10'h3a0); + + // if u is inside (-16, 16) + wire u_inside = (!u[8:4] || &u[8:4]); //(u < 9'h10 || u >= 9'h1f0); + + // if v is inside (-24, 24) + wire v_inside = (v < 10'h18 || v >= 10'h3e8); + assign result = !(y_inside && u_inside && v_inside); + +endmodule + +module Blend +( + input clk, + input clk_en, + input [5:0] rule, + input [23:0] E, + input [23:0] A, + input [23:0] B, + input [23:0] D, + input [23:0] F, + input [23:0] H, + output [23:0] Result +); + + localparam BLEND1 = 7'b110_10_00; // (A * 12 + B * 4 ) >> 4 + localparam BLEND2 = 7'b100_10_10; // (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 7'b101_10_01; // (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 7'b110_01_01; // (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 7'b010_11_11; // (A * 4 + B * 6 + C * 6) >> 4 + localparam BLEND6 = 7'b111_00_00; // (A * 14 + B * 1 + C * 1) >> 4 + + reg [23:0] a,b,d,e,h,f; + reg [3:0] bl_rule; + reg [1:0] df_rule; + always @(posedge clk) if (clk_en) begin + {bl_rule,df_rule} <= rule; + a <= A; b <= B; d <= D; e <= E; f <= F; h <= H; + end + + wire is_diff; + DiffCheck diff_checker(df_rule[1] ? b : h, df_rule[0] ? d : f, is_diff); + + reg [23:0] i10,i20,i30; + reg [6:0] op0; + always @(posedge clk) if (clk_en) begin + i10 <= e; + case({!is_diff, bl_rule}) + 1,11,12,13,17: {op0, i20, i30} <= {BLEND1, a, 24'd0}; + 2,14,18: {op0, i20, i30} <= {BLEND1, d, 24'd0}; + 3,15,19: {op0, i20, i30} <= {BLEND1, b, 24'd0}; + 4,20,24,27: {op0, i20, i30} <= {BLEND2, d, b}; + 5,21: {op0, i20, i30} <= {BLEND2, a, b}; + 6,22: {op0, i20, i30} <= {BLEND2, a, d}; + 25,29: {op0, i20, i30} <= {BLEND5, d, b}; + 26: {op0, i20, i30} <= {BLEND6, d, b}; + 28: {op0, i20, i30} <= {BLEND4, d, b}; + 30: {op0, i20, i30} <= {BLEND3, b, d}; + 31: {op0, i20, i30} <= {BLEND3, d, b}; + default: {op0, i20, i30} <= {BLEND1, e, 24'd0}; + endcase + end + + reg [23:0] i1,i2,i3; + reg [6:0] op; + always @(posedge clk) if (clk_en) begin + op <= op0; i1 <= i10; i2 <= i20; i3 <= i30; + end + + function [34:0] mul24x3; + input [23:0] op1; + input [2:0] op2; + begin + mul24x3 = 0; + if(op2[0]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0]}; + if(op2[1]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 1'b0}; + if(op2[2]) mul24x3 = mul24x3 + {op1[23:16], 4'b0000, op1[15:8], 4'b0000, op1[7:0], 2'b00}; + end + endfunction + + wire [35:0] res = {mul24x3(i1, op[6:4]), 1'b0} + mul24x3(i2, {op[3:2], !op[3:2]}) + mul24x3(i3, {op[1:0], !op[3:2]}); + + always @(posedge clk) if (clk_en) Result <= {res[35:28],res[23:16],res[11:4]}; + +endmodule diff --git a/sys/i2c.v b/sys/i2c.v new file mode 100644 index 0000000..35c8cbd --- /dev/null +++ b/sys/i2c.v @@ -0,0 +1,103 @@ + +module i2c +( + input CLK, + + input START, + input READ, + input [6:0] I2C_ADDR, + input I2C_WLEN, // 0 - one byte, 1 - two bytes + input [7:0] I2C_WDATA1, + input [7:0] I2C_WDATA2, + output [7:0] I2C_RDATA, + output reg END = 1, + output reg ACK = 0, + + //I2C bus + output I2C_SCL, + inout I2C_SDA +); + + +// Clock Setting +parameter CLK_Freq = 50_000_000; // 50 MHz +parameter I2C_Freq = 400_000; // 400 KHz + +localparam I2C_FreqX2 = I2C_Freq*2; + +reg I2C_CLOCK; +reg [31:0] cnt; +wire [31:0] cnt_next = cnt + I2C_FreqX2; + +always @(posedge CLK) begin + cnt <= cnt_next; + if(cnt_next >= CLK_Freq) begin + cnt <= cnt_next - CLK_Freq; + I2C_CLOCK <= ~I2C_CLOCK; + end +end + +assign I2C_SCL = (SCLK | I2C_CLOCK) ? 1'bZ : 1'b0; +assign I2C_SDA = SDO[3] ? 1'bz : 1'b0; + +reg SCLK; +reg [3:0] SDO; +reg [0:7] rdata; + +reg [5:0] SD_COUNTER; +reg [0:31] SD; + +initial begin + SD_COUNTER = 'b111111; + SD = 'hFFFF; + SCLK = 1; + SDO = 4'b1111; +end + +assign I2C_RDATA = rdata; + +always @(posedge CLK) begin + reg old_clk; + reg old_st; + reg rd,len; + + old_clk <= I2C_CLOCK; + old_st <= START; + + // delay to make sure SDA changed while SCL is stabilized at low + if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO[0] <= SD[SD_COUNTER[4:0]]; + SDO[3:1] <= SDO[2:0]; + + if(~old_st && START) begin + SCLK <= 1; + SDO <= 4'b1111; + ACK <= 0; + END <= 0; + rd <= READ; + len <= I2C_WLEN; + if(READ) SD <= {2'b10, I2C_ADDR, 1'b1, 1'b1, 8'b11111111, 1'b0, 3'b011, 9'b111111111}; + else SD <= {2'b10, I2C_ADDR, 1'b0, 1'b1, I2C_WDATA1, 1'b1, I2C_WDATA2, 4'b1011}; + SD_COUNTER <= 0; + end else begin + if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin + SD_COUNTER <= SD_COUNTER + 6'd1; + case(SD_COUNTER) + 01: SCLK <= 0; + 10: ACK <= ACK | I2C_SDA; + 19: if(~rd) begin + ACK <= ACK | I2C_SDA; + if(~len) SD_COUNTER <= 29; + end + 20: if(rd) SCLK <= 1; + 23: if(rd) END <= 1; + 28: if(~rd) ACK <= ACK | I2C_SDA; + 29: if(~rd) SCLK <= 1; + 32: if(~rd) END <= 1; + endcase + + if(SD_COUNTER >= 11 && SD_COUNTER <= 18) rdata[SD_COUNTER[4:0]-11] <= I2C_SDA; + end + end +end + +endmodule diff --git a/sys/i2s.v b/sys/i2s.v new file mode 100644 index 0000000..7d4517b --- /dev/null +++ b/sys/i2s.v @@ -0,0 +1,54 @@ + +module i2s +#( + parameter AUDIO_DW = 16 +) +( + input reset, + input clk, + input ce, + + output reg sclk, + output reg lrclk, + output reg sdata, + + input [AUDIO_DW-1:0] left_chan, + input [AUDIO_DW-1:0] right_chan +); + +always @(posedge clk) begin + reg [7:0] bit_cnt; + reg msclk; + + reg [AUDIO_DW-1:0] left; + reg [AUDIO_DW-1:0] right; + + if (reset) begin + bit_cnt <= 1; + lrclk <= 1; + sclk <= 1; + msclk <= 1; + end + else begin + sclk <= msclk; + if(ce) begin + msclk <= ~msclk; + if(msclk) begin + if(bit_cnt >= AUDIO_DW) begin + bit_cnt <= 1; + lrclk <= ~lrclk; + if(lrclk) begin + left <= left_chan; + right <= right_chan; + end + end + else begin + bit_cnt <= bit_cnt + 1'd1; + end + sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt]; + end + end + end +end + +endmodule diff --git a/sys/iir_filter.v b/sys/iir_filter.v new file mode 100644 index 0000000..a5336e9 --- /dev/null +++ b/sys/iir_filter.v @@ -0,0 +1,213 @@ + +// 3-tap IIR filter for 2 channels. +// Copyright (C) 2020 Sorgelig +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +// +// Can be converted to 2-tap (coeff_x2 = 0, coeff_y2 = 0) or 1-tap (coeff_x1,2 = 0, coeff_y1,2 = 0) +// +module IIR_filter +#( + parameter use_params = 1, // set to 1 to use following parameters, 0 for input port variables. + parameter stereo = 1, // 0 for mono (input_l) + + parameter coeff_x = 0.00000774701983513660, // Base gain value for X. Float. Range: 0.0 ... 0.999(9) + parameter coeff_x0 = 3, // Gain scale factor for X0. Integer. Range -7 ... +7 + parameter coeff_x1 = 3, // Gain scale factor for X1. Integer. Range -7 ... +7 + parameter coeff_x2 = 1, // Gain scale factor for X2. Integer. Range -7 ... +7 + parameter coeff_y0 = -2.96438150626551080000, // Coefficient for Y0. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y1 = 2.92939452735121100000, // Coefficient for Y1. Float. Range -3.999(9) ... 3.999(9) + parameter coeff_y2 = -0.96500747158831091000 // Coefficient for Y2. Float. Range -3.999(9) ... 3.999(9) +) +( + input clk, + input reset, + + input ce, // must be double of calculated rate for stereo! + input sample_ce, // desired output sample rate + + input [39:0] cx, + input [7:0] cx0, + input [7:0] cx1, + input [7:0] cx2, + input [23:0] cy0, + input [23:0] cy1, + input [23:0] cy2, + + input [15:0] input_l, input_r, // signed samples + output [15:0] output_l, output_r // signed samples +); + +localparam [39:0] pcoeff_x = coeff_x * 40'h8000000000; +localparam [31:0] pcoeff_y0 = coeff_y0 * 24'h200000; +localparam [31:0] pcoeff_y1 = coeff_y1 * 24'h200000; +localparam [31:0] pcoeff_y2 = coeff_y2 * 24'h200000; + +wire [39:0] vcoeff = use_params ? pcoeff_x : cx; +wire [23:0] vcoeff_y0 = use_params ? pcoeff_y0[23:0] : cy0; +wire [23:0] vcoeff_y1 = use_params ? pcoeff_y1[23:0] : cy1; +wire [23:0] vcoeff_y2 = use_params ? pcoeff_y2[23:0] : cy2; + +wire [59:0] inp_mul = $signed(inp) * $signed(vcoeff); + +wire [39:0] x = inp_mul[59:20]; +wire [39:0] y = x + tap0; + +wire [39:0] tap0; +iir_filter_tap iir_tap_0 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x0[7:0] : cx0), + .cy(vcoeff_y0), + .x(x), + .y(y), + .z(tap1), + .tap(tap0) +); + +wire [39:0] tap1; +iir_filter_tap iir_tap_1 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x1[7:0] : cx1), + .cy(vcoeff_y1), + .x(x), + .y(y), + .z(tap2), + .tap(tap1) +); + +wire [39:0] tap2; +iir_filter_tap iir_tap_2 +( + .clk(clk), + .reset(reset), + .ce(ce), + .ch(ch), + .cx(use_params ? coeff_x2[7:0] : cx2), + .cy(vcoeff_y2), + .x(x), + .y(y), + .z(0), + .tap(tap2) +); + +wire [15:0] y_clamp = (~y[39] & |y[38:35]) ? 16'h7FFF : (y[39] & ~&y[38:35]) ? 16'h8000 : y[35:20]; + +reg ch = 0; +reg [15:0] out_l, out_r, out_m; +reg [15:0] inp, inp_m; +always @(posedge clk) if (ce) begin + if(!stereo) begin + ch <= 0; + inp <= input_l; + out_l <= y_clamp; + out_r <= y_clamp; + end + else begin + ch <= ~ch; + if(ch) begin + out_m <= y_clamp; + inp <= inp_m; + end + else begin + out_l <= out_m; + out_r <= y_clamp; + inp <= input_l; + inp_m <= input_r; + end + end +end + +reg [31:0] out; +always @(posedge clk) if (sample_ce) out <= {out_l, out_r}; + +assign {output_l, output_r} = out; + +endmodule + +module iir_filter_tap +( + input clk, + input reset, + + input ce, + input ch, + + input [7:0] cx, + input [23:0] cy, + + input [39:0] x, + input [39:0] y, + input [39:0] z, + output [39:0] tap +); + +wire signed [60:0] y_mul = $signed(y[36:0]) * $signed(cy); + +function [39:0] x_mul; + input [39:0] x; +begin + x_mul = 0; + if(cx[0]) x_mul = x_mul + {{4{x[39]}}, x[39:4]}; + if(cx[1]) x_mul = x_mul + {{3{x[39]}}, x[39:3]}; + if(cx[2]) x_mul = x_mul + {{2{x[39]}}, x[39:2]}; + if(cx[7]) x_mul = ~x_mul; //cheap NEG +end +endfunction + +(* ramstyle = "logic" *) reg [39:0] intreg[2]; +always @(posedge clk, posedge reset) begin + if(reset) {intreg[0],intreg[1]} <= 80'd0; + else if(ce) intreg[ch] <= x_mul(x) - y_mul[60:21] + z; +end + +assign tap = intreg[ch]; + +endmodule + +// simplified IIR 1-tap. +module DC_blocker +( + input clk, + input ce, // 48/96 KHz + input mute, + + input sample_rate, + input [15:0] din, + output [15:0] dout +); + +wire [39:0] x = {din[15], din, 23'd0}; +wire [39:0] x0 = x - (sample_rate ? {{11{x[39]}}, x[39:11]} : {{10{x[39]}}, x[39:10]}); +wire [39:0] y1 = y - (sample_rate ? {{10{y[39]}}, y[39:10]} : {{09{y[39]}}, y[39:09]}); +wire [39:0] y0 = x0 - x1 + y1; + +reg [39:0] x1, y; +always @(posedge clk) if(ce) begin + x1 <= x0; + y <= ^y0[39:38] ? {{2{y0[39]}},{38{y0[38]}}} : y0; +end + +assign dout = mute ? 16'd0 : y[38:23]; + +endmodule diff --git a/sys/ltc2308.sv b/sys/ltc2308.sv new file mode 100644 index 0000000..4d3ccc1 --- /dev/null +++ b/sys/ltc2308.sv @@ -0,0 +1,162 @@ +//============================================================================ +// +// LTC2308 controller +// Copyright (C) 2019 Sorgelig +// +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + + +// NUM_CH 1..8 +// Sampling rate = ADC_RATE/NUM_CH +// ADC_RATE max is ~500KHz +// CLK_RATE max is ~80MHz +module ltc2308 #(parameter NUM_CH = 2, ADC_RATE = 96000, CLK_RATE = 50000000) +( + input reset, + input clk, + + inout [3:0] ADC_BUS, + + output reg dout_sync, // toggle with every ADC round + output reg [(NUM_CH*12)-1:0] dout // 12 bits per channel (unsigned) +); + +localparam TCONV = CLK_RATE/625000; + +reg sck; +wire sdo = cfg[5]; + +assign ADC_BUS[3] = sck; +wire sdi = ADC_BUS[2]; +assign ADC_BUS[1] = sdo; +assign ADC_BUS[0] = convst; + +reg convst; +reg [5:0] cfg; + +reg [31:0] sum; +wire [31:0] next_sum = sum + ADC_RATE; + +reg [2:0] pin; +wire [2:0] next_pin = (pin == (NUM_CH-1)) ? 3'd0 : (pin + 1'd1); + +always @(posedge clk) begin + reg [7:0] tconv; + reg [3:0] bitcnt; + reg [10:0] adcin; + + convst <= 0; + + if(reset) begin + sum <= 0; + tconv <= 0; + bitcnt <= 0; + sck <= 0; + cfg <= 0; + dout <= 0; + pin <= NUM_CH[2:0]-1'd1; + end + else begin + sum <= next_sum; + if(next_sum >= CLK_RATE) begin + sum <= next_sum - CLK_RATE; + tconv <= TCONV[7:0]; + convst <= 1; + bitcnt <= 12; + cfg <= {1'b1, next_pin[0], next_pin[2:1], 1'b1, 1'b0}; + if(!next_pin) dout_sync <= ~dout_sync; + end + + if(tconv) tconv <= tconv - 1'd1; + else if(bitcnt) begin + sck <= ~sck; + + if(sck) cfg <= cfg<<1; + else begin + adcin <= {adcin[9:0],sdi}; + bitcnt <= bitcnt - 1'd1; + if(bitcnt == 1) begin + dout[pin*12 +:12] <= {adcin,sdi}; + pin <= next_pin; + end + end + end + else sck <= 0; + end +end + +endmodule + +module ltc2308_tape #(parameter HIST_LOW = 16, HIST_HIGH = 64, ADC_RATE = 48000, CLK_RATE = 50000000, NUM_CH = 1) +( + input reset, + input clk, + + inout [3:0] ADC_BUS, + output reg dout, + output active, + output adc_sync, + output [(NUM_CH*12)-1:0] adc_data +); + +ltc2308 #(NUM_CH, ADC_RATE, CLK_RATE) adc +( + .reset(reset), + .clk(clk), + + .ADC_BUS(ADC_BUS), + .dout(adc_data), + .dout_sync(adc_sync) +); + +always @(posedge clk) begin + reg [13:0] data1,data2,data3,data4, sum; + reg adc_sync_d; + + adc_sync_d<=adc_sync; + if(adc_sync_d ^ adc_sync) begin + data1 <= data2; + data2 <= data3; + data3 <= data4; + data4 <= adc_data[11:0]; + + sum <= data1+data2+data3+data4; + + if(sum[13:2]HIST_HIGH) dout <= 1; + end +end + +assign active = |act; + +reg [1:0] act; +always @(posedge clk) begin + reg [31:0] onesec; + reg old_dout; + + onesec <= onesec + 1; + if(onesec>CLK_RATE) begin + onesec <= 0; + if(act) act <= act - 1'd1; + end + + old_dout <= dout; + if(old_dout ^ dout) act <= 2; +end + +endmodule diff --git a/sys/math.sv b/sys/math.sv new file mode 100644 index 0000000..1cf327f --- /dev/null +++ b/sys/math.sv @@ -0,0 +1,109 @@ + +// result = num/div +module sys_udiv +#( + parameter NB_NUM, + parameter NB_DIV +) +( + input clk, + input start, + output busy, + + input [NB_NUM-1:0] num, + input [NB_DIV-1:0] div, + output reg [NB_NUM-1:0] result, + output reg [NB_DIV-1:0] remainder +); + +reg run; +assign busy = run; + +always @(posedge clk) begin + reg [5:0] cpt; + reg [NB_NUM+NB_DIV+1:0] rem; + + if (start) begin + cpt <= 0; + run <= 1; + rem <= num; + end + else if (run) begin + cpt <= cpt + 1'd1; + run <= (cpt != NB_NUM + 1'd1); + remainder <= rem[NB_NUM+NB_DIV:NB_NUM+1]; + if (!rem[NB_DIV + NB_NUM + 1'd1]) + rem <= {rem[NB_DIV+NB_NUM:0] - (div << NB_NUM),1'b0}; + else + rem <= {rem[NB_DIV+NB_NUM:0] + (div << NB_NUM),1'b0}; + result <= {result[NB_NUM-2:0], !rem[NB_DIV + NB_NUM + 1'd1]}; + end +end + +endmodule + +// result = mul1*mul2 +module sys_umul +#( + parameter NB_MUL1, + parameter NB_MUL2 +) +( + input clk, + input start, + output busy, + + input [NB_MUL1-1:0] mul1, + input [NB_MUL2-1:0] mul2, + output reg [NB_MUL1+NB_MUL2-1:0] result +); + +reg run; +assign busy = run; + +always @(posedge clk) begin + reg [NB_MUL1+NB_MUL2-1:0] add; + reg [NB_MUL2-1:0] map; + + if (start) begin + run <= 1; + result <= 0; + add <= mul1; + map <= mul2; + end + else if (run) begin + if(!map) run <= 0; + if(map[0]) result <= result + add; + add <= add << 1; + map <= map >> 1; + end +end + +endmodule + +// result = (mul1*mul2)/div +module sys_umuldiv +#( + parameter NB_MUL1, + parameter NB_MUL2, + parameter NB_DIV +) +( + input clk, + input start, + output busy, + + input [NB_MUL1-1:0] mul1, + input [NB_MUL2-1:0] mul2, + input [NB_DIV-1:0] div, + output [NB_MUL1+NB_MUL2-1:0] result, + output [NB_DIV-1:0] remainder +); + +wire mul_run; +wire [NB_MUL1+NB_MUL2-1:0] mul_res; +sys_umul #(NB_MUL1,NB_MUL2) umul(clk,start,mul_run,mul1,mul2,mul_res); + +sys_udiv #(NB_MUL1+NB_MUL2,NB_DIV) udiv(clk,start|mul_run,busy,mul_res,div,result,remainder); + +endmodule diff --git a/sys/mcp23009.sv b/sys/mcp23009.sv new file mode 100644 index 0000000..82eaf37 --- /dev/null +++ b/sys/mcp23009.sv @@ -0,0 +1,120 @@ +// +// MCP23009 +// (C) 2019 Alexey Melnikov +// +module mcp23009 +( + input clk, + + output reg [2:0] btn, + input [2:0] led, + output reg flg_sd_cd, + output reg flg_present, + output reg flg_mode, + + output scl, + inout sda +); + + +reg start = 0; +wire ready; +wire error; +reg rw; +wire [7:0] dout; +reg [15:0] din; + +i2c #(50_000_000, 500_000) i2c +( + .CLK(clk), + .START(start), + .READ(rw), + .I2C_ADDR('h20), + .I2C_WLEN(1), + .I2C_WDATA1(din[15:8]), + .I2C_WDATA2(din[7:0]), + .I2C_RDATA(dout), + .END(ready), + .ACK(error), + .I2C_SCL(scl), + .I2C_SDA(sda) +); + +always@(posedge clk) begin + reg [3:0] idx = 0; + reg [1:0] state = 0; + reg [15:0] timeout = 0; + + if(~&timeout) begin + timeout <= timeout + 1'd1; + start <= 0; + state <= 0; + idx <= 0; + btn <= 0; + rw <= 0; + flg_sd_cd <= 1; + flg_present <= 0; + flg_mode <= 1; + end + else begin + if(~&init_data[idx]) begin + case(state) + 0: begin + start <= 1; + state <= 1; + din <= init_data[idx]; + end + 1: if(~ready) state <= 2; + 2: begin + start <= 0; + if(ready) begin + state <= 0; + if(!error) idx <= idx + 1'd1; + end + end + endcase + end + else begin + case(state) + 0: begin + start <= 1; + state <= 1; + din <= {8'h09,5'b00000,led}; + end + 1: if(~ready) state <= 2; + 2: begin + start <= 0; + if(ready) begin + state <= 0; + rw <= 0; + if(!error) begin + if(rw) begin + {flg_sd_cd, flg_mode, btn} <= {dout[7:3]}; + flg_present <= 1; + end + rw <= ~rw; + end + end + end + endcase + end + end +end + +wire [15:0] init_data[12] = +'{ + 16'h00F8, + 16'h0138, + 16'h0200, + 16'h0300, + 16'h0400, + 16'h0524, + 16'h06FF, + 16'h0700, + 16'h0800, + 16'h0900, + 16'h0A00, + 16'hFFFF +}; + +endmodule diff --git a/sys/mt32pi.sv b/sys/mt32pi.sv new file mode 100644 index 0000000..cafa880 --- /dev/null +++ b/sys/mt32pi.sv @@ -0,0 +1,283 @@ +// +// Communication module to MT32-pi (external MIDI emulator on RPi) +// (C) 2020 Sorgelig, Kitrinx +// +// https://github.com/dwhinham/mt32-pi +// + +module mt32pi +( + input CLK_AUDIO, + + input CLK_VIDEO, + input CE_PIXEL, + input VGA_VS, + input VGA_DE, + + input [6:0] USER_IN, + output [6:0] USER_OUT, + + input reset, + input midi_tx, + output midi_rx, + + output reg [15:0] mt32_i2s_r, + output reg [15:0] mt32_i2s_l, + + output reg mt32_available, + + input mt32_mode_req, + input [1:0] mt32_rom_req, + input [7:0] mt32_sf_req, + + output reg [7:0] mt32_mode, + output reg [7:0] mt32_rom, + output reg [7:0] mt32_sf, + output reg mt32_newmode, + + output reg mt32_lcd_en, + output reg mt32_lcd_pix, + output reg mt32_lcd_update +); + +// +// Pin | USB Name | Signal +// ----+----------+-------------- +// 0 | D+ | I/O I2C_SDA / RX (midi in) +// 1 | D- | O TX (midi out) +// 2 | TX- | I I2S_WS (1 == right) +// 3 | GND_d | I I2C_SCL +// 4 | RX+ | I I2S_BCLK +// 5 | RX- | I I2S_DAT +// 6 | TX+ | - none +// + +assign USER_OUT[0] = sda_out; +assign USER_OUT[1] = midi_tx; +assign USER_OUT[6:2] = '1; + + +// +// crossed/straight cable selection +// + +generate + genvar i; + for(i = 0; i<2; i++) begin : clk_rate + wire clk_in = i ? USER_IN[6] : USER_IN[4]; + reg [4:0] cnt; + always @(posedge CLK_AUDIO) begin : clkr + reg clk_sr, clk, old_clk; + reg [4:0] cnt_tmp; + + clk_sr <= clk_in; + if (clk_sr == clk_in) clk <= clk_sr; + + if(~&cnt_tmp) cnt_tmp <= cnt_tmp + 1'd1; + else cnt <= '1; + + old_clk <= clk; + if(~old_clk & clk) begin + cnt <= cnt_tmp; + cnt_tmp <= 0; + end + end + end + + reg crossed; + always @(posedge CLK_AUDIO) crossed <= (clk_rate[0].cnt <= clk_rate[1].cnt); +endgenerate + +wire i2s_ws = crossed ? USER_IN[2] : USER_IN[5]; +wire i2s_data = crossed ? USER_IN[5] : USER_IN[2]; +wire i2s_bclk = crossed ? USER_IN[4] : USER_IN[6]; +assign midi_rx = ~mt32_available ? USER_IN[0] : crossed ? USER_IN[6] : USER_IN[4]; + + +// +// i2s receiver +// + +always @(posedge CLK_AUDIO) begin : i2s_proc + reg [15:0] i2s_buf = 0; + reg [4:0] i2s_cnt = 0; + reg clk_sr; + reg i2s_clk = 0; + reg old_clk, old_ws; + reg i2s_next = 0; + + // Debounce clock + clk_sr <= i2s_bclk; + if (clk_sr == i2s_bclk) i2s_clk <= clk_sr; + + // Latch data and ws on rising edge + old_clk <= i2s_clk; + if (i2s_clk && ~old_clk) begin + + if (~i2s_cnt[4]) begin + i2s_cnt <= i2s_cnt + 1'd1; + i2s_buf[~i2s_cnt[3:0]] <= i2s_data; + end + + // Word Select will change 1 clock before the new word starts + old_ws <= i2s_ws; + if (old_ws != i2s_ws) i2s_next <= 1; + end + + if (i2s_next) begin + i2s_next <= 0; + i2s_cnt <= 0; + i2s_buf <= 0; + + if (i2s_ws) mt32_i2s_l <= i2s_buf; + else mt32_i2s_r <= i2s_buf; + end + + if (reset) begin + i2s_buf <= 0; + mt32_i2s_l <= 0; + mt32_i2s_r <= 0; + end +end + + +// +// i2c slave +// + +reg sda_out; +reg [7:0] lcd_data[1024]; +reg lcd_sz; + +reg reset_r = 0; +wire [7:0] mode_req = reset_r ? 8'hA0 : mt32_mode_req ? 8'hA2 : 8'hA1; +wire [7:0] rom_req = {6'd0, mt32_rom_req}; + +always @(posedge CLK_AUDIO) begin : i2c_slave + reg sda_sr, scl_sr; + reg old_sda, old_scl; + reg sda, scl; + reg [7:0] tmp; + reg [3:0] cnt = 0; + reg [10:0] bcnt = 0; + reg ack; + reg i2c_rw; + reg disp, dispdata; + reg [2:0] div; + reg old_reset; + + old_reset <= reset; + if(old_reset & ~reset) sda_out <= 1; + + div <= div + 1'd1; + if(!div) begin + sda_sr <= USER_IN[0]; + if(sda_sr == USER_IN[0]) sda <= sda_sr; + old_sda <= sda; + + scl_sr <= USER_IN[3]; + if(scl_sr == USER_IN[3]) scl <= scl_sr; + old_scl <= scl; + + //start + if(old_scl & scl & old_sda & ~sda) begin + cnt <= 9; + bcnt <= 0; + ack <= 0; + i2c_rw <= 0; + disp <= 0; + dispdata <= 0; + end + + //stop + if(old_scl & scl & ~old_sda & sda) begin + cnt <= 0; + if(dispdata) begin + lcd_sz <= ~bcnt[9]; + mt32_lcd_update <= ~mt32_lcd_update; + end + end + + //data latch + if(~old_scl && scl && cnt) begin + tmp <= {tmp[6:0], sda}; + cnt <= cnt - 1'd1; + end + + if(!cnt) sda_out <= 1; + + //data set + if(old_scl && ~scl) begin + sda_out <= 1; + if(cnt == 1) begin + if(!bcnt) begin + if(tmp[7:1] == 'h45 || tmp[7:1] == 'h3c) begin + disp <= (tmp[7:1] == 'h3c); + sda_out <= 0; + mt32_available <= 1; + ack <= 1; + i2c_rw <= tmp[0]; + bcnt <= bcnt + 1'd1; + cnt <= 10; + end + else begin + // wrong address, stop + cnt <= 0; + end + end + else if(ack) begin + if(~i2c_rw) begin + if(disp) begin + if(bcnt == 1) dispdata <= (tmp[7:6] == 2'b01); + else if(dispdata) lcd_data[bcnt[9:0] - 2'd2] <= tmp; + end + else begin + if(bcnt == 1) mt32_mode <= tmp; + if(bcnt == 2) mt32_rom <= tmp; + if(bcnt == 3) mt32_sf <= tmp; + if(bcnt == 3) mt32_newmode <= ~mt32_newmode; + end + end + if(~&bcnt) bcnt <= bcnt + 1'd1; + sda_out <= 0; + cnt <= 10; + end + end + else if(i2c_rw && ack && cnt && ~disp) begin + if(bcnt == 1) sda_out <= mode_req[cnt[2:0] - 2'd2]; + if(bcnt == 2) sda_out <= rom_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) sda_out <= mt32_sf_req[cnt[2:0] - 2'd2]; + if(bcnt == 3) reset_r <= 0; + end + end + end + + if(reset) begin + reset_r <= 1; + mt32_available <= 0; + end +end + +always @(posedge CLK_VIDEO) begin + reg old_de, old_vs; + reg [7:0] hcnt; + reg [6:0] vcnt; + reg [7:0] sh; + + if(CE_PIXEL) begin + old_de <= VGA_DE; + old_vs <= VGA_VS; + + if(~&hcnt) hcnt <= hcnt + 1'd1; + sh <= (sh << 1) | (~old_de & VGA_DE); + if(sh[7]) hcnt <= 0; + + if(old_de & ~VGA_DE & ~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & VGA_VS) vcnt <= 0; + + mt32_lcd_en <= mt32_available & ~hcnt[7] && (lcd_sz ? !vcnt[6] : !vcnt[6:5]); + mt32_lcd_pix <= lcd_data[{vcnt[5:3],hcnt[6:0]}][vcnt[2:0]]; + end +end + +endmodule diff --git a/sys/osd.v b/sys/osd.v new file mode 100644 index 0000000..c354f6f --- /dev/null +++ b/sys/osd.v @@ -0,0 +1,286 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd +( + input clk_sys, + input io_osd, + input io_strobe, + input [15:0] io_din, + + input clk_video, + input [23:0] din, + input de_in, + input vs_in, + input hs_in, + output [23:0] dout, + output reg de_out, + output reg vs_out, + output reg hs_out, + + output reg osd_status +); + +parameter OSD_COLOR = 3'd4; + +localparam OSD_WIDTH = 12'd256; +localparam OSD_HEIGHT = 12'd64; + +`ifdef OSD_HEADER +localparam OSD_HDR = 12'd24; +`else +localparam OSD_HDR = 12'd0; +`endif + +reg osd_enable; +(* ramstyle="no_rw_check" *) reg [7:0] osd_buffer[OSD_HDR ? (4096+1024) : 4096]; + +reg info = 0; +reg [8:0] infoh; +reg [8:0] infow; +reg [21:0] infox; +reg [21:0] infoy; +reg [21:0] osd_h; +reg [21:0] osd_t; +reg [21:0] osd_w; + +reg [1:0] rot = 0; + +always@(posedge clk_sys) begin + reg [12:0] bcnt; + reg [7:0] cmd; + reg has_cmd; + reg old_strobe; + reg highres = 0; + + osd_t <= rot[0] ? OSD_WIDTH : (OSD_HEIGHT<<1); + osd_h <= rot[0] ? (info ? infow : OSD_WIDTH) : info ? infoh : (OSD_HEIGHT<> (9-rot[0])) > 1) ? (((cnt+1'b1) >> (9-rot[0])) - 1'd1) : 22'd0; + pixcnt <= 0; + end +end + +reg [2:0] osd_de; +reg osd_pixel; +reg [21:0] v_cnt; +reg v_cnt_h, v_cnt_1, v_cnt_2, v_cnt_3, v_cnt_4; +reg [21:0] v_osd_start_h, v_osd_start_1, v_osd_start_2, v_osd_start_3, v_osd_start_4, v_osd_start_5; +reg [21:0] v_info_start_h, v_info_start_1, v_info_start_2, v_info_start_3, v_info_start_4, v_info_start_5; + +wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR); + +// pipeline the comparisons a bit +always @(posedge clk_video) if(ce_pix) begin + v_cnt_h <= v_cnt <= osd_t; + v_cnt_1 <= v_cnt < 320; + v_cnt_2 <= v_cnt < 640; + v_cnt_3 <= v_cnt < 960; + v_cnt_4 <= v_cnt < 1280; + + v_osd_start_h <= (v_cnt-(osd_h_hdr>>1))>>1; + v_osd_start_1 <= (v_cnt-osd_h_hdr)>>1; + v_osd_start_2 <= (v_cnt-(osd_h_hdr<<1))>>1; + v_osd_start_3 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<1)))>>1; + v_osd_start_4 <= (v_cnt-(osd_h_hdr<<2))>>1; + v_osd_start_5 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<2)))>>1; + + v_info_start_h <= rot[0] ? infox : infoy; + v_info_start_1 <= rot[0] ? infox : infoy; + v_info_start_2 <= rot[0] ? (infox<<1) : (infoy<<1); + v_info_start_3 <= rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1)); + v_info_start_4 <= rot[0] ? (infox << 2) : (infoy << 2); + v_info_start_5 <= rot[0] ? (infox + (infox << 2)) : (infoy + (infoy << 2)); +end + +always @(posedge clk_video) begin + reg deD; + reg [2:0] osd_div; + reg [2:0] multiscan; + reg [7:0] osd_byte; + reg [23:0] h_cnt; + reg [21:0] dsp_width; + reg [21:0] osd_vcnt; + reg [21:0] h_osd_start; + reg [21:0] v_osd_start; + reg [21:0] osd_hcnt; + reg [21:0] osd_hcnt2; + reg osd_de1,osd_de2; + reg [1:0] osd_en; + reg f1; + reg half; + + if(ce_pix) begin + + deD <= de_in; + if(~&h_cnt) h_cnt <= h_cnt + 1'd1; + + if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1; + if(~&osd_hcnt2) osd_hcnt2 <= osd_hcnt2 + 1'd1; + + if (h_cnt == h_osd_start) begin + osd_de[0] <= osd_en[1] && osd_h && ( + osd_vcnt[11] ? (osd_vcnt[7] && (osd_vcnt[6:0] >= 4) && (osd_vcnt[6:0] < 19)) : + (info && (rot == 3)) ? !osd_vcnt[21:8] : + (osd_vcnt < osd_h) + ); + osd_hcnt <= 0; + osd_hcnt2 <= 0; + if(info && rot == 1) osd_hcnt2 <= 22'd128-infoh; + end + if (osd_hcnt+1 == osd_w) osd_de[0] <= 0; + + // falling edge of de + if(!de_in && deD) dsp_width <= h_cnt[21:0]; + + // rising edge of de + if(de_in && !deD) begin + h_cnt <= 0; + v_cnt <= v_cnt + 1'd1; + h_osd_start <= info ? (rot[0] ? infoy : infox) : (((dsp_width - osd_w)>>1) - 2'd2); + + if(h_cnt > {dsp_width, 2'b00}) begin + v_cnt <= 1; + f1 <= ~f1; // skip every other frame for interlace compatibility. + if(~f1) begin + + osd_en <= (osd_en << 1) | osd_enable; + if(~osd_enable) osd_en <= 0; + + half <= 0; + if(v_cnt_h) begin + multiscan <= 0; + v_osd_start <= info ? v_info_start_h : v_osd_start_h; + half <= 1; + end + else if(v_cnt_1 | (rot[0] & v_cnt_2)) begin + multiscan <= 0; + v_osd_start <= info ? v_info_start_1 : v_osd_start_1; + end + else if(rot[0] ? v_cnt_3 : v_cnt_2) begin + multiscan <= 1; + v_osd_start <= info ? v_info_start_2 : v_osd_start_2; + end + else if(rot[0] ? v_cnt_4 : v_cnt_3) begin + multiscan <= 2; + v_osd_start <= info ? v_info_start_3 : v_osd_start_3; + end + else if(rot[0] | v_cnt_4) begin + multiscan <= 3; + v_osd_start <= info ? v_info_start_4 : v_osd_start_4; + end + else begin + multiscan <= 4; + v_osd_start <= info ? v_info_start_5 : v_osd_start_5; + end + end + end + + osd_div <= osd_div + 1'd1; + if(osd_div == multiscan) begin + osd_div <= 0; + if(~osd_vcnt[10]) osd_vcnt <= osd_vcnt + 1'd1 + half; + if(osd_vcnt == 'b100010011111 && ~info) osd_vcnt <= 0; + end + if(v_osd_start == v_cnt) begin + {osd_div,osd_vcnt} <= 0; + if(info && rot == 3) osd_vcnt <= 22'd256-infow; + else if(OSD_HDR && !rot) osd_vcnt <= {~info, 3'b000, ~info, 7'b0000000}; + end + end + + osd_byte <= osd_buffer[rot[0] ? ({osd_hcnt2[6:3], osd_vcnt[7:0]} ^ { {4{~rot[1]}}, {8{rot[1]}} }) : {osd_vcnt[7:3], osd_hcnt[7:0]}]; + osd_pixel <= osd_byte[rot[0] ? ((osd_hcnt2[2:0]-1'd1) ^ {3{~rot[1]}}) : osd_vcnt[2:0]]; + osd_de[2:1] <= osd_de[1:0]; + end +end + +reg [23:0] rdout; +assign dout = rdout; + +always @(posedge clk_video) begin + reg [23:0] ordout1, nrdout1, rdout2, rdout3; + reg de1,de2,de3; + reg osd_mux; + reg vs1,vs2,vs3; + reg hs1,hs2,hs3; + + nrdout1 <= din; + ordout1 <= {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]},// 23:16 + {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]},// 15:8 + {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; // 7:0 + + osd_mux <= ~osd_de[2]; + rdout2 <= osd_mux ? nrdout1 : ordout1; + rdout3 <= rdout2; + + de1 <= de_in; de2 <= de1; de3 <= de2; + hs1 <= hs_in; hs2 <= hs1; hs3 <= hs2; + vs1 <= vs_in; vs2 <= vs1; vs3 <= vs2; + + rdout <= rdout3; + de_out <= de3; + hs_out <= hs3; + vs_out <= vs3; +end + +endmodule diff --git a/sys/pll.13.qip b/sys/pll.13.qip new file mode 100644 index 0000000..a6a1dca --- /dev/null +++ b/sys/pll.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll.v +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll/pll_0002.v + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.13.qip b/sys/pll_audio.13.qip new file mode 100644 index 0000000..e987931 --- /dev/null +++ b/sys/pll_audio.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"] +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"] + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.qip b/sys/pll_audio.qip new file mode 100644 index 0000000..abb013b --- /dev/null +++ b/sys/pll_audio.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_audio" -name MISC_FILE [file join $::quartus(qip_path) "pll_audio.cmp"] +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlv" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_audio" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_NAME "cGxsX2F1ZGlvXzAwMDI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MjQuNTc2::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MTUyODMyMTE2Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MTc=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MjQuNTc2MDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSw5LDgsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwyLDIwLDQwMDAsNDE3Ljc5MiBNSHosMTUyODMyMTE2Myxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio.v"] +set_global_assignment -library "pll_audio" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.v"] +set_global_assignment -library "pll_audio" -name QIP_FILE [file join $::quartus(qip_path) "pll_audio/pll_audio_0002.qip"] + +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_audio_0002" -library "pll_audio" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_audio.v b/sys/pll_audio.v new file mode 100644 index 0000000..e96b248 --- /dev/null +++ b/sys/pll_audio.v @@ -0,0 +1,252 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll_audio.v + +// Generated using ACDS version 17.0 602 + +`timescale 1 ps / 1 ps +module pll_audio ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0 // outclk0.clk + ); + + pll_audio_0002 pll_audio_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .locked () // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_audio.vo +// RELATED_FILES: pll_audio.v, pll_audio_0002.v diff --git a/sys/pll_audio/pll_audio_0002.qip b/sys/pll_audio/pll_audio_0002.qip new file mode 100644 index 0000000..dadd4b8 --- /dev/null +++ b/sys/pll_audio/pll_audio_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_audio_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_audio/pll_audio_0002.v b/sys/pll_audio/pll_audio_0002.v new file mode 100644 index 0000000..37eea13 --- /dev/null +++ b/sys/pll_audio/pll_audio_0002.v @@ -0,0 +1,87 @@ +`timescale 1ns/10ps +module pll_audio_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(1), + .output_clock_frequency0("24.576000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("0 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/sys/pll_cfg.qip b/sys/pll_cfg.qip new file mode 100644 index 0000000..0b560f9 --- /dev/null +++ b/sys/pll_cfg.qip @@ -0,0 +1,5 @@ +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/pll_cfg_hdmi.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_top.v"] +set_global_assignment -library "pll_cfg" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_cfg/altera_pll_reconfig_core.v"] diff --git a/sys/pll_cfg/altera_pll_reconfig_core.v b/sys/pll_cfg/altera_pll_reconfig_core.v new file mode 100644 index 0000000..8499567 --- /dev/null +++ b/sys/pll_cfg/altera_pll_reconfig_core.v @@ -0,0 +1,2184 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +`timescale 1ps/1ps + +module altera_pll_reconfig_core +#( + parameter reconf_width = 64, + parameter device_family = "Cyclone V", + // MIF Streaming parameters + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + parameter ROM_ADDR_WIDTH = 9, + parameter ROM_DATA_WIDTH = 32, + parameter ROM_NUM_WORDS = 512 +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire [31:0] mgmt_readdata, + output wire mgmt_waitrequest, + input wire [5:0] mgmt_address, + input wire mgmt_read, + input wire mgmt_write, + input wire [31:0] mgmt_writedata, + + //other + output wire mif_start_out, + output reg [ROM_ADDR_WIDTH-1:0] mif_base_addr +); + localparam mode_WR = 1'b0; + localparam mode_POLL = 1'b1; + localparam MODE_REG = 6'b000000; + localparam STATUS_REG = 6'b000001; + localparam START_REG = 6'b000010; + localparam N_REG = 6'b000011; + localparam M_REG = 6'b000100; + localparam C_COUNTERS_REG = 6'b000101; + localparam DPS_REG = 6'b000110; + localparam DSM_REG = 6'b000111; + localparam BWCTRL_REG = 6'b001000; + localparam CP_CURRENT_REG = 6'b001001; + localparam ANY_DPRIO = 6'b100000; + localparam CNT_BASE = 5'b001010; + localparam VCO_REG = 6'b011100; + localparam MIF_REG = 6'b011111; + + //C Counters + localparam number_of_counters = 5'd18; + localparam CNT_0 = 1'd0, CNT_1 = 5'd1, CNT_2 = 5'd2, + CNT_3 = 5'd3, CNT_4 = 5'd4, CNT_5 = 5'd5, + CNT_6 = 5'd6, CNT_7 = 5'd7, CNT_8 = 5'd8, + CNT_9 = 5'd9, CNT_10 = 5'd10, CNT_11 = 5'd11, + CNT_12 = 5'd12, CNT_13 = 5'd13, CNT_14 = 5'd14, + CNT_15 = 5'd15, CNT_16 = 5'd16, CNT_17 = 5'd17; + //C counter addresses + localparam C_CNT_0_DIV_ADDR = 5'h00; + localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11; + localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15; + localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17; + localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14; + localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16; + //N counter addresses + localparam N_CNT_DIV_ADDR = 5'h13; + localparam N_CNT_BYPASS_EN_ADDR = 5'h15; + localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17; + //M counter addresses + localparam M_CNT_DIV_ADDR = 5'h12; + localparam M_CNT_BYPASS_EN_ADDR = 5'h15; + localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17; + + //DSM address + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18; + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19; + localparam DSM_K_READY_ADDR = 5'h17; + localparam DSM_K_DITHER_ADDR = 5'h17; + localparam DSM_OUT_SEL_ADDR = 6'h30; + + //Other DSM params + localparam DSM_K_READY_BIT_INDEX = 4'd11; + //BWCTRL address + //Bit 0-3 of addr + localparam BWCTRL_ADDR = 6'h30; + //CP_CURRENT address + //Bit 0-2 of addr + localparam CP_CURRENT_ADDR = 6'h31; + + // VCODIV address + localparam VCO_ADDR = 5'h17; + + localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4, + FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10, + ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15; + localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10; + + wire clk; + wire reset; + wire gnd; + + wire [5: 0] slave_address; + wire slave_read; + wire slave_write; + wire [31: 0] slave_writedata; + + reg [31: 0] slave_readdata_d; + reg [31: 0] slave_readdata_q; + wire slave_waitrequest; + reg slave_mode; + + assign clk = mgmt_clk; + + assign slave_address = mgmt_address; + assign slave_read = mgmt_read; + assign slave_write = mgmt_write; + assign slave_writedata = mgmt_writedata; + + reg read_waitrequest; + // Outputs + assign mgmt_readdata = slave_readdata_q; + assign mgmt_waitrequest = slave_waitrequest | read_waitrequest; //Read waitrequest asserted in polling mode + + //internal signals + wire locked_orig; + wire locked; + + wire pll_start; + wire pll_start_valid; + reg status_read; + wire read_slave_mode_asserted; + + wire pll_start_asserted; + + reg [1:0] current_state; + reg [1:0] next_state; + + reg status;//0=busy, 1=ready + //user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load); + //declaring the init wires. These will have 0 on them for 64 clk cycles + wire [ 5:0] init_dprio_address; + wire init_dprio_read; + wire [ 1:0] init_dprio_byteen; + wire init_dprio_write; + wire [15:0] init_dprio_writedata; + + wire init_atpgmode; + wire init_mdio_dis; + wire init_scanen; + wire init_ser_shift_load; + wire dprio_init_done; + + //DPRIO output signals after initialization is done + wire dprio_clk; + reg avmm_dprio_write; + reg avmm_dprio_read; + reg [5:0] avmm_dprio_address; + reg [15:0] avmm_dprio_writedata; + reg [1:0] avmm_dprio_byteen; + wire avmm_atpgmode; + wire avmm_mdio_dis; + wire avmm_scanen; + + //Final output wires that are muxed between the init and avmm wires. + wire dprio_init_reset; + wire [5:0] dprio_address /*synthesis keep*/; + wire dprio_read/*synthesis keep*/; + wire [1:0] dprio_byteen/*synthesis keep*/; + wire dprio_write/*synthesis keep*/; + wire [15:0] dprio_writedata/*synthesis keep*/; + wire dprio_mdio_dis/*synthesis keep*/; + wire dprio_ser_shift_load/*synthesis keep*/; + wire dprio_atpgmode/*synthesis keep*/; + wire dprio_scanen/*synthesis keep*/; + + + //other PLL signals for dyn ph shift + wire phase_done/*synthesis keep*/; + wire phase_en/*synthesis keep*/; + wire up_dn/*synthesis keep*/; + wire [4:0] cnt_sel; + + //DPRIO input signals + wire [15:0] dprio_readdata; + + //internal logic signals + //storage registers for user sent data + reg dprio_temp_read_1; + reg dprio_temp_read_2; + reg dprio_start; + reg mif_start_assert; + reg dps_start_assert; + wire usr_valid_changes; + reg [3:0] dprio_cur_state; + reg [3:0] dprio_next_state; + reg [15:0] dprio_temp_m_n_c_readdata_1_d; + reg [15:0] dprio_temp_m_n_c_readdata_2_d; + reg [15:0] dprio_temp_m_n_c_readdata_1_q; + reg [15:0] dprio_temp_m_n_c_readdata_2_q; + reg dprio_write_done; + //C counters signals + reg [7:0] usr_c_cnt_lo; + reg [7:0] usr_c_cnt_hi; + reg usr_c_cnt_bypass_en; + reg usr_c_cnt_odd_duty_div_en; + reg [7:0] temp_c_cnt_lo [0:17]; + reg [7:0] temp_c_cnt_hi [0:17]; + reg temp_c_cnt_bypass_en [0:17]; + reg temp_c_cnt_odd_duty_div_en [0:17]; + reg any_c_cnt_changed; + reg all_c_cnt_done_q; + reg all_c_cnt_done_d; + reg [17:0] c_cnt_changed; + reg [17:0] c_cnt_done_d; + reg [17:0] c_cnt_done_q; + //N counter signals + reg [7:0] usr_n_cnt_lo; + reg [7:0] usr_n_cnt_hi; + reg usr_n_cnt_bypass_en; + reg usr_n_cnt_odd_duty_div_en; + reg n_cnt_changed; + reg n_cnt_done_d; + reg n_cnt_done_q; + //M counter signals + reg [7:0] usr_m_cnt_lo; + reg [7:0] usr_m_cnt_hi; + reg usr_m_cnt_bypass_en; + reg usr_m_cnt_odd_duty_div_en; + reg m_cnt_changed; + reg m_cnt_done_d; + reg m_cnt_done_q; + //dyn phase regs + reg [15:0] usr_num_shifts; + reg [4:0] usr_cnt_sel /*synthesis preserve*/; + reg usr_up_dn; + reg dps_changed; + wire dps_changed_valid; + wire dps_done; + + //DSM Signals + reg [31:0] usr_k_value; + reg dsm_k_changed; + reg dsm_k_done_d; + reg dsm_k_done_q; + reg dsm_k_ready_false_done_d; + //BW signals + reg [3:0] usr_bwctrl_value; + reg bwctrl_changed; + reg bwctrl_done_d; + reg bwctrl_done_q; + //CP signals + reg [2:0] usr_cp_current_value; + reg cp_current_changed; + reg cp_current_done_d; + reg cp_current_done_q; + //VCO signals + reg usr_vco_value; + reg vco_changed; + reg vco_done_d; + reg vco_done_q; + //Manual DPRIO signals + reg manual_dprio_done_q; + reg manual_dprio_done_d; + reg manual_dprio_changed; + reg [5:0] usr_dprio_address; + reg [15:0] usr_dprio_writedata_0; + reg usr_r_w; + //keeping track of which operation happened last + reg [5:0] operation_address; + // Address wires for all C_counter DPRIO registers + // These are outputs of LUTS, changing depending + // on whether PLL_0 or PLL_1 being used + + + //Fitter will tell if FPLL1 is being used + wire fpll_1; + + // other + reg mif_reg_asserted; + // MAIN FSM + + // Synchronize locked signal + altera_std_synchronizer #( + .depth(3) + ) altera_std_synchronizer_inst ( + .clk(mgmt_clk), + .reset_n(~mgmt_reset), + .din(locked_orig), + .dout(locked) + ); + + always @(posedge clk) + begin + if (reset) + begin + dprio_cur_state <= DPRIO_IDLE; + current_state <= IDLE; + end + else + begin + current_state <= next_state; + dprio_cur_state <= dprio_next_state; + end + end + + always @(*) + begin + case(current_state) + IDLE: + begin + if (pll_start & !slave_waitrequest & usr_valid_changes) + next_state = WAIT_ON_LOCK; + else + next_state = IDLE; + end + WAIT_ON_LOCK: + begin + if (locked & dps_done & dprio_write_done) // received locked high from PLL + begin + if (slave_mode==mode_WR) //if the mode is waitrequest, then + // goto IDLE state directly + next_state = IDLE; + else + next_state = LOCKED; //otherwise go the locked state + end + else + next_state = WAIT_ON_LOCK; + end + + LOCKED: + begin + if (status_read) // stay in LOCKED until user reads status + next_state = IDLE; + else + next_state = LOCKED; + end + + default: next_state = 2'bxx; + + endcase + end + + + // ask the pll to start reconfig + assign pll_start = (pll_start_asserted & (current_state==IDLE)) ; + assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ; + + + + // WRITE OPERATIONS + assign pll_start_asserted = slave_write & (slave_address == START_REG); + assign mif_start_out = pll_start & mif_reg_asserted; + + //reading the mode register to determine what mode the slave will operate + //in. + always @(posedge clk) + begin + if (reset) + slave_mode <= mode_WR; + else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest) + slave_mode <= slave_writedata[0]; + end + + //record which values user wants to change. + + //reading in the actual values that need to be reconfigged and sending + //them to the PLL + always @(posedge clk) + begin + if (reset) + begin + //reset all regs here + //BW signals reset + usr_bwctrl_value <= 0; + bwctrl_changed <= 0; + bwctrl_done_q <= 0; + //CP signals reset + usr_cp_current_value <= 0; + cp_current_changed <= 0; + cp_current_done_q <= 0; + //VCO signals reset + usr_vco_value <= 0; + vco_changed <= 0; + vco_done_q <= 0; + //DSM signals reset + usr_k_value <= 0; + dsm_k_changed <= 0; + dsm_k_done_q <= 0; + //N counter signals reset + usr_n_cnt_lo <= 0; + usr_n_cnt_hi <= 0; + usr_n_cnt_bypass_en <= 0; + usr_n_cnt_odd_duty_div_en <= 0; + n_cnt_changed <= 0; + n_cnt_done_q <= 0; + //M counter signals reset + usr_m_cnt_lo <= 0; + usr_m_cnt_hi <= 0; + usr_m_cnt_bypass_en <= 0; + usr_m_cnt_odd_duty_div_en <= 0; + m_cnt_changed <= 0; + m_cnt_done_q <= 0; + //C counter signals reset + usr_c_cnt_lo <= 0; + usr_c_cnt_hi <= 0; + usr_c_cnt_bypass_en <= 0; + usr_c_cnt_odd_duty_div_en <= 0; + any_c_cnt_changed <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + //generic signals + dprio_start <= 0; + mif_start_assert <= 0; + dps_start_assert <= 0; + dprio_temp_m_n_c_readdata_1_q <= 0; + dprio_temp_m_n_c_readdata_2_q <= 0; + c_cnt_done_q <= 0; + //DPS signals + usr_up_dn <= 0; + usr_cnt_sel <= 0; + usr_num_shifts <= 0; + dps_changed <= 0; + //manual DPRIO signals + manual_dprio_changed <= 0; + usr_dprio_address <= 0; + usr_dprio_writedata_0 <= 0; + usr_r_w <= 0; + operation_address <= 0; + mif_reg_asserted <= 0; + mif_base_addr <= 0; + end + else + begin + if (dprio_temp_read_1) + begin + dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d; + end + if (dprio_temp_read_2) + begin + dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d; + end + if ((dps_done)) dps_changed <= 0; + if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d; + if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d; + if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d; + if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d; + if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d; + if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d; + if (cp_current_done_d) cp_current_done_q <= cp_current_done_d; + if (vco_done_d) vco_done_q <= vco_done_d; + if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d; + + if (mif_start_out == 1'b1) + mif_start_assert <= 0; // Signaled MIF block to start, so deassert on next cycle + + if (dps_done != 1'b1) + dps_start_assert <= 0; // DPS has started, so dessert its start signal on next cycle + + if (dprio_next_state == ONE) + dprio_start <= 0; + if (dprio_write_done) + begin + bwctrl_done_q <= 0; + cp_current_done_q <= 0; + vco_done_q <= 0; + dsm_k_done_q <= 0; + dsm_k_done_q <= 0; + n_cnt_done_q <= 0; + m_cnt_done_q <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + dsm_k_changed <= 0; + n_cnt_changed <= 0; + m_cnt_changed <= 0; + any_c_cnt_changed <= 0; + bwctrl_changed <= 0; + cp_current_changed <= 0; + vco_changed <= 0; + manual_dprio_changed <= 0; + manual_dprio_done_q <= 0; + if (dps_changed | dps_changed_valid | !dps_done ) + begin + usr_cnt_sel <= usr_cnt_sel; + end + else + begin + usr_cnt_sel <= 0; + end + mif_reg_asserted <= 0; + end + else + begin + dsm_k_changed <= dsm_k_changed; + n_cnt_changed <= n_cnt_changed; + m_cnt_changed <= m_cnt_changed; + any_c_cnt_changed <= any_c_cnt_changed; + manual_dprio_changed <= manual_dprio_changed; + mif_reg_asserted <= mif_reg_asserted; + usr_cnt_sel <= usr_cnt_sel; + end + + + if(slave_write & !slave_waitrequest) + begin + case(slave_address) + //read in the values here from the user and act on them + DSM_REG: + begin + operation_address <= DSM_REG; + usr_k_value <= slave_writedata[31:0]; + dsm_k_changed <= 1'b1; + dsm_k_done_q <= 0; + dprio_start <= 1'b1; + end + N_REG: + begin + operation_address <= N_REG; + usr_n_cnt_lo <= slave_writedata[7:0]; + usr_n_cnt_hi <= slave_writedata[15:8]; + usr_n_cnt_bypass_en <= slave_writedata[16]; + usr_n_cnt_odd_duty_div_en <= slave_writedata[17]; + n_cnt_changed <= 1'b1; + n_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + M_REG: + begin + operation_address <= M_REG; + usr_m_cnt_lo <= slave_writedata[7:0]; + usr_m_cnt_hi <= slave_writedata[15:8]; + usr_m_cnt_bypass_en <= slave_writedata[16]; + usr_m_cnt_odd_duty_div_en <= slave_writedata[17]; + m_cnt_changed <= 1'b1; + m_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + DPS_REG: + begin + operation_address <= DPS_REG; + usr_num_shifts <= slave_writedata[15:0]; + usr_cnt_sel <= slave_writedata[20:16]; + usr_up_dn <= slave_writedata[21]; + dps_changed <= 1; + dps_start_assert <= 1; + end + C_COUNTERS_REG: + begin + operation_address <= C_COUNTERS_REG; + usr_c_cnt_lo <= slave_writedata[7:0]; + usr_c_cnt_hi <= slave_writedata[15:8]; + usr_c_cnt_bypass_en <= slave_writedata[16]; + usr_c_cnt_odd_duty_div_en <= slave_writedata[17]; + usr_cnt_sel <= slave_writedata[22:18]; + any_c_cnt_changed <= 1'b1; + all_c_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + BWCTRL_REG: + begin + usr_bwctrl_value <= slave_writedata[3:0]; + bwctrl_changed <= 1'b1; + bwctrl_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= BWCTRL_REG; + end + CP_CURRENT_REG: + begin + usr_cp_current_value <= slave_writedata[2:0]; + cp_current_changed <= 1'b1; + cp_current_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= CP_CURRENT_REG; + end + VCO_REG: + begin + usr_vco_value <= slave_writedata[0]; + vco_changed <= 1'b1; + vco_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= VCO_REG; + end + ANY_DPRIO: + begin + operation_address <= ANY_DPRIO; + manual_dprio_changed <= 1'b1; + usr_dprio_address <= slave_writedata[5:0]; + usr_dprio_writedata_0 <= slave_writedata[21:6]; + usr_r_w <= slave_writedata[22]; + manual_dprio_done_q <= 0; + dprio_start <= 1'b1; + end + MIF_REG: + begin + mif_reg_asserted <= 1'b1; + mif_base_addr <= slave_writedata[ROM_ADDR_WIDTH-1:0]; + mif_start_assert <= 1'b1; + end + endcase + end + end + end + //C Counter assigning values to the 2-d array of values for each C counter + + reg [4:0] j; + always @(posedge clk) + begin + + if (reset) + begin + c_cnt_changed[17:0] <= 0; + for (j = 0; j < number_of_counters; j = j + 1'b1) + begin : c_cnt_reset + temp_c_cnt_bypass_en[j] <= 0; + temp_c_cnt_odd_duty_div_en[j] <= 0; + temp_c_cnt_lo[j][7:0] <= 0; + temp_c_cnt_hi[j][7:0] <= 0; + end + end + else + begin + if (dprio_write_done) + begin + c_cnt_changed <= 0; + end + if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG)) + begin + case (cnt_sel) + CNT_0: + begin + temp_c_cnt_lo [0] <= usr_c_cnt_lo; + temp_c_cnt_hi [0] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [0] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [0] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [0] <= 1'b1; + end + CNT_1: + begin + temp_c_cnt_lo [1] <= usr_c_cnt_lo; + temp_c_cnt_hi [1] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [1] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [1] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [1] <= 1'b1; + end + CNT_2: + begin + temp_c_cnt_lo [2] <= usr_c_cnt_lo; + temp_c_cnt_hi [2] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [2] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [2] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [2] <= 1'b1; + end + CNT_3: + begin + temp_c_cnt_lo [3] <= usr_c_cnt_lo; + temp_c_cnt_hi [3] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [3] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [3] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [3] <= 1'b1; + end + CNT_4: + begin + temp_c_cnt_lo [4] <= usr_c_cnt_lo; + temp_c_cnt_hi [4] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [4] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [4] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [4] <= 1'b1; + end + CNT_5: + begin + temp_c_cnt_lo [5] <= usr_c_cnt_lo; + temp_c_cnt_hi [5] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [5] <= 1'b1; + end + CNT_6: + begin + temp_c_cnt_lo [6] <= usr_c_cnt_lo; + temp_c_cnt_hi [6] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [6] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [6] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [6] <= 1'b1; + end + CNT_7: + begin + temp_c_cnt_lo [7] <= usr_c_cnt_lo; + temp_c_cnt_hi [7] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [7] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [7] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [7] <= 1'b1; + end + CNT_8: + begin + temp_c_cnt_lo [8] <= usr_c_cnt_lo; + temp_c_cnt_hi [8] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [8] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [8] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [8] <= 1'b1; + end + CNT_9: + begin + temp_c_cnt_lo [9] <= usr_c_cnt_lo; + temp_c_cnt_hi [9] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [9] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [9] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [9] <= 1'b1; + end + CNT_10: + begin + temp_c_cnt_lo [10] <= usr_c_cnt_lo; + temp_c_cnt_hi [10] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [10] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [10] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [10] <= 1'b1; + end + CNT_11: + begin + temp_c_cnt_lo [11] <= usr_c_cnt_lo; + temp_c_cnt_hi [11] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [11] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [11] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [11] <= 1'b1; + end + CNT_12: + begin + temp_c_cnt_lo [12] <= usr_c_cnt_lo; + temp_c_cnt_hi [12] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [12] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [12] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [12] <= 1'b1; + end + CNT_13: + begin + temp_c_cnt_lo [13] <= usr_c_cnt_lo; + temp_c_cnt_hi [13] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [13] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [13] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [13] <= 1'b1; + end + CNT_14: + begin + temp_c_cnt_lo [14] <= usr_c_cnt_lo; + temp_c_cnt_hi [14] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [14] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [14] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [14] <= 1'b1; + end + CNT_15: + begin + temp_c_cnt_lo [15] <= usr_c_cnt_lo; + temp_c_cnt_hi [15] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [15] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [15] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [15] <= 1'b1; + end + CNT_16: + begin + temp_c_cnt_lo [16] <= usr_c_cnt_lo; + temp_c_cnt_hi [16] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [16] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [16] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [16] <= 1'b1; + end + CNT_17: + begin + temp_c_cnt_lo [17] <= usr_c_cnt_lo; + temp_c_cnt_hi [17] <= usr_c_cnt_hi; + temp_c_cnt_bypass_en [17] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [17] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [17] <= 1'b1; + end + endcase + + end + end + end + + + //logic to handle which writes the user indicated and wants to start. + assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed; + + + //start the reconfig operations by writing to the DPRIO + reg break_loop; + reg [4:0] i; + always @(*) + begin + dprio_temp_read_1 = 0; + dprio_temp_read_2 = 0; + dprio_temp_m_n_c_readdata_1_d = 0; + dprio_temp_m_n_c_readdata_2_d = 0; + break_loop = 0; + dprio_next_state = DPRIO_IDLE; + avmm_dprio_write = 0; + avmm_dprio_read = 0; + avmm_dprio_address = 0; + avmm_dprio_writedata = 0; + avmm_dprio_byteen = 0; + dprio_write_done = 1; + manual_dprio_done_d = 0; + n_cnt_done_d = 0; + dsm_k_done_d = 0; + dsm_k_ready_false_done_d = 0; + m_cnt_done_d = 0; + c_cnt_done_d[17:0] = 0; + all_c_cnt_done_d = 0; + bwctrl_done_d = 0; + cp_current_done_d = 0; + vco_done_d = 0; + i = 0; + + // Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes) + if (dprio_start | mif_start_assert) + dprio_write_done = 0; + + if (current_state == WAIT_ON_LOCK) + begin + case (dprio_cur_state) + ONE: + begin + if (n_cnt_changed & !n_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = N_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_n_cnt_lo; + avmm_dprio_writedata[15:8] = usr_n_cnt_hi; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = M_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_m_cnt_lo; + avmm_dprio_writedata[15:8] = usr_m_cnt_hi; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_hilo + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i; + else avmm_dprio_address = C_CNT_0_DIV_ADDR + i; + avmm_dprio_writedata[7:0] = temp_c_cnt_lo[i]; + avmm_dprio_writedata[15:8] = temp_c_cnt_hi[i]; + //To break from the loop, since only one counter + //is addressed at a time + break_loop = 1'b1; + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (cp_current_changed & !cp_current_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (vco_changed & !vco_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_write = usr_r_w; + avmm_dprio_address = usr_dprio_address; + avmm_dprio_writedata[15:0] = usr_dprio_writedata_0; + end + else dprio_next_state = DPRIO_IDLE; + end + + TWO: + begin + //handle reading the two setting bits on n_cnt, then + //writing them back while preserving other bits. + //Issue two consecutive reads then wait; readLatency=3 + dprio_write_done = 0; + dprio_next_state = THREE; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + //reading the K ready 16 bit word. Need to write 0 to it + //afterwards to indicate that K has not been done writing + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + dprio_next_state = FOUR; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + dprio_next_state = FOUR; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + dprio_next_state = FOUR; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + dprio_next_state = FOUR; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + avmm_dprio_read = ~usr_r_w; + avmm_dprio_address = usr_dprio_address; + dprio_next_state = DPRIO_DONE; + end + else dprio_next_state = DPRIO_IDLE; + end + THREE: + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + dprio_next_state = FOUR; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + else dprio_next_state = DPRIO_IDLE; + end + FOUR: + begin + dprio_temp_read_1 = 1'b1; + dprio_write_done = 0; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + dprio_temp_m_n_c_readdata_1_d = dprio_readdata; + dprio_next_state = FIVE; + end + else dprio_next_state = DPRIO_IDLE; + end + FIVE: + begin + dprio_write_done = 0; + dprio_temp_read_2 = 1'b1; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + //this is where DSM ready value comes. + //Need to store in a register to be used later + dprio_temp_m_n_c_readdata_2_d = dprio_readdata; + dprio_next_state = SIX; + end + else dprio_next_state = DPRIO_IDLE; + end + SIX: + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = SEVEN; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_bypass_en; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_bypass_en; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_write = 0; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_write = 0; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_write = 0; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_write = 0; + end + else dprio_next_state = DPRIO_IDLE; + end + SEVEN: + begin + dprio_write_done = 0; + dprio_next_state = EIGHT; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en; + n_cnt_done_d = 1'b1; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en; + m_cnt_done_d = 1'b1; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0; + dsm_k_ready_false_done_d = 1'b1; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + avmm_dprio_writedata[3:0] = usr_bwctrl_value; + bwctrl_done_d = 1'b1; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + avmm_dprio_writedata[2:0] = usr_cp_current_value; + cp_current_done_d = 1'b1; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + avmm_dprio_writedata[8] = usr_vco_value; + vco_done_d = 1'b1; + end + + + //if all C_cnt that were changed are done, then assert all_c_cnt_done + if (c_cnt_done_d == c_cnt_changed) + all_c_cnt_done_d = 1'b1; + if (n_cnt_changed & n_cnt_done_d) + dprio_next_state = DPRIO_DONE; + if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q) + dprio_next_state = ONE; + else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q) + dprio_next_state = ONE; + else if (dsm_k_changed & !dsm_k_ready_false_done_d) + dprio_next_state = TWO; + else if (dsm_k_changed & !dsm_k_done_q) + dprio_next_state = EIGHT; + else if (bwctrl_changed & !bwctrl_done_d) + dprio_next_state = TWO; + else if (cp_current_changed & !cp_current_done_d) + dprio_next_state = TWO; + else if (vco_changed & !vco_done_d) + dprio_next_state = TWO; + else + begin + dprio_next_state = DPRIO_DONE; + dprio_write_done = 1'b1; + end + end + //finish the rest of the DSM reads/writes + //writing k value, writing k_ready to 1. + EIGHT: + begin + dprio_write_done = 0; + dprio_next_state = NINE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0; + avmm_dprio_writedata[15:0] = usr_k_value[15:0]; + end + end + NINE: + begin + dprio_write_done = 0; + dprio_next_state = TEN; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1; + avmm_dprio_writedata[15:0] = usr_k_value[31:16]; + end + end + TEN: + begin + dprio_write_done = 0; + dprio_next_state = ONE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + //already have the readdata for DSM_K_READY_ADDR since we read it + //earlier. Just reuse here + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1; + dsm_k_done_d = 1'b1; + end + end + DPRIO_DONE: + begin + dprio_write_done = 1'b1; + if (dprio_start) dprio_next_state = DPRIO_IDLE; + else dprio_next_state = DPRIO_DONE; + end + DPRIO_IDLE: + begin + if (dprio_start) dprio_next_state = ONE; + else dprio_next_state = DPRIO_IDLE; + end + default: dprio_next_state = 4'bxxxx; + endcase + end + + end + + + //assert the waitreq signal according to the state of the slave + assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0; + + // Read operations + always @(*) + begin + status = 0; + if (slave_mode == mode_POLL) + //asserting status to 1 if the slave is done. + status = (current_state == LOCKED); + end + //************************************************************// + //************************************************************// + //******************** READ STATE MACHINE ********************// + //************************************************************// + //************************************************************// + reg [1:0] current_read_state; + reg [1:0] next_read_state; + reg [5:0] slave_address_int_d; + reg [5:0] slave_address_int_q; + reg dprio_read_1; + reg [5:0] dprio_address_1; + reg [1:0] dprio_byteen_1; + reg [4:0] usr_cnt_sel_1; + localparam READ = 2'b00, READ_WAIT = 2'b01, READ_IDLE = 2'b10, READ_POST_WAIT = 2'b11; + + always @(*) + begin + if(next_read_state == READ_IDLE) + begin + read_waitrequest <= 1'b0; + end + else + begin + read_waitrequest <= 1'b1; + end + end + + always @(posedge clk) + begin + if (reset) + begin + current_read_state <= READ_IDLE; + slave_address_int_q <= 0; + slave_readdata_q <= 0; + end + else + begin + current_read_state <= next_read_state; + slave_address_int_q <= slave_address_int_d; + slave_readdata_q <= slave_readdata_d; + end + end + always @(*) + begin + dprio_read_1 = 0; + dprio_address_1 = 0; + dprio_byteen_1 = 0; + slave_address_int_d = 0; + slave_readdata_d = 0; + status_read = 0; + usr_cnt_sel_1 = 0; + case(current_read_state) + READ_IDLE: + begin + slave_address_int_d = 0; + next_read_state = READ_IDLE; + if ((current_state != WAIT_ON_LOCK) && slave_read) + begin + slave_address_int_d = slave_address; + if ((slave_address >= CNT_BASE) && (slave_address < CNT_BASE+18)) + begin + next_read_state = READ_WAIT; + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + usr_cnt_sel_1 = (slave_address[4:0] - CNT_BASE); + if (fpll_1) dprio_address_1 = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - cnt_sel; + else dprio_address_1 = C_CNT_0_DIV_ADDR + cnt_sel; + end + else + begin + case (slave_address) + MODE_REG: + begin + next_read_state = READ_WAIT; + slave_readdata_d = slave_mode; + end + STATUS_REG: + begin + next_read_state = READ_WAIT; + status_read = 1'b1; + slave_readdata_d = status; + end + N_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = N_CNT_DIV_ADDR; + next_read_state = READ_WAIT; + end + M_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = M_CNT_DIV_ADDR; + next_read_state = READ_WAIT; + end + BWCTRL_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = BWCTRL_ADDR; + next_read_state = READ_WAIT; + end + CP_CURRENT_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = CP_CURRENT_ADDR; + next_read_state = READ_WAIT; + end + VCO_REG: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = 1'b1; + dprio_address_1 = VCO_ADDR; + next_read_state = READ_WAIT; + end + ANY_DPRIO: + begin + dprio_byteen_1 = 2'b11; + dprio_read_1 = ~slave_writedata[22]; + dprio_address_1 = slave_writedata[5:0]; + next_read_state = READ_WAIT; + end + default : next_read_state = READ_IDLE; + endcase + end + end + else + next_read_state = READ_IDLE; + end + READ_WAIT: + begin + next_read_state = READ; + slave_address_int_d = slave_address_int_q; + case (slave_address_int_q) + MODE_REG: + begin + slave_readdata_d = slave_readdata_q; + end + STATUS_REG: + begin + slave_readdata_d = slave_readdata_q; + end + endcase + end + READ: + begin + next_read_state = READ_POST_WAIT; + slave_address_int_d = slave_address_int_q; + slave_readdata_d = dprio_readdata; + case (slave_address_int_q) + MODE_REG: + begin + slave_readdata_d = slave_readdata_q; + end + STATUS_REG: + begin + slave_readdata_d = slave_readdata_q; + end + BWCTRL_REG: + begin + slave_readdata_d = dprio_readdata[3:0]; + end + CP_CURRENT_REG: + begin + slave_readdata_d = dprio_readdata[2:0]; + end + VCO_REG: + begin + slave_readdata_d = dprio_readdata[8]; + end + ANY_DPRIO: + begin + slave_readdata_d = dprio_readdata; + end + endcase + end + READ_POST_WAIT: + begin + next_read_state = READ_IDLE; + end + default: next_read_state = 2'bxx; + endcase + end + + + dyn_phase_shift dyn_phase_shift_inst ( + .clk(clk), + .reset(reset), + .phase_done(phase_done), + .pll_start_valid(pll_start_valid), + .dps_changed(dps_changed), + .dps_changed_valid(dps_changed_valid), + .dprio_write_done(dprio_write_done), + .usr_num_shifts(usr_num_shifts), + .usr_cnt_sel(usr_cnt_sel|usr_cnt_sel_1), + .usr_up_dn(usr_up_dn), + .locked(locked), + .dps_done(dps_done), + .phase_en(phase_en), + .up_dn(up_dn), + .cnt_sel(cnt_sel)); + defparam dyn_phase_shift_inst.device_family = device_family; + + assign dprio_clk = clk; + self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset); + + dprio_mux dprio_mux_inst ( + .init_dprio_address(init_dprio_address), + .init_dprio_read(init_dprio_read), + .init_dprio_byteen(init_dprio_byteen), + .init_dprio_write(init_dprio_write), + .init_dprio_writedata(init_dprio_writedata), + + + .init_atpgmode(init_atpgmode), + .init_mdio_dis(init_mdio_dis), + .init_scanen(init_scanen), + .init_ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done), + + // Inputs from avmm master + .avmm_dprio_address(avmm_dprio_address | dprio_address_1), + .avmm_dprio_read(avmm_dprio_read | dprio_read_1), + .avmm_dprio_byteen(avmm_dprio_byteen | dprio_byteen_1), + .avmm_dprio_write(avmm_dprio_write), + .avmm_dprio_writedata(avmm_dprio_writedata), + + .avmm_atpgmode(avmm_atpgmode), + .avmm_mdio_dis(avmm_mdio_dis), + .avmm_scanen(avmm_scanen), + + // Outputs to fpll + .dprio_address(dprio_address), + .dprio_read(dprio_read), + .dprio_byteen(dprio_byteen), + .dprio_write(dprio_write), + .dprio_writedata(dprio_writedata), + + .atpgmode(dprio_atpgmode), + .mdio_dis(dprio_mdio_dis), + .scanen(dprio_scanen), + .ser_shift_load(dprio_ser_shift_load) + ); + + + fpll_dprio_init fpll_dprio_init_inst ( + .clk(clk), + .reset_n(~reset), + .locked(locked), + + //outputs + .dprio_address(init_dprio_address), + .dprio_read(init_dprio_read), + .dprio_byteen(init_dprio_byteen), + .dprio_write(init_dprio_write), + .dprio_writedata(init_dprio_writedata), + + .atpgmode(init_atpgmode), + .mdio_dis(init_mdio_dis), + .scanen(init_scanen), + .ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done)); + + //address luts, to be reconfigged by the Fitter + //FPLL_1 or 0 address lut + generic_lcell_comb lcell_fpll_0_1 ( + .dataa(1'b0), + .combout (fpll_1)); + defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_fpll_0_1.dont_touch = "on"; + defparam lcell_fpll_0_1.family = device_family; + + + wire dprio_read_combout; + generic_lcell_comb lcell_dprio_read ( + .dataa(fpll_1), + .datab(dprio_read), + .datac(1'b0), + .datad(1'b0), + .datae(1'b0), + .dataf(1'b0), + .combout (dprio_read_combout)); + defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_dprio_read.dont_touch = "on"; + defparam lcell_dprio_read.family = device_family; + + + + + + //assign reconfig_to_pll signals + assign reconfig_to_pll[0] = dprio_clk; + assign reconfig_to_pll[1] = ~dprio_init_reset; + assign reconfig_to_pll[2] = dprio_write; + assign reconfig_to_pll[3] = dprio_read_combout; + assign reconfig_to_pll[9:4] = dprio_address; + assign reconfig_to_pll[25:10] = dprio_writedata; + assign reconfig_to_pll[27:26] = dprio_byteen; + assign reconfig_to_pll[28] = dprio_ser_shift_load; + assign reconfig_to_pll[29] = dprio_mdio_dis; + assign reconfig_to_pll[30] = phase_en; + assign reconfig_to_pll[31] = up_dn; + assign reconfig_to_pll[36:32] = cnt_sel; + assign reconfig_to_pll[37] = dprio_scanen; + assign reconfig_to_pll[38] = dprio_atpgmode; + //assign reconfig_to_pll[40:37] = clken; + assign reconfig_to_pll[63:39] = 0; + + //assign reconfig_from_pll signals + assign dprio_readdata = reconfig_from_pll [15:0]; + assign locked_orig = reconfig_from_pll [16]; + assign phase_done = reconfig_from_pll [17]; + +endmodule +module self_reset (input wire mgmt_reset, input wire clk, output wire reset, output wire init_reset); + + localparam RESET_COUNTER_VALUE = 3'd2; + localparam INITIAL_WAIT_VALUE = 9'd340; + reg [9:0]counter; + reg local_reset; + reg usr_mode_init_wait; + initial + begin + local_reset = 1'b1; + counter = 0; + usr_mode_init_wait = 0; + end + + always @(posedge clk) + begin + if (mgmt_reset) + begin + counter <= 0; + end + else + begin + if (!usr_mode_init_wait) + begin + if (counter == INITIAL_WAIT_VALUE) + begin + local_reset <= 0; + usr_mode_init_wait <= 1'b1; + counter <= 0; + end + else + begin + counter <= counter + 1'b1; + end + end + else + begin + if (counter == RESET_COUNTER_VALUE) + local_reset <= 0; + else + counter <= counter + 1'b1; + end + end + end + assign reset = mgmt_reset | local_reset; + assign init_reset = local_reset; +endmodule + +module dprio_mux ( + // Inputs from init block + input [ 5:0] init_dprio_address, + input init_dprio_read, + input [ 1:0] init_dprio_byteen, + input init_dprio_write, + input [15:0] init_dprio_writedata, + + input init_atpgmode, + input init_mdio_dis, + input init_scanen, + input init_ser_shift_load, + input dprio_init_done, + + // Inputs from avmm master + input [ 5:0] avmm_dprio_address, + input avmm_dprio_read, + input [ 1:0] avmm_dprio_byteen, + input avmm_dprio_write, + input [15:0] avmm_dprio_writedata, + + input avmm_atpgmode, + input avmm_mdio_dis, + input avmm_scanen, + input avmm_ser_shift_load, + + // Outputs to fpll + output [ 5:0] dprio_address, + output dprio_read, + output [ 1:0] dprio_byteen, + output dprio_write, + output [15:0] dprio_writedata, + + output atpgmode, + output mdio_dis, + output scanen, + output ser_shift_load +); + + assign dprio_address = dprio_init_done ? avmm_dprio_address : init_dprio_address; + assign dprio_read = dprio_init_done ? avmm_dprio_read : init_dprio_read; + assign dprio_byteen = dprio_init_done ? avmm_dprio_byteen : init_dprio_byteen; + assign dprio_write = dprio_init_done ? avmm_dprio_write : init_dprio_write; + assign dprio_writedata = dprio_init_done ? avmm_dprio_writedata : init_dprio_writedata; + + assign atpgmode = init_atpgmode; + assign scanen = init_scanen; + assign mdio_dis = init_mdio_dis; + assign ser_shift_load = init_ser_shift_load ; +endmodule +module fpll_dprio_init ( + input clk, + input reset_n, + input locked, + + output [ 5:0] dprio_address, + output dprio_read, + output [ 1:0] dprio_byteen, + output dprio_write, + output [15:0] dprio_writedata, + + output reg atpgmode, + output reg mdio_dis, + output reg scanen, + output reg ser_shift_load, + output reg dprio_init_done +); + + reg [1:0] rst_n = 2'b00; + reg [6:0] count = 7'd0; + reg init_done_forever; + + // Internal versions of control signals + wire int_mdio_dis; + wire int_ser_shift_load; + wire int_dprio_init_done; + wire int_atpgmode/*synthesis keep*/; + wire int_scanen/*synthesis keep*/; + + + assign dprio_address = count[6] ? 5'b0 : count[5:0] ; + assign dprio_byteen = 2'b11; // always enabled + assign dprio_write = ~count[6] & reset_n ; // write for first 64 cycles + assign dprio_read = 1'b0; + assign dprio_writedata = 16'd0; + + assign int_ser_shift_load = count[6] ? |count[2:1] : 1'b1; + assign int_mdio_dis = count[6] ? ~count[2] : 1'b1; + assign int_dprio_init_done = ~init_done_forever ? (count[6] ? &count[2:0] : 1'b0) + : 1'b1; + assign int_atpgmode = 0; + assign int_scanen = 0; + + initial begin + count = 7'd0; + init_done_forever = 0; + mdio_dis = 1'b1; + ser_shift_load = 1'b1; + dprio_init_done = 1'b0; + scanen = 1'b0; + atpgmode = 1'b0; + end + + // reset synch. + always @(posedge clk or negedge reset_n) + if(!reset_n) rst_n <= 2'b00; + else rst_n <= {rst_n[0],1'b1}; + + // counter + always @(posedge clk) + begin + if (!rst_n[1]) + init_done_forever <= 1'b0; + else + begin + if (count[6] && &count[1:0]) + init_done_forever <= 1'b1; + end + end + always @(posedge clk or negedge rst_n[1]) + begin + if(!rst_n[1]) + begin + count <= 7'd0; + end + else if(~int_dprio_init_done) + begin + count <= count + 7'd1; + end + else + begin + count <= count; + end + end + + // outputs + always @(posedge clk) begin + mdio_dis <= int_mdio_dis; + ser_shift_load <= int_ser_shift_load; + dprio_init_done <= int_dprio_init_done; + atpgmode <= int_atpgmode; + scanen <= int_scanen; + end + +endmodule +module dyn_phase_shift +#( + parameter device_family = "Cyclone V" +) ( + + input wire clk, + input wire reset, + input wire phase_done, + input wire pll_start_valid, + input wire dps_changed, + input wire dprio_write_done, + input wire [15:0] usr_num_shifts, + input wire [4:0] usr_cnt_sel, + input wire usr_up_dn, + input wire locked, + + //output + output wire dps_done, + output reg phase_en, + output wire up_dn, + output wire dps_changed_valid, + output wire [4:0] cnt_sel); + + + + reg first_phase_shift_d; + reg first_phase_shift_q; + reg [15:0] phase_en_counter; + reg [3:0] dps_current_state; + reg [3:0] dps_next_state; + localparam DPS_START = 4'd0, DPS_WAIT_PHASE_DONE = 4'd1, DPS_DONE = 4'd2, DPS_WAIT_PHASE_EN = 4'd3, DPS_WAIT_DPRIO_WRITING = 4'd4, DPS_CHANGED = 4'd5; + localparam PHASE_EN_WAIT_COUNTER = 5'd1; + + reg [15:0] shifts_done_counter; + reg phase_done_final; + wire gnd /*synthesis keep*/; + + //fsm + //always block controlling the state regs + always @(posedge clk) + begin + if (reset) + begin + dps_current_state <= DPS_DONE; + end + else + begin + dps_current_state <= dps_next_state; + end + end + //the combinational part. assigning the next state + //this turns on the phase_done_final signal when phase_done does this: + //_____ ______ + // |______| + always @(*) + begin + phase_done_final = 0; + first_phase_shift_d = 0; + phase_en = 0; + dps_next_state = DPS_DONE; + case (dps_current_state) + DPS_START: + begin + phase_en = 1'b1; + dps_next_state = DPS_WAIT_PHASE_EN; + end + DPS_WAIT_PHASE_EN: + begin + phase_en = 1'b1; + if (first_phase_shift_q) + begin + first_phase_shift_d = 1'b1; + dps_next_state = DPS_WAIT_PHASE_EN; + end + else + begin + if (phase_en_counter == PHASE_EN_WAIT_COUNTER) + dps_next_state = DPS_WAIT_PHASE_DONE; + else dps_next_state = DPS_WAIT_PHASE_EN; + end + end + DPS_WAIT_PHASE_DONE: + begin + if (!phase_done | !locked) + begin + dps_next_state = DPS_WAIT_PHASE_DONE; + end + else + begin + if ((usr_num_shifts != shifts_done_counter) & (usr_num_shifts != 0)) + begin + dps_next_state = DPS_START; + phase_done_final = 1'b1; + end + else + begin + dps_next_state = DPS_DONE; + end + + end + end + DPS_DONE: + begin + phase_done_final = 0; + if (dps_changed) + dps_next_state = DPS_CHANGED; + else dps_next_state = DPS_DONE; + + end + DPS_CHANGED: + begin + if (pll_start_valid) + dps_next_state = DPS_WAIT_DPRIO_WRITING; + else + dps_next_state = DPS_CHANGED; + end + DPS_WAIT_DPRIO_WRITING: + begin + if (dprio_write_done) + dps_next_state = DPS_START; + else + dps_next_state = DPS_WAIT_DPRIO_WRITING; + end + + default: dps_next_state = 4'bxxxx; + endcase + + + end + + always @(posedge clk) + begin + + + if (dps_current_state == DPS_WAIT_PHASE_DONE) + phase_en_counter <= 0; + else if (dps_current_state == DPS_WAIT_PHASE_EN) + phase_en_counter <= phase_en_counter + 1'b1; + + if (reset) + begin + phase_en_counter <= 0; + shifts_done_counter <= 1'b1; + first_phase_shift_q <= 1; + end + else + begin + if (first_phase_shift_d) + first_phase_shift_q <= 0; + if (dps_done) + begin + shifts_done_counter <= 1'b1; + end + else + begin + if (phase_done_final & (dps_next_state!= DPS_DONE)) + shifts_done_counter <= shifts_done_counter + 1'b1; + else + shifts_done_counter <= shifts_done_counter; + end + end + end + + assign dps_changed_valid = (dps_current_state == DPS_CHANGED); + assign dps_done =(dps_current_state == DPS_DONE) | (dps_current_state == DPS_CHANGED); + assign up_dn = usr_up_dn; + assign gnd = 1'b0; + + //cnt select luts (5) + generic_lcell_comb lcell_cnt_sel_0 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[0])); + defparam lcell_cnt_sel_0.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_cnt_sel_0.dont_touch = "on"; + defparam lcell_cnt_sel_0.family = device_family; + generic_lcell_comb lcell_cnt_sel_1 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[1])); + defparam lcell_cnt_sel_1.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_cnt_sel_1.dont_touch = "on"; + defparam lcell_cnt_sel_1.family = device_family; + generic_lcell_comb lcell_cnt_sel_2 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[2])); + defparam lcell_cnt_sel_2.lut_mask = 64'hF0F0F0F0F0F0F0F0; + defparam lcell_cnt_sel_2.dont_touch = "on"; + defparam lcell_cnt_sel_2.family = device_family; + generic_lcell_comb lcell_cnt_sel_3 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[3])); + defparam lcell_cnt_sel_3.lut_mask = 64'hFF00FF00FF00FF00; + defparam lcell_cnt_sel_3.dont_touch = "on"; + defparam lcell_cnt_sel_3.family = device_family; + generic_lcell_comb lcell_cnt_sel_4 ( + .dataa(usr_cnt_sel[0]), + .datab(usr_cnt_sel[1]), + .datac(usr_cnt_sel[2]), + .datad(usr_cnt_sel[3]), + .datae(usr_cnt_sel[4]), + .dataf(gnd), + .combout (cnt_sel[4])); + defparam lcell_cnt_sel_4.lut_mask = 64'hFFFF0000FFFF0000; + defparam lcell_cnt_sel_4.dont_touch = "on"; + defparam lcell_cnt_sel_4.family = device_family; + + +endmodule + +module generic_lcell_comb +#( + //parameter + parameter family = "Cyclone V", + parameter lut_mask = 64'hAAAAAAAAAAAAAAAA, + parameter dont_touch = "on" +) ( + + input dataa, + input datab, + input datac, + input datad, + input datae, + input dataf, + + output combout +); + + generate + if (family == "Stratix V") + begin + stratixv_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Arria V") + begin + arriav_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Arria V GZ") + begin + arriavgz_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + else if (family == "Cyclone V") + begin + cyclonev_lcell_comb lcell_inst ( + .dataa(dataa), + .datab(datab), + .datac(datac), + .datad(datad), + .datae(datae), + .dataf(dataf), + .combout (combout)); + defparam lcell_inst.lut_mask = lut_mask; + defparam lcell_inst.dont_touch = dont_touch; + end + endgenerate +endmodule diff --git a/sys/pll_cfg/altera_pll_reconfig_top.v b/sys/pll_cfg/altera_pll_reconfig_top.v new file mode 100644 index 0000000..9a9e93e --- /dev/null +++ b/sys/pll_cfg/altera_pll_reconfig_top.v @@ -0,0 +1,428 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +`timescale 1ps/1ps + +module altera_pll_reconfig_top +#( + parameter reconf_width = 64, + parameter device_family = "Cyclone V", + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + + parameter ROM_ADDR_WIDTH = 9, + parameter ROM_DATA_WIDTH = 32, + parameter ROM_NUM_WORDS = 512, + + parameter ENABLE_MIF = 0, + parameter MIF_FILE_NAME = "", + + parameter ENABLE_BYTEENABLE = 0, + parameter BYTEENABLE_WIDTH = 4, + parameter WAIT_FOR_LOCK = 1 +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire [RECONFIG_DATA_WIDTH-1:0] mgmt_readdata, + output wire mgmt_waitrequest, + input wire [RECONFIG_ADDR_WIDTH-1:0] mgmt_address, + input wire mgmt_read, + input wire mgmt_write, + input wire [RECONFIG_DATA_WIDTH-1:0] mgmt_writedata, + + //conditional input + input wire [BYTEENABLE_WIDTH-1:0] mgmt_byteenable +); + +localparam NM28_START_REG = 6'b000010; +localparam NM20_START_REG = 9'b000000000; +localparam NM20_MIFSTART_ADDR = 9'b000010000; + +localparam MIF_STATE_DONE = 2'b00; +localparam MIF_STATE_START = 2'b01; +localparam MIF_STATE_BUSY = 2'b10; + +wire mgmt_byteenable_write; +assign mgmt_byteenable_write = (ENABLE_BYTEENABLE == 1) ? + ((mgmt_byteenable == {BYTEENABLE_WIDTH{1'b1}}) ? mgmt_write : 1'b0) : + mgmt_write; + +generate +if (device_family == "Arria 10") +begin:nm20_reconfig + if(ENABLE_MIF == 1) + begin:mif_reconfig_20nm // Generate Reconfig with MIF + + // MIF-related regs/wires + reg [RECONFIG_ADDR_WIDTH-1:0] reconfig_mgmt_addr; + reg reconfig_mgmt_read; + reg reconfig_mgmt_write; + reg [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_writedata; + wire reconfig_mgmt_waitrequest; + wire [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_readdata; + + wire [RECONFIG_ADDR_WIDTH-1:0] mif2reconfig_addr; + wire mif_busy; + wire mif2reconfig_read; + wire mif2reconfig_write; + wire [RECONFIG_DATA_WIDTH-1:0] mif2reconfig_writedata; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + reg mif_select; + //wire mif_user_start; // start signal provided by user to start mif + //reg user_start; + + reg [1:0] mif_curstate; + reg [1:0] mif_nextstate; + + wire mif_start; //start signal to mif reader + + assign mgmt_waitrequest = reconfig_mgmt_waitrequest | mif_busy;// | user_start; + // Don't output readdata if MIF streaming is taking place + assign mgmt_readdata = (mif_select) ? 32'b0 : reconfig_mgmt_readdata; + + //user must lower this by the time mif streaming is done - suggest to lower after 1 cycle + assign mif_start = mgmt_byteenable_write & (mgmt_address == NM20_MIFSTART_ADDR); + + //mif base addr is initially specified by the user + assign mif_base_addr = mgmt_writedata[ROM_ADDR_WIDTH-1:0]; + + //MIF statemachine + always @(posedge mgmt_clk) + begin + if(mgmt_reset) + mif_curstate <= MIF_STATE_DONE; + else + mif_curstate <= mif_nextstate; + end + + always @(*) + begin + case (mif_curstate) + MIF_STATE_DONE: + begin + if(mif_start) + mif_nextstate <= MIF_STATE_START; + else + mif_nextstate <= MIF_STATE_DONE; + end + MIF_STATE_START: + begin + mif_nextstate <= MIF_STATE_BUSY; + end + MIF_STATE_BUSY: + begin + if(mif_busy) + mif_nextstate <= MIF_STATE_BUSY; + else + mif_nextstate <= MIF_STATE_DONE; + end + endcase + end + + //Mif muxes + always @(*) + begin + if (mgmt_reset) + begin + reconfig_mgmt_addr <= 0; + reconfig_mgmt_read <= 0; + reconfig_mgmt_write <= 0; + reconfig_mgmt_writedata <= 0; + //user_start <= 0; + end + else + begin + reconfig_mgmt_addr <= (mif_select) ? mif2reconfig_addr : mgmt_address; + reconfig_mgmt_read <= (mif_select) ? mif2reconfig_read : mgmt_read; + reconfig_mgmt_write <= (mif_select) ? mif2reconfig_write : mgmt_byteenable_write; + reconfig_mgmt_writedata <= (mif_select) ? mif2reconfig_writedata : mgmt_writedata; + //user_start <= (mgmt_address == NM20_START_REG && mgmt_write == 1'b1) ? 1'b1 : 1'b0; + end + end + + always @(*) + begin + if (mgmt_reset) + begin + mif_select <= 0; + end + else + begin + mif_select <= (mif_start || mif_busy) ? 1'b1 : 1'b0; + end + end + + twentynm_pll_reconfig_mif_reader + #( + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS), + .DEVICE_FAMILY(device_family), + .ENABLE_MIF(ENABLE_MIF), + .MIF_FILE_NAME(MIF_FILE_NAME) + ) twentynm_pll_reconfig_mif_reader_inst0 ( + .mif_clk(mgmt_clk), + .mif_rst(mgmt_reset), + + //Altera_PLL Reconfig interface + //inputs + .reconfig_waitrequest(reconfig_mgmt_waitrequest), + //.reconfig_read_data(reconfig_mgmt_readdata), + //outputs + .reconfig_write_data(mif2reconfig_writedata), + .reconfig_addr(mif2reconfig_addr), + .reconfig_write(mif2reconfig_write), + .reconfig_read(mif2reconfig_read), + + //MIF Ctrl Interface + //inputs + .mif_base_addr(mif_base_addr), + .mif_start(mif_start), + //outputs + .mif_busy(mif_busy) + ); + + // ------ END MIF-RELATED MANAGEMENT ------ + + twentynm_iopll_reconfig_core + #( + .WAIT_FOR_LOCK(WAIT_FOR_LOCK) + ) twentynm_iopll_reconfig_core_inst ( + // Inputs + .mgmt_clk(mgmt_clk), + .mgmt_rst_n(~mgmt_reset), + .mgmt_read(reconfig_mgmt_read), + .mgmt_write(reconfig_mgmt_write), + .mgmt_address(reconfig_mgmt_addr), + .mgmt_writedata(reconfig_mgmt_writedata), + + // Outputs + .mgmt_readdata(reconfig_mgmt_readdata), + .mgmt_waitrequest(reconfig_mgmt_waitrequest), + + // PLL Conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); + + end // End generate reconfig with MIF + else + begin:reconfig_core_20nm + twentynm_iopll_reconfig_core + #( + .WAIT_FOR_LOCK(WAIT_FOR_LOCK) + ) twentynm_iopll_reconfig_core_inst ( + // Inputs + .mgmt_clk(mgmt_clk), + .mgmt_rst_n(~mgmt_reset), + .mgmt_read(mgmt_read), + .mgmt_write(mgmt_byteenable_write), + .mgmt_address(mgmt_address), + .mgmt_writedata(mgmt_writedata), + + // Outputs + .mgmt_readdata(mgmt_readdata), + .mgmt_waitrequest(mgmt_waitrequest), + + // PLL Conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); + end +end // 20nm reconfig +else +begin:NM28_reconfig + if (ENABLE_MIF == 1) + begin:mif_reconfig // Generate Reconfig with MIF + + // MIF-related regs/wires + reg [RECONFIG_ADDR_WIDTH-1:0] reconfig_mgmt_addr; + reg reconfig_mgmt_read; + reg reconfig_mgmt_write; + reg [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_writedata; + wire reconfig_mgmt_waitrequest; + wire [RECONFIG_DATA_WIDTH-1:0] reconfig_mgmt_readdata; + + wire [RECONFIG_ADDR_WIDTH-1:0] mif2reconfig_addr; + wire mif2reconfig_busy; + wire mif2reconfig_read; + wire mif2reconfig_write; + wire [RECONFIG_DATA_WIDTH-1:0] mif2reconfig_writedata; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + reg mif_select; + reg user_start; + + wire reconfig2mif_start_out; + + assign mgmt_waitrequest = reconfig_mgmt_waitrequest | mif2reconfig_busy | user_start; + // Don't output readdata if MIF streaming is taking place + assign mgmt_readdata = (mif_select) ? 32'b0 : reconfig_mgmt_readdata; + + always @(posedge mgmt_clk) + begin + if (mgmt_reset) + begin + reconfig_mgmt_addr <= 0; + reconfig_mgmt_read <= 0; + reconfig_mgmt_write <= 0; + reconfig_mgmt_writedata <= 0; + user_start <= 0; + end + else + begin + reconfig_mgmt_addr <= (mif_select) ? mif2reconfig_addr : mgmt_address; + reconfig_mgmt_read <= (mif_select) ? mif2reconfig_read : mgmt_read; + reconfig_mgmt_write <= (mif_select) ? mif2reconfig_write : mgmt_byteenable_write; + reconfig_mgmt_writedata <= (mif_select) ? mif2reconfig_writedata : mgmt_writedata; + user_start <= (mgmt_address == NM28_START_REG && mgmt_byteenable_write == 1'b1) ? 1'b1 : 1'b0; + end + end + + always @(*) + begin + if (mgmt_reset) + begin + mif_select <= 0; + end + else + begin + mif_select <= (reconfig2mif_start_out || mif2reconfig_busy) ? 1'b1 : 1'b0; + end + end + + altera_pll_reconfig_mif_reader + #( + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS), + .DEVICE_FAMILY(device_family), + .ENABLE_MIF(ENABLE_MIF), + .MIF_FILE_NAME(MIF_FILE_NAME) + ) altera_pll_reconfig_mif_reader_inst0 ( + .mif_clk(mgmt_clk), + .mif_rst(mgmt_reset), + + //Altera_PLL Reconfig interface + //inputs + .reconfig_busy(reconfig_mgmt_waitrequest), + .reconfig_read_data(reconfig_mgmt_readdata), + //outputs + .reconfig_write_data(mif2reconfig_writedata), + .reconfig_addr(mif2reconfig_addr), + .reconfig_write(mif2reconfig_write), + .reconfig_read(mif2reconfig_read), + + //MIF Ctrl Interface + //inputs + .mif_base_addr(mif_base_addr), + .mif_start(reconfig2mif_start_out), + //outputs + .mif_busy(mif2reconfig_busy) + ); + + // ------ END MIF-RELATED MANAGEMENT ------ + + + altera_pll_reconfig_core + #( + .reconf_width(reconf_width), + .device_family(device_family), + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS) + ) altera_pll_reconfig_core_inst0 ( + //inputs + .mgmt_clk(mgmt_clk), + .mgmt_reset(mgmt_reset), + + //PLL interface conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + + //User data outputs + .mgmt_readdata(reconfig_mgmt_readdata), + .mgmt_waitrequest(reconfig_mgmt_waitrequest), + + //User data inputs + .mgmt_address(reconfig_mgmt_addr), + .mgmt_read(reconfig_mgmt_read), + .mgmt_write(reconfig_mgmt_write), + .mgmt_writedata(reconfig_mgmt_writedata), + + // other + .mif_start_out(reconfig2mif_start_out), + .mif_base_addr(mif_base_addr) + ); + + end // End generate reconfig with MIF + else + begin:reconfig_core // Generate Reconfig core only + + wire reconfig2mif_start_out; + wire [ROM_ADDR_WIDTH-1:0] mif_base_addr; + + altera_pll_reconfig_core + #( + .reconf_width(reconf_width), + .device_family(device_family), + .RECONFIG_ADDR_WIDTH(RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH(RECONFIG_DATA_WIDTH), + .ROM_ADDR_WIDTH(ROM_ADDR_WIDTH), + .ROM_DATA_WIDTH(ROM_DATA_WIDTH), + .ROM_NUM_WORDS(ROM_NUM_WORDS) + ) altera_pll_reconfig_core_inst0 ( + //inputs + .mgmt_clk(mgmt_clk), + .mgmt_reset(mgmt_reset), + + //PLL interface conduits + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + + //User data outputs + .mgmt_readdata(mgmt_readdata), + .mgmt_waitrequest(mgmt_waitrequest), + + //User data inputs + .mgmt_address(mgmt_address), + .mgmt_read(mgmt_read), + .mgmt_write(mgmt_byteenable_write), + .mgmt_writedata(mgmt_writedata), + + // other + .mif_start_out(reconfig2mif_start_out), + .mif_base_addr(mif_base_addr) + ); + + + end // End generate reconfig core only +end // End 28nm Reconfig +endgenerate + +endmodule + diff --git a/sys/pll_cfg/pll_cfg.v b/sys/pll_cfg/pll_cfg.v new file mode 100644 index 0000000..2a2f078 --- /dev/null +++ b/sys/pll_cfg/pll_cfg.v @@ -0,0 +1,86 @@ +// megafunction wizard: %Altera PLL Reconfig v17.0% +// GENERATION: XML +// pll_cfg.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_cfg #( + parameter ENABLE_BYTEENABLE = 0, + parameter BYTEENABLE_WIDTH = 4, + parameter RECONFIG_ADDR_WIDTH = 6, + parameter RECONFIG_DATA_WIDTH = 32, + parameter reconf_width = 64, + parameter WAIT_FOR_LOCK = 1 + ) ( + input wire mgmt_clk, // mgmt_clk.clk + input wire mgmt_reset, // mgmt_reset.reset + output wire mgmt_waitrequest, // mgmt_avalon_slave.waitrequest + input wire mgmt_read, // .read + input wire mgmt_write, // .write + output wire [31:0] mgmt_readdata, // .readdata + input wire [5:0] mgmt_address, // .address + input wire [31:0] mgmt_writedata, // .writedata + output wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll + input wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll + ); + + altera_pll_reconfig_top #( + .device_family ("Cyclone V"), + .ENABLE_MIF (0), + .MIF_FILE_NAME ("sys/pll_cfg.mif"), + .ENABLE_BYTEENABLE (ENABLE_BYTEENABLE), + .BYTEENABLE_WIDTH (BYTEENABLE_WIDTH), + .RECONFIG_ADDR_WIDTH (RECONFIG_ADDR_WIDTH), + .RECONFIG_DATA_WIDTH (RECONFIG_DATA_WIDTH), + .reconf_width (reconf_width), + .WAIT_FOR_LOCK (WAIT_FOR_LOCK) + ) pll_cfg_inst ( + .mgmt_clk (mgmt_clk), // mgmt_clk.clk + .mgmt_reset (mgmt_reset), // mgmt_reset.reset + .mgmt_waitrequest (mgmt_waitrequest), // mgmt_avalon_slave.waitrequest + .mgmt_read (mgmt_read), // .read + .mgmt_write (mgmt_write), // .write + .mgmt_readdata (mgmt_readdata), // .readdata + .mgmt_address (mgmt_address), // .address + .mgmt_writedata (mgmt_writedata), // .writedata + .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll + .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll + .mgmt_byteenable (4'b0000) // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_cfg.vo +// RELATED_FILES: pll_cfg.v, altera_pll_reconfig_top.v, altera_pll_reconfig_core.v, altera_std_synchronizer.v diff --git a/sys/pll_cfg/pll_cfg_hdmi.v b/sys/pll_cfg/pll_cfg_hdmi.v new file mode 100644 index 0000000..1912c2a --- /dev/null +++ b/sys/pll_cfg/pll_cfg_hdmi.v @@ -0,0 +1,1282 @@ +// (C) 2001-2017 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + +// original file was altera_pll_reconfig_core.v +// not needed functionality was cut out to reduce ressource consumption + +module pll_cfg_hdmi +#( + parameter reconf_width = 64, + parameter device_family = "Cyclone V" +) ( + + //input + input wire mgmt_clk, + input wire mgmt_reset, + + + //conduits + output wire [reconf_width-1:0] reconfig_to_pll, + input wire [reconf_width-1:0] reconfig_from_pll, + + // user data (avalon-MM slave interface) + output wire mgmt_waitrequest, + input wire [5:0] mgmt_address, + input wire mgmt_write, + input wire [31:0] mgmt_writedata +); + localparam mode_WR = 1'b0; + localparam MODE_REG = 6'b000000; + localparam START_REG = 6'b000010; + localparam N_REG = 6'b000011; + localparam M_REG = 6'b000100; + localparam C_COUNTERS_REG = 6'b000101; + //localparam DPS_REG = 6'b000110; // unused + localparam DSM_REG = 6'b000111; + localparam BWCTRL_REG = 6'b001000; + localparam CP_CURRENT_REG = 6'b001001; + //localparam ANY_DPRIO = 6'b100000; // unused + //localparam CNT_BASE = 5'b001010; // unused + //localparam VCO_REG = 6'b011100; // unused + + //C Counters + localparam number_of_counters = 5'd6; + //C counter addresses + localparam C_CNT_0_DIV_ADDR = 5'h00; + localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11; + localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15; + localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17; + localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14; + localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16; + //N counter addresses + localparam N_CNT_DIV_ADDR = 5'h13; + localparam N_CNT_BYPASS_EN_ADDR = 5'h15; + localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17; + //M counter addresses + localparam M_CNT_DIV_ADDR = 5'h12; + localparam M_CNT_BYPASS_EN_ADDR = 5'h15; + localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17; + + //DSM address + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18; + localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19; + localparam DSM_K_READY_ADDR = 5'h17; + localparam DSM_K_DITHER_ADDR = 5'h17; + localparam DSM_OUT_SEL_ADDR = 6'h30; + + //Other DSM params + localparam DSM_K_READY_BIT_INDEX = 4'd11; + //BWCTRL address + //Bit 0-3 of addr + localparam BWCTRL_ADDR = 6'h30; + //CP_CURRENT address + //Bit 0-2 of addr + localparam CP_CURRENT_ADDR = 6'h31; + + // VCODIV address + localparam VCO_ADDR = 5'h17; + + localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4, + FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10, + ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15; + localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10; + + wire clk; + wire reset; + wire gnd; + + wire [5: 0] slave_address; + wire slave_write; + wire [31: 0] slave_writedata; + + wire slave_waitrequest; + reg slave_mode; + + assign clk = mgmt_clk; + + assign slave_address = mgmt_address; + assign slave_write = mgmt_write; + assign slave_writedata = mgmt_writedata; + + // Outputs + assign mgmt_waitrequest = slave_waitrequest; //Read waitrequest asserted in polling mode + + //internal signals + wire locked_orig; + wire locked; + + wire pll_start; + wire pll_start_valid; + + wire pll_start_asserted; + + reg [1:0] current_state; + reg [1:0] next_state; + + reg status;//0=busy, 1=ready + //user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load); + //declaring the init wires. These will have 0 on them for 64 clk cycles + wire [ 5:0] init_dprio_address; + wire init_dprio_read; + wire [ 1:0] init_dprio_byteen; + wire init_dprio_write; + wire [15:0] init_dprio_writedata; + + wire init_atpgmode; + wire init_mdio_dis; + wire init_scanen; + wire init_ser_shift_load; + wire dprio_init_done; + + //DPRIO output signals after initialization is done + wire dprio_clk; + reg avmm_dprio_write; + reg avmm_dprio_read; + reg [5:0] avmm_dprio_address; + reg [15:0] avmm_dprio_writedata; + reg [1:0] avmm_dprio_byteen; + wire avmm_atpgmode; + wire avmm_mdio_dis; + wire avmm_scanen; + + //Final output wires that are muxed between the init and avmm wires. + wire dprio_init_reset; + wire [5:0] dprio_address /*synthesis keep*/; + wire dprio_read/*synthesis keep*/; + wire [1:0] dprio_byteen/*synthesis keep*/; + wire dprio_write/*synthesis keep*/; + wire [15:0] dprio_writedata/*synthesis keep*/; + wire dprio_mdio_dis/*synthesis keep*/; + wire dprio_ser_shift_load/*synthesis keep*/; + wire dprio_atpgmode/*synthesis keep*/; + wire dprio_scanen/*synthesis keep*/; + + + //other PLL signals for dyn ph shift + wire phase_done/*synthesis keep*/; + wire phase_en/*synthesis keep*/; + wire up_dn/*synthesis keep*/; + wire [4:0] cnt_sel; + + //DPRIO input signals + wire [15:0] dprio_readdata; + + //internal logic signals + //storage registers for user sent data + reg dprio_temp_read_1; + reg dprio_temp_read_2; + reg dprio_start; + wire usr_valid_changes; + reg [3:0] dprio_cur_state; + reg [3:0] dprio_next_state; + reg [15:0] dprio_temp_m_n_c_readdata_1_d; + reg [15:0] dprio_temp_m_n_c_readdata_2_d; + reg [15:0] dprio_temp_m_n_c_readdata_1_q; + reg [15:0] dprio_temp_m_n_c_readdata_2_q; + reg dprio_write_done; + //C counters signals + reg [7:0] usr_c_cnt_lo; + reg [7:0] usr_c_cnt_hi; + reg usr_c_cnt_bypass_en; + reg usr_c_cnt_odd_duty_div_en; + reg temp_c_cnt_bypass_en [0:17]; + reg temp_c_cnt_odd_duty_div_en [0:17]; + reg any_c_cnt_changed; + reg all_c_cnt_done_q; + reg all_c_cnt_done_d; + reg [17:0] c_cnt_changed; + reg [17:0] c_cnt_done_d; + reg [17:0] c_cnt_done_q; + //N counter signals + reg [7:0] usr_n_cnt_lo; + reg [7:0] usr_n_cnt_hi; + reg usr_n_cnt_bypass_en; + reg usr_n_cnt_odd_duty_div_en; + reg n_cnt_changed; + reg n_cnt_done_d; + reg n_cnt_done_q; + //M counter signals + reg [7:0] usr_m_cnt_lo; + reg [7:0] usr_m_cnt_hi; + reg usr_m_cnt_bypass_en; + reg usr_m_cnt_odd_duty_div_en; + reg m_cnt_changed; + reg m_cnt_done_d; + reg m_cnt_done_q; + //dyn phase regs + reg [15:0] usr_num_shifts; + reg [4:0] usr_cnt_sel /*synthesis preserve*/; + reg usr_up_dn; + reg dps_changed; + wire dps_changed_valid; + wire dps_done; + + //DSM Signals + reg [31:0] usr_k_value; + reg dsm_k_changed; + reg dsm_k_done_d; + reg dsm_k_done_q; + reg dsm_k_ready_false_done_d; + //BW signals + reg [3:0] usr_bwctrl_value; + reg bwctrl_changed; + reg bwctrl_done_d; + reg bwctrl_done_q; + //CP signals + reg [2:0] usr_cp_current_value; + reg cp_current_changed; + reg cp_current_done_d; + reg cp_current_done_q; + //VCO signals + reg usr_vco_value; + reg vco_changed; + reg vco_done_d; + reg vco_done_q; + //Manual DPRIO signals + reg manual_dprio_done_q; + reg manual_dprio_done_d; + reg manual_dprio_changed; + reg [5:0] usr_dprio_address; + reg [15:0] usr_dprio_writedata_0; + reg usr_r_w; + //keeping track of which operation happened last + reg [5:0] operation_address; + // Address wires for all C_counter DPRIO registers + // These are outputs of LUTS, changing depending + // on whether PLL_0 or PLL_1 being used + + + //Fitter will tell if FPLL1 is being used + wire fpll_1; + + // MAIN FSM + + // Synchronize locked signal + altera_std_synchronizer #( + .depth(3) + ) altera_std_synchronizer_inst ( + .clk(mgmt_clk), + .reset_n(~mgmt_reset), + .din(locked_orig), + .dout(locked) + ); + + always @(posedge clk) + begin + if (reset) + begin + dprio_cur_state <= DPRIO_IDLE; + current_state <= IDLE; + end + else + begin + current_state <= next_state; + dprio_cur_state <= dprio_next_state; + end + end + + always @(*) + begin + case(current_state) + IDLE: + begin + if (pll_start & !slave_waitrequest & usr_valid_changes) + next_state = WAIT_ON_LOCK; + else + next_state = IDLE; + end + WAIT_ON_LOCK: + begin + if (locked & dps_done & dprio_write_done) // received locked high from PLL + begin + if (slave_mode==mode_WR) //if the mode is waitrequest, then + // goto IDLE state directly + next_state = IDLE; + else + next_state = LOCKED; //otherwise go the locked state + end + else + next_state = WAIT_ON_LOCK; + end + + LOCKED: + begin + next_state = LOCKED; + end + + default: next_state = 2'bxx; + + endcase + end + + + // ask the pll to start reconfig + assign pll_start = (pll_start_asserted & (current_state==IDLE)) ; + assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ; + + + + // WRITE OPERATIONS + assign pll_start_asserted = slave_write & (slave_address == START_REG); + + //reading the mode register to determine what mode the slave will operate + //in. + always @(posedge clk) + begin + if (reset) + slave_mode <= mode_WR; + else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest) + slave_mode <= slave_writedata[0]; + end + + //record which values user wants to change. + + //reading in the actual values that need to be reconfigged and sending + //them to the PLL + always @(posedge clk) + begin + if (reset) + begin + //reset all regs here + //BW signals reset + usr_bwctrl_value <= 0; + bwctrl_changed <= 0; + bwctrl_done_q <= 0; + //CP signals reset + usr_cp_current_value <= 0; + cp_current_changed <= 0; + cp_current_done_q <= 0; + //VCO signals reset + usr_vco_value <= 0; + vco_changed <= 0; + vco_done_q <= 0; + //DSM signals reset + usr_k_value <= 0; + dsm_k_changed <= 0; + dsm_k_done_q <= 0; + //N counter signals reset + usr_n_cnt_lo <= 0; + usr_n_cnt_hi <= 0; + usr_n_cnt_bypass_en <= 0; + usr_n_cnt_odd_duty_div_en <= 0; + n_cnt_changed <= 0; + n_cnt_done_q <= 0; + //M counter signals reset + usr_m_cnt_lo <= 0; + usr_m_cnt_hi <= 0; + usr_m_cnt_bypass_en <= 0; + usr_m_cnt_odd_duty_div_en <= 0; + m_cnt_changed <= 0; + m_cnt_done_q <= 0; + //C counter signals reset + usr_c_cnt_lo <= 0; + usr_c_cnt_hi <= 0; + usr_c_cnt_bypass_en <= 0; + usr_c_cnt_odd_duty_div_en <= 0; + any_c_cnt_changed <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + //generic signals + dprio_start <= 0; + dprio_temp_m_n_c_readdata_1_q <= 0; + dprio_temp_m_n_c_readdata_2_q <= 0; + c_cnt_done_q <= 0; + //DPS signals + usr_up_dn <= 0; + usr_cnt_sel <= 0; + usr_num_shifts <= 0; + dps_changed <= 0; + //manual DPRIO signals + manual_dprio_changed <= 0; + usr_dprio_address <= 0; + usr_dprio_writedata_0 <= 0; + usr_r_w <= 0; + operation_address <= 0; + end + else + begin + if (dprio_temp_read_1) + begin + dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d; + end + if (dprio_temp_read_2) + begin + dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d; + end + if ((dps_done)) dps_changed <= 0; + if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d; + if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d; + if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d; + if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d; + if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d; + if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d; + if (cp_current_done_d) cp_current_done_q <= cp_current_done_d; + if (vco_done_d) vco_done_q <= vco_done_d; + if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d; + + if (dprio_next_state == ONE) + dprio_start <= 0; + if (dprio_write_done) + begin + bwctrl_done_q <= 0; + cp_current_done_q <= 0; + vco_done_q <= 0; + dsm_k_done_q <= 0; + dsm_k_done_q <= 0; + n_cnt_done_q <= 0; + m_cnt_done_q <= 0; + all_c_cnt_done_q <= 0; + c_cnt_done_q <= 0; + dsm_k_changed <= 0; + n_cnt_changed <= 0; + m_cnt_changed <= 0; + any_c_cnt_changed <= 0; + bwctrl_changed <= 0; + cp_current_changed <= 0; + vco_changed <= 0; + manual_dprio_changed <= 0; + manual_dprio_done_q <= 0; + + end + else + begin + dsm_k_changed <= dsm_k_changed; + n_cnt_changed <= n_cnt_changed; + m_cnt_changed <= m_cnt_changed; + any_c_cnt_changed <= any_c_cnt_changed; + manual_dprio_changed <= manual_dprio_changed; + end + + + if(slave_write & !slave_waitrequest) + begin + case(slave_address) + //read in the values here from the user and act on them + DSM_REG: + begin + operation_address <= DSM_REG; + usr_k_value <= slave_writedata[31:0]; + dsm_k_changed <= 1'b1; + dsm_k_done_q <= 0; + dprio_start <= 1'b1; + end + N_REG: + begin + operation_address <= N_REG; + usr_n_cnt_lo <= slave_writedata[7:0]; + usr_n_cnt_hi <= slave_writedata[15:8]; + usr_n_cnt_bypass_en <= slave_writedata[16]; + usr_n_cnt_odd_duty_div_en <= slave_writedata[17]; + n_cnt_changed <= 1'b1; + n_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + M_REG: + begin + operation_address <= M_REG; + usr_m_cnt_lo <= slave_writedata[7:0]; + usr_m_cnt_hi <= slave_writedata[15:8]; + usr_m_cnt_bypass_en <= slave_writedata[16]; + usr_m_cnt_odd_duty_div_en <= slave_writedata[17]; + m_cnt_changed <= 1'b1; + m_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + //DPS_REG: + //begin + // operation_address <= DPS_REG; + // usr_num_shifts <= slave_writedata[15:0]; + // usr_up_dn <= slave_writedata[21]; + // dps_changed <= 1; + //end + C_COUNTERS_REG: + begin + operation_address <= C_COUNTERS_REG; + usr_c_cnt_lo <= slave_writedata[7:0]; + usr_c_cnt_hi <= slave_writedata[15:8]; + usr_c_cnt_bypass_en <= slave_writedata[16]; + usr_c_cnt_odd_duty_div_en <= slave_writedata[17]; + any_c_cnt_changed <= 1'b1; + all_c_cnt_done_q <= 0; + dprio_start <= 1'b1; + end + BWCTRL_REG: + begin + usr_bwctrl_value <= slave_writedata[3:0]; + bwctrl_changed <= 1'b1; + bwctrl_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= BWCTRL_REG; + end + CP_CURRENT_REG: + begin + usr_cp_current_value <= slave_writedata[2:0]; + cp_current_changed <= 1'b1; + cp_current_done_q <= 0; + dprio_start <= 1'b1; + operation_address <= CP_CURRENT_REG; + end + //VCO_REG: + //begin + // usr_vco_value <= slave_writedata[0]; + // vco_changed <= 1'b1; + // vco_done_q <= 0; + // dprio_start <= 1'b1; + // operation_address <= VCO_REG; + //end + //ANY_DPRIO: + //begin + // operation_address <= ANY_DPRIO; + // manual_dprio_changed <= 1'b1; + // usr_dprio_address <= slave_writedata[5:0]; + // usr_dprio_writedata_0 <= slave_writedata[21:6]; + // usr_r_w <= slave_writedata[22]; + // manual_dprio_done_q <= 0; + // dprio_start <= 1'b1; + //end + endcase + end + end + end + //C Counter assigning values to the 2-d array of values for each C counter + + reg [4:0] j; + always @(posedge clk) + begin + + if (reset) + begin + c_cnt_changed[17:0] <= 0; + for (j = 0; j < number_of_counters; j = j + 1'b1) + begin : c_cnt_reset + temp_c_cnt_bypass_en[j] <= 0; + temp_c_cnt_odd_duty_div_en[j] <= 0; + end + end + else + begin + if (dprio_write_done) + begin + c_cnt_changed <= 0; + end + if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG)) + begin + temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en; + temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en; + c_cnt_changed [5] <= 1'b1; + end + end + end + + + //logic to handle which writes the user indicated and wants to start. + assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed; + + + //start the reconfig operations by writing to the DPRIO + reg break_loop; + reg [4:0] i; + always @(*) + begin + dprio_temp_read_1 = 0; + dprio_temp_read_2 = 0; + dprio_temp_m_n_c_readdata_1_d = 0; + dprio_temp_m_n_c_readdata_2_d = 0; + break_loop = 0; + dprio_next_state = DPRIO_IDLE; + avmm_dprio_write = 0; + avmm_dprio_read = 0; + avmm_dprio_address = 0; + avmm_dprio_writedata = 0; + avmm_dprio_byteen = 0; + dprio_write_done = 1; + manual_dprio_done_d = 0; + n_cnt_done_d = 0; + dsm_k_done_d = 0; + dsm_k_ready_false_done_d = 0; + m_cnt_done_d = 0; + c_cnt_done_d[17:0] = 0; + all_c_cnt_done_d = 0; + bwctrl_done_d = 0; + cp_current_done_d = 0; + vco_done_d = 0; + i = 0; + + // Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes) + if (dprio_start) + dprio_write_done = 0; + + if (current_state == WAIT_ON_LOCK) + begin + case (dprio_cur_state) + ONE: + begin + if (n_cnt_changed & !n_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = N_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_n_cnt_lo; + avmm_dprio_writedata[15:8] = usr_n_cnt_hi; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_address = M_CNT_DIV_ADDR; + avmm_dprio_writedata[7:0] = usr_m_cnt_lo; + avmm_dprio_writedata[15:8] = usr_m_cnt_hi; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + + for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_hilo + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i; + else avmm_dprio_address = C_CNT_0_DIV_ADDR + i; + avmm_dprio_writedata[7:0] = usr_c_cnt_lo; + avmm_dprio_writedata[15:8] = usr_c_cnt_hi; + //To break from the loop, since only one counter + //is addressed at a time + break_loop = 1'b1; + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (cp_current_changed & !cp_current_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (vco_changed & !vco_done_q) + begin + dprio_write_done = 0; + avmm_dprio_write = 0; + dprio_next_state = TWO; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + dprio_next_state = TWO; + avmm_dprio_write = usr_r_w; + avmm_dprio_address = usr_dprio_address; + avmm_dprio_writedata[15:0] = usr_dprio_writedata_0; + end + else dprio_next_state = DPRIO_IDLE; + end + + TWO: + begin + //handle reading the two setting bits on n_cnt, then + //writing them back while preserving other bits. + //Issue two consecutive reads then wait; readLatency=3 + dprio_write_done = 0; + dprio_next_state = THREE; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + //reading the K ready 16 bit word. Need to write 0 to it + //afterwards to indicate that K has not been done writing + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + dprio_next_state = FOUR; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + dprio_next_state = FOUR; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + dprio_next_state = FOUR; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + dprio_next_state = FOUR; + end + else if (manual_dprio_changed & !manual_dprio_done_q) + begin + avmm_dprio_read = ~usr_r_w; + avmm_dprio_address = usr_dprio_address; + dprio_next_state = DPRIO_DONE; + end + else dprio_next_state = DPRIO_IDLE; + end + THREE: + begin + dprio_write_done = 0; + avmm_dprio_byteen = 2'b11; + avmm_dprio_read = 1'b1; + dprio_next_state = FOUR; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_read_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + break_loop = 1'b1; + end + end + end + end + end + else dprio_next_state = DPRIO_IDLE; + end + FOUR: + begin + dprio_temp_read_1 = 1'b1; + dprio_write_done = 0; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + dprio_temp_m_n_c_readdata_1_d = dprio_readdata; + dprio_next_state = FIVE; + end + else dprio_next_state = DPRIO_IDLE; + end + FIVE: + begin + dprio_write_done = 0; + dprio_temp_read_2 = 1'b1; + if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed) + begin + //this is where DSM ready value comes. + //Need to store in a register to be used later + dprio_temp_m_n_c_readdata_2_d = dprio_readdata; + dprio_next_state = SIX; + end + else dprio_next_state = DPRIO_IDLE; + end + SIX: + begin + dprio_write_done = 0; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + dprio_next_state = SEVEN; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_bypass_en; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_BYPASS_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_bypass_en; + end + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_bypass + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i]; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_write = 0; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_write = 0; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_write = 0; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_write = 0; + end + else dprio_next_state = DPRIO_IDLE; + end + SEVEN: + begin + dprio_write_done = 0; + dprio_next_state = EIGHT; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + if (n_cnt_changed & !n_cnt_done_q) + begin + avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en; + n_cnt_done_d = 1'b1; + end + else if (m_cnt_changed & !m_cnt_done_q) + begin + avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en; + m_cnt_done_d = 1'b1; + end + + else if (any_c_cnt_changed & !all_c_cnt_done_q) + begin + for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1) + begin : c_cnt_write_odd_div + if (fpll_1) + begin + if (i > 13) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + else + begin + if (i < 4) + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + //have to OR the signals to prevent + //overwriting of previous dones + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + else + begin + if (c_cnt_changed[i] & !c_cnt_done_q[i]) + begin + avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR; + avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i]; + c_cnt_done_d[i] = 1'b1; + c_cnt_done_d = c_cnt_done_d | c_cnt_done_q; + break_loop = 1'b1; + end + end + end + end + end + else if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0; + dsm_k_ready_false_done_d = 1'b1; + end + else if (bwctrl_changed & !bwctrl_done_q) + begin + avmm_dprio_address = BWCTRL_ADDR; + avmm_dprio_writedata[3:0] = usr_bwctrl_value; + bwctrl_done_d = 1'b1; + end + else if (cp_current_changed & !cp_current_done_q) + begin + avmm_dprio_address = CP_CURRENT_ADDR; + avmm_dprio_writedata[2:0] = usr_cp_current_value; + cp_current_done_d = 1'b1; + end + else if (vco_changed & !vco_done_q) + begin + avmm_dprio_address = VCO_ADDR; + avmm_dprio_writedata[8] = usr_vco_value; + vco_done_d = 1'b1; + end + + + //if all C_cnt that were changed are done, then assert all_c_cnt_done + if (c_cnt_done_d == c_cnt_changed) + all_c_cnt_done_d = 1'b1; + if (n_cnt_changed & n_cnt_done_d) + dprio_next_state = DPRIO_DONE; + if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q) + dprio_next_state = ONE; + else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q) + dprio_next_state = ONE; + else if (dsm_k_changed & !dsm_k_ready_false_done_d) + dprio_next_state = TWO; + else if (dsm_k_changed & !dsm_k_done_q) + dprio_next_state = EIGHT; + else if (bwctrl_changed & !bwctrl_done_d) + dprio_next_state = TWO; + else if (cp_current_changed & !cp_current_done_d) + dprio_next_state = TWO; + else if (vco_changed & !vco_done_d) + dprio_next_state = TWO; + else + begin + dprio_next_state = DPRIO_DONE; + dprio_write_done = 1'b1; + end + end + //finish the rest of the DSM reads/writes + //writing k value, writing k_ready to 1. + EIGHT: + begin + dprio_write_done = 0; + dprio_next_state = NINE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0; + avmm_dprio_writedata[15:0] = usr_k_value[15:0]; + end + end + NINE: + begin + dprio_write_done = 0; + dprio_next_state = TEN; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1; + avmm_dprio_writedata[15:0] = usr_k_value[31:16]; + end + end + TEN: + begin + dprio_write_done = 0; + dprio_next_state = ONE; + avmm_dprio_write = 1'b1; + avmm_dprio_byteen = 2'b11; + if (dsm_k_changed & !dsm_k_done_q) + begin + avmm_dprio_address = DSM_K_READY_ADDR; + //already have the readdata for DSM_K_READY_ADDR since we read it + //earlier. Just reuse here + avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q; + avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1; + dsm_k_done_d = 1'b1; + end + end + DPRIO_DONE: + begin + dprio_write_done = 1'b1; + if (dprio_start) dprio_next_state = DPRIO_IDLE; + else dprio_next_state = DPRIO_DONE; + end + DPRIO_IDLE: + begin + if (dprio_start) dprio_next_state = ONE; + else dprio_next_state = DPRIO_IDLE; + end + default: dprio_next_state = 4'bxxxx; + endcase + end + + end + + + //assert the waitreq signal according to the state of the slave + assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0; + + + dyn_phase_shift dyn_phase_shift_inst ( + .clk(clk), + .reset(reset), + .phase_done(phase_done), + .pll_start_valid(pll_start_valid), + .dps_changed(dps_changed), + .dps_changed_valid(dps_changed_valid), + .dprio_write_done(dprio_write_done), + .usr_num_shifts(usr_num_shifts), + .usr_cnt_sel(usr_cnt_sel), + .usr_up_dn(usr_up_dn), + .locked(locked), + .dps_done(dps_done), + .phase_en(phase_en), + .up_dn(up_dn), + .cnt_sel(cnt_sel)); + defparam dyn_phase_shift_inst.device_family = device_family; + + assign dprio_clk = clk; + self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset); + + dprio_mux dprio_mux_inst ( + .init_dprio_address(init_dprio_address), + .init_dprio_read(init_dprio_read), + .init_dprio_byteen(init_dprio_byteen), + .init_dprio_write(init_dprio_write), + .init_dprio_writedata(init_dprio_writedata), + + + .init_atpgmode(init_atpgmode), + .init_mdio_dis(init_mdio_dis), + .init_scanen(init_scanen), + .init_ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done), + + // Inputs from avmm master + .avmm_dprio_address(avmm_dprio_address), + .avmm_dprio_read(avmm_dprio_read), + .avmm_dprio_byteen(avmm_dprio_byteen), + .avmm_dprio_write(avmm_dprio_write), + .avmm_dprio_writedata(avmm_dprio_writedata), + + .avmm_atpgmode(avmm_atpgmode), + .avmm_mdio_dis(avmm_mdio_dis), + .avmm_scanen(avmm_scanen), + + // Outputs to fpll + .dprio_address(dprio_address), + .dprio_read(dprio_read), + .dprio_byteen(dprio_byteen), + .dprio_write(dprio_write), + .dprio_writedata(dprio_writedata), + + .atpgmode(dprio_atpgmode), + .mdio_dis(dprio_mdio_dis), + .scanen(dprio_scanen), + .ser_shift_load(dprio_ser_shift_load) + ); + + + fpll_dprio_init fpll_dprio_init_inst ( + .clk(clk), + .reset_n(~reset), + .locked(locked), + + //outputs + .dprio_address(init_dprio_address), + .dprio_read(init_dprio_read), + .dprio_byteen(init_dprio_byteen), + .dprio_write(init_dprio_write), + .dprio_writedata(init_dprio_writedata), + + .atpgmode(init_atpgmode), + .mdio_dis(init_mdio_dis), + .scanen(init_scanen), + .ser_shift_load(init_ser_shift_load), + .dprio_init_done(dprio_init_done)); + + //address luts, to be reconfigged by the Fitter + //FPLL_1 or 0 address lut + generic_lcell_comb lcell_fpll_0_1 ( + .dataa(1'b0), + .combout (fpll_1)); + defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA; + defparam lcell_fpll_0_1.dont_touch = "on"; + defparam lcell_fpll_0_1.family = device_family; + + + wire dprio_read_combout; + generic_lcell_comb lcell_dprio_read ( + .dataa(fpll_1), + .datab(dprio_read), + .datac(1'b0), + .datad(1'b0), + .datae(1'b0), + .dataf(1'b0), + .combout (dprio_read_combout)); + defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC; + defparam lcell_dprio_read.dont_touch = "on"; + defparam lcell_dprio_read.family = device_family; + + + + + + //assign reconfig_to_pll signals + assign reconfig_to_pll[0] = dprio_clk; + assign reconfig_to_pll[1] = ~dprio_init_reset; + assign reconfig_to_pll[2] = dprio_write; + assign reconfig_to_pll[3] = dprio_read_combout; + assign reconfig_to_pll[9:4] = dprio_address; + assign reconfig_to_pll[25:10] = dprio_writedata; + assign reconfig_to_pll[27:26] = dprio_byteen; + assign reconfig_to_pll[28] = dprio_ser_shift_load; + assign reconfig_to_pll[29] = dprio_mdio_dis; + assign reconfig_to_pll[30] = phase_en; + assign reconfig_to_pll[31] = up_dn; + assign reconfig_to_pll[36:32] = cnt_sel; + assign reconfig_to_pll[37] = dprio_scanen; + assign reconfig_to_pll[38] = dprio_atpgmode; + //assign reconfig_to_pll[40:37] = clken; + assign reconfig_to_pll[63:39] = 0; + + //assign reconfig_from_pll signals + assign dprio_readdata = reconfig_from_pll [15:0]; + assign locked_orig = reconfig_from_pll [16]; + assign phase_done = reconfig_from_pll [17]; + +endmodule diff --git a/sys/pll_hdmi.13.qip b/sys/pll_hdmi.13.qip new file mode 100644 index 0000000..76def89 --- /dev/null +++ b/sys/pll_hdmi.13.qip @@ -0,0 +1,17 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -name SYNTHESIS_ONLY_QIP ON + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_hdmi.qip b/sys/pll_hdmi.qip new file mode 100644 index 0000000..be34aeb --- /dev/null +++ b/sys/pll_hdmi.qip @@ -0,0 +1,483 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWk=" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWlfMDAwMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZyYWN0aW9uYWxfY291dA==::MzI=::cGxsX2ZyYWN0aW9uYWxfY291dA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::cGxsX2RzbV9vdXRfc2Vs" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::MTQ4LjU=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MzkwODQyMDE1Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::Mw==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NjUuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MjcuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::MTQ4LjUwMDAwMCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::dHJ1ZQ==::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::Q3ljbG9uZSBW::UExMIFRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::UmVjb25maWd1cmFibGU=::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfaGlfZGl2::NA==::bV9jbnRfaGlfZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfbG9fZGl2::NA==::bV9jbnRfbG9fZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfaGlfZGl2::MjU2::bl9jbnRfaGlfZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfbG9fZGl2::MjU2::bl9jbnRfbG9fZGl2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfYnlwYXNzX2Vu::ZmFsc2U=::bV9jbnRfYnlwYXNzX2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfYnlwYXNzX2Vu::dHJ1ZQ==::bl9jbnRfYnlwYXNzX2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bV9jbnRfb2RkX2Rpdl9kdXR5X2Vu::ZmFsc2U=::bV9jbnRfb2RkX2Rpdl9kdXR5X2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bl9jbnRfb2RkX2Rpdl9kdXR5X2Vu::ZmFsc2U=::bl9jbnRfb2RkX2Rpdl9kdXR5X2Vu" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MA==::Mg==::Y19jbnRfaGlfZGl2MA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MA==::MQ==::Y19jbnRfbG9fZGl2MA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDA=::MQ==::Y19jbnRfcHJzdDA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qw::MA==::Y19jbnRfcGhfbXV4X3Byc3Qw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMA==::ZmFsc2U=::Y19jbnRfYnlwYXNzX2VuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMA==::dHJ1ZQ==::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MQ==::MQ==::Y19jbnRfaGlfZGl2MQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MQ==::MQ==::Y19jbnRfbG9fZGl2MQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE=::MQ==::Y19jbnRfcHJzdDE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qx::MA==::Y19jbnRfcGhfbXV4X3Byc3Qx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Mg==::MQ==::Y19jbnRfaGlfZGl2Mg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Mg==::MQ==::Y19jbnRfbG9fZGl2Mg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDI=::MQ==::Y19jbnRfcHJzdDI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qy::MA==::Y19jbnRfcGhfbXV4X3Byc3Qy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMg==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMg==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMg==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Mw==::MQ==::Y19jbnRfaGlfZGl2Mw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Mw==::MQ==::Y19jbnRfbG9fZGl2Mw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDM=::MQ==::Y19jbnRfcHJzdDM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Qz::MA==::Y19jbnRfcGhfbXV4X3Byc3Qz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMw==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMw==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NA==::MQ==::Y19jbnRfaGlfZGl2NA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NA==::MQ==::Y19jbnRfbG9fZGl2NA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDQ=::MQ==::Y19jbnRfcHJzdDQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q0::MA==::Y19jbnRfcGhfbXV4X3Byc3Q0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNA==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2NQ==::MQ==::Y19jbnRfaGlfZGl2NQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2NQ==::MQ==::Y19jbnRfbG9fZGl2NQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDU=::MQ==::Y19jbnRfcHJzdDU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q1::MA==::Y19jbnRfcGhfbXV4X3Byc3Q1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Ng==::MQ==::Y19jbnRfaGlfZGl2Ng==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Ng==::MQ==::Y19jbnRfbG9fZGl2Ng==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDY=::MQ==::Y19jbnRfcHJzdDY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q2::MA==::Y19jbnRfcGhfbXV4X3Byc3Q2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNg==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNg==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNg==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2Nw==::MQ==::Y19jbnRfaGlfZGl2Nw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2Nw==::MQ==::Y19jbnRfbG9fZGl2Nw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDc=::MQ==::Y19jbnRfcHJzdDc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q3::MA==::Y19jbnRfcGhfbXV4X3Byc3Q3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjNw==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuNw==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNw==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2OA==::MQ==::Y19jbnRfaGlfZGl2OA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2OA==::MQ==::Y19jbnRfbG9fZGl2OA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDg=::MQ==::Y19jbnRfcHJzdDg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q4::MA==::Y19jbnRfcGhfbXV4X3Byc3Q4" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjOA==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuOA==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOA==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2OQ==::MQ==::Y19jbnRfaGlfZGl2OQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2OQ==::MQ==::Y19jbnRfbG9fZGl2OQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDk=::MQ==::Y19jbnRfcHJzdDk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3Q5::MA==::Y19jbnRfcGhfbXV4X3Byc3Q5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjOQ==::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuOQ==::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOQ==::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuOQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTA=::MQ==::Y19jbnRfaGlfZGl2MTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTA=::MQ==::Y19jbnRfbG9fZGl2MTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEw::MQ==::Y19jbnRfcHJzdDEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMA==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTA=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTA=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTA=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTE=::MQ==::Y19jbnRfaGlfZGl2MTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTE=::MQ==::Y19jbnRfbG9fZGl2MTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEx::MQ==::Y19jbnRfcHJzdDEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMQ==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTE=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTE=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTE=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTI=::MQ==::Y19jbnRfaGlfZGl2MTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTI=::MQ==::Y19jbnRfbG9fZGl2MTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEy::MQ==::Y19jbnRfcHJzdDEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMg==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTI=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTI=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTI=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTM=::MQ==::Y19jbnRfaGlfZGl2MTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTM=::MQ==::Y19jbnRfbG9fZGl2MTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDEz::MQ==::Y19jbnRfcHJzdDEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxMw==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTM=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTM=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTM=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTQ=::MQ==::Y19jbnRfaGlfZGl2MTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTQ=::MQ==::Y19jbnRfbG9fZGl2MTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE0::MQ==::Y19jbnRfcHJzdDE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNA==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTQ=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTQ=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTQ=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTU=::MQ==::Y19jbnRfaGlfZGl2MTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTU=::MQ==::Y19jbnRfbG9fZGl2MTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE1::MQ==::Y19jbnRfcHJzdDE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNQ==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTU=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTU=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTU=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTY=::MQ==::Y19jbnRfaGlfZGl2MTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTY=::MQ==::Y19jbnRfbG9fZGl2MTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE2::MQ==::Y19jbnRfcHJzdDE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNg==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTY=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTY=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTY=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaGlfZGl2MTc=::MQ==::Y19jbnRfaGlfZGl2MTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfbG9fZGl2MTc=::MQ==::Y19jbnRfbG9fZGl2MTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcHJzdDE3::MQ==::Y19jbnRfcHJzdDE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfcGhfbXV4X3Byc3QxNw==::MA==::Y19jbnRfcGhfbXV4X3Byc3QxNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfaW5fc3JjMTc=::cGhfbXV4X2Nsaw==::Y19jbnRfaW5fc3JjMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfYnlwYXNzX2VuMTc=::dHJ1ZQ==::Y19jbnRfYnlwYXNzX2VuMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTc=::ZmFsc2U=::Y19jbnRfb2RkX2Rpdl9kdXR5X2VuMTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3Zjb19kaXY=::Mg==::cGxsX3Zjb19kaXY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2NwX2N1cnJlbnQ=::MjA=::cGxsX2NwX2N1cnJlbnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2J3Y3RybA==::NDAwMA==::cGxsX2J3Y3RybA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX291dHB1dF9jbGtfZnJlcXVlbmN5::NDQ1LjQ5OTk5OSBNSHo=::cGxsX291dHB1dF9jbGtfZnJlcXVlbmN5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZyYWN0aW9uYWxfZGl2aXNpb24=::MzkwODQyMDE1Mw==::cGxsX2ZyYWN0aW9uYWxfZGl2aXNpb24=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bWltaWNfZmJjbGtfdHlwZQ==::bm9uZQ==::bWltaWNfZmJjbGtfdHlwZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZiY2xrX211eF8x::Z2xi::cGxsX2ZiY2xrX211eF8x" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX2ZiY2xrX211eF8y::bV9jbnQ=::cGxsX2ZiY2xrX211eF8y" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX21fY250X2luX3NyYw==::cGhfbXV4X2Nsaw==::cGxsX21fY250X2luX3NyYw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3NsZl9yc3Q=::dHJ1ZQ==::cGxsX3NsZl9yc3Q=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSwyLDEsMSwwLHBoX211eF9jbGssZmFsc2UsdHJ1ZSwyLDIwLDQwMDAsNDQ1LjQ5OTk5OSBNSHosMzkwODQyMDE1Myxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] +set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.qip"] + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_hdmi.v b/sys/pll_hdmi.v new file mode 100644 index 0000000..52a9de9 --- /dev/null +++ b/sys/pll_hdmi.v @@ -0,0 +1,256 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll_hdmi.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_hdmi ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + input wire [63:0] reconfig_to_pll, // reconfig_to_pll.reconfig_to_pll + output wire [63:0] reconfig_from_pll // reconfig_from_pll.reconfig_from_pll + ); + + pll_hdmi_0002 pll_hdmi_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .reconfig_to_pll (reconfig_to_pll), // reconfig_to_pll.reconfig_to_pll + .reconfig_from_pll (reconfig_from_pll), // reconfig_from_pll.reconfig_from_pll + .locked () // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_hdmi.vo +// RELATED_FILES: pll_hdmi.v, pll_hdmi_0002.v diff --git a/sys/pll_hdmi/pll_hdmi_0002.qip b/sys/pll_hdmi/pll_hdmi_0002.qip new file mode 100644 index 0000000..3cb7073 --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.qip @@ -0,0 +1,2 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name UNFORCE_MERGE_PLL_OUTPUT_COUNTER ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_hdmi/pll_hdmi_0002.v b/sys/pll_hdmi/pll_hdmi_0002.v new file mode 100644 index 0000000..dc63100 --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.v @@ -0,0 +1,241 @@ +`timescale 1ns/10ps +module pll_hdmi_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'locked' + output wire locked, + + // interface 'reconfig_to_pll' + input wire [63:0] reconfig_to_pll, + + // interface 'reconfig_from_pll' + output wire [63:0] reconfig_from_pll +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .pll_fractional_cout(32), + .pll_dsm_out_sel("1st_order"), + .operation_mode("direct"), + .number_of_clocks(1), + .output_clock_frequency0("148.500000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("0 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("Cyclone V"), + .pll_subtype("Reconfigurable"), + .m_cnt_hi_div(4), + .m_cnt_lo_div(4), + .n_cnt_hi_div(256), + .n_cnt_lo_div(256), + .m_cnt_bypass_en("false"), + .n_cnt_bypass_en("true"), + .m_cnt_odd_div_duty_en("false"), + .n_cnt_odd_div_duty_en("false"), + .c_cnt_hi_div0(2), + .c_cnt_lo_div0(1), + .c_cnt_prst0(1), + .c_cnt_ph_mux_prst0(0), + .c_cnt_in_src0("ph_mux_clk"), + .c_cnt_bypass_en0("false"), + .c_cnt_odd_div_duty_en0("true"), + .c_cnt_hi_div1(1), + .c_cnt_lo_div1(1), + .c_cnt_prst1(1), + .c_cnt_ph_mux_prst1(0), + .c_cnt_in_src1("ph_mux_clk"), + .c_cnt_bypass_en1("true"), + .c_cnt_odd_div_duty_en1("false"), + .c_cnt_hi_div2(1), + .c_cnt_lo_div2(1), + .c_cnt_prst2(1), + .c_cnt_ph_mux_prst2(0), + .c_cnt_in_src2("ph_mux_clk"), + .c_cnt_bypass_en2("true"), + .c_cnt_odd_div_duty_en2("false"), + .c_cnt_hi_div3(1), + .c_cnt_lo_div3(1), + .c_cnt_prst3(1), + .c_cnt_ph_mux_prst3(0), + .c_cnt_in_src3("ph_mux_clk"), + .c_cnt_bypass_en3("true"), + .c_cnt_odd_div_duty_en3("false"), + .c_cnt_hi_div4(1), + .c_cnt_lo_div4(1), + .c_cnt_prst4(1), + .c_cnt_ph_mux_prst4(0), + .c_cnt_in_src4("ph_mux_clk"), + .c_cnt_bypass_en4("true"), + .c_cnt_odd_div_duty_en4("false"), + .c_cnt_hi_div5(1), + .c_cnt_lo_div5(1), + .c_cnt_prst5(1), + .c_cnt_ph_mux_prst5(0), + .c_cnt_in_src5("ph_mux_clk"), + .c_cnt_bypass_en5("true"), + .c_cnt_odd_div_duty_en5("false"), + .c_cnt_hi_div6(1), + .c_cnt_lo_div6(1), + .c_cnt_prst6(1), + .c_cnt_ph_mux_prst6(0), + .c_cnt_in_src6("ph_mux_clk"), + .c_cnt_bypass_en6("true"), + .c_cnt_odd_div_duty_en6("false"), + .c_cnt_hi_div7(1), + .c_cnt_lo_div7(1), + .c_cnt_prst7(1), + .c_cnt_ph_mux_prst7(0), + .c_cnt_in_src7("ph_mux_clk"), + .c_cnt_bypass_en7("true"), + .c_cnt_odd_div_duty_en7("false"), + .c_cnt_hi_div8(1), + .c_cnt_lo_div8(1), + .c_cnt_prst8(1), + .c_cnt_ph_mux_prst8(0), + .c_cnt_in_src8("ph_mux_clk"), + .c_cnt_bypass_en8("true"), + .c_cnt_odd_div_duty_en8("false"), + .c_cnt_hi_div9(1), + .c_cnt_lo_div9(1), + .c_cnt_prst9(1), + .c_cnt_ph_mux_prst9(0), + .c_cnt_in_src9("ph_mux_clk"), + .c_cnt_bypass_en9("true"), + .c_cnt_odd_div_duty_en9("false"), + .c_cnt_hi_div10(1), + .c_cnt_lo_div10(1), + .c_cnt_prst10(1), + .c_cnt_ph_mux_prst10(0), + .c_cnt_in_src10("ph_mux_clk"), + .c_cnt_bypass_en10("true"), + .c_cnt_odd_div_duty_en10("false"), + .c_cnt_hi_div11(1), + .c_cnt_lo_div11(1), + .c_cnt_prst11(1), + .c_cnt_ph_mux_prst11(0), + .c_cnt_in_src11("ph_mux_clk"), + .c_cnt_bypass_en11("true"), + .c_cnt_odd_div_duty_en11("false"), + .c_cnt_hi_div12(1), + .c_cnt_lo_div12(1), + .c_cnt_prst12(1), + .c_cnt_ph_mux_prst12(0), + .c_cnt_in_src12("ph_mux_clk"), + .c_cnt_bypass_en12("true"), + .c_cnt_odd_div_duty_en12("false"), + .c_cnt_hi_div13(1), + .c_cnt_lo_div13(1), + .c_cnt_prst13(1), + .c_cnt_ph_mux_prst13(0), + .c_cnt_in_src13("ph_mux_clk"), + .c_cnt_bypass_en13("true"), + .c_cnt_odd_div_duty_en13("false"), + .c_cnt_hi_div14(1), + .c_cnt_lo_div14(1), + .c_cnt_prst14(1), + .c_cnt_ph_mux_prst14(0), + .c_cnt_in_src14("ph_mux_clk"), + .c_cnt_bypass_en14("true"), + .c_cnt_odd_div_duty_en14("false"), + .c_cnt_hi_div15(1), + .c_cnt_lo_div15(1), + .c_cnt_prst15(1), + .c_cnt_ph_mux_prst15(0), + .c_cnt_in_src15("ph_mux_clk"), + .c_cnt_bypass_en15("true"), + .c_cnt_odd_div_duty_en15("false"), + .c_cnt_hi_div16(1), + .c_cnt_lo_div16(1), + .c_cnt_prst16(1), + .c_cnt_ph_mux_prst16(0), + .c_cnt_in_src16("ph_mux_clk"), + .c_cnt_bypass_en16("true"), + .c_cnt_odd_div_duty_en16("false"), + .c_cnt_hi_div17(1), + .c_cnt_lo_div17(1), + .c_cnt_prst17(1), + .c_cnt_ph_mux_prst17(0), + .c_cnt_in_src17("ph_mux_clk"), + .c_cnt_bypass_en17("true"), + .c_cnt_odd_div_duty_en17("false"), + .pll_vco_div(2), + .pll_cp_current(20), + .pll_bwctrl(4000), + .pll_output_clk_frequency("445.499999 MHz"), + .pll_fractional_division("3908420153"), + .mimic_fbclk_type("none"), + .pll_fbclk_mux_1("glb"), + .pll_fbclk_mux_2("m_cnt"), + .pll_m_cnt_in_src("ph_mux_clk"), + .pll_slf_rst("true") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_0}), + .locked (locked), + .reconfig_to_pll (reconfig_to_pll), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk), + .reconfig_from_pll (reconfig_from_pll) + ); +endmodule + diff --git a/sys/pll_hdmi_adj.vhd b/sys/pll_hdmi_adj.vhd new file mode 100644 index 0000000..67287cb --- /dev/null +++ b/sys/pll_hdmi_adj.vhd @@ -0,0 +1,433 @@ +-------------------------------------------------------------------------------- +-- HDMI PLL Adjust +-------------------------------------------------------------------------------- + +-- Changes the HDMI PLL frequency according to the scaler suggestions. +-------------------------------------------- +-- LLTUNE : +-- 0 : Input Display Enable +-- 1 : Input Vsync +-- 2 : Input Interlaced mode +-- 3 : Input Interlaced field +-- 4 : Output Image frame +-- 5 : +-- 6 : Input clock +-- 7 : Output clock + +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY pll_hdmi_adj IS + PORT ( + -- Scaler + llena : IN std_logic; -- 0=Disabled 1=Enabled + lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler + + locked : OUT std_logic; + + -- Signals from reconfig commands + i_waitrequest : OUT std_logic; + i_write : IN std_logic; + i_address : IN unsigned(5 DOWNTO 0); + i_writedata : IN unsigned(31 DOWNTO 0); + + -- Outputs to PLL_HDMI_CFG + o_waitrequest : IN std_logic; + o_write : OUT std_logic; + o_address : OUT unsigned(5 DOWNTO 0); + o_writedata : OUT unsigned(31 DOWNTO 0); + + ------------------------------------ + clk : IN std_logic; + reset_na : IN std_logic + ); + +BEGIN + + +END ENTITY pll_hdmi_adj; + +--############################################################################## + +ARCHITECTURE rtl OF pll_hdmi_adj IS + + SIGNAL i_clk,i_de,i_de2,i_vss,i_vss2,i_vss_delay,i_ce : std_logic; + SIGNAL i_linecpt,i_line : natural RANGE 0 TO 2**12-1; + SIGNAL i_delay : natural RANGE 0 TO 2**14-1; + + SIGNAL pwrite : std_logic; + SIGNAL paddress : unsigned(5 DOWNTO 0); + SIGNAL pdata : unsigned(31 DOWNTO 0); + TYPE enum_state IS (sIDLE,sW1,sW2,sW3,sW4,sW5,sW6); + SIGNAL state : enum_state; + SIGNAL tune_freq,tune_phase : unsigned(5 DOWNTO 0); + SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0); + SIGNAL mfrac,mfrac_mem,mfrac_ref,diff : unsigned(40 DOWNTO 0); + SIGNAL mul : unsigned(15 DOWNTO 0); + SIGNAL sign,sign_pre : std_logic; + SIGNAL expand : boolean; + SIGNAL up,modo,phm,dir : std_logic; + SIGNAL cpt : natural RANGE 0 TO 3; + SIGNAL col : natural RANGE 0 TO 15; + + SIGNAL icpt,ocpt,o2cpt,ssh,ofsize,ifsize : natural RANGE 0 TO 2**24-1; + SIGNAL ivss,ivss2,itog : std_logic; + SIGNAL ovss,ovss2,otog : std_logic; + SIGNAL sync,pulse,los,lop : std_logic; + SIGNAL osize,offset,osizep,offsetp : signed(23 DOWNTO 0); + SIGNAL logcpt : natural RANGE 0 TO 31; + SIGNAL udiff : integer RANGE -2**23 TO 2**23-1 :=0; + +BEGIN + + ---------------------------------------------------------------------------- + -- 4 lines delay to input + i_vss<=lltune(0); + i_de <=lltune(1); + i_ce <=lltune(5); + i_clk<=lltune(6); + + Delay:PROCESS(i_clk) IS + BEGIN + IF rising_edge(i_clk) THEN + IF i_ce='1' THEN + -- Measure input line time. + i_de2<=i_de; + + IF i_de='1' AND i_de2='0' THEN + i_linecpt<=0; + IF i_vss='1' THEN + i_line<=i_linecpt; + END IF; + ELSE + i_linecpt<=i_linecpt+1; + END IF; + + -- Delay 4 lines + i_vss2<=i_vss; + IF i_vss/=i_vss2 THEN + i_delay<=0; + ELSIF i_delay=i_line * 4 THEN + i_vss_delay<=i_vss; + ELSE + i_delay<=i_delay+1; + END IF; + END IF; + END IF; + END PROCESS Delay; + + ---------------------------------------------------------------------------- + -- Sample image sizes + Sampler:PROCESS(clk,reset_na) IS + BEGIN + IF reset_na='0' THEN +--pragma synthesis_off + otog<='0'; + itog<='0'; + ivss<='0'; + ivss2<='0'; + ovss<='0'; + ovss2<='0'; +--pragma synthesis_on + + ELSIF rising_edge(clk) THEN + -- Clock domain crossing + + ivss<=i_vss_delay; -- + ivss2<=ivss; + + ovss<=lltune(4); -- + ovss2<=ovss; + + otog<=otog XOR (ovss AND NOT ovss2); + + -- Measure output frame time + IF ovss='1' AND ovss2='0' AND otog='1' THEN + ocpt<=0; + osizep<=to_signed(ocpt,24); + ELSE + ocpt<=ocpt+1; + END IF; + IF ovss='0' AND ovss2='1' AND otog='0' THEN + o2cpt<=0; + ELSE + o2cpt<=o2cpt+1; + END IF; + + -- Measure output image time + IF ovss='0' AND ovss2='1' AND otog='0' THEN + ofsize<=ocpt; + END IF; + + itog<=itog XOR (ivss AND NOT ivss2); + + -- Measure input frame time + IF ivss='1' AND ivss2='0' AND itog='1' THEN + icpt<=0; + osize<=osizep; + udiff<=integer(to_integer(osizep)) - integer(icpt); + sync<='1'; + ELSE + icpt<=icpt+1; + sync<='0'; + END IF; + + -- Measure input image time + IF ivss='0' AND ivss2='1' AND itog='0' THEN + ifsize<=icpt; + END IF; + + expand<=(ofsize>=ifsize); + -- IN | ######### | EXPAND = 1 + -- OUT | ############# | + + -- IN | ######### | EXPAND = 0 + -- OUT | ###### | + + IF expand THEN + IF ivss='1' AND ivss2='0' AND itog='1' THEN + offset<=to_signed(ocpt,24); + END IF; + ELSE + IF ivss='0' AND ivss2='1' AND itog='0' THEN + offset<=to_signed(o2cpt,24); + END IF; + END IF; + + -------------------------------------------- + pulse<='0'; + IF sync='1' THEN + logcpt<=0; + ssh<=to_integer(osize); + los<='0'; + lop<='0'; + + ELSIF logcpt<24 THEN + -- Frequency difference + IF udiff>0 AND ssh=osize/2 AND ssh<(osize-offset) AND lop='0' THEN + tune_phase<='1' & to_unsigned(logcpt,5); + lop<='1'; + END IF; + ssh<=ssh/2; + logcpt<=logcpt+1; + + ELSIF logcpt=24 THEN + pulse<='1'; + ssh<=ssh/2; + logcpt<=logcpt+1; + END IF; + + END IF; + END PROCESS Sampler; + + ---------------------------------------------------------------------------- + -- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf. + -- 000100 : M counter + -- 000111 : M counter Fractional Value K + + Comb:PROCESS(i_write,i_address, + i_writedata,pwrite,paddress,pdata) IS + BEGIN + IF i_write='1' THEN + o_write <=i_write; + o_address <=i_address; + o_writedata <=i_writedata; + ELSE + o_write <=pwrite; + o_address <=paddress; + o_writedata<=pdata; + END IF; + END PROCESS Comb; + + i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0'; + + ---------------------------------------------------------------------------- + Schmurtz:PROCESS(clk,reset_na) IS + VARIABLE off_v,ofp_v : natural RANGE 0 TO 63; + VARIABLE diff_v : unsigned(40 DOWNTO 0); + VARIABLE mulco : unsigned(15 DOWNTO 0); + VARIABLE up_v,sign_v : std_logic; + BEGIN + IF reset_na='0' THEN + modo<='0'; + state<=sIDLE; + ELSIF rising_edge(clk) THEN + ------------------------------------------------------ + -- Snoop accesses to PLL reconfiguration + IF i_address="000100" AND i_write='1' THEN + mfrac (40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_ref(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mfrac_mem(40 DOWNTO 32)<=('0' & i_writedata(15 DOWNTO 8)) + + ('0' & i_writedata(7 DOWNTO 0)); + mul<=i_writedata(15 DOWNTO 0); + modo<='1'; + END IF; + + IF i_address="000111" AND i_write='1' THEN + mfrac (31 DOWNTO 0)<=i_writedata; + mfrac_ref(31 DOWNTO 0)<=i_writedata; + mfrac_mem(31 DOWNTO 0)<=i_writedata; + modo<='1'; + END IF; + + ------------------------------------------------------ + -- Tuning + off_v:=to_integer('0' & tune_freq(4 DOWNTO 0)); + ofp_v:=to_integer('0' & tune_phase(4 DOWNTO 0)); + --IF off_v<8 THEN off_v:=8; END IF; + --IF ofp_v<7 THEN ofp_v:=7; END IF; + IF off_v<4 THEN off_v:=4; END IF; + IF ofp_v<4 THEN ofp_v:=4; END IF; + + IF off_v>=18 AND ofp_v>=18 THEN + locked<=llena; + ELSE + locked<='0'; + END IF; + + up_v:='0'; + IF pulse='1' THEN + cpt<=(cpt+1) MOD 4; + IF llena='0' THEN + -- Recover original freq when disabling low lag mode + cpt<=0; + col<=0; + IF modo='1' THEN + mfrac<=mfrac_mem; + mfrac_ref<=mfrac_mem; + up<='1'; + modo<='0'; + END IF; + + ELSIF phm='0' AND cpt=0 THEN + -- Frequency adjust + sign_v:=tune_freq(5); + IF col<10 THEN col<=col+1; END IF; + IF off_v>=16 AND col>=10 THEN + phm<='1'; + col<=0; + ELSE + off_v:=off_v+1; + IF off_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + up<='1'; + END IF; + + ELSIF cpt=0 THEN + -- Phase adjust + sign_v:=NOT tune_phase(5); + col<=col+1; + IF col>=10 THEN + phm<='0'; + up_v:='1'; + off_v:=31; + col<=0; + ELSE + off_v:=ofp_v + 1; + IF ofp_v>7 THEN + off_v:=off_v + 1; + END IF; + IF ofp_v>14 THEN + off_v:=off_v + 2; + END IF; + IF ofp_v>17 THEN + off_v:=off_v + 3; + END IF; + up_v:='1'; + END IF; + up<='1'; + END IF; + END IF; + + diff_v:=shift_right(mfrac_ref,off_v); + IF sign_v='0' THEN + diff_v:=mfrac_ref + diff_v; + ELSE + diff_v:=mfrac_ref - diff_v; + END IF; + + IF up_v='1' THEN + mfrac<=diff_v; + END IF; + + IF up_v='1' AND phm='0' THEN + mfrac_ref<=diff_v; + END IF; + + ------------------------------------------------------ + -- Update PLL registers + mulco:=mfrac(40 DOWNTO 33) & (mfrac(40 DOWNTO 33) + ('0' & mfrac(32))); + + CASE state IS + WHEN sIDLE => + pwrite<='0'; + IF up='1' THEN + up<='0'; + IF mulco/=mul THEN + state<=sW1; + ELSE + state<=sW3; + END IF; + END IF; + + WHEN sW1 => -- Change M multiplier + mul<=mulco; + pdata<=x"0000" & mulco; + paddress<="000100"; + pwrite<='1'; + state<=sW2; + + WHEN sW2 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW3; + pwrite<='0'; + END IF; + + WHEN sW3 => -- Change M fractional value + pdata<=mfrac(31 DOWNTO 0); + paddress<="000111"; + pwrite<='1'; + state<=sW4; + + WHEN sW4 => + IF pwrite='1' AND o_waitrequest='0' THEN + state<=sW5; + pwrite<='0'; + END IF; + + WHEN sW5 => + pdata<=x"0000_0001"; + paddress<="000010"; + pwrite<='1'; + state<=sW6; + + WHEN sW6 => + IF pwrite='1' AND o_waitrequest='0' THEN + pwrite<='0'; + state<=sIDLE; + END IF; + END CASE; + + END IF; + END PROCESS Schmurtz; + + ---------------------------------------------------------------------------- + +END ARCHITECTURE rtl; + diff --git a/sys/pll_q13.qip b/sys/pll_q13.qip new file mode 100644 index 0000000..78e7e40 --- /dev/null +++ b/sys/pll_q13.qip @@ -0,0 +1,4 @@ +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.13.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] diff --git a/sys/pll_q17.qip b/sys/pll_q17.qip new file mode 100644 index 0000000..85cc84b --- /dev/null +++ b/sys/pll_q17.qip @@ -0,0 +1,4 @@ +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_audio.qip ] +set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] diff --git a/sys/scandoubler.v b/sys/scandoubler.v new file mode 100644 index 0000000..81e7c3f --- /dev/null +++ b/sys/scandoubler.v @@ -0,0 +1,211 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017-2021 Alexey Melnikov +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_vid, + input hq2x, + + // shifter video interface + input ce_pix, + input hs_in, + input vs_in, + input hb_in, + input vb_in, + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + + // output interface + output ce_pix_out, + output reg hs_out, + output vs_out, + output hb_out, + output vb_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; + +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg [7:0] pix_in_cnt = 0; +wire [7:0] pc_in = pix_in_cnt + 1'b1; +reg [7:0] pixsz, pixsz2, pixsz4 = 0; + +reg ce_x4i, ce_x1i; +always @(posedge clk_vid) begin + reg old_ce, valid, hs; + + if(~&pix_len) pix_len <= pl; + if(~&pix_in_cnt) pix_in_cnt <= pc_in; + + ce_x4i <= 0; + ce_x1i <= 0; + + // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. + if((pc_in == pixsz4) || (pc_in == pixsz2) || (pc_in == (pixsz2+pixsz4))) ce_x4i <= 1; + + old_ce <= ce_pix; + if(~old_ce & ce_pix) begin + if(valid & ~hb_in & ~vb_in) begin + pixsz <= pl; + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + end + pix_len <= 0; + valid <= 1; + end + + hs <= hs_in; + if((~hs & hs_in) || (pc_in >= pixsz)) begin + ce_x4i <= 1; + ce_x1i <= 1; + pix_in_cnt <= 0; + end + + if(hb_in | vb_in) valid <= 0; +end + +reg req_line_reset; +reg [DWIDTH:0] r_d, g_d, b_d; +always @(posedge clk_vid) begin + if(ce_x1i) begin + req_line_reset <= hb_in; + r_d <= r_in; + g_d <= g_in; + b_d <= b_in; + end +end + +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_vid), + + .ce_in(ce_x4i), + .inputpixel({b_d,g_d,r_d}), + .disable_hq2x(~hq2x), + .reset_frame(vb_in), + .reset_line(req_line_reset), + + .ce_out(ce_x4o), + .read_y(sd_line), + .hblank(hbo[0]&hbo[8]), + .outpixel({b_out,g_out,r_out}) +); + +reg [7:0] pix_out_cnt = 0; +wire [7:0] pc_out = pix_out_cnt + 1'b1; + +reg ce_x4o, ce_x2o; +always @(posedge clk_vid) begin + reg hs; + + if(~&pix_out_cnt) pix_out_cnt <= pc_out; + + ce_x4o <= 0; + ce_x2o <= 0; + + // use such odd comparison to place ce_x4 evenly if master clock isn't multiple of 4. + if((pc_out == pixsz4) || (pc_out == pixsz2) || (pc_out == (pixsz2+pixsz4))) ce_x4o <= 1; + if( pc_out == pixsz2) ce_x2o <= 1; + + hs <= hs_out; + if((~hs & hs_out) || (pc_out >= pixsz)) begin + ce_x2o <= 1; + ce_x4o <= 1; + pix_out_cnt <= 0; + end +end + +reg [1:0] sd_line; +reg [3:0] vbo; +reg [3:0] vso; +reg [8:0] hbo; +always @(posedge clk_vid) begin + + reg [31:0] hcnt; + reg [30:0] sd_hcnt; + reg [30:0] hs_start, hs_end; + reg [30:0] hde_start, hde_end; + + reg hs, hb; + + if(ce_x4o) begin + hbo[8:1] <= hbo[7:0]; + end + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + if(sd_hcnt == hde_start) begin + sd_hcnt <= 0; + vbo[3:1] <= vbo[2:0]; + end + + if(sd_hcnt == hs_end) begin + sd_line <= sd_line + 1'd1; + if(&vbo[3:2]) sd_line <= 1; + vso[3:1] <= vso[2:0]; + end + + if(sd_hcnt == hde_start)hbo[0] <= 0; + if(sd_hcnt == hde_end) hbo[0] <= 1; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_end) hs_out <= 0; + if(sd_hcnt == hs_start) hs_out <= 1; + + hs <= hs_in; + hb <= hb_in; + + hcnt <= hcnt + 1'd1; + if(hb && !hb_in) begin + hde_start <= hcnt[31:1]; + hbo[0] <= 0; + hcnt <= 0; + sd_hcnt <= 0; + vbo <= {vbo[2:0],vb_in}; + end + + if(!hb && hb_in) hde_end <= hcnt[31:1]; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_end <= hcnt[31:1]; + vso[0] <= vs_in; + end + + // save position of rising edge + if(!hs && hs_in) hs_start <= hcnt[31:1]; +end + +assign vs_out = vso[3]; +assign ce_pix_out = hq2x ? ce_x4o : ce_x2o; + +//Compensate picture shift after HQ2x +assign vb_out = vbo[3]; +assign hb_out = hbo[6]; + +endmodule diff --git a/sys/scanlines.v b/sys/scanlines.v new file mode 100644 index 0000000..43f890f --- /dev/null +++ b/sys/scanlines.v @@ -0,0 +1,68 @@ +module scanlines #(parameter v2=0) +( + input clk, + + input [1:0] scanlines, + input [23:0] din, + input hs_in,vs_in, + input de_in,ce_in, + + output reg [23:0] dout, + output reg hs_out,vs_out, + output reg de_out,ce_out +); + +reg [1:0] scanline; +always @(posedge clk) begin + reg old_hs, old_vs; + + old_hs <= hs_in; + old_vs <= vs_in; + + if(old_hs && ~hs_in) begin + if(v2) begin + scanline <= scanline + 1'd1; + if (scanline == scanlines) scanline <= 0; + end + else scanline <= scanline ^ scanlines; + end + if(old_vs && ~vs_in) scanline <= 0; +end + +wire [7:0] r,g,b; +assign {r,g,b} = din; + +reg [23:0] d; +always @(*) begin + case(scanline) + 1: // reduce 25% = 1/2 + 1/4 + d = {{1'b0, r[7:1]} + {2'b00, r[7:2]}, + {1'b0, g[7:1]} + {2'b00, g[7:2]}, + {1'b0, b[7:1]} + {2'b00, b[7:2]}}; + + 2: // reduce 50% = 1/2 + d = {{1'b0, r[7:1]}, + {1'b0, g[7:1]}, + {1'b0, b[7:1]}}; + + 3: // reduce 75% = 1/4 + d = {{2'b00, r[7:2]}, + {2'b00, g[7:2]}, + {2'b00, b[7:2]}}; + + default: d = {r,g,b}; + endcase +end + +always @(posedge clk) begin + reg [23:0] dout1, dout2; + reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2; + + dout <= dout2; dout2 <= dout1; dout1 <= d; + vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in; + hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in; + de_out <= de2; de2 <= de1; de1 <= de_in; + ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in; +end + +endmodule diff --git a/sys/sd_card.sv b/sys/sd_card.sv new file mode 100644 index 0000000..8cb0560 --- /dev/null +++ b/sys/sd_card.sv @@ -0,0 +1,463 @@ +// +// sd_card.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2015-2018 Sorgelig +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the Lesser GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// http://elm-chan.org/docs/mmc/mmc_e.html +// +///////////////////////////////////////////////////////////////////////// + +// +// Made module syncrhronous. Total code refactoring. (Sorgelig) +// clk_spi must be at least 2 x sck for proper work. + +module sd_card #(parameter WIDE = 0, OCTAL=0) +( + input clk_sys, + input reset, + + input sdhc, + input img_mounted, + input [63:0] img_size, + + output reg [31:0] sd_lba, + output reg sd_rd, + output reg sd_wr, + input sd_ack, + + input [AW:0] sd_buff_addr, + input [DW:0] sd_buff_dout, + output [DW:0] sd_buff_din, + input sd_buff_wr, + + // SPI interface + input clk_spi, + + input ss, + input sck, + input [SW:0] mosi, + output reg [SW:0] miso +); + +localparam AW = WIDE ? 7 : 8; +localparam DW = WIDE ? 15 : 7; +localparam SZ = OCTAL ? 8 : 1; +localparam SW = SZ-1; + +wire [7:0] DATA_TOKEN_CMD25 = 8'hfc; +wire [7:0] STOP_TRAN = 8'hfd; +wire [7:0] DATA_TOKEN = 8'hfe; +wire [7:0] WRITE_DATA_RESPONSE = 8'h05; + +// number of bytes to wait after a command before sending the reply +localparam NCR = 5+3; // 5 bytes are required (command length) + +localparam RD_STATE_IDLE = 0; +localparam RD_STATE_START = 1; +localparam RD_STATE_WAIT_IO = 2; +localparam RD_STATE_SEND_TOKEN = 3; +localparam RD_STATE_SEND_DATA = 4; +localparam RD_STATE_WAIT_M = 5; + +localparam WR_STATE_IDLE = 0; +localparam WR_STATE_EXP_DTOKEN = 1; +localparam WR_STATE_RECV_DATA = 2; +localparam WR_STATE_RECV_CRC0 = 3; +localparam WR_STATE_RECV_CRC1 = 4; +localparam WR_STATE_SEND_DRESP = 5; +localparam WR_STATE_BUSY = 6; + +localparam PREF_STATE_IDLE = 0; +localparam PREF_STATE_RD = 1; +localparam PREF_STATE_FINISH = 2; + +altsyncram sdbuf +( + .clock0 (clk_sys), + .address_a ({sd_buf,sd_buff_addr}), + .data_a (sd_buff_dout), + .wren_a (sd_ack & sd_buff_wr), + .q_a (sd_buff_din), + + .clock1 (clk_spi), + .address_b ({spi_buf,buffer_ptr}), + .data_b (buffer_din), + .wren_b (buffer_wr), + .q_b (buffer_dout), + + .aclr0(1'b0), + .aclr1(1'b0), + .addressstall_a(1'b0), + .addressstall_b(1'b0), + .byteena_a(1'b1), + .byteena_b(1'b1), + .clocken0(1'b1), + .clocken1(1'b1), + .clocken2(1'b1), + .clocken3(1'b1), + .eccstatus(), + .rden_a(1'b1), + .rden_b(1'b1) +); +defparam + sdbuf.numwords_a = 1<<(AW+3), + sdbuf.widthad_a = AW+3, + sdbuf.width_a = DW+1, + sdbuf.numwords_b = 2048, + sdbuf.widthad_b = 11, + sdbuf.width_b = 8, + sdbuf.address_reg_b = "CLOCK1", + sdbuf.clock_enable_input_a = "BYPASS", + sdbuf.clock_enable_input_b = "BYPASS", + sdbuf.clock_enable_output_a = "BYPASS", + sdbuf.clock_enable_output_b = "BYPASS", + sdbuf.indata_reg_b = "CLOCK1", + sdbuf.intended_device_family = "Cyclone V", + sdbuf.lpm_type = "altsyncram", + sdbuf.operation_mode = "BIDIR_DUAL_PORT", + sdbuf.outdata_aclr_a = "NONE", + sdbuf.outdata_aclr_b = "NONE", + sdbuf.outdata_reg_a = "UNREGISTERED", + sdbuf.outdata_reg_b = "UNREGISTERED", + sdbuf.power_up_uninitialized = "FALSE", + sdbuf.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + sdbuf.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ", + sdbuf.width_byteena_a = 1, + sdbuf.width_byteena_b = 1, + sdbuf.wrcontrol_wraddress_reg_b = "CLOCK1"; + +reg [26:0] csd_size; +reg csd_sdhc; +always @(posedge clk_sys) begin + if (img_mounted) begin + csd_sdhc <= sdhc; + if (sdhc) begin + csd_size[0] <= 0; + csd_size[22:1] <= img_size[40:19]; // in 512K units + csd_size[26:23] <= 0; + end + else begin + csd_size[2:0] <= 7; // C_SIZE_MULT + csd_size[14:3] <= 12'b101101101101; + csd_size[26:15] <= img_size[29:18]; // in 256K units ((2**(C_SIZE_MULT+2))*512) + end + end +end + +wire [127:0] CSD = {1'b0,csd_sdhc,6'h00,8'h0e,8'h00,8'h32,8'h5b,8'h59,6'h00,csd_size,7'h7f,8'h80,8'h0a,8'h40,8'h40,8'hf1}; +wire [127:0] CID = {8'hcd,8'hc7,8'h00,8'h93,8'h6f,8'h2f,8'h73,8'h00,8'h00,8'h44,8'h32,8'h38,8'h34,8'h00,8'h00,8'h3e}; + +reg [8:0] buffer_ptr; +reg [7:0] buffer_din; +wire [7:0] buffer_dout; +reg buffer_wr; + +reg [1:0] sd_buf, spi_buf; + +reg [6:0] sbuf; +reg [2:0] bit_cnt; + +wire last_bit = &bit_cnt || OCTAL; +wire [7:0] ibuf = OCTAL ? mosi : {sbuf,mosi[0]}; + +always @(posedge clk_spi) begin + reg [2:0] read_state; + reg [2:0] write_state; + reg [1:0] pref_state; + reg [5:0] cmd; + reg cmd55; + reg [39:0] reply; + reg [3:0] byte_cnt; + reg old_sck; + reg [2:0] ack; + reg [2:0] wait_m_cnt; + reg [31:0] arg; + + ack[1:0] <= {ack[0],sd_ack}; + if(ack[1] == ack[0]) ack[2] <= ack[1]; + + if(~ack[2] & ack[1]) {sd_rd,sd_wr} <= 0; + if( ack[2] & ~ack[1]) begin + sd_buf <= sd_buf + 1'd1; + sd_lba <= sd_lba + 1; + end + + buffer_wr <= 0; + + if(reset) begin + bit_cnt <= 0; + byte_cnt <= '1; + miso <= '1; + cmd <= 0; + sd_wr <= 0; + sd_rd <= 0; + read_state <= RD_STATE_IDLE; + write_state <= WR_STATE_IDLE; + pref_state <= PREF_STATE_IDLE; + end + else begin + + if(buffer_wr) begin + if(~&buffer_ptr) buffer_ptr <= buffer_ptr + 1'd1; + else begin + spi_buf <= spi_buf + 1'd1; + sd_wr <= 1; + end + end + + case(pref_state) + PREF_STATE_IDLE: + if(((sd_buf - spi_buf) <= 1) && (read_state != RD_STATE_IDLE) && (cmd == 17 || cmd == 18)) begin + sd_rd <= 1; + pref_state <= PREF_STATE_RD; + end + + PREF_STATE_RD: + if(read_state == RD_STATE_IDLE) begin + pref_state <= PREF_STATE_IDLE; + end + else if(ack[2] & ~ack[1]) begin + pref_state <= (cmd == 18) ? PREF_STATE_IDLE : PREF_STATE_FINISH; + end + + PREF_STATE_FINISH: + if(read_state == RD_STATE_IDLE) begin + pref_state <= PREF_STATE_IDLE; + end + endcase + + old_sck <= sck; + if(ss) begin + bit_cnt <= 0; + byte_cnt <= '1; + miso <= '1; + end + else if(old_sck & ~sck) begin + miso <= '1; // default: send 1's (busy/wait) + if(byte_cnt >= NCR) {miso,reply} <= {reply, {SZ{1'b1}}}; + + // ---------- read state machine processing ------------- + case(read_state) + RD_STATE_IDLE: ; + + RD_STATE_START: begin + if(byte_cnt == NCR && last_bit) read_state <= (cmd == 9 || cmd == 10) ? RD_STATE_SEND_TOKEN : RD_STATE_WAIT_IO; + end + + // waiting for io controller to return data + RD_STATE_WAIT_IO: begin + if(sd_buf != spi_buf && last_bit) read_state <= RD_STATE_SEND_TOKEN; + end + + // send data token + RD_STATE_SEND_TOKEN: begin + miso <= DATA_TOKEN[~bit_cnt -:SZ]; + if(last_bit) begin + read_state <= RD_STATE_SEND_DATA; // next: send data + buffer_ptr <= 0; + end + end + + // send data + RD_STATE_SEND_DATA: begin + + miso <= (cmd == 9) ? CSD[{buffer_ptr[3:0],~bit_cnt} -:SZ] : (cmd == 10) ? CID[{buffer_ptr[3:0],~bit_cnt} -:SZ] : buffer_dout[~bit_cnt -:SZ]; + + if(last_bit) begin + + // sent 512 sector data bytes? + if(cmd == 17 && &buffer_ptr) read_state <= RD_STATE_IDLE; + else if(cmd == 18 && &buffer_ptr) begin + read_state <= RD_STATE_WAIT_M; + wait_m_cnt <= 0; + end + + // sent 16 cid/csd data bytes? + else if((cmd == 9 || cmd == 10) && &buffer_ptr[3:0]) read_state <= RD_STATE_IDLE; + + // not done yet -> trigger read of next data byte + else buffer_ptr <= buffer_ptr + 1'd1; + end + end + + RD_STATE_WAIT_M: begin + if(last_bit) begin + wait_m_cnt <= wait_m_cnt + 1'd1; + if(&wait_m_cnt) begin + spi_buf <= spi_buf + 1'd1; + read_state <= RD_STATE_WAIT_IO; + end + end + end + endcase + + // ------------------ write support ---------------------- + // send write data response + if(write_state == WR_STATE_SEND_DRESP) miso <= WRITE_DATA_RESPONSE[~bit_cnt -:SZ]; + + // busy after write until the io controller sends ack + if(write_state == WR_STATE_BUSY) miso <= 0; + end + else if(~old_sck & sck) begin + + sbuf[6:0] <= {sbuf[5:0],mosi[0]}; + bit_cnt <= bit_cnt + SZ[2:0]; + + if(last_bit) begin + // finished reading one byte + // byte counter runs against 15 byte boundary + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + // byte_cnt > 6 -> complete command received + // first byte of valid command is 01xxxxxx + // don't accept new commands once a write or read command has been accepted + if(byte_cnt > 5 && + ((write_state == WR_STATE_IDLE && read_state == RD_STATE_IDLE && ibuf[7:6] == 1) || + (read_state != RD_STATE_IDLE && ibuf == 8'h4c))) begin + byte_cnt <= 0; + cmd <= ibuf[5:0]; + cmd55 <= (cmd == 55); // set cmd55 flag if previous command was 55 + if(ibuf[5:0] == 12) read_state <= RD_STATE_IDLE; + end + + // parse additional command bytes + if(byte_cnt == 0) arg[31:24] <= ibuf; + if(byte_cnt == 1) arg[23:16] <= ibuf; + if(byte_cnt == 2) arg[15:8] <= ibuf; + if(byte_cnt == 3) arg[7:0] <= ibuf; + + // last byte (crc) received, evaluate + if(byte_cnt == 4) begin + + // default: + reply <= 40'h04FFFFFFFF; // illegal command + + case(cmd) + // CMD0: GO_IDLE_STATE + 0: reply[39:32] <= 1; // ok, busy + + // CMD1: SEND_OP_COND + 1: reply[39:32] <= 0; + + // CMD8: SEND_IF_COND (V2 only) + 8: reply <= 40'h01000001AA; // ok, busy + + // CMD9: SEND_CSD + 9, + // CMD10: SEND_CID + 10: begin + reply[39:32] <= 0; + read_state <= RD_STATE_START; + end + + // CMD12: STOP_TRANSMISSION + 12: reply[39:32] <= 0; + + // CMD13: SEND_STATUS + 13: reply[39:24] <= 16'h0000; + + // CMD16: SET_BLOCKLEN + 16: reply[39:32] <= (arg == 512) ? 8'h00 : 8'h40; // we only support a block size of 512 + + // CMD17: READ_SINGLE_BLOCK + 17, + // CMD18: READ_MULTIPLE + 18: begin + reply[39:32] <= 0; + read_state <= RD_STATE_START; + spi_buf <= 0; + sd_buf <= 0; + sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]}; + end + + // ACMD23: SET_WR_BLK_ERASE_COUNT + 23: reply[39:32] <= 0; + + // CMD24: WRITE_BLOCK + 24, + // CMD25: WRITE_MULTIPLE + 25: begin + reply[39:32] <= 0; + write_state <= WR_STATE_EXP_DTOKEN; // expect data token + spi_buf <= 0; + sd_buf <= 0; + sd_lba <= csd_sdhc ? arg : {9'd0, arg[31:9]}; + end + + // ACMD41: APP_SEND_OP_COND + 41: if(cmd55) reply[39:32] <= 0; // ok, not busy + + // CMD55: APP_COND + 55: reply[39:32] <= 1; // ok, busy + + // CMD58: READ_OCR + 58: reply <= { 8'h00, 1'b1, csd_sdhc, 30'd0 }; // bit 30 = 1 -> high capacity card + + // CMD59: CRC_ON_OFF + 59: reply[39:32] <= 0; + endcase + end + + // ---------- handle write ----------- + case(write_state) + // do nothing in idle state + WR_STATE_IDLE: ; + + // waiting for data token + WR_STATE_EXP_DTOKEN: begin + buffer_ptr <= 0; + if(cmd == 24) begin + if(ibuf == DATA_TOKEN) write_state <= WR_STATE_RECV_DATA; + end + else begin + if(ibuf == DATA_TOKEN_CMD25) write_state <= WR_STATE_RECV_DATA; + if(ibuf == STOP_TRAN) write_state <= WR_STATE_IDLE; + end + end + + // transfer 512 bytes + WR_STATE_RECV_DATA: begin + // push one byte into local buffer + buffer_wr <= 1; + buffer_din <= ibuf; + + // all bytes written? + if(&buffer_ptr) write_state <= WR_STATE_RECV_CRC0; + end + + // transfer 1st crc byte + WR_STATE_RECV_CRC0: + write_state <= WR_STATE_RECV_CRC1; + + // transfer 2nd crc byte + WR_STATE_RECV_CRC1: + write_state <= WR_STATE_SEND_DRESP; + + // send data response + WR_STATE_SEND_DRESP: + write_state <= WR_STATE_BUSY; + + // wait for io controller to accept data + WR_STATE_BUSY: + if(spi_buf == sd_buf) write_state <= (cmd == 25) ? WR_STATE_EXP_DTOKEN : WR_STATE_IDLE; + endcase + end + end + end +end + +endmodule diff --git a/sys/shadowmask.sv b/sys/shadowmask.sv new file mode 100644 index 0000000..572679c --- /dev/null +++ b/sys/shadowmask.sv @@ -0,0 +1,136 @@ +module shadowmask +( + input clk, + input clk_sys, + + input cmd_wr, + input [15:0] cmd_in, + + input [23:0] din, + input hs_in,vs_in, + input de_in, + input brd_in, + input enable, + + output reg [23:0] dout, + output reg hs_out,vs_out, + output reg de_out +); + + +reg [4:0] hmax; +reg [4:0] vmax; +reg [7:0] mask_idx; +reg mask_2x; +reg mask_rotate; +reg mask_enable; +reg [10:0] mask_lut[256]; + +always @(posedge clk) begin + reg [4:0] hcount; + reg [4:0] vcount; + reg [3:0] hindex; + reg [3:0] vindex; + reg [4:0] hmax2; + reg [4:0] vmax2; + reg [11:0] pcnt,pde; + reg old_hs, old_vs, old_brd; + reg next_v; + + old_hs <= hs_in; + old_vs <= vs_in; + old_brd<= brd_in; + + // hcount and vcount counts pixel rows and columns + // hindex and vindex half the value of the counters for double size patterns + // hindex2, vindex2 swap the h and v counters for drawing rotated masks + hindex <= mask_2x ? hcount[4:1] : hcount[3:0]; + vindex <= mask_2x ? vcount[4:1] : vcount[3:0]; + mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex}; + + // hmax and vmax store these sizes + // hmax2 and vmax2 swap the values to handle rotation + hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x; + vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x; + + pcnt <= pcnt+1'd1; + if(old_brd && ~brd_in) pde <= pcnt-4'd3; + + hcount <= hcount+1'b1; + if(hcount == hmax2 || pde == pcnt) hcount <= 0; + + if(~old_brd && brd_in) next_v <= 1; + if(old_vs && ~vs_in) vcount <= 0; + if(old_hs && ~hs_in) begin + vcount <= vcount + next_v; + next_v <= 0; + pcnt <= 0; + if (vcount == vmax2) vcount <= 0; + end +end + +reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers +always @(posedge clk) begin + reg [10:0] lut; + + lut <= mask_lut[mask_idx]; + + r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels + if (mask_enable) begin + r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + end +end + +always @(posedge clk) begin + reg [11:0] vid; + reg [7:0] r1, g1, b1; + reg [7:0] r2, g2, b2; + reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5% + reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100% + reg [8:0] r4, g4, b4; + + // C1 - data input + {r1,g1,b1} <= din; + vid <= {vid[8:0],vs_in, hs_in, de_in}; + + // C2 - relax timings + {r2,g2,b2} <= {r1,g1,b1}; + + // C3 - perform multiplications + r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]); + r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]); + g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]); + g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]); + b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]); + b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]); + + // C4 - combine results + r4 <= r3_x + r3_y; + g4 <= g3_x + g3_y; + b4 <= b3_x + b3_y; + + // C5 - clamp and output + dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]}; + {vs_out,hs_out,de_out} <= vid[11:9]; +end + +// clock in mask commands +always @(posedge clk_sys) begin + reg m_enable; + reg [7:0] idx; + + if (cmd_wr) begin + case(cmd_in[15:13]) + 3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end + 3'b001: vmax <= cmd_in[3:0]; + 3'b010: hmax <= cmd_in[3:0]; + 3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end + endcase + end + + mask_enable <= m_enable & enable; +end + +endmodule diff --git a/sys/sigma_delta_dac.v b/sys/sigma_delta_dac.v new file mode 100644 index 0000000..d0d6be0 --- /dev/null +++ b/sys/sigma_delta_dac.v @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/sys/spdif.v b/sys/spdif.v new file mode 100644 index 0000000..eee2b08 --- /dev/null +++ b/sys/spdif.v @@ -0,0 +1,320 @@ +//----------------------------------------------------------------- +// SPDIF Transmitter +// V0.1 +// Ultra-Embedded.com +// Copyright 2012 +// +// Email: admin@ultra-embedded.com +// +// License: GPL +// If you would like a version with a more permissive license for +// use in closed source commercial applications please contact me +// for details. +//----------------------------------------------------------------- +// +// This file is open source HDL; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this file; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +//----------------------------------------------------------------- +// altera message_off 10762 +// altera message_off 10240 + +module spdif +( + input clk_i, + input rst_i, + + // SPDIF bit output enable + // Single cycle pulse synchronous to clk_i which drives + // the output bit rate. + // For 44.1KHz, 44100×32×2×2 = 5,644,800Hz + // For 48KHz, 48000×32×2×2 = 6,144,000Hz + input bit_out_en_i, + + // Output + output spdif_o, + + // Audio interface (16-bit x 2 = RL) + input [31:0] sample_i, + output reg sample_req_o +); + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [15:0] audio_sample_q; +reg [8:0] subframe_count_q; + +reg load_subframe_q; +reg [7:0] preamble_q; +wire [31:0] subframe_w; + +reg [5:0] bit_count_q; +reg bit_toggle_q; + +reg spdif_out_q; + +reg [5:0] parity_count_q; + +reg channel_status_bit_q; + +//----------------------------------------------------------------- +// Subframe Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + subframe_count_q <= 9'd0; + else if (load_subframe_q) + begin + // 192 frames (384 subframes) in an audio block + if (subframe_count_q == 9'd383) + subframe_count_q <= 9'd0; + else + subframe_count_q <= subframe_count_q + 9'd1; + end +end + +//----------------------------------------------------------------- +// Sample capture +//----------------------------------------------------------------- +reg [15:0] sample_buf_q; + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + audio_sample_q <= 16'h0000; + sample_buf_q <= 16'h0000; + sample_req_o <= 1'b0; + end + else if (load_subframe_q) + begin + // Start of frame (first subframe)? + if (subframe_count_q[0] == 1'b0) + begin + // Use left sample + audio_sample_q <= sample_i[15:0]; + + // Store right sample + sample_buf_q <= sample_i[31:16]; + + // Request next sample + sample_req_o <= 1'b1; + end + else + begin + // Use right sample + audio_sample_q <= sample_buf_q; + + sample_req_o <= 1'b0; + end + end + else + sample_req_o <= 1'b0; +end + +// Timeslots 3 - 0 = Preamble +assign subframe_w[3:0] = 4'b0000; + +// Timeslots 7 - 4 = 24-bit audio LSB +assign subframe_w[7:4] = 4'b0000; + +// Timeslots 11 - 8 = 20-bit audio LSB +assign subframe_w[11:8] = 4'b0000; + +// Timeslots 27 - 12 = 16-bit audio +assign subframe_w[27:12] = audio_sample_q; + +// Timeslots 28 = Validity +assign subframe_w[28] = 1'b0; // Valid + +// Timeslots 29 = User bit +assign subframe_w[29] = 1'b0; + +// Timeslots 30 = Channel status bit +assign subframe_w[30] = channel_status_bit_q ; //was constant 1'b0 enabling copy-bit; + +// Timeslots 31 = Even Parity bit (31:4) +assign subframe_w[31] = 1'b0; + +//----------------------------------------------------------------- +// Preamble and Channel status bit +//----------------------------------------------------------------- +localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block +localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data +localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block + +reg [7:0] preamble_r; +reg channel_status_bit_r; + +always @ * +begin + // Start of audio block? + // Z(B) - Left channel + if (subframe_count_q == 9'd0) + preamble_r = PREAMBLE_Z; // Z(B) + // Right Channel? + else if (subframe_count_q[0] == 1'b1) + preamble_r = PREAMBLE_Y; // Y(W) + // Left Channel (but not start of block)? + else + preamble_r = PREAMBLE_X; // X(M) + + if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted + channel_status_bit_r = 1'b1; + else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media + channel_status_bit_r = 1'b1; + else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r) + channel_status_bit_r = 1'b1; + else + channel_status_bit_r = 1'b0; // everything else defaults to 0 +end + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + preamble_q <= 8'h00; + channel_status_bit_q <= 1'b0; + end + else if (load_subframe_q) + begin + preamble_q <= preamble_r; + channel_status_bit_q <= channel_status_bit_r; + end +end + +//----------------------------------------------------------------- +// Parity Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + parity_count_q <= 6'd0; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + parity_count_q <= 6'd0; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + // On first pass through this timeslot, count number of high bits + if (bit_count_q[0] == 0 && subframe_w[bit_count_q / 2] == 1'b1) + parity_count_q <= parity_count_q + 6'd1; + end + end +end + +//----------------------------------------------------------------- +// Bit Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +begin + if (rst_i == 1'b1) + begin + bit_count_q <= 6'b0; + load_subframe_q <= 1'b1; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // 32 timeslots (x2 for double frequency) + if (bit_count_q == 6'd63) + begin + bit_count_q <= 6'd0; + load_subframe_q <= 1'b1; + end + else + begin + bit_count_q <= bit_count_q + 6'd1; + load_subframe_q <= 1'b0; + end + end + else + load_subframe_q <= 1'b0; +end + +//----------------------------------------------------------------- +// Bit half toggle +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +if (rst_i == 1'b1) + bit_toggle_q <= 1'b0; +// Time to output a bit? +else if (bit_out_en_i) + bit_toggle_q <= ~bit_toggle_q; + +//----------------------------------------------------------------- +// Output bit (BMC encoded) +//----------------------------------------------------------------- +reg bit_r; + +always @ * +begin + bit_r = spdif_out_q; + + // Time to output a bit? + if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + bit_r = preamble_q[bit_count_q[2:0]]; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + if (subframe_w[bit_count_q / 2] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + // Parity timeslot + else + begin + // Even number of high bits, make odd + if (parity_count_q[0] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + end +end + +always @ (posedge rst_i or posedge clk_i ) +if (rst_i == 1'b1) + spdif_out_q <= 1'b0; +else + spdif_out_q <= bit_r; + +assign spdif_o = spdif_out_q; + +endmodule diff --git a/sys/sys.qip b/sys/sys.qip new file mode 100644 index 0000000..ced8e8b --- /dev/null +++ b/sys/sys.qip @@ -0,0 +1,34 @@ +set_global_assignment -name QIP_FILE [join [list $::quartus(qip_path) pll_q [regexp -inline {[0-9]+} $quartus(version)] .qip] {}] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sys_top.v ] +set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) math.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) shadowmask.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freak.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freezer.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) yc_out.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2c.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) alsa.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i2s.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) spdif.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) audio_out.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) iir_filter.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sysmem.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) sd_card.sv ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hps_io.sv ] diff --git a/sys/sys.tcl b/sys/sys.tcl new file mode 100644 index 0000000..6228a14 --- /dev/null +++ b/sys/sys.tcl @@ -0,0 +1,220 @@ +set_global_assignment -name FAMILY "Cyclone V" +set_global_assignment -name DEVICE 5CSEBA6U23I7 +set_global_assignment -name DEVICE_FILTER_PACKAGE UFBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 672 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 + +#============================================================ +# ADC +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_CONVST +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SCK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDI +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDO +set_location_assignment PIN_U9 -to ADC_CONVST +set_location_assignment PIN_V10 -to ADC_SCK +set_location_assignment PIN_AC4 -to ADC_SDI +set_location_assignment PIN_AD4 -to ADC_SDO + +#============================================================ +# I2C LEDS/BUTTONS +#============================================================ +set_location_assignment PIN_U14 -to IO_SCL +set_location_assignment PIN_AG9 -to IO_SDA +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to IO_S* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to IO_S* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to IO_S* + +#============================================================ +# USER PORT +#============================================================ +set_location_assignment PIN_AF17 -to USER_IO[6] +set_location_assignment PIN_AF15 -to USER_IO[5] +set_location_assignment PIN_AG16 -to USER_IO[4] +set_location_assignment PIN_AH11 -to USER_IO[3] +set_location_assignment PIN_AH12 -to USER_IO[2] +set_location_assignment PIN_AH9 -to USER_IO[1] +set_location_assignment PIN_AG11 -to USER_IO[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to USER_IO[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to USER_IO[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to USER_IO[*] + +#============================================================ +# SDIO_CD or SPDIF_OUT +#============================================================ +set_location_assignment PIN_AH7 -to SDCD_SPDIF +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDCD_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDCD_SPDIF +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDCD_SPDIF + +#============================================================ +# SDRAM +#============================================================ +set_location_assignment PIN_Y11 -to SDRAM_A[0] +set_location_assignment PIN_AA26 -to SDRAM_A[1] +set_location_assignment PIN_AA13 -to SDRAM_A[2] +set_location_assignment PIN_AA11 -to SDRAM_A[3] +set_location_assignment PIN_W11 -to SDRAM_A[4] +set_location_assignment PIN_Y19 -to SDRAM_A[5] +set_location_assignment PIN_AB23 -to SDRAM_A[6] +set_location_assignment PIN_AC23 -to SDRAM_A[7] +set_location_assignment PIN_AC22 -to SDRAM_A[8] +set_location_assignment PIN_C12 -to SDRAM_A[9] +set_location_assignment PIN_AB26 -to SDRAM_A[10] +set_location_assignment PIN_AD17 -to SDRAM_A[11] +set_location_assignment PIN_D12 -to SDRAM_A[12] +set_location_assignment PIN_Y17 -to SDRAM_BA[0] +set_location_assignment PIN_AB25 -to SDRAM_BA[1] +set_location_assignment PIN_E8 -to SDRAM_DQ[0] +set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_D11 -to SDRAM_DQ[2] +set_location_assignment PIN_W12 -to SDRAM_DQ[3] +set_location_assignment PIN_AH13 -to SDRAM_DQ[4] +set_location_assignment PIN_D8 -to SDRAM_DQ[5] +set_location_assignment PIN_AH14 -to SDRAM_DQ[6] +set_location_assignment PIN_AF7 -to SDRAM_DQ[7] +set_location_assignment PIN_AE24 -to SDRAM_DQ[8] +set_location_assignment PIN_AD23 -to SDRAM_DQ[9] +set_location_assignment PIN_AE6 -to SDRAM_DQ[10] +set_location_assignment PIN_AE23 -to SDRAM_DQ[11] +set_location_assignment PIN_AG14 -to SDRAM_DQ[12] +set_location_assignment PIN_AD5 -to SDRAM_DQ[13] +set_location_assignment PIN_AF4 -to SDRAM_DQ[14] +set_location_assignment PIN_AH3 -to SDRAM_DQ[15] +set_location_assignment PIN_AG13 -to SDRAM_DQML +set_location_assignment PIN_AF13 -to SDRAM_DQMH +set_location_assignment PIN_AD20 -to SDRAM_CLK +set_location_assignment PIN_AG10 -to SDRAM_CKE +set_location_assignment PIN_AA19 -to SDRAM_nWE +set_location_assignment PIN_AA18 -to SDRAM_nCAS +set_location_assignment PIN_Y18 -to SDRAM_nCS +set_location_assignment PIN_W14 -to SDRAM_nRAS + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_* + +#============================================================ +# SPI SD +#============================================================ +set_location_assignment PIN_AE15 -to SD_SPI_CS +set_location_assignment PIN_AH8 -to SD_SPI_MISO +set_location_assignment PIN_AG8 -to SD_SPI_CLK +set_location_assignment PIN_U13 -to SD_SPI_MOSI +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SD_SPI* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_SPI* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SD_SPI* + + +#============================================================ +# CLOCK +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK1_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK3_50 +set_location_assignment PIN_V11 -to FPGA_CLK1_50 +set_location_assignment PIN_Y13 -to FPGA_CLK2_50 +set_location_assignment PIN_E11 -to FPGA_CLK3_50 + +#============================================================ +# HDMI +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2S +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_LRCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_MCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_D[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_DE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_HS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_VS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to HDMI_TX_CLK +set_location_assignment PIN_U10 -to HDMI_I2C_SCL +set_location_assignment PIN_AA4 -to HDMI_I2C_SDA +set_location_assignment PIN_T13 -to HDMI_I2S +set_location_assignment PIN_T11 -to HDMI_LRCLK +set_location_assignment PIN_U11 -to HDMI_MCLK +set_location_assignment PIN_T12 -to HDMI_SCLK +set_location_assignment PIN_AG5 -to HDMI_TX_CLK +set_location_assignment PIN_AD19 -to HDMI_TX_DE +set_location_assignment PIN_AD12 -to HDMI_TX_D[0] +set_location_assignment PIN_AE12 -to HDMI_TX_D[1] +set_location_assignment PIN_W8 -to HDMI_TX_D[2] +set_location_assignment PIN_Y8 -to HDMI_TX_D[3] +set_location_assignment PIN_AD11 -to HDMI_TX_D[4] +set_location_assignment PIN_AD10 -to HDMI_TX_D[5] +set_location_assignment PIN_AE11 -to HDMI_TX_D[6] +set_location_assignment PIN_Y5 -to HDMI_TX_D[7] +set_location_assignment PIN_AF10 -to HDMI_TX_D[8] +set_location_assignment PIN_Y4 -to HDMI_TX_D[9] +set_location_assignment PIN_AE9 -to HDMI_TX_D[10] +set_location_assignment PIN_AB4 -to HDMI_TX_D[11] +set_location_assignment PIN_AE7 -to HDMI_TX_D[12] +set_location_assignment PIN_AF6 -to HDMI_TX_D[13] +set_location_assignment PIN_AF8 -to HDMI_TX_D[14] +set_location_assignment PIN_AF5 -to HDMI_TX_D[15] +set_location_assignment PIN_AE4 -to HDMI_TX_D[16] +set_location_assignment PIN_AH2 -to HDMI_TX_D[17] +set_location_assignment PIN_AH4 -to HDMI_TX_D[18] +set_location_assignment PIN_AH5 -to HDMI_TX_D[19] +set_location_assignment PIN_AH6 -to HDMI_TX_D[20] +set_location_assignment PIN_AG6 -to HDMI_TX_D[21] +set_location_assignment PIN_AF9 -to HDMI_TX_D[22] +set_location_assignment PIN_AE8 -to HDMI_TX_D[23] +set_location_assignment PIN_T8 -to HDMI_TX_HS +set_location_assignment PIN_AF11 -to HDMI_TX_INT +set_location_assignment PIN_V13 -to HDMI_TX_VS + +#============================================================ +# KEY +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[1] +set_location_assignment PIN_AH17 -to KEY[0] +set_location_assignment PIN_AH16 -to KEY[1] + +#============================================================ +# LED +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7] +set_location_assignment PIN_W15 -to LED[0] +set_location_assignment PIN_AA24 -to LED[1] +set_location_assignment PIN_V16 -to LED[2] +set_location_assignment PIN_V15 -to LED[3] +set_location_assignment PIN_AF26 -to LED[4] +set_location_assignment PIN_AE26 -to LED[5] +set_location_assignment PIN_Y16 -to LED[6] +set_location_assignment PIN_AA23 -to LED[7] + +#============================================================ +# SW +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] +set_location_assignment PIN_Y24 -to SW[0] +set_location_assignment PIN_W24 -to SW[1] +set_location_assignment PIN_W21 -to SW[2] +set_location_assignment PIN_W20 -to SW[3] + +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALSPIMASTER_X52_Y72_N111 -entity sys_top -to spi +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALUART_X52_Y67_N111 -entity sys_top -to uart +set_instance_assignment -name HPS_LOCATION HPSINTERFACEPERIPHERALI2C_X52_Y60_N111 -entity sys_top -to hdmi_i2c + +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" + +set_global_assignment -name CDF_FILE jtag.cdf +set_global_assignment -name QIP_FILE sys/sys.qip + diff --git a/sys/sys_analog.tcl b/sys/sys_analog.tcl new file mode 100644 index 0000000..7ffb3ec --- /dev/null +++ b/sys/sys_analog.tcl @@ -0,0 +1,71 @@ +#============================================================ +# SDIO +#============================================================ +set_location_assignment PIN_AF25 -to SDIO_DAT[0] +set_location_assignment PIN_AF23 -to SDIO_DAT[1] +set_location_assignment PIN_AD26 -to SDIO_DAT[2] +set_location_assignment PIN_AF28 -to SDIO_DAT[3] +set_location_assignment PIN_AF27 -to SDIO_CMD +set_location_assignment PIN_AH26 -to SDIO_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDIO_* + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDIO_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_DAT[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CMD + +#============================================================ +# VGA +#============================================================ +set_location_assignment PIN_AE17 -to VGA_R[0] +set_location_assignment PIN_AE20 -to VGA_R[1] +set_location_assignment PIN_AF20 -to VGA_R[2] +set_location_assignment PIN_AH18 -to VGA_R[3] +set_location_assignment PIN_AH19 -to VGA_R[4] +set_location_assignment PIN_AF21 -to VGA_R[5] + +set_location_assignment PIN_AE19 -to VGA_G[0] +set_location_assignment PIN_AG15 -to VGA_G[1] +set_location_assignment PIN_AF18 -to VGA_G[2] +set_location_assignment PIN_AG18 -to VGA_G[3] +set_location_assignment PIN_AG19 -to VGA_G[4] +set_location_assignment PIN_AG20 -to VGA_G[5] + +set_location_assignment PIN_AG21 -to VGA_B[0] +set_location_assignment PIN_AA20 -to VGA_B[1] +set_location_assignment PIN_AE22 -to VGA_B[2] +set_location_assignment PIN_AF22 -to VGA_B[3] +set_location_assignment PIN_AH23 -to VGA_B[4] +set_location_assignment PIN_AH21 -to VGA_B[5] + +set_location_assignment PIN_AH22 -to VGA_HS +set_location_assignment PIN_AG24 -to VGA_VS + +set_location_assignment PIN_AH27 -to VGA_EN +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to VGA_EN + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to VGA_* + +#============================================================ +# AUDIO +#============================================================ +set_location_assignment PIN_AC24 -to AUDIO_L +set_location_assignment PIN_AE25 -to AUDIO_R +set_location_assignment PIN_AG26 -to AUDIO_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to AUDIO_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to AUDIO_* + +#============================================================ +# I/O #1 +#============================================================ +set_location_assignment PIN_Y15 -to LED_USER +set_location_assignment PIN_AA15 -to LED_HDD +set_location_assignment PIN_AG28 -to LED_POWER + +set_location_assignment PIN_AH24 -to BTN_USER +set_location_assignment PIN_AG25 -to BTN_OSD +set_location_assignment PIN_AG23 -to BTN_RESET + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to BTN_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to BTN_* diff --git a/sys/sys_dual_sdram.tcl b/sys/sys_dual_sdram.tcl new file mode 100644 index 0000000..930a23d --- /dev/null +++ b/sys/sys_dual_sdram.tcl @@ -0,0 +1,51 @@ +#============================================================ +# Secondary SDRAM +#============================================================ +set_location_assignment PIN_Y15 -to SDRAM2_DQ[0] +set_location_assignment PIN_AC24 -to SDRAM2_DQ[1] +set_location_assignment PIN_AA15 -to SDRAM2_DQ[2] +set_location_assignment PIN_AD26 -to SDRAM2_DQ[3] +set_location_assignment PIN_AG28 -to SDRAM2_DQ[4] +set_location_assignment PIN_AF28 -to SDRAM2_DQ[5] +set_location_assignment PIN_AE25 -to SDRAM2_DQ[6] +set_location_assignment PIN_AF27 -to SDRAM2_DQ[7] +set_location_assignment PIN_AG26 -to SDRAM2_DQ[14] +set_location_assignment PIN_AH27 -to SDRAM2_DQ[15] + +set_location_assignment PIN_AG25 -to SDRAM2_DQ[13] +set_location_assignment PIN_AH26 -to SDRAM2_DQ[12] +set_location_assignment PIN_AH24 -to SDRAM2_DQ[11] +set_location_assignment PIN_AF25 -to SDRAM2_DQ[10] +set_location_assignment PIN_AG23 -to SDRAM2_DQ[9] +set_location_assignment PIN_AF23 -to SDRAM2_DQ[8] +set_location_assignment PIN_AG24 -to SDRAM2_A[12] +set_location_assignment PIN_AH22 -to SDRAM2_CLK +set_location_assignment PIN_AH21 -to SDRAM2_A[9] +set_location_assignment PIN_AG21 -to SDRAM2_A[11] +set_location_assignment PIN_AH23 -to SDRAM2_A[7] +set_location_assignment PIN_AA20 -to SDRAM2_A[8] +set_location_assignment PIN_AF22 -to SDRAM2_A[5] +set_location_assignment PIN_AE22 -to SDRAM2_A[6] +set_location_assignment PIN_AG20 -to SDRAM2_nWE +set_location_assignment PIN_AF21 -to SDRAM2_A[4] + +set_location_assignment PIN_AG19 -to SDRAM2_nCAS +set_location_assignment PIN_AH19 -to SDRAM2_nRAS +set_location_assignment PIN_AG18 -to SDRAM2_nCS +set_location_assignment PIN_AH18 -to SDRAM2_BA[0] +set_location_assignment PIN_AF18 -to SDRAM2_BA[1] +set_location_assignment PIN_AF20 -to SDRAM2_A[10] +set_location_assignment PIN_AG15 -to SDRAM2_A[0] +set_location_assignment PIN_AE20 -to SDRAM2_A[1] +set_location_assignment PIN_AE19 -to SDRAM2_A[2] +set_location_assignment PIN_AE17 -to SDRAM2_A[3] + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM2_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDRAM2_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_* + +set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1" diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc new file mode 100644 index 0000000..d0e6a1b --- /dev/null +++ b/sys/sys_top.sdc @@ -0,0 +1,77 @@ +# Specify root clocks +create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] +create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] +create_clock -period "100.0 MHz" [get_pins -compatibility_mode spi|sclk_out] -name spi_sck +create_clock -period "10.0 MHz" [get_pins -compatibility_mode hdmi_i2c|out_clk] -name hdmi_sck + +derive_pll_clocks +derive_clock_uncertainty + +# Decouple different clock groups (to simplify routing) +set_clock_groups -exclusive \ + -group [get_clocks { *|pll|pll_inst|altera_pll_i|*[*].*|divclk}] \ + -group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { pll_audio|pll_audio_inst|altera_pll_i|*[0].*|divclk}] \ + -group [get_clocks { spi_sck}] \ + -group [get_clocks { hdmi_sck}] \ + -group [get_clocks { *|h2f_user0_clk}] \ + -group [get_clocks { FPGA_CLK1_50 }] \ + -group [get_clocks { FPGA_CLK2_50 }] \ + -group [get_clocks { FPGA_CLK3_50 }] + +set_false_path -from [get_ports {KEY*}] +set_false_path -from [get_ports {BTN_*}] +set_false_path -to [get_ports {LED_*}] +set_false_path -to [get_ports {VGA_*}] +set_false_path -from [get_ports {VGA_EN}] +set_false_path -to [get_ports {AUDIO_SPDIF}] +set_false_path -to [get_ports {AUDIO_L}] +set_false_path -to [get_ports {AUDIO_R}] +set_false_path -from {get_ports {SW[*]}} +set_false_path -to {cfg[*]} +set_false_path -from {cfg[*]} +set_false_path -from {VSET[*]} +set_false_path -to {wcalc[*] hcalc[*]} +set_false_path -to {hdmi_width[*] hdmi_height[*]} +set_false_path -to {deb_* btn_en btn_up} + +set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 +set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 + +set_false_path -to {*_osd|v_cnt*} +set_false_path -to {*_osd|v_osd_start*} +set_false_path -to {*_osd|v_info_start*} +set_false_path -to {*_osd|h_osd_start*} +set_false_path -from {*_osd|v_osd_start*} +set_false_path -from {*_osd|v_info_start*} +set_false_path -from {*_osd|h_osd_start*} +set_false_path -from {*_osd|rot*} +set_false_path -from {*_osd|dsp_width*} +set_false_path -to {*_osd|half} + +set_false_path -to {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} +set_false_path -from {WIDTH[*] HFP[*] HS[*] HBP[*] HEIGHT[*] VFP[*] VS[*] VBP[*]} +set_false_path -to {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} +set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*] LFB_HMAX[*] LFB_VMIN[*] LFB_VMAX[*]} +set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} +set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]} +set_false_path -from {aflt_* acx* acy* areset* arc*} +set_false_path -from {arx* ary*} +set_false_path -from {vs_line*} +set_false_path -from {ColorBurst_Range* PhaseInc* pal_en cvbs yc_en} + +set_false_path -from {ascal|o_ihsize*} +set_false_path -from {ascal|o_ivsize*} +set_false_path -from {ascal|o_format*} +set_false_path -from {ascal|o_hdown} +set_false_path -from {ascal|o_vdown} +set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr} +set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*} +set_false_path -from {ascal|o_htotal* ascal|o_vtotal*} +set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*} +set_false_path -from {ascal|o_hsize* ascal|o_vsize*} + +set_false_path -from {mcp23009|flg_*} +set_false_path -to {sysmem|fpga_interfaces|clocks_resets*} diff --git a/sys/sys_top.v b/sys/sys_top.v new file mode 100644 index 0000000..c21cc48 --- /dev/null +++ b/sys/sys_top.v @@ -0,0 +1,1906 @@ +//============================================================================ +// +// MiSTer hardware abstraction module +// (c)2017-2020 Alexey Melnikov +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ + +module sys_top +( + /////////// CLOCK ////////// + input FPGA_CLK1_50, + input FPGA_CLK2_50, + input FPGA_CLK3_50, + + //////////// HDMI ////////// + output HDMI_I2C_SCL, + inout HDMI_I2C_SDA, + + output HDMI_MCLK, + output HDMI_SCLK, + output HDMI_LRCLK, + output HDMI_I2S, + + output HDMI_TX_CLK, + output HDMI_TX_DE, + output [23:0] HDMI_TX_D, + output HDMI_TX_HS, + output HDMI_TX_VS, + + input HDMI_TX_INT, + + //////////// SDR /////////// + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE, + +`ifdef MISTER_DUAL_SDRAM + ////////// SDR #2 ////////// + output [12:0] SDRAM2_A, + inout [15:0] SDRAM2_DQ, + output SDRAM2_nWE, + output SDRAM2_nCAS, + output SDRAM2_nRAS, + output SDRAM2_nCS, + output [1:0] SDRAM2_BA, + output SDRAM2_CLK, + +`else + //////////// VGA /////////// + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + inout VGA_HS, + output VGA_VS, + input VGA_EN, // active low + + /////////// AUDIO ////////// + output AUDIO_L, + output AUDIO_R, + output AUDIO_SPDIF, + + //////////// SDIO /////////// + inout [3:0] SDIO_DAT, + inout SDIO_CMD, + output SDIO_CLK, + + //////////// I/O /////////// + output LED_USER, + output LED_HDD, + output LED_POWER, + input BTN_USER, + input BTN_OSD, + input BTN_RESET, +`endif + + ////////// I/O ALT ///////// + output SD_SPI_CS, + input SD_SPI_MISO, + output SD_SPI_CLK, + output SD_SPI_MOSI, + + inout SDCD_SPDIF, + output IO_SCL, + inout IO_SDA, + + ////////// ADC ////////////// + output ADC_SCK, + input ADC_SDO, + output ADC_SDI, + output ADC_CONVST, + + ////////// MB KEY /////////// + input [1:0] KEY, + + ////////// MB SWITCH //////// + input [3:0] SW, + + ////////// MB LED /////////// + output [7:0] LED, + + ///////// USER IO /////////// + inout [6:0] USER_IO +); + +////////////////////// Secondary SD /////////////////////////////////// +wire SD_CS, SD_CLK, SD_MOSI, SD_MISO, SD_CD; + +`ifndef MISTER_DUAL_SDRAM + assign SD_CD = mcp_en ? mcp_sdcd : SDCD_SPDIF; + assign SD_MISO = SD_CD | (mcp_en ? SD_SPI_MISO : (VGA_EN | SDIO_DAT[0])); + assign SD_SPI_CS = mcp_en ? (mcp_sdcd ? 1'bZ : SD_CS) : (sog & ~cs1 & ~VGA_EN) ? 1'b1 : 1'bZ; + assign SD_SPI_CLK = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_CLK; + assign SD_SPI_MOSI = (~mcp_en | mcp_sdcd) ? 1'bZ : SD_MOSI; + assign {SDIO_CLK,SDIO_CMD,SDIO_DAT} = av_dis ? 6'bZZZZZZ : (mcp_en | (SDCD_SPDIF & ~SW[2])) ? {vga_g,vga_r,vga_b} : {SD_CLK,SD_MOSI,SD_CS,3'bZZZ}; +`else + assign SD_CD = mcp_sdcd; + assign SD_MISO = mcp_sdcd | SD_SPI_MISO; + assign SD_SPI_CS = mcp_sdcd ? 1'bZ : SD_CS; + assign SD_SPI_CLK = mcp_sdcd ? 1'bZ : SD_CLK; + assign SD_SPI_MOSI = mcp_sdcd ? 1'bZ : SD_MOSI; +`endif + +////////////////////// LEDs/Buttons /////////////////////////////////// + +reg [7:0] led_overtake = 0; +reg [7:0] led_state = 0; + +wire led_p = led_power[1] ? ~led_power[0] : 1'b0; +wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); +wire led_u = ~led_user; +wire led_locked; + +//LEDs on de10-nano board +assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}); + +wire [2:0] mcp_btn; +wire mcp_sdcd; +wire mcp_en; +wire mcp_mode; +mcp23009 mcp23009 +( + .clk(FPGA_CLK2_50), + + .btn(mcp_btn), + .led({led_p, led_d, led_u}), + .flg_sd_cd(mcp_sdcd), + .flg_present(mcp_en), + .flg_mode(mcp_mode), + + .scl(IO_SCL), + .sda(IO_SDA) +); + +wire io_dig = mcp_en ? mcp_mode : SW[3]; + +`ifndef MISTER_DUAL_SDRAM + wire av_dis = io_dig | VGA_EN; + assign LED_POWER = av_dis ? 1'bZ : mcp_en ? de1 : led_p ? 1'bZ : 1'b0; + assign LED_HDD = av_dis ? 1'bZ : mcp_en ? (sog & ~cs1) : led_d ? 1'bZ : 1'b0; + //assign LED_USER = av_dis ? 1'bZ : mcp_en ? ~vga_tx_clk : led_u ? 1'bZ : 1'b0; + assign LED_USER = VGA_TX_CLK; + wire BTN_DIS = VGA_EN; +`else + wire BTN_RESET = SDRAM2_DQ[9]; + wire BTN_OSD = SDRAM2_DQ[13]; + wire BTN_USER = SDRAM2_DQ[11]; + wire BTN_DIS = SDRAM2_DQ[15]; +`endif + +reg BTN_EN = 0; +reg [25:0] btn_timeout = 0; +initial btn_timeout = 0; +always @(posedge FPGA_CLK2_50) begin + reg btn_up = 0; + reg btn_en = 0; + + btn_up <= BTN_RESET & BTN_OSD & BTN_USER; + if(~reset & btn_up & ~&btn_timeout) btn_timeout <= btn_timeout + 1'd1; + btn_en <= ~BTN_DIS; + BTN_EN <= &btn_timeout & btn_en; +end + +wire btn_r = (mcp_en | SW[3]) ? mcp_btn[1] : (BTN_EN & ~BTN_RESET); +wire btn_o = (mcp_en | SW[3]) ? mcp_btn[2] : (BTN_EN & ~BTN_OSD ); +wire btn_u = (mcp_en | SW[3]) ? mcp_btn[0] : (BTN_EN & ~BTN_USER ); + +reg btn_user, btn_osd; +always @(posedge FPGA_CLK2_50) begin + integer div; + reg [7:0] deb_user; + reg [7:0] deb_osd; + + div <= div + 1'b1; + if(div > 100000) div <= 0; + + if(!div) begin + deb_user <= {deb_user[6:0], btn_u | ~KEY[1]}; + if(&deb_user) btn_user <= 1; + if(!deb_user) btn_user <= 0; + + deb_osd <= {deb_osd[6:0], btn_o | ~KEY[0]}; + if(&deb_osd) btn_osd <= 1; + if(!deb_osd) btn_osd <= 0; + end +end + +///////////////////////// HPS I/O ///////////////////////////////////// + +// gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) +// used to avoid lockups while JTAG loading +wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], io_dig, 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys}; +wire [31:0] gp_out; + +wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future. +wire io_wait; +wire io_wide; +wire [15:0] io_dout; +wire [15:0] io_din = gp_outr[15:0]; +wire io_clk = gp_outr[17]; +wire io_ss0 = gp_outr[18]; +wire io_ss1 = gp_outr[19]; +wire io_ss2 = gp_outr[20]; + +`ifndef MISTER_DEBUG_NOHDMI + wire io_osd_hdmi = io_ss1 & ~io_ss0; +`endif + +wire io_fpga = ~io_ss1 & io_ss0; +wire io_uio = ~io_ss1 & io_ss2; + +reg io_ack; +reg rack; +wire io_strobe = ~rack & io_clk; + +always @(posedge clk_sys) begin + if(~(io_wait | vs_wait) | io_strobe) begin + rack <= io_clk; + io_ack <= rack; + end +end + +reg [31:0] gp_outr; +always @(posedge clk_sys) begin + reg [31:0] gp_outd; + gp_outr <= gp_outd; + gp_outd <= gp_out; +end + +`ifdef MISTER_DUAL_SDRAM + wire [7:0] core_type = 'hA8; // generic core, dual SDRAM. +`else + wire [7:0] core_type = 'hA4; // generic core. +`endif + +// HPS will not communicate to core if magic is different +wire [31:0] core_magic = {24'h5CA623, core_type}; + +cyclonev_hps_interface_mpu_general_purpose h2f_gp +( + .gp_in({~gp_out[31] ? core_magic : gp_in}), + .gp_out(gp_out) +); + + +reg [15:0] cfg; +reg cfg_set = 0; + +`ifdef MISTER_DEBUG_NOHDMI + wire vga_fb = 0; + wire direct_video = 1; +`else + wire vga_fb = cfg[12] | vga_force_scaler; + wire direct_video = cfg[10]; +`endif + +wire audio_96k = cfg[6]; +wire csync_en = cfg[3]; +wire io_osd_vga = io_ss1 & ~io_ss2; +`ifndef MISTER_DUAL_SDRAM + wire ypbpr_en = cfg[5]; + wire sog = cfg[9]; + `ifdef MISTER_DEBUG_NOHDMI + wire vga_scaler = 0; + `else + wire vga_scaler = cfg[2] | vga_force_scaler; + `endif +`endif + +reg cfg_custom_t = 0; +reg [5:0] cfg_custom_p1; +reg [31:0] cfg_custom_p2; + +reg [4:0] vol_att; +initial vol_att = 5'b11111; + +reg [11:0] coef_addr; +reg [9:0] coef_data; +reg coef_wr = 0; + +wire[12:0] ARX, ARY; +reg [11:0] VSET = 0, HSET = 0; +reg FREESCALE = 0; +reg [2:0] scaler_flt; +reg lowlat = 0; +reg cfg_done = 0; + +reg vs_wait = 0; +reg [11:0] vs_line = 0; + +reg scaler_out = 0; +reg vrr_mode = 0; +wire hdmi_blackout; + +reg [31:0] aflt_rate = 7056000; +reg [39:0] acx = 4258969; +reg [7:0] acx0 = 3; +reg [7:0] acx1 = 3; +reg [7:0] acx2 = 1; +reg [23:0] acy0 = -24'd6216759; +reg [23:0] acy1 = 24'd6143386; +reg [23:0] acy2 = -24'd2023767; +reg areset = 0; +reg [12:0] arc1x = 0; +reg [12:0] arc1y = 0; +reg [12:0] arc2x = 0; +reg [12:0] arc2y = 0; +reg [15:0] io_dout_sys; + +always@(posedge clk_sys) begin + reg [7:0] cmd; + reg has_cmd; + reg [7:0] cnt = 0; + reg vs_d0,vs_d1,vs_d2; + reg [4:0] acx_att; + reg [7:0] fb_crc; + + coef_wr <= 0; + +`ifndef MISTER_DEBUG_NOHDMI + shadowmask_wr <= 0; +`endif + + if(~io_uio) begin + has_cmd <= 0; + cmd <= 0; + areset <= 0; + acx_att <= 0; + acx <= acx >> acx_att; + io_dout_sys <= 0; + end + else + if(io_strobe) begin + io_dout_sys <= 0; + if(!has_cmd) begin + has_cmd <= 1; + cmd <= io_din[7:0]; + cnt <= 0; + if(io_din[7:0] == 'h30) vs_wait <= 1; + if(io_din[7:0] == 'h39) begin + aflt_rate <= 7056000; + acx <= 4258969; + acx0 <= 3; + acx1 <= 3; + acx2 <= 1; + acy0 <= -24'd6216759; + acy1 <= 24'd6143386; + acy2 <= -24'd2023767; + areset <= 1; + end + if(io_din[7:0] == 'h20) io_dout_sys <= 'b11; +`ifndef MISTER_DEBUG_NOHDMI + if(io_din[7:0] == 'h40) io_dout_sys <= fb_crc; +`endif + end + else begin + cnt <= cnt + 1'd1; + if(cmd == 1) begin + cfg <= io_din; + cfg_set <= 1; + scaler_out <= 1; + end + if(cmd == 'h20) begin + cfg_set <= 0; + if(cnt<8) begin + case(cnt[2:0]) + 0: {HDMI_PR,vrr_mode,WIDTH} <= {io_din[15:14], io_din[11:0]}; + 1: HFP <= io_din[11:0]; + 2: HS <= {io_din[15], io_din[11:0]}; + 3: HBP <= io_din[11:0]; + 4: HEIGHT <= io_din[11:0]; + 5: VFP <= io_din[11:0]; + 6: VS <= {io_din[15],io_din[11:0]}; + 7: VBP <= io_din[11:0]; + endcase +`ifndef MISTER_DEBUG_NOHDMI + if(cnt == 1) begin + cfg_custom_p1 <= 0; + cfg_custom_p2 <= 0; + cfg_custom_t <= ~cfg_custom_t; + end + end + else begin + if(cnt[1:0]==0) cfg_custom_p1 <= io_din[5:0]; + if(cnt[1:0]==1) cfg_custom_p2[15:0] <= io_din; + if(cnt[1:0]==2) begin + cfg_custom_p2[31:16] <= io_din; + cfg_custom_t <= ~cfg_custom_t; + cnt[2:0] <= 3'b100; + end + if(cnt == 8) {lowlat,cfg_done} <= {io_din[15],1'b1}; +`endif + end + end + if(cmd == 'h2F) begin + case(cnt[3:0]) + 0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]}; + 1: LFB_BASE[15:0] <= io_din[15:0]; + 2: LFB_BASE[31:16] <= io_din[15:0]; + 3: LFB_WIDTH <= io_din[11:0]; + 4: LFB_HEIGHT <= io_din[11:0]; + 5: LFB_HMIN <= io_din[11:0]; + 6: LFB_HMAX <= io_din[11:0]; + 7: LFB_VMIN <= io_din[11:0]; + 8: LFB_VMAX <= io_din[11:0]; + 9: LFB_STRIDE <= io_din[13:0]; + endcase + end + if(cmd == 'h25) {led_overtake, led_state} <= io_din; + if(cmd == 'h26) vol_att <= io_din[4:0]; + if(cmd == 'h27) VSET <= io_din[11:0]; + if(cmd == 'h2A) begin + if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[9:0]}; + else coef_addr <= io_din[11:0]; + end + if(cmd == 'h2B) scaler_flt <= io_din[2:0]; + if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]}; + if(cmd == 'h38) vs_line <= io_din[11:0]; + if(cmd == 'h39) begin + case(cnt[3:0]) + 0: acx_att <= io_din[4:0]; + 1: aflt_rate[15:0] <= io_din; + 2: aflt_rate[31:16] <= io_din; + 3: acx[15:0] <= io_din; + 4: acx[31:16] <= io_din; + 5: acx[39:32] <= io_din[7:0]; + 6: acx0 <= io_din[7:0]; + 7: acx1 <= io_din[7:0]; + 8: acx2 <= io_din[7:0]; + 9: acy0[15:0] <= io_din; + 10: acy0[23:16] <= io_din[7:0]; + 11: acy1[15:0] <= io_din; + 12: acy1[23:16] <= io_din[7:0]; + 13: acy2[15:0] <= io_din; + 14: acy2[23:16] <= io_din[7:0]; + endcase + end + if(cmd == 'h3A) begin + case(cnt[3:0]) + 0: arc1x <= io_din[12:0]; + 1: arc1y <= io_din[12:0]; + 2: arc2x <= io_din[12:0]; + 3: arc2y <= io_din[12:0]; + endcase + end +`ifndef MISTER_DEBUG_NOHDMI + if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din}; + if(cmd == 'h40) begin + case(cnt[3:0]) + 0: io_dout_sys <= {arxy, arx}; + 1: io_dout_sys <= {arxy, ary}; + 2: io_dout_sys <= {LFB_EN, FB_EN, FB_FMT}; + 3: io_dout_sys <= FB_WIDTH; + 4: io_dout_sys <= FB_HEIGHT; + 5: io_dout_sys <= FB_BASE[15:0]; + 6: io_dout_sys <= FB_BASE[31:16]; + 7: io_dout_sys <= FB_STRIDE; + endcase + end +`endif +`ifndef MISTER_DISABLE_YC + if(cmd == 'h41) begin + case(cnt[3:0]) + 0: {pal_en,cvbs,yc_en} <= io_din[2:0]; + 1: PhaseInc[15:0] <= io_din; + 2: PhaseInc[31:16] <= io_din; + 3: PhaseInc[39:32] <= io_din[7:0]; + 4: ColorBurst_Range[15:0] <= io_din; + 5: ColorBurst_Range[16] <= io_din[0]; + endcase + end +`endif + end + end + +`ifndef MISTER_DEBUG_NOHDMI + fb_crc <= {LFB_EN, FB_EN, FB_FMT} + ^ FB_WIDTH[7:0] ^ FB_WIDTH[11:8] + ^ FB_HEIGHT[7:0] ^ FB_HEIGHT[11:8] + ^ arx[7:0] ^ arx[11:8] ^ arxy + ^ ary[7:0] ^ ary[11:8]; +`endif + + vs_d0 <= HDMI_TX_VS; + if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0; + + vs_d2 <= vs_d1; + if(~vs_d2 & vs_d1) vs_wait <= 0; +end + +cyclonev_hps_interface_peripheral_uart uart +( + .ri(0), + .dsr(uart_dsr), + .dcd(uart_dsr), + .dtr(uart_dtr), + + .cts(uart_cts), + .rts(uart_rts), + .rxd(uart_rxd), + .txd(uart_txd) +); + +wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; +cyclonev_hps_interface_interrupts interrupts +( + .irq(f2h_irq) +); + +/////////////////////////// RESET /////////////////////////////////// + +reg reset_req = 0; +always @(posedge FPGA_CLK2_50) begin + reg [1:0] resetd, resetd2; + reg old_reset; + + //latch the reset + old_reset <= reset; + if(~old_reset & reset) reset_req <= 1; + + //special combination to set/clear the reset + //preventing of accidental reset control + if(resetd==1) reset_req <= 1; + if(resetd==2 && resetd2==0) reset_req <= 0; + + resetd <= gp_out[31:30]; + resetd2 <= resetd; +end + +//////////////////// SYSTEM MEMORY & SCALER ///////////////////////// + +wire reset; +wire clk_100m; + +sysmem_lite sysmem +( + //Reset/Clock + .reset_core_req(reset_req), + .reset_out(reset), + .clock(clk_100m), + + //DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button. + .reset_hps_cold_req(btn_r), + + //64-bit DDR3 RAM access + .ram1_clk(ram_clk), + .ram1_address(ram_address), + .ram1_burstcount(ram_burstcount), + .ram1_waitrequest(ram_waitrequest), + .ram1_readdata(ram_readdata), + .ram1_readdatavalid(ram_readdatavalid), + .ram1_read(ram_read), + .ram1_writedata(ram_writedata), + .ram1_byteenable(ram_byteenable), + .ram1_write(ram_write), + + //64-bit DDR3 RAM access + .ram2_clk(clk_audio), + .ram2_address(ram2_address), + .ram2_burstcount(ram2_burstcount), + .ram2_waitrequest(ram2_waitrequest), + .ram2_readdata(ram2_readdata), + .ram2_readdatavalid(ram2_readdatavalid), + .ram2_read(ram2_read), + .ram2_writedata(ram2_writedata), + .ram2_byteenable(ram2_byteenable), + .ram2_write(ram2_write), + + //128-bit DDR3 RAM access + // HDMI frame buffer + .vbuf_clk(clk_100m), + .vbuf_address(vbuf_address), + .vbuf_burstcount(vbuf_burstcount), + .vbuf_waitrequest(vbuf_waitrequest), + .vbuf_writedata(vbuf_writedata), + .vbuf_byteenable(vbuf_byteenable), + .vbuf_write(vbuf_write), + .vbuf_readdata(vbuf_readdata), + .vbuf_readdatavalid(vbuf_readdatavalid), + .vbuf_read(vbuf_read) +); + +wire [28:0] ram2_address; +wire [7:0] ram2_burstcount; +wire [7:0] ram2_byteenable; +wire ram2_waitrequest; +wire [63:0] ram2_readdata; +wire [63:0] ram2_writedata; +wire ram2_readdatavalid; +wire ram2_read; +wire ram2_write; +wire [7:0] ram2_bcnt; + +ddr_svc ddr_svc +( + .clk(clk_audio), + + .ram_waitrequest(ram2_waitrequest), + .ram_burstcnt(ram2_burstcount), + .ram_addr(ram2_address), + .ram_readdata(ram2_readdata), + .ram_read_ready(ram2_readdatavalid), + .ram_read(ram2_read), + .ram_writedata(ram2_writedata), + .ram_byteenable(ram2_byteenable), + .ram_write(ram2_write), + .ram_bcnt(ram2_bcnt), + +`ifndef MISTER_DISABLE_ALSA + .ch0_addr(alsa_address), + .ch0_burst(1), + .ch0_data(alsa_readdata), + .ch0_req(alsa_req), + .ch0_ready(alsa_ready), +`endif + + .ch1_addr(pal_addr), + .ch1_burst(128), + .ch1_data(pal_data), + .ch1_req(pal_req), + .ch1_ready(pal_wr) +); + +wire clk_pal = clk_audio; + + +wire [27:0] vbuf_address; +wire [7:0] vbuf_burstcount; +wire vbuf_waitrequest; +wire [127:0] vbuf_readdata; +wire vbuf_readdatavalid; +wire vbuf_read; +wire [127:0] vbuf_writedata; +wire [15:0] vbuf_byteenable; +wire vbuf_write; + +wire [23:0] hdmi_data; +wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd; +wire freeze; + +`ifndef MISTER_DEBUG_NOHDMI + wire clk_hdmi = hdmi_clk_out; + + ascal + #( + .RAMBASE(32'h20000000), + `ifdef MISTER_SMALL_VBUF + .RAMSIZE(32'h00200000), + `else + .RAMSIZE(32'h00800000), + `endif + `ifndef MISTER_FB + .PALETTE2("false"), + `else + `ifndef MISTER_FB_PALETTE + .PALETTE2("false"), + `endif + `endif + `ifdef MISTER_DISABLE_ADAPTIVE + .ADAPTIVE("false"), + `endif + `ifdef MISTER_DOWNSCALE_NN + .DOWNSCALE_NN("true"), + `endif + .FRAC(8), + .N_DW(128), + .N_AW(28) + ) + ascal + ( + .reset_na (~reset_req), + .run (1), + .freeze (freeze), + + .i_clk (clk_ihdmi), + .i_ce (ce_hpix), + .i_r (hr_out), + .i_g (hg_out), + .i_b (hb_out), + .i_hs (hhs_fix), + .i_vs (hvs_fix), + .i_fl (f1), + .i_de (hde_emu), + .iauto (1), + .himin (0), + .himax (0), + .vimin (0), + .vimax (0), + + .o_clk (clk_hdmi), + .o_ce (scaler_out), + .o_r (hdmi_data[23:16]), + .o_g (hdmi_data[15:8]), + .o_b (hdmi_data[7:0]), + .o_hs (hdmi_hs), + .o_vs (hdmi_vs), + .o_de (hdmi_de), + .o_vbl (hdmi_vbl), + .o_brd (hdmi_brd), + .o_lltune (lltune), + .htotal (WIDTH + HFP + HBP + HS[11:0]), + .hsstart (WIDTH + HFP), + .hsend (WIDTH + HFP + HS[11:0]), + .hdisp (WIDTH), + .hmin (hmin), + .hmax (hmax), + .vtotal (HEIGHT + VFP + VBP + VS[11:0]), + .vsstart (HEIGHT + VFP), + .vsend (HEIGHT + VFP + VS[11:0]), + .vdisp (HEIGHT), + .vmin (vmin), + .vmax (vmax), + .vrr (vrr_mode), + .vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1), + .swblack (hdmi_blackout), + + .mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}), + .poly_clk (clk_sys), + .poly_a (coef_addr), + .poly_dw (coef_data), + .poly_wr (coef_wr), + + .pal1_clk (clk_pal), + .pal1_dw (pal_d), + .pal1_a (pal_a), + .pal1_wr (pal_wr), + + `ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + .pal2_clk (fb_pal_clk), + .pal2_dw (fb_pal_d), + .pal2_dr (fb_pal_q), + .pal2_a (fb_pal_a), + .pal2_wr (fb_pal_wr), + .pal_n (fb_en), + `endif + `endif + + .o_fb_ena (FB_EN), + .o_fb_hsize (FB_WIDTH), + .o_fb_vsize (FB_HEIGHT), + .o_fb_format (FB_FMT), + .o_fb_base (FB_BASE), + .o_fb_stride (FB_STRIDE), + + .avl_clk (clk_100m), + .avl_waitrequest (vbuf_waitrequest), + .avl_readdata (vbuf_readdata), + .avl_readdatavalid(vbuf_readdatavalid), + .avl_burstcount (vbuf_burstcount), + .avl_writedata (vbuf_writedata), + .avl_address (vbuf_address), + .avl_write (vbuf_write), + .avl_read (vbuf_read), + .avl_byteenable (vbuf_byteenable) + ); +`endif + +reg LFB_EN = 0; +reg LFB_FLT = 0; +reg [5:0] LFB_FMT = 0; +reg [11:0] LFB_WIDTH = 0; +reg [11:0] LFB_HEIGHT = 0; +reg [11:0] LFB_HMIN = 0; +reg [11:0] LFB_HMAX = 0; +reg [11:0] LFB_VMIN = 0; +reg [11:0] LFB_VMAX = 0; +reg [31:0] LFB_BASE = 0; +reg [13:0] LFB_STRIDE = 0; + +reg FB_EN = 0; +reg [5:0] FB_FMT = 0; +reg [11:0] FB_WIDTH = 0; +reg [11:0] FB_HEIGHT = 0; +reg [31:0] FB_BASE = 0; +reg [13:0] FB_STRIDE = 0; + +always @(posedge clk_sys) begin + FB_EN <= LFB_EN | fb_en; + if(LFB_EN) begin + FB_FMT <= LFB_FMT; + FB_WIDTH <= LFB_WIDTH; + FB_HEIGHT <= LFB_HEIGHT; + FB_BASE <= LFB_BASE; + FB_STRIDE <= LFB_STRIDE; + end + else begin + FB_FMT <= fb_fmt; + FB_WIDTH <= fb_width; + FB_HEIGHT <= fb_height; + FB_BASE <= fb_base; + FB_STRIDE <= fb_stride; + end +end + +`ifdef MISTER_FB + reg fb_vbl; + always @(posedge clk_vid) fb_vbl <= hdmi_vbl; +`endif + +reg ar_md_start; +wire ar_md_busy; +reg [11:0] ar_md_mul1, ar_md_mul2, ar_md_div; +wire [11:0] ar_md_res; + +sys_umuldiv #(12,12,12) ar_muldiv +( + .clk(clk_vid), + .start(ar_md_start), + .busy(ar_md_busy), + + .mul1(ar_md_mul1), + .mul2(ar_md_mul2), + .div(ar_md_div), + .result(ar_md_res) +); + +reg [11:0] hmin; +reg [11:0] hmax; +reg [11:0] vmin; +reg [11:0] vmax; +reg [11:0] hdmi_height; +reg [11:0] hdmi_width; + +reg [11:0] arx; +reg [11:0] ary; +reg arxy; + +always @(posedge clk_vid) begin + reg [11:0] hmini,hmaxi,vmini,vmaxi; + reg [11:0] wcalc,videow; + reg [11:0] hcalc,videoh; + reg [2:0] state; + + hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT; + hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET << HDMI_PR : WIDTH << HDMI_PR; + + if(!ARY) begin + if(ARX == 1) begin + arx <= arc1x[11:0]; + ary <= arc1y[11:0]; + arxy <= arc1x[12] | arc1y[12]; + end + else if(ARX == 2) begin + arx <= arc2x[11:0]; + ary <= arc2y[11:0]; + arxy <= arc2x[12] | arc2y[12]; + end + else begin + arx <= 0; + ary <= 0; + arxy <= 0; + end + end + else begin + arx <= ARX[11:0]; + ary <= ARY[11:0]; + arxy <= ARX[12] | ARY[12]; + end + + ar_md_start <= 0; + state <= state + 1'd1; + case(state) + 0: if(LFB_EN) begin + hmini <= LFB_HMIN; + vmini <= LFB_VMIN; + hmaxi <= LFB_HMAX; + vmaxi <= LFB_VMAX; + state <= 0; + end + else if(FREESCALE || !arx || !ary) begin + wcalc <= hdmi_width; + hcalc <= hdmi_height; + state <= 6; + end + else if(arxy) begin + wcalc <= arx; + hcalc <= ary; + state <= 6; + end + + 1: begin + ar_md_mul1 <= hdmi_height; + ar_md_mul2 <= arx; + ar_md_div <= ary; + ar_md_start<= 1; + end + 2: begin + wcalc <= ar_md_res; + if(ar_md_start | ar_md_busy) state <= 2; + end + + 3: begin + ar_md_mul1 <= hdmi_width; + ar_md_mul2 <= ary; + ar_md_div <= arx; + ar_md_start<= 1; + end + 4: begin + hcalc <= ar_md_res; + if(ar_md_start | ar_md_busy) state <= 4; + end + + 6: begin + videow <= (wcalc > hdmi_width) ? (hdmi_width >> HDMI_PR) : (wcalc[11:0] >> HDMI_PR); + videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0]; + end + + 7: begin + hmini <= ((WIDTH - videow)>>1); + hmaxi <= ((WIDTH - videow)>>1) + videow - 1'd1; + vmini <= ((HEIGHT - videoh)>>1); + vmaxi <= ((HEIGHT - videoh)>>1) + videoh - 1'd1; + end + endcase + + hmin <= hmini; + hmax <= hmaxi; + vmin <= vmini; + vmax <= vmaxi; +end + +`ifndef MISTER_DEBUG_NOHDMI + wire [15:0] lltune; + pll_hdmi_adj pll_hdmi_adj + ( + .clk(FPGA_CLK1_50), + .reset_na(~reset_req), + + .llena(lowlat), + .lltune({16{cfg_done}} & lltune), + .locked(led_locked), + .i_waitrequest(adj_waitrequest), + .i_write(adj_write), + .i_address(adj_address), + .i_writedata(adj_data), + .o_waitrequest(cfg_waitrequest), + .o_write(cfg_write), + .o_address(cfg_address), + .o_writedata(cfg_data) + ); +`else + assign led_locked = 0; +`endif + +wire [63:0] pal_data; +wire [47:0] pal_d = {pal_data[55:32], pal_data[23:0]}; +wire [6:0] pal_a = ram2_bcnt[6:0]; +wire pal_wr; + +reg [28:0] pal_addr; +reg pal_req = 0; +always @(posedge clk_pal) begin + reg old_vs1, old_vs2; + + pal_addr <= LFB_BASE[31:3] - 29'd512; + + old_vs1 <= hdmi_vs; + old_vs2 <= old_vs1; + + if(~old_vs2 & old_vs1 & ~FB_FMT[2] & FB_FMT[1] & FB_FMT[0] & FB_EN) pal_req <= ~pal_req; +end + + +///////////////////////// HDMI output ///////////////////////////////// +`ifndef MISTER_DEBUG_NOHDMI + wire hdmi_clk_out; + pll_hdmi pll_hdmi + ( + .refclk(FPGA_CLK1_50), + .rst(reset_req), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll), + .outclk_0(hdmi_clk_out) + ); +`endif + +//1920x1080@60 PCLK=148.5MHz CEA +reg [11:0] WIDTH = 1920; +reg [11:0] HFP = 88; +reg [12:0] HS = 48; +reg [11:0] HBP = 148; +reg [11:0] HEIGHT = 1080; +reg [11:0] VFP = 4; +reg [12:0] VS = 5; +reg [11:0] VBP = 36; +reg HDMI_PR = 0; + +wire [63:0] reconfig_to_pll; +wire [63:0] reconfig_from_pll; +wire cfg_waitrequest,adj_waitrequest; +wire cfg_write; +wire [5:0] cfg_address; +wire [31:0] cfg_data; +reg adj_write; +reg [5:0] adj_address; +reg [31:0] adj_data; + +`ifndef MISTER_DEBUG_NOHDMI + pll_cfg_hdmi pll_cfg_hdmi + ( + .mgmt_clk(FPGA_CLK1_50), + .mgmt_reset(reset_req), + .mgmt_waitrequest(cfg_waitrequest), + .mgmt_write(cfg_write), + .mgmt_address(cfg_address), + .mgmt_writedata(cfg_data), + .reconfig_to_pll(reconfig_to_pll), + .reconfig_from_pll(reconfig_from_pll) + ); + + reg cfg_got = 0; + always @(posedge clk_sys) begin + reg vsd, vsd2; + if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set; + else begin + vsd <= HDMI_TX_VS; + vsd2 <= vsd; + if(~vsd2 & vsd) cfg_got <= cfg_set; + end + end + + reg cfg_ready = 0; + always @(posedge FPGA_CLK1_50) begin + reg gotd = 0, gotd2 = 0; + reg custd = 0, custd2 = 0; + reg old_wait = 0; + + gotd <= cfg_got; + gotd2 <= gotd; + + adj_write <= 0; + + custd <= cfg_custom_t; + custd2 <= custd; + if(custd2 != custd & ~gotd) begin + adj_address <= cfg_custom_p1; + adj_data <= cfg_custom_p2; + adj_write <= 1; + end + + if(~gotd2 & gotd) begin + adj_address <= 2; + adj_data <= 0; + adj_write <= 1; + end + + old_wait <= adj_waitrequest; + if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1; + end +`else + wire cfg_ready = 1; +`endif + +assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ; +assign HDMI_I2C_SDA = hdmi_sda_en ? 1'b0 : 1'bZ; + +wire hdmi_scl_en, hdmi_sda_en; +cyclonev_hps_interface_peripheral_i2c hdmi_i2c +( + .out_clk(hdmi_scl_en), + .scl(HDMI_I2C_SCL), + .out_data(hdmi_sda_en), + .sda(HDMI_I2C_SDA) +); + +`ifndef MISTER_DEBUG_NOHDMI + `ifdef MISTER_FB + reg dis_output; + always @(posedge clk_hdmi) begin + reg dis; + dis <= fb_force_blank & ~LFB_EN; + dis_output <= dis; + end + `else + wire dis_output = 0; + `endif + + wire [23:0] hdmi_data_mask; + wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; + + reg [15:0] shadowmask_data; + reg shadowmask_wr = 0; + + shadowmask HDMI_shadowmask + ( + .clk(clk_hdmi), + .clk_sys(clk_sys), + + .cmd_wr(shadowmask_wr), + .cmd_in(shadowmask_data), + + .din(dis_output ? 24'd0 : hdmi_data), + .hs_in(hdmi_hs), + .vs_in(hdmi_vs), + .de_in(hdmi_de), + .brd_in(hdmi_brd), + .enable(~LFB_EN), + + .dout(hdmi_data_mask), + .hs_out(hdmi_hs_mask), + .vs_out(hdmi_vs_mask), + .de_out(hdmi_de_mask) + ); + + wire [23:0] hdmi_data_osd; + wire hdmi_de_osd, hdmi_vs_osd, hdmi_hs_osd; + + osd hdmi_osd + ( + .clk_sys(clk_sys), + + .io_osd(io_osd_hdmi), + .io_strobe(io_strobe), + .io_din(io_din), + + .clk_video(clk_hdmi), + .din(hdmi_data_mask), + .hs_in(hdmi_hs_mask), + .vs_in(hdmi_vs_mask), + .de_in(hdmi_de_mask), + + .dout(hdmi_data_osd), + .hs_out(hdmi_hs_osd), + .vs_out(hdmi_vs_osd), + .de_out(hdmi_de_osd) + ); + + wire hdmi_cs_osd; + csync csync_hdmi(clk_hdmi, hdmi_hs_osd, hdmi_vs_osd, hdmi_cs_osd); +`endif + +reg [23:0] dv_data; +reg dv_hs, dv_vs, dv_de; +wire [23:0] dv_data_osd; +wire dv_hs_osd, dv_vs_osd, dv_cs_osd; + +always @(posedge clk_vid) begin + reg [23:0] dv_d1, dv_d2; + reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2; + reg [12:0] vsz, vcnt, vcnt_l, vcnt_ll; + reg old_hs, old_vs; + reg vde; + reg [3:0] hss; + + if(ce_pix) begin + hss <= (hss << 1) | dv_hs_osd; + + old_hs <= dv_hs_osd; + if(~old_hs && dv_hs_osd) begin + old_vs <= dv_vs_osd; + if(~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & dv_vs_osd) begin + if (vcnt != vcnt_ll || vcnt < vcnt_l) vsz <= vcnt; + vcnt_l <= vcnt; + vcnt_ll <= vcnt_l; + end + if(old_vs & ~dv_vs_osd) vcnt <= 0; + + if(vcnt == 1) vde <= 1; + if(vcnt == vsz - 3) vde <= 0; + end + + dv_de1 <= !{hss,dv_hs_osd} && vde; + end + + dv_d1 <= dv_data_osd; + dv_hs1 <= csync_en ? dv_cs_osd : dv_hs_osd; + dv_vs1 <= dv_vs_osd; + + dv_d2 <= dv_d1; + dv_de2 <= dv_de1; + dv_hs2 <= dv_hs1; + dv_vs2 <= dv_vs1; + + dv_data<= dv_d2; + dv_de <= dv_de2; + dv_hs <= dv_hs2; + dv_vs <= dv_vs2; +end + +`ifndef MISTER_DISABLE_YC + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = ~yc_en ? {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd } : {yc_o, yc_hs, yc_vs, yc_cs }; +`else + assign {dv_data_osd, dv_hs_osd, dv_vs_osd, dv_cs_osd } = {vga_data_osd, vga_hs_osd, vga_vs_osd, vga_cs_osd }; +`endif + +wire hdmi_tx_clk; +`ifndef MISTER_DEBUG_NOHDMI + cyclonev_clkselect hdmi_clk_sw + ( + .clkselect({1'b1, ~vga_fb & direct_video}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(hdmi_tx_clk) + ); +`else + assign hdmi_tx_clk = clk_vid; +`endif + +altddio_out +#( + .extend_oe_disable("OFF"), + .intended_device_family("Cyclone V"), + .invert_output("OFF"), + .lpm_hint("UNUSED"), + .lpm_type("altddio_out"), + .oe_reg("UNREGISTERED"), + .power_up_high("OFF"), + .width(1) +) +hdmiclk_ddr +( + .datain_h(1'b0), + .datain_l(1'b1), + .outclock(hdmi_tx_clk), + .dataout(HDMI_TX_CLK), + .aclr(1'b0), + .aset(1'b0), + .oe(1'b1), + .outclocken(1'b1), + .sclr(1'b0), + .sset(1'b0) +); + +reg hdmi_out_hs; +reg hdmi_out_vs; +reg hdmi_out_de; +reg [23:0] hdmi_out_d; + +always @(posedge hdmi_tx_clk) begin + reg [23:0] hdmi_dv_data; + reg hdmi_dv_hs, hdmi_dv_vs, hdmi_dv_de; + + reg hs,vs,de; + reg [23:0] d; + + hdmi_dv_data <= dv_data; + hdmi_dv_hs <= dv_hs; + hdmi_dv_vs <= dv_vs; + hdmi_dv_de <= dv_de; + +`ifndef MISTER_DEBUG_NOHDMI + hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd; + vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd; + de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd; + d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd; +`else + hs <= hdmi_dv_hs; + vs <= hdmi_dv_vs; + de <= hdmi_dv_de; + d <= hdmi_dv_data; +`endif + + hdmi_out_hs <= hs; + hdmi_out_vs <= vs; + hdmi_out_de <= de; + hdmi_out_d <= d; +end + +assign HDMI_TX_HS = hdmi_out_hs; +assign HDMI_TX_VS = hdmi_out_vs; +assign HDMI_TX_DE = hdmi_out_de; +assign HDMI_TX_D = hdmi_out_d; + +///////////////////////// VGA output ////////////////////////////////// + +`ifndef MISTER_DUAL_SDRAM + wire vga_tx_clk; + `ifndef MISTER_DEBUG_NOHDMI + cyclonev_clkselect vga_clk_sw + ( + .clkselect({1'b1, ~vga_fb & ~vga_scaler}), + .inclk({clk_vid, hdmi_clk_out, 2'b00}), + .outclk(vga_tx_clk) + ); + `else + assign vga_tx_clk = clk_vid; + `endif + + wire VGA_TX_CLK; + altddio_out + #( + .extend_oe_disable("OFF"), + .intended_device_family("Cyclone V"), + .invert_output("OFF"), + .lpm_hint("UNUSED"), + .lpm_type("altddio_out"), + .oe_reg("UNREGISTERED"), + .power_up_high("OFF"), + .width(1) + ) + vgaclk_ddr + ( + .datain_h(1'b0), + .datain_l(1'b1), + .outclock(vga_tx_clk), + .dataout(VGA_TX_CLK), + .aclr(~mcp_en & ~av_dis), + .aset(1'b0), + .oe(~av_dis & (mcp_en | ~led_u)), + .outclocken(1'b1), + .sclr(1'b0), + .sset(1'b0) + ); +`endif + +wire [23:0] vga_data_sl; +wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl; +scanlines #(0) VGA_scanlines +( + .clk(clk_vid), + + .scanlines(scanlines), + .din(de_emu ? {r_out, g_out, b_out} : 24'd0), + .hs_in(hs_fix), + .vs_in(vs_fix), + .de_in(de_emu), + .ce_in(ce_pix), + + .dout(vga_data_sl), + .hs_out(vga_hs_sl), + .vs_out(vga_vs_sl), + .de_out(vga_de_sl), + .ce_out(vga_ce_sl) +); + +wire [23:0] vga_data_osd; +wire vga_vs_osd, vga_hs_osd, vga_de_osd; +osd vga_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd_vga), + .io_strobe(io_strobe), + .io_din(io_din), + .osd_status(osd_status), + + .clk_video(clk_vid), + .din(vga_data_sl), + .hs_in(vga_hs_sl), + .vs_in(vga_vs_sl), + .de_in(vga_de_sl), + + .dout(vga_data_osd), + .hs_out(vga_hs_osd), + .vs_out(vga_vs_osd), + .de_out(vga_de_osd) +); + +wire vga_cs_osd; +csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); + +`ifndef MISTER_DISABLE_YC + reg pal_en; + reg yc_en; + reg cvbs; + reg [16:0] ColorBurst_Range; + reg [39:0] PhaseInc; + wire [23:0] yc_o; + wire yc_hs, yc_vs, yc_cs, yc_de; + + yc_out yc_out + ( + .clk(clk_vid), + .PAL_EN(pal_en), + .CVBS(cvbs), + .PHASE_INC(PhaseInc), + .COLORBURST_RANGE(ColorBurst_Range), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .de(vga_de_osd), + .dout(yc_o), + .din(vga_data_osd), + .hsync_o(yc_hs), + .vsync_o(yc_vs), + .csync_o(yc_cs), + .de_o(yc_de) + ); +`endif + +`ifndef MISTER_DUAL_SDRAM + wire VGA_DISABLE; + wire [23:0] vgas_o; + wire vgas_hs, vgas_vs, vgas_cs, vgas_de; + `ifndef MISTER_DEBUG_NOHDMI + vga_out vga_scaler_out + ( + .clk(clk_hdmi), + .ypbpr_en(ypbpr_en), + .hsync(hdmi_hs_osd), + .vsync(hdmi_vs_osd), + .csync(hdmi_cs_osd), + .de(hdmi_de_osd), + .dout(vgas_o), + .din({24{hdmi_de_osd}} & hdmi_data_osd), + .hsync_o(vgas_hs), + .vsync_o(vgas_vs), + .csync_o(vgas_cs), + .de_o(vgas_de) + ); + `else + assign {vgas_o, vgas_hs, vgas_vs, vgas_cs, vgas_de} = 0; + `endif + + wire [23:0] vga_o, vga_o_t; + wire vga_hs, vga_vs, vga_cs, vga_de, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t; + vga_out vga_out + ( + .clk(clk_vid), + .ypbpr_en(ypbpr_en), + .hsync(vga_hs_osd), + .vsync(vga_vs_osd), + .csync(vga_cs_osd), + .de(vga_de_osd), + .dout(vga_o_t), + .din(vga_data_osd), + .hsync_o(vga_hs_t), + .vsync_o(vga_vs_t), + .csync_o(vga_cs_t), + .de_o(vga_de_t) + ); + + `ifndef MISTER_DISABLE_YC + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = ~yc_en ? {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } : {yc_o, yc_hs, yc_vs, yc_cs, yc_de }; + `else + assign {vga_o, vga_hs, vga_vs, vga_cs, vga_de } = {vga_o_t, vga_hs_t, vga_vs_t, vga_cs_t, vga_de_t } ; + `endif + + wire vgas_en = vga_fb | vga_scaler; + + wire cs1 = vgas_en ? vgas_cs : vga_cs; + wire de1 = vgas_en ? vgas_de : vga_de; + + assign VGA_VS = av_dis ? 1'bZ : ((vgas_en ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en); + assign VGA_HS = av_dis ? 1'bZ : (vgas_en ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs)); + assign VGA_R = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18]; + assign VGA_G = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10]; + assign VGA_B = av_dis ? 6'bZZZZZZ : vgas_en ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ; + + wire [1:0] vga_r = vgas_en ? vgas_o[17:16] : VGA_DISABLE ? 2'd0 : vga_o[17:16]; + wire [1:0] vga_g = vgas_en ? vgas_o[9:8] : VGA_DISABLE ? 2'd0 : vga_o[9:8]; + wire [1:0] vga_b = vgas_en ? vgas_o[1:0] : VGA_DISABLE ? 2'd0 : vga_o[1:0]; +`endif + +reg video_sync = 0; +always @(posedge clk_vid) begin + reg [11:0] line_cnt = 0; + reg [11:0] sync_line = 0; + reg [1:0] hs_cnt = 0; + reg old_hs; + + old_hs <= hs_fix; + if(~old_hs & hs_fix) begin + + video_sync <= (sync_line == line_cnt); + + line_cnt <= line_cnt + 1'd1; + if(~hs_cnt[1]) begin + hs_cnt <= hs_cnt + 1'd1; + if(hs_cnt[0]) begin + sync_line <= (line_cnt - vs_line); + line_cnt <= 0; + end + end + end + + if(de_emu) hs_cnt <= 0; +end + +///////////////////////// Audio output //////////////////////////////// + +assign SDCD_SPDIF = (mcp_en & ~spdif) ? 1'b0 : 1'bZ; + +`ifndef MISTER_DUAL_SDRAM + wire analog_l, analog_r; + + assign AUDIO_SPDIF = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_LRCLK : spdif; + assign AUDIO_R = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_I2S : analog_r; + assign AUDIO_L = av_dis ? 1'bZ : (SW[0] | mcp_en) ? HDMI_SCLK : analog_l; +`endif + +assign HDMI_MCLK = clk_audio; +wire clk_audio; + +pll_audio pll_audio +( + .refclk(FPGA_CLK3_50), + .rst(0), + .outclk_0(clk_audio) +); + +wire spdif; +audio_out audio_out +( + .reset(reset | areset), + .clk(clk_audio), + + .att(vol_att), + .mix(audio_mix), + .sample_rate(audio_96k), + + .flt_rate(aflt_rate), + .cx(acx), + .cx0(acx0), + .cx1(acx1), + .cx2(acx2), + .cy0(acy0), + .cy1(acy1), + .cy2(acy2), + + .is_signed(audio_s), + .core_l(audio_l), + .core_r(audio_r), + +`ifndef MISTER_DISABLE_ALSA + .alsa_l(alsa_l), + .alsa_r(alsa_r), +`endif + + .i2s_bclk(HDMI_SCLK), + .i2s_lrclk(HDMI_LRCLK), + .i2s_data(HDMI_I2S), +`ifndef MISTER_DUAL_SDRAM + .dac_l(analog_l), + .dac_r(analog_r), +`endif + .spdif(spdif) +); + + +`ifndef MISTER_DISABLE_ALSA + wire aspi_sck,aspi_mosi,aspi_ss,aspi_miso; + cyclonev_hps_interface_peripheral_spi_master spi + ( + .sclk_out(aspi_sck), + .txd(aspi_mosi), // mosi + .rxd(aspi_miso), // miso + + .ss_0_n(aspi_ss), + .ss_in_n(1) + ); + + wire [28:0] alsa_address; + wire [63:0] alsa_readdata; + wire alsa_ready; + wire alsa_req; + wire alsa_late; + + wire [15:0] alsa_l, alsa_r; + + alsa alsa + ( + .reset(reset), + .clk(clk_audio), + + .ram_address(alsa_address), + .ram_data(alsa_readdata), + .ram_req(alsa_req), + .ram_ready(alsa_ready), + + .spi_ss(aspi_ss), + .spi_sck(aspi_sck), + .spi_mosi(aspi_mosi), + .spi_miso(aspi_miso), + + .pcm_l(alsa_l), + .pcm_r(alsa_r) + ); +`endif + +//////////////// User I/O (USB 3.0 connector) ///////////////////////// + +assign USER_IO[0] = !user_out[0] ? 1'b0 : 1'bZ; +assign USER_IO[1] = !user_out[1] ? 1'b0 : 1'bZ; +assign USER_IO[2] = !(SW[1] ? HDMI_I2S : user_out[2]) ? 1'b0 : 1'bZ; +assign USER_IO[3] = !user_out[3] ? 1'b0 : 1'bZ; +assign USER_IO[4] = !(SW[1] ? HDMI_SCLK : user_out[4]) ? 1'b0 : 1'bZ; +assign USER_IO[5] = !(SW[1] ? HDMI_LRCLK : user_out[5]) ? 1'b0 : 1'bZ; +assign USER_IO[6] = !user_out[6] ? 1'b0 : 1'bZ; + +assign user_in[0] = USER_IO[0]; +assign user_in[1] = USER_IO[1]; +assign user_in[2] = SW[1] | USER_IO[2]; +assign user_in[3] = USER_IO[3]; +assign user_in[4] = SW[1] | USER_IO[4]; +assign user_in[5] = SW[1] | USER_IO[5]; +assign user_in[6] = USER_IO[6]; + + +/////////////////// User module connection //////////////////////////// + +wire clk_sys; +wire [15:0] audio_l, audio_r; +wire audio_s; +wire [1:0] audio_mix; +wire [1:0] scanlines; +wire [7:0] r_out, g_out, b_out, hr_out, hg_out, hb_out; +wire vs_fix, hs_fix, de_emu, vs_emu, hs_emu, f1; +wire hvs_fix, hhs_fix, hde_emu; +wire clk_vid, ce_pix, clk_ihdmi, ce_hpix; +wire vga_force_scaler; + +wire ram_clk; +wire [28:0] ram_address; +wire [7:0] ram_burstcount; +wire ram_waitrequest; +wire [63:0] ram_readdata; +wire ram_readdatavalid; +wire ram_read; +wire [63:0] ram_writedata; +wire [7:0] ram_byteenable; +wire ram_write; + +wire led_user; +wire [1:0] led_power; +wire [1:0] led_disk; +wire [1:0] btn; + +sync_fix sync_v(clk_vid, vs_emu, vs_fix); +sync_fix sync_h(clk_vid, hs_emu, hs_fix); + +wire [6:0] user_out, user_in; + +assign clk_ihdmi= clk_vid; +assign ce_hpix = vga_ce_sl; +assign hr_out = vga_data_sl[23:16]; +assign hg_out = vga_data_sl[15:8]; +assign hb_out = vga_data_sl[7:0]; +assign hhs_fix = vga_hs_sl; +assign hvs_fix = vga_vs_sl; +assign hde_emu = vga_de_sl; + +wire uart_dtr; +wire uart_dsr; +wire uart_cts; +wire uart_rts; +wire uart_rxd; +wire uart_txd; + +wire osd_status; + +wire fb_en; +wire [4:0] fb_fmt; +wire [11:0] fb_width; +wire [11:0] fb_height; +wire [31:0] fb_base; +wire [13:0] fb_stride; + + +`ifdef MISTER_FB + `ifdef MISTER_FB_PALETTE + wire fb_pal_clk; + wire [7:0] fb_pal_a; + wire [23:0] fb_pal_d; + wire [23:0] fb_pal_q; + wire fb_pal_wr; + `endif + wire fb_force_blank; +`else + assign fb_en = 0; + assign fb_fmt = 0; + assign fb_width = 0; + assign fb_height = 0; + assign fb_base = 0; + assign fb_stride = 0; +`endif + +reg [1:0] sl_r; +wire [1:0] sl = sl_r; +always @(posedge clk_sys) sl_r <= FB_EN ? 2'b00 : scanlines; + +emu emu +( + .CLK_50M(FPGA_CLK2_50), + .RESET(reset), + .HPS_BUS({fb_en, sl, f1, HDMI_TX_VS, + clk_100m, clk_ihdmi, + ce_hpix, hde_emu, hhs_fix, hvs_fix, + io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), + + .VGA_R(r_out), + .VGA_G(g_out), + .VGA_B(b_out), + .VGA_HS(hs_emu), + .VGA_VS(vs_emu), + .VGA_DE(de_emu), + .VGA_F1(f1), + .VGA_SCALER(vga_force_scaler), + +`ifndef MISTER_DUAL_SDRAM + .VGA_DISABLE(VGA_DISABLE), +`endif + + .HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width), + .HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height), + .HDMI_FREEZE(freeze), + .HDMI_BLACKOUT(hdmi_blackout), + + .CLK_VIDEO(clk_vid), + .CE_PIXEL(ce_pix), + .VGA_SL(scanlines), + .VIDEO_ARX(ARX), + .VIDEO_ARY(ARY), + +`ifdef MISTER_FB + .FB_EN(fb_en), + .FB_FORMAT(fb_fmt), + .FB_WIDTH(fb_width), + .FB_HEIGHT(fb_height), + .FB_BASE(fb_base), + .FB_STRIDE(fb_stride), + .FB_VBL(fb_vbl), + .FB_LL(lowlat), + .FB_FORCE_BLANK(fb_force_blank), + +`ifdef MISTER_FB_PALETTE + .FB_PAL_CLK (fb_pal_clk), + .FB_PAL_ADDR(fb_pal_a), + .FB_PAL_DOUT(fb_pal_d), + .FB_PAL_DIN (fb_pal_q), + .FB_PAL_WR (fb_pal_wr), +`endif + +`endif + + .LED_USER(led_user), + .LED_POWER(led_power), + .LED_DISK(led_disk), + + .CLK_AUDIO(clk_audio), + .AUDIO_L(audio_l), + .AUDIO_R(audio_r), + .AUDIO_S(audio_s), + .AUDIO_MIX(audio_mix), + + .ADC_BUS({ADC_SCK,ADC_SDO,ADC_SDI,ADC_CONVST}), + + .DDRAM_CLK(ram_clk), + .DDRAM_ADDR(ram_address), + .DDRAM_BURSTCNT(ram_burstcount), + .DDRAM_BUSY(ram_waitrequest), + .DDRAM_DOUT(ram_readdata), + .DDRAM_DOUT_READY(ram_readdatavalid), + .DDRAM_RD(ram_read), + .DDRAM_DIN(ram_writedata), + .DDRAM_BE(ram_byteenable), + .DDRAM_WE(ram_write), + + .SDRAM_DQ(SDRAM_DQ), + .SDRAM_A(SDRAM_A), + .SDRAM_DQML(SDRAM_DQML), + .SDRAM_DQMH(SDRAM_DQMH), + .SDRAM_BA(SDRAM_BA), + .SDRAM_nCS(SDRAM_nCS), + .SDRAM_nWE(SDRAM_nWE), + .SDRAM_nRAS(SDRAM_nRAS), + .SDRAM_nCAS(SDRAM_nCAS), + .SDRAM_CLK(SDRAM_CLK), + .SDRAM_CKE(SDRAM_CKE), + +`ifdef MISTER_DUAL_SDRAM + .SDRAM2_DQ(SDRAM2_DQ), + .SDRAM2_A(SDRAM2_A), + .SDRAM2_BA(SDRAM2_BA), + .SDRAM2_nCS(SDRAM2_nCS), + .SDRAM2_nWE(SDRAM2_nWE), + .SDRAM2_nRAS(SDRAM2_nRAS), + .SDRAM2_nCAS(SDRAM2_nCAS), + .SDRAM2_CLK(SDRAM2_CLK), + .SDRAM2_EN(io_dig), +`endif + + .BUTTONS(btn), + .OSD_STATUS(osd_status), + + .SD_SCK(SD_CLK), + .SD_MOSI(SD_MOSI), + .SD_MISO(SD_MISO), + .SD_CS(SD_CS), + .SD_CD(SD_CD), + + .UART_CTS(uart_rts), + .UART_RTS(uart_cts), + .UART_RXD(uart_txd), + .UART_TXD(uart_rxd), + .UART_DTR(uart_dsr), + .UART_DSR(uart_dtr), + + .USER_OUT(user_out), + .USER_IN(user_in) +); + +endmodule + +///////////////////////////////////////////////////////////////////// + +module sync_fix +( + input clk, + + input sync_in, + output sync_out +); + +assign sync_out = sync_in ^ pol; + +reg pol; +always @(posedge clk) begin + reg [31:0] cnt; + reg s1,s2; + + s1 <= sync_in; + s2 <= s1; + cnt <= s2 ? (cnt - 1) : (cnt + 1); + + if(~s2 & s1) begin + cnt <= 0; + pol <= cnt[31]; + end +end + +endmodule + +///////////////////////////////////////////////////////////////////// + +// CSync generation +// Shifts HSync left by 1 HSync period during VSync + +module csync +( + input clk, + input hsync, + input vsync, + + output csync +); + +assign csync = (csync_vs ^ csync_hs); + +reg csync_hs, csync_vs; +always @(posedge clk) begin + reg prev_hs; + reg [15:0] h_cnt, line_len, hs_len; + + // Count line/Hsync length + h_cnt <= h_cnt + 1'd1; + + prev_hs <= hsync; + if (prev_hs ^ hsync) begin + h_cnt <= 0; + if (hsync) begin + line_len <= h_cnt - hs_len; + csync_hs <= 0; + end + else hs_len <= h_cnt; + end + + if (~vsync) csync_hs <= hsync; + else if(h_cnt == line_len) csync_hs <= 1; + + csync_vs <= vsync; +end + +endmodule diff --git a/sys/sysmem.sv b/sys/sysmem.sv new file mode 100644 index 0000000..8c17e86 --- /dev/null +++ b/sys/sysmem.sv @@ -0,0 +1,570 @@ +`timescale 1 ps / 1 ps +module sysmem_lite +( + output clock, + output reset_out, + + input reset_hps_cold_req, + input reset_hps_warm_req, + input reset_core_req, + + input ram1_clk, + input [28:0] ram1_address, + input [7:0] ram1_burstcount, + output ram1_waitrequest, + output [63:0] ram1_readdata, + output ram1_readdatavalid, + input ram1_read, + input [63:0] ram1_writedata, + input [7:0] ram1_byteenable, + input ram1_write, + + input ram2_clk, + input [28:0] ram2_address, + input [7:0] ram2_burstcount, + output ram2_waitrequest, + output [63:0] ram2_readdata, + output ram2_readdatavalid, + input ram2_read, + input [63:0] ram2_writedata, + input [7:0] ram2_byteenable, + input ram2_write, + + input vbuf_clk, + input [27:0] vbuf_address, + input [7:0] vbuf_burstcount, + output vbuf_waitrequest, + output [127:0] vbuf_readdata, + output vbuf_readdatavalid, + input vbuf_read, + input [127:0] vbuf_writedata, + input [15:0] vbuf_byteenable, + input vbuf_write +); + +assign reset_out = ~init_reset_n | ~hps_h2f_reset_n | reset_core_req; + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram1 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram1_address; +wire [7:0] f2h_ram1_burstcount; +wire f2h_ram1_waitrequest; +wire [63:0] f2h_ram1_readdata; +wire f2h_ram1_readdatavalid; +wire f2h_ram1_read; +wire [63:0] f2h_ram1_writedata; +wire [7:0] f2h_ram1_byteenable; +wire f2h_ram1_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram1_reset_1 = 1'b1; +always @(posedge ram1_clk) begin + ram1_reset_0 <= reset_out; + ram1_reset_1 <= ram1_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram1 +( + .clk (ram1_clk), + .rst_req_sync (ram1_reset_1), + + .waitrequest_slave (ram1_waitrequest), + .burstcount_slave (ram1_burstcount), + .address_slave (ram1_address), + .readdata_slave (ram1_readdata), + .readdatavalid_slave (ram1_readdatavalid), + .read_slave (ram1_read), + .writedata_slave (ram1_writedata), + .byteenable_slave (ram1_byteenable), + .write_slave (ram1_write), + + .waitrequest_master (f2h_ram1_waitrequest), + .burstcount_master (f2h_ram1_burstcount), + .address_master (f2h_ram1_address), + .readdata_master (f2h_ram1_readdata), + .readdatavalid_master (f2h_ram1_readdatavalid), + .read_master (f2h_ram1_read), + .writedata_master (f2h_ram1_writedata), + .byteenable_master (f2h_ram1_byteenable), + .write_master (f2h_ram1_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_ram2 //// +//////////////////////////////////////////////////////// +wire [28:0] f2h_ram2_address; +wire [7:0] f2h_ram2_burstcount; +wire f2h_ram2_waitrequest; +wire [63:0] f2h_ram2_readdata; +wire f2h_ram2_readdatavalid; +wire f2h_ram2_read; +wire [63:0] f2h_ram2_writedata; +wire [7:0] f2h_ram2_byteenable; +wire f2h_ram2_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg ram2_reset_1 = 1'b1; +always @(posedge ram2_clk) begin + ram2_reset_0 <= reset_out; + ram2_reset_1 <= ram2_reset_0; +end + +f2sdram_safe_terminator #(64, 8) f2sdram_safe_terminator_ram2 +( + .clk (ram2_clk), + .rst_req_sync (ram2_reset_1), + + .waitrequest_slave (ram2_waitrequest), + .burstcount_slave (ram2_burstcount), + .address_slave (ram2_address), + .readdata_slave (ram2_readdata), + .readdatavalid_slave (ram2_readdatavalid), + .read_slave (ram2_read), + .writedata_slave (ram2_writedata), + .byteenable_slave (ram2_byteenable), + .write_slave (ram2_write), + + .waitrequest_master (f2h_ram2_waitrequest), + .burstcount_master (f2h_ram2_burstcount), + .address_master (f2h_ram2_address), + .readdata_master (f2h_ram2_readdata), + .readdatavalid_master (f2h_ram2_readdatavalid), + .read_master (f2h_ram2_read), + .writedata_master (f2h_ram2_writedata), + .byteenable_master (f2h_ram2_byteenable), + .write_master (f2h_ram2_write) +); + +//////////////////////////////////////////////////////// +//// f2sdram_safe_terminator_vbuf //// +//////////////////////////////////////////////////////// +wire [27:0] f2h_vbuf_address; +wire [7:0] f2h_vbuf_burstcount; +wire f2h_vbuf_waitrequest; +wire [127:0] f2h_vbuf_readdata; +wire f2h_vbuf_readdatavalid; +wire f2h_vbuf_read; +wire [127:0] f2h_vbuf_writedata; +wire [15:0] f2h_vbuf_byteenable; +wire f2h_vbuf_write; + +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_0 = 1'b1; +(* altera_attribute = {"-name SYNCHRONIZER_IDENTIFICATION FORCED_IF_ASYNCHRONOUS"} *) reg vbuf_reset_1 = 1'b1; +always @(posedge vbuf_clk) begin + vbuf_reset_0 <= reset_out; + vbuf_reset_1 <= vbuf_reset_0; +end + +f2sdram_safe_terminator #(128, 8) f2sdram_safe_terminator_vbuf +( + .clk (vbuf_clk), + .rst_req_sync (vbuf_reset_1), + + .waitrequest_slave (vbuf_waitrequest), + .burstcount_slave (vbuf_burstcount), + .address_slave (vbuf_address), + .readdata_slave (vbuf_readdata), + .readdatavalid_slave (vbuf_readdatavalid), + .read_slave (vbuf_read), + .writedata_slave (vbuf_writedata), + .byteenable_slave (vbuf_byteenable), + .write_slave (vbuf_write), + + .waitrequest_master (f2h_vbuf_waitrequest), + .burstcount_master (f2h_vbuf_burstcount), + .address_master (f2h_vbuf_address), + .readdata_master (f2h_vbuf_readdata), + .readdatavalid_master (f2h_vbuf_readdatavalid), + .read_master (f2h_vbuf_read), + .writedata_master (f2h_vbuf_writedata), + .byteenable_master (f2h_vbuf_byteenable), + .write_master (f2h_vbuf_write) +); + +//////////////////////////////////////////////////////// +//// HPS <> FPGA interfaces //// +//////////////////////////////////////////////////////// +sysmem_HPS_fpga_interfaces fpga_interfaces ( + .f2h_cold_rst_req_n (~reset_hps_cold_req), + .f2h_warm_rst_req_n (~reset_hps_warm_req), + .h2f_user0_clk (clock), + .h2f_rst_n (hps_h2f_reset_n), + .f2h_sdram0_clk (vbuf_clk), + .f2h_sdram0_ADDRESS (f2h_vbuf_address), + .f2h_sdram0_BURSTCOUNT (f2h_vbuf_burstcount), + .f2h_sdram0_WAITREQUEST (f2h_vbuf_waitrequest), + .f2h_sdram0_READDATA (f2h_vbuf_readdata), + .f2h_sdram0_READDATAVALID (f2h_vbuf_readdatavalid), + .f2h_sdram0_READ (f2h_vbuf_read), + .f2h_sdram0_WRITEDATA (f2h_vbuf_writedata), + .f2h_sdram0_BYTEENABLE (f2h_vbuf_byteenable), + .f2h_sdram0_WRITE (f2h_vbuf_write), + .f2h_sdram1_clk (ram1_clk), + .f2h_sdram1_ADDRESS (f2h_ram1_address), + .f2h_sdram1_BURSTCOUNT (f2h_ram1_burstcount), + .f2h_sdram1_WAITREQUEST (f2h_ram1_waitrequest), + .f2h_sdram1_READDATA (f2h_ram1_readdata), + .f2h_sdram1_READDATAVALID (f2h_ram1_readdatavalid), + .f2h_sdram1_READ (f2h_ram1_read), + .f2h_sdram1_WRITEDATA (f2h_ram1_writedata), + .f2h_sdram1_BYTEENABLE (f2h_ram1_byteenable), + .f2h_sdram1_WRITE (f2h_ram1_write), + .f2h_sdram2_clk (ram2_clk), + .f2h_sdram2_ADDRESS (f2h_ram2_address), + .f2h_sdram2_BURSTCOUNT (f2h_ram2_burstcount), + .f2h_sdram2_WAITREQUEST (f2h_ram2_waitrequest), + .f2h_sdram2_READDATA (f2h_ram2_readdata), + .f2h_sdram2_READDATAVALID (f2h_ram2_readdatavalid), + .f2h_sdram2_READ (f2h_ram2_read), + .f2h_sdram2_WRITEDATA (f2h_ram2_writedata), + .f2h_sdram2_BYTEENABLE (f2h_ram2_byteenable), + .f2h_sdram2_WRITE (f2h_ram2_write) +); + +wire hps_h2f_reset_n; + +reg init_reset_n = 0; +always @(posedge clock) begin + integer timeout = 0; + + if(timeout < 2000000) begin + init_reset_n <= 0; + timeout <= timeout + 1; + end + else init_reset_n <= 1; +end + +endmodule + + +module sysmem_HPS_fpga_interfaces +( + // h2f_reset + output wire [1 - 1 : 0 ] h2f_rst_n + + // f2h_cold_reset_req + ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n + + // f2h_warm_reset_req + ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n + + // h2f_user0_clock + ,output wire [1 - 1 : 0 ] h2f_user0_clk + + // f2h_sdram0_data + ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST + ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram0_READ + ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA + ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE + + // f2h_sdram0_clock + ,input wire [1 - 1 : 0 ] f2h_sdram0_clk + + // f2h_sdram1_data + ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram1_READ + ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE + + // f2h_sdram1_clock + ,input wire [1 - 1 : 0 ] f2h_sdram1_clk + + // f2h_sdram2_data + ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram2_READ + ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE + + // f2h_sdram2_clock + ,input wire [1 - 1 : 0 ] f2h_sdram2_clk +); + + +wire [29 - 1 : 0] intermediate; +assign intermediate[0:0] = ~intermediate[1:1]; +assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; +assign intermediate[2:2] = intermediate[9:9]; +assign intermediate[3:3] = intermediate[9:9]; +assign intermediate[5:5] = intermediate[9:9]; +assign intermediate[6:6] = intermediate[9:9]; +assign intermediate[10:10] = intermediate[9:9]; +assign intermediate[11:11] = ~intermediate[12:12]; +assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; +assign intermediate[13:13] = intermediate[18:18]; +assign intermediate[15:15] = intermediate[18:18]; +assign intermediate[19:19] = intermediate[18:18]; +assign intermediate[20:20] = ~intermediate[21:21]; +assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; +assign intermediate[22:22] = intermediate[27:27]; +assign intermediate[24:24] = intermediate[27:27]; +assign intermediate[28:28] = intermediate[27:27]; +assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; +assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; +assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; +assign intermediate[4:4] = f2h_sdram0_READ[0:0]; +assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; +assign intermediate[9:9] = f2h_sdram0_clk[0:0]; +assign intermediate[14:14] = f2h_sdram1_READ[0:0]; +assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; +assign intermediate[18:18] = f2h_sdram1_clk[0:0]; +assign intermediate[23:23] = f2h_sdram2_READ[0:0]; +assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; +assign intermediate[27:27] = f2h_sdram2_clk[0:0]; + +cyclonev_hps_interface_clocks_resets clocks_resets( + .f2h_warm_rst_req_n({ + f2h_warm_rst_req_n[0:0] // 0:0 + }) +,.f2h_pending_rst_ack({ + 1'b1 // 0:0 + }) +,.f2h_dbg_rst_req_n({ + 1'b1 // 0:0 + }) +,.h2f_rst_n({ + h2f_rst_n[0:0] // 0:0 + }) +,.f2h_cold_rst_req_n({ + f2h_cold_rst_req_n[0:0] // 0:0 + }) +,.h2f_user0_clk({ + h2f_user0_clk[0:0] // 0:0 + }) +); + + +cyclonev_hps_interface_dbg_apb debug_apb( + .DBG_APB_DISABLE({ + 1'b0 // 0:0 + }) +,.P_CLK_EN({ + 1'b0 // 0:0 + }) +); + + +cyclonev_hps_interface_tpiu_trace tpiu( + .traceclk_ctl({ + 1'b1 // 0:0 + }) +); + + +cyclonev_hps_interface_boot_from_fpga boot_from_fpga( + .boot_from_fpga_ready({ + 1'b0 // 0:0 + }) +,.boot_from_fpga_on_failure({ + 1'b0 // 0:0 + }) +,.bsel_en({ + 1'b0 // 0:0 + }) +,.csel_en({ + 1'b0 // 0:0 + }) +,.csel({ + 2'b01 // 1:0 + }) +,.bsel({ + 3'b001 // 2:0 + }) +); + + +cyclonev_hps_interface_fpga2hps fpga2hps( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_hps2fpga hps2fpga( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_fpga2sdram f2sdram( + .cfg_rfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.cfg_wfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.rd_ready_3({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_2({ + intermediate[28:28] // 0:0 + }) +,.rd_ready_2({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_1({ + intermediate[19:19] // 0:0 + }) +,.rd_ready_1({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_0({ + intermediate[10:10] // 0:0 + }) +,.rd_ready_0({ + 1'b1 // 0:0 + }) +,.wrack_ready_2({ + 1'b1 // 0:0 + }) +,.wrack_ready_1({ + 1'b1 // 0:0 + }) +,.wrack_ready_0({ + 1'b1 // 0:0 + }) +,.cmd_ready_2({ + intermediate[21:21] // 0:0 + }) +,.cmd_ready_1({ + intermediate[12:12] // 0:0 + }) +,.cmd_ready_0({ + intermediate[1:1] // 0:0 + }) +,.cfg_port_width({ + 12'b000000010110 // 11:0 + }) +,.rd_valid_3({ + f2h_sdram2_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_2({ + f2h_sdram1_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_1({ + f2h_sdram0_READDATAVALID[0:0] // 0:0 + }) +,.rd_clk_3({ + intermediate[22:22] // 0:0 + }) +,.rd_data_3({ + f2h_sdram2_READDATA[63:0] // 63:0 + }) +,.rd_clk_2({ + intermediate[13:13] // 0:0 + }) +,.rd_data_2({ + f2h_sdram1_READDATA[63:0] // 63:0 + }) +,.rd_clk_1({ + intermediate[3:3] // 0:0 + }) +,.rd_data_1({ + f2h_sdram0_READDATA[127:64] // 63:0 + }) +,.rd_clk_0({ + intermediate[2:2] // 0:0 + }) +,.rd_data_0({ + f2h_sdram0_READDATA[63:0] // 63:0 + }) +,.cfg_axi_mm_select({ + 6'b000000 // 5:0 + }) +,.cmd_valid_2({ + intermediate[26:26] // 0:0 + }) +,.cmd_valid_1({ + intermediate[17:17] // 0:0 + }) +,.cmd_valid_0({ + intermediate[8:8] // 0:0 + }) +,.cfg_cport_rfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_data_3({ + 2'b00 // 89:88 + ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram2_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_2({ + 2'b00 // 89:88 + ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram1_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_1({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[127:64] // 63:0 + }) +,.cfg_cport_type({ + 12'b000000111111 // 11:0 + }) +,.wr_data_0({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[63:0] // 63:0 + }) +,.cfg_cport_wfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_clk_3({ + intermediate[24:24] // 0:0 + }) +,.wr_clk_2({ + intermediate[15:15] // 0:0 + }) +,.wr_clk_1({ + intermediate[6:6] // 0:0 + }) +,.wr_clk_0({ + intermediate[5:5] // 0:0 + }) +,.cmd_data_2({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram2_ADDRESS[28:0] // 30:2 + ,intermediate[25:25] // 1:1 + ,intermediate[23:23] // 0:0 + }) +,.cmd_data_1({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram1_ADDRESS[28:0] // 30:2 + ,intermediate[16:16] // 1:1 + ,intermediate[14:14] // 0:0 + }) +,.cmd_data_0({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 + ,4'b0000 // 33:30 + ,f2h_sdram0_ADDRESS[27:0] // 29:2 + ,intermediate[7:7] // 1:1 + ,intermediate[4:4] // 0:0 + }) +); + +endmodule diff --git a/sys/vga_out.sv b/sys/vga_out.sv new file mode 100644 index 0000000..4160635 --- /dev/null +++ b/sys/vga_out.sv @@ -0,0 +1,73 @@ + +module vga_out +( + input clk, + input ypbpr_en, + + input hsync, + input vsync, + input csync, + input de, + + input [23:0] din, + output [23:0] dout, + + output reg hsync_o, + output reg vsync_o, + output reg csync_o, + output reg de_o +); + +wire [7:0] red = din[23:16]; +wire [7:0] green = din[15:8]; +wire [7:0] blue = din[7:0]; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html + + +// Y = 0.301*R + 0.586*G + 0.113*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.168*R - 0.332*G + 0.500*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.500*R - 0.418*G - 0.082*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +reg [7:0] y, pb, pr; +reg [23:0] rgb; +always @(posedge clk) begin + reg [18:0] y_1r, pb_1r, pr_1r; + reg [18:0] y_1g, pb_1g, pr_1g; + reg [18:0] y_1b, pb_1b, pr_1b; + reg [18:0] y_2, pb_2, pr_2; + reg [23:0] din1, din2; + reg hsync2, vsync2, csync2, de2; + reg hsync1, vsync1, csync1, de1; + + y_1r <= {red, 6'd0} + {red, 3'd0} + {red, 2'd0} + red; + pb_1r <= 19'd32768 - ({red, 5'd0} + {red, 3'd0} + {red, 1'd0}); + pr_1r <= 19'd32768 + {red, 7'd0}; + + y_1g <= {green, 7'd0} + {green, 4'd0} + {green, 2'd0} + {green, 1'd0}; + pb_1g <= {green, 6'd0} + {green, 4'd0} + {green, 2'd0} + green; + pr_1g <= {green, 6'd0} + {green, 5'd0} + {green, 3'd0} + {green, 1'd0}; + + y_1b <= {blue, 4'd0} + {blue, 3'd0} + {blue, 2'd0} + blue; + pb_1b <= {blue, 7'd0}; + pr_1b <= {blue, 4'd0} + {blue, 2'd0} + blue; + + y_2 <= y_1r + y_1g + y_1b; + pb_2 <= pb_1r - pb_1g + pb_1b; + pr_2 <= pr_1r - pr_1g - pr_1b; + + y <= y_2[18] ? 8'd0 : y_2[16] ? 8'd255 : y_2[15:8]; + pb <= pb_2[18] ? 8'd0 : pb_2[16] ? 8'd255 : pb_2[15:8]; + pr <= pr_2[18] ? 8'd0 : pr_2[16] ? 8'd255 : pr_2[15:8]; + + hsync_o <= hsync2; hsync2 <= hsync1; hsync1 <= hsync; + vsync_o <= vsync2; vsync2 <= vsync1; vsync1 <= vsync; + csync_o <= csync2; csync2 <= csync1; csync1 <= csync; + de_o <= de2; de2 <= de1; de1 <= de; + + rgb <= din2; din2 <= din1; din1 <= din; +end + +assign dout = ypbpr_en ? {pr, y, pb} : rgb; + +endmodule diff --git a/sys/video_cleaner.sv b/sys/video_cleaner.sv new file mode 100644 index 0000000..ddcd2d5 --- /dev/null +++ b/sys/video_cleaner.sv @@ -0,0 +1,108 @@ +// +// +// Copyright (c) 2018 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +module video_cleaner +( + input clk_vid, + input ce_pix, + + input [7:0] R, + input [7:0] G, + input [7:0] B, + + input HSync, + input VSync, + input HBlank, + input VBlank, + + //optional de + input DE_in, + + //optional interlace support + input interlace, + input f1, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output VGA_DE, + + // optional aligned blank + output reg HBlank_out, + output reg VBlank_out, + + // optional aligned de + output reg DE_out +); + +wire hs, vs; +s_fix sync_v(clk_vid, HSync, hs); +s_fix sync_h(clk_vid, VSync, vs); + +wire hbl = hs | HBlank; +wire vbl = vs | VBlank; + +assign VGA_DE = ~(HBlank_out | VBlank_out); + +always @(posedge clk_vid) begin + if(ce_pix) begin + HBlank_out <= hbl; + + VGA_HS <= hs; + + VGA_R <= R; + VGA_G <= G; + VGA_B <= B; + DE_out <= DE_in; + + if (interlace & f1) begin + VGA_VS <= vs; + VBlank_out <= vbl; + end else begin + if(~VGA_HS & hs) VGA_VS <= vs; + if(HBlank_out & ~hbl) VBlank_out <= vbl; + end + end +end + +endmodule + +module s_fix +( + input clk, + + input sync_in, + output sync_out +); + +assign sync_out = sync_in ^ pol; + +reg pol; +always @(posedge clk) begin + integer pos = 0, neg = 0, cnt = 0; + reg s1,s2; + + s1 <= sync_in; + s2 <= s1; + + if(~s2 & s1) neg <= cnt; + if(s2 & ~s1) pos <= cnt; + + cnt <= cnt + 1; + if(s2 != s1) cnt <= 0; + + pol <= pos > neg; +end + +endmodule diff --git a/sys/video_freak.sv b/sys/video_freak.sv new file mode 100644 index 0000000..4348ee2 --- /dev/null +++ b/sys/video_freak.sv @@ -0,0 +1,329 @@ +// +// +// Video crop +// Copyright (c) 2020 Grabulosaure, (c) 2021 Alexey Melnikov +// +// Integer scaling +// Copyright (c) 2021 Alexey Melnikov +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +module video_freak +( + input CLK_VIDEO, + input CE_PIXEL, + input VGA_VS, + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + output VGA_DE, + output reg [12:0] VIDEO_ARX, + output reg [12:0] VIDEO_ARY, + + input VGA_DE_IN, + input [11:0] ARX, + input [11:0] ARY, + input [11:0] CROP_SIZE, + input [4:0] CROP_OFF, // -16...+15 + input [2:0] SCALE //0 - normal, 1 - V-integer, 2 - HV-Integer-, 3 - HV-Integer+, 4 - HV-Integer +); + +reg mul_start; +wire mul_run; +reg [11:0] mul_arg1, mul_arg2; +wire [23:0] mul_res; +sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); + +reg vde; +reg [11:0] arxo,aryo; +reg [11:0] vsize; +reg [11:0] hsize; + +always @(posedge CLK_VIDEO) begin + reg old_de, old_vs,ovde; + reg [11:0] vtot,vcpt,vcrop,voff; + reg [11:0] hcpt; + reg [11:0] vadj; + reg [23:0] ARXG,ARYG; + reg [11:0] arx,ary; + reg [1:0] vcalc; + + if (CE_PIXEL) begin + old_de <= VGA_DE_IN; + old_vs <= VGA_VS; + if (VGA_VS & ~old_vs) begin + vcpt <= 0; + vtot <= vcpt; + vcalc <= 1; + vcrop <= (CROP_SIZE >= vcpt) ? 12'd0 : CROP_SIZE; + end + + if (VGA_DE_IN) hcpt <= hcpt + 1'd1; + if (~VGA_DE_IN & old_de) begin + vcpt <= vcpt + 1'd1; + if(!vcpt) hsize <= hcpt; + hcpt <= 0; + end + end + + arx <= ARX; + ary <= ARY; + + vsize <= vcrop ? vcrop : vtot; + + mul_start <= 0; + + if(!vcrop || !ary || !arx) begin + arxo <= arx; + aryo <= ary; + end + else if (vcalc) begin + if(~mul_start & ~mul_run) begin + vcalc <= vcalc + 1'd1; + case(vcalc) + 1: begin + mul_arg1 <= arx; + mul_arg2 <= vtot; + mul_start <= 1; + end + + 2: begin + ARXG <= mul_res; + mul_arg1 <= ary; + mul_arg2 <= vcrop; + mul_start <= 1; + end + + 3: begin + ARYG <= mul_res; + end + endcase + end + end + else if (ARXG[23] | ARYG[23]) begin + arxo <= ARXG[23:12]; + aryo <= ARYG[23:12]; + end + else begin + ARXG <= ARXG << 1; + ARYG <= ARYG << 1; + end + + vadj <= (vtot-vcrop) + {{6{CROP_OFF[4]}},CROP_OFF,1'b0}; + voff <= vadj[11] ? 12'd0 : ((vadj[11:1] + vcrop) > vtot) ? vtot-vcrop : vadj[11:1]; + ovde <= ((vcpt >= voff) && (vcpt < (vcrop + voff))) || !vcrop; + vde <= ovde; +end + +assign VGA_DE = vde & VGA_DE_IN; + +video_scale_int scale +( + .CLK_VIDEO(CLK_VIDEO), + .HDMI_WIDTH(HDMI_WIDTH), + .HDMI_HEIGHT(HDMI_HEIGHT), + .SCALE(SCALE), + .hsize(hsize), + .vsize(vsize), + .arx_i(arxo), + .ary_i(aryo), + .arx_o(VIDEO_ARX), + .ary_o(VIDEO_ARY) +); + +endmodule + + +module video_scale_int +( + input CLK_VIDEO, + + input [11:0] HDMI_WIDTH, + input [11:0] HDMI_HEIGHT, + + input [2:0] SCALE, + + input [11:0] hsize, + input [11:0] vsize, + + input [11:0] arx_i, + input [11:0] ary_i, + + output reg [12:0] arx_o, + output reg [12:0] ary_o +); + +reg div_start; +wire div_run; +reg [23:0] div_num; +reg [11:0] div_den; +wire [23:0] div_res; +sys_udiv #(24,12) div(CLK_VIDEO,div_start,div_run, div_num,div_den,div_res); + +reg mul_start; +wire mul_run; +reg [11:0] mul_arg1, mul_arg2; +wire [23:0] mul_res; +sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res); + +always @(posedge CLK_VIDEO) begin + reg [11:0] oheight,htarget,wres,hinteger,wideres; + reg [12:0] arxf,aryf; + reg [3:0] cnt; + reg narrow; + + div_start <= 0; + mul_start <= 0; + + if (!SCALE || (!ary_i && arx_i)) begin + arxf <= arx_i; + aryf <= ary_i; + end + else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin + cnt <= cnt + 1'd1; + case(cnt) + // example ideal and non-ideal cases: + // [1] 720x400 4:3 VGA 80x25 text-mode (non-square pixels) + // [2] 640x480 4:3 VGA graphics mode (square pixels) + // [3] 512x512 4:3 X68000 graphics mode (non-square pixels) + 0: begin + div_num <= HDMI_HEIGHT; + div_den <= vsize; + div_start <= 1; + end + // [1] 1080 / 400 -> 2 + // [2] 1080 / 480 -> 2 + // [3] 1080 / 512 -> 2 + + 1: if(!div_res[11:0]) begin + // screen resolution is lower than video resolution. + // Integer scaling is impossible. + arxf <= arx_i; + aryf <= ary_i; + cnt <= 0; + end + else begin + mul_arg1 <= vsize; + mul_arg2 <= div_res[11:0]; + mul_start <= 1; + end + // [1] 1080 / 400 * 400 -> 800 + // [2] 1080 / 480 * 480 -> 960 + // [3] 1080 / 512 * 512 -> 1024 + + 2: begin + oheight <= mul_res[11:0]; + if(!ary_i) begin + cnt <= 8; + end + end + + 3: begin + mul_arg1 <= mul_res[11:0]; + mul_arg2 <= arx_i; + mul_start <= 1; + end + // [1] 1080 / 400 * 400 * 4 -> 3200 + // [2] 1080 / 480 * 480 * 4 -> 3840 + // [3] 1080 / 512 * 512 * 4 -> 4096 + + 4: begin + div_num <= mul_res; + div_den <= ary_i; + div_start <= 1; + end + // [1] 1080 / 480 * 480 * 4 / 3 -> 1066 + // [2] 1080 / 480 * 480 * 4 / 3 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 -> 1365 + // saved as htarget + + 5: begin + htarget <= div_res[11:0]; + div_num <= div_res; + div_den <= hsize; + div_start <= 1; + end + // computes wide scaling factor as a ceiling division + // [1] 1080 / 400 * 400 * 4 / 3 / 720 -> 1 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 -> 2 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 -> 2 + + 6: begin + mul_arg1 <= hsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + // [1] 1080 / 400 * 400 * 4 / 3 / 720 * 720 -> 720 + // [2] 1080 / 480 * 480 * 4 / 3 / 640 * 640 -> 1280 + // [3] 1080 / 512 * 512 * 4 / 3 / 512 * 512 -> 1024 + + 7: if(mul_res <= HDMI_WIDTH) begin + hinteger = mul_res[11:0]; + cnt <= 12; + end + + 8: begin + div_num <= HDMI_WIDTH; + div_den <= hsize; + div_start <= 1; + end + // [1] 1920 / 720 -> 2 + // [2] 1920 / 640 -> 3 + // [3] 1920 / 512 -> 3 + + 9: begin + mul_arg1 <= hsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + // [1] 1920 / 720 * 720 -> 1440 + // [2] 1920 / 640 * 640 -> 1920 + // [3] 1920 / 512 * 512 -> 1536 + + 10: begin + hinteger <= mul_res[11:0]; + mul_arg1 <= vsize; + mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1; + mul_start <= 1; + end + + 11: begin + oheight <= mul_res[11:0]; + end + + 12: begin + wideres <= hinteger + hsize; + narrow <= ((htarget - hinteger) <= (wideres - htarget)) || (wideres > HDMI_WIDTH); + wres <= hinteger == htarget ? hinteger : wideres; + end + // [1] 1066 - 720 = 346 <= 1440 - 1066 = 374 || 1440 > 1920 -> true + // [2] 1280 - 1280 = 0 <= 1920 - 1280 = 640 || 1920 > 1920 -> true + // [3] 1365 - 1024 = 341 <= 1536 - 1365 = 171 || 1536 > 1920 -> false + // 1. narrow flag is true when mul_res[11:0] narrow width is closer to + // htarget aspect ratio target width or when wideres wider width + // does not fit to the screen. + // 2. wres becomes wideres only when mul_res[11:0] narrow width not equal + // to target width, meaning it is not optimal for source aspect ratio. + // otherwise it is set to narrow width that is optimal. + + 13: begin + case(SCALE) + 2: arxf <= {1'b1, hinteger}; + 3: arxf <= {1'b1, (wres > HDMI_WIDTH) ? hinteger : wres}; + 4: arxf <= {1'b1, narrow ? hinteger : wres}; + default: arxf <= {1'b1, div_num[11:0]}; + endcase + aryf <= {1'b1, oheight}; + end + endcase + end + + arx_o <= arxf; + ary_o <= aryf; +end + +endmodule diff --git a/sys/video_freezer.sv b/sys/video_freezer.sv new file mode 100644 index 0000000..cfbdf22 --- /dev/null +++ b/sys/video_freezer.sv @@ -0,0 +1,143 @@ +// +// video freeze with sync +// (C) Alexey Melnikov +// +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +module video_freezer +( + input clk, + + output sync, + input freeze, + + input hs_in, + input vs_in, + input hbl_in, + input vbl_in, + + output hs_out, + output vs_out, + output hbl_out, + output vbl_out +); + +sync_lock #(33) vs_lock +( + .clk(clk), + .sync_in(vs_in), + .sync_out(vs_out), + .de_in(vbl_in), + .de_out(vbl_out), + .freeze(freeze) +); + +wire sync_pt; +sync_lock #(21) hs_lock +( + .clk(clk), + .sync_in(hs_in), + .sync_out(hs_out), + .de_in(hbl_in), + .de_out(hbl_out), + .freeze(freeze), + .sync_pt(sync_pt) +); + +reg sync_o; +always @(posedge clk) begin + reg old_hs, old_vs; + reg vs_sync; + + old_vs <= vs_out; + + if(~old_vs & vs_out) vs_sync <= 1; + if(sync_pt & vs_sync) begin + vs_sync <= 0; + sync_o <= ~sync_o; + end +end + +assign sync = sync_o; + +endmodule + + +module sync_lock #(parameter WIDTH) +( + input clk, + + input sync_in, + input de_in, + + output sync_out, + output de_out, + + input freeze, + output sync_pt, + output valid +); + +reg [WIDTH-1:0] f_len, s_len, de_start, de_end; +reg sync_valid; + +reg old_sync; +always @(posedge clk) old_sync <= sync_in; + +always @(posedge clk) begin + reg [WIDTH-1:0] cnti; + reg f_valid; + reg old_de; + + cnti <= cnti + 1'd1; + if(~old_sync & sync_in) begin + if(sync_valid) f_len <= cnti; + f_valid <= 1; + sync_valid <= f_valid; + cnti <= 0; + end + + if(old_sync & ~sync_in & sync_valid) s_len <= cnti; + + old_de <= de_in; + if(~old_de & de_in & sync_valid) de_start <= cnti; + if(old_de & ~de_in & sync_valid) de_end <= cnti; + + if(freeze) {f_valid, sync_valid} <= 0; +end + +reg sync_o, de_o, sync_o_pre; +always @(posedge clk) begin + reg [WIDTH-1:0] cnto; + + cnto <= cnto + 1'd1; + if(old_sync & ~sync_in & sync_valid) cnto <= s_len + 2'd2; + if(cnto == f_len) cnto <= 0; + + sync_o_pre <= (cnto == (s_len>>1)); // middle in sync + if(cnto == f_len) sync_o <= 1; + if(cnto == s_len) sync_o <= 0; + if(cnto == de_start) de_o <= 1; + if(cnto == de_end) de_o <= 0; +end + +assign sync_out = freeze ? sync_o : sync_in; +assign valid = sync_valid; +assign sync_pt = sync_o_pre; +assign de_out = freeze ? de_o : de_in; + +endmodule diff --git a/sys/video_mixer.sv b/sys/video_mixer.sv new file mode 100644 index 0000000..fd0b08f --- /dev/null +++ b/sys/video_mixer.sv @@ -0,0 +1,219 @@ +// +// +// Copyright (c) 2017,2021 Alexey Melnikov +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels when HBlank = 0; +// HALF_DEPTH: If =1 then color dept is 4 bits per component +// +// altera message_off 10720 +// altera message_off 12161 + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + parameter GAMMA = 0 +) +( + input CLK_VIDEO, // should be multiple by (ce_pix*4) + output reg CE_PIXEL, // output pixel clock enable + + input ce_pix, // input pixel clock or clock_enable + + input scandoubler, + input hq2x, // high quality 2x scaling + + inout [21:0] gamma_bus, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Positive pulses. + input HSync, + input VSync, + input HBlank, + input VBlank, + + // Freeze engine + // HDMI: displays last frame + // VGA: black screen with HSync and VSync + input HDMI_FREEZE, + output freeze_sync, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output reg VGA_DE +); + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; +localparam DWIDTH_SD = GAMMA ? 7 : DWIDTH; +localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH; + +wire frz_hs, frz_vs; +wire frz_hbl, frz_vbl; +video_freezer freezer +( + .clk(CLK_VIDEO), + .freeze(HDMI_FREEZE), + .hs_in(HSync), + .vs_in(VSync), + .hbl_in(HBlank), + .vbl_in(VBlank), + .sync(freeze_sync), + .hs_out(frz_hs), + .vs_out(frz_vs), + .hbl_out(frz_hbl), + .vbl_out(frz_vbl) +); + +reg frz; +always @(posedge CLK_VIDEO) begin + reg frz1; + + frz1 <= HDMI_FREEZE; + frz <= frz1; +end + +generate + if(GAMMA && HALF_DEPTH) begin + wire [7:0] R_in = frz ? 8'd0 : {R,R}; + wire [7:0] G_in = frz ? 8'd0 : {G,G}; + wire [7:0] B_in = frz ? 8'd0 : {B,B}; + end else begin + wire [DWIDTH:0] R_in = frz ? 1'd0 : R; + wire [DWIDTH:0] G_in = frz ? 1'd0 : G; + wire [DWIDTH:0] B_in = frz ? 1'd0 : B; + end +endgenerate + +wire hs_g, vs_g; +wire hb_g, vb_g; +wire [DWIDTH_SD:0] R_gamma, G_gamma, B_gamma; + +generate + if(GAMMA) begin + assign gamma_bus[21] = 1; + gamma_corr gamma( + .clk_sys(gamma_bus[20]), + .clk_vid(CLK_VIDEO), + .ce_pix(ce_pix), + + .gamma_en(gamma_bus[19]), + .gamma_wr(gamma_bus[18]), + .gamma_wr_addr(gamma_bus[17:8]), + .gamma_value(gamma_bus[7:0]), + + .HSync(frz_hs), + .VSync(frz_vs), + .HBlank(frz_hbl), + .VBlank(frz_vbl), + .RGB_in({R_in,G_in,B_in}), + + .HSync_out(hs_g), + .VSync_out(vs_g), + .HBlank_out(hb_g), + .VBlank_out(vb_g), + .RGB_out({R_gamma,G_gamma,B_gamma}) + ); + end else begin + assign gamma_bus[21] = 0; + assign {R_gamma,G_gamma,B_gamma} = {R_in,G_in,B_in}; + assign {hs_g, vs_g, hb_g, vb_g} = {frz_hs, frz_vs, frz_hbl, frz_vbl}; + end +endgenerate + +wire [DWIDTH_SD:0] R_sd; +wire [DWIDTH_SD:0] G_sd; +wire [DWIDTH_SD:0] B_sd; +wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd +( + .clk_vid(CLK_VIDEO), + .hq2x(hq2x), + + .ce_pix(ce_pix), + .hs_in(hs_g), + .vs_in(vs_g), + .hb_in(hb_g), + .vb_in(vb_g), + .r_in(R_gamma), + .g_in(G_gamma), + .b_in(B_gamma), + + .ce_pix_out(ce_pix_sd), + .hs_out(hs_sd), + .vs_out(vs_sd), + .hb_out(hb_sd), + .vb_out(vb_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH_SD:0] rt = (scandoubler ? R_sd : R_gamma); +wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma); +wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma); + +always @(posedge CLK_VIDEO) begin + reg [7:0] r,g,b; + reg hde,vde,hs,vs, old_vs; + reg old_hde; + reg old_ce; + reg ce_osc, fs_osc; + + old_ce <= ce_pix; + ce_osc <= ce_osc | (old_ce ^ ce_pix); + + old_vs <= vs; + if(~old_vs & vs) begin + fs_osc <= ce_osc; + ce_osc <= 0; + end + + CE_PIXEL <= scandoubler ? ce_pix_sd : fs_osc ? (~old_ce & ce_pix) : ce_pix; + + if(!GAMMA && HALF_DEPTH) begin + r <= {rt,rt}; + g <= {gt,gt}; + b <= {bt,bt}; + end + else begin + r <= rt; + g <= gt; + b <= bt; + end + + hde <= scandoubler ? ~hb_sd : ~hb_g; + vde <= scandoubler ? ~vb_sd : ~vb_g; + vs <= scandoubler ? vs_sd : vs_g; + hs <= scandoubler ? hs_sd : hs_g; + + if(CE_PIXEL) begin + VGA_R <= r; + VGA_G <= g; + VGA_B <= b; + + VGA_VS <= vs; + VGA_HS <= hs; + + old_hde <= hde; + if(old_hde ^ hde) VGA_DE <= vde & hde; + end +end + +endmodule diff --git a/sys/yc_out.sv b/sys/yc_out.sv new file mode 100644 index 0000000..984fc37 --- /dev/null +++ b/sys/yc_out.sv @@ -0,0 +1,233 @@ +//============================================================================ +// YC - Luma / Chroma Generation +// Copyright (C) 2022 Mike Simone +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +//============================================================================ +/* +Colorspace +Y 0.299R' + 0.587G' + 0.114B' +U 0.492(B' - Y) = 504 (X 1024) +V 0.877(R' - Y) = 898 (X 1024) +*/ +////////////////////////////////////////////////////////// + +module yc_out +( + input clk, + input [39:0] PHASE_INC, + input PAL_EN, + input CVBS, + input [16:0] COLORBURST_RANGE, + + input hsync, + input vsync, + input csync, + input de, + + input [23:0] din, + output [23:0] dout, + + output reg hsync_o, + output reg vsync_o, + output reg csync_o, + output reg de_o +); + +wire [7:0] red = din[23:16]; +wire [7:0] green = din[15:8]; +wire [7:0] blue = din[7:0]; + +logic [9:0] red_1, blue_1, green_1, red_2, blue_2, green_2; + +logic signed [20:0] yr = 0, yb = 0, yg = 0; + +typedef struct { + logic signed [20:0] y; + logic signed [20:0] c; + logic signed [20:0] u; + logic signed [20:0] v; + logic hsync; + logic vsync; + logic csync; + logic de; +} phase_t; + +localparam MAX_PHASES = 7'd8; + +phase_t phase[MAX_PHASES]; +reg unsigned [7:0] Y, C, c, U, V; + + +reg [10:0] cburst_phase; // colorburst counter +reg unsigned [7:0] vref = 'd128; // Voltage reference point (Used for Chroma) +logic [7:0] chroma_LUT_COS; // Chroma cos LUT reference +logic [7:0] chroma_LUT_SIN; // Chroma sin LUT reference +logic [7:0] chroma_LUT_BURST; // Chroma colorburst LUT reference +logic [7:0] chroma_LUT = 8'd0; + +/* +THe following LUT table was calculated by Sin(2*pi*t/2^8) where t: 0 - 255 +*/ + +/************************************* + 8 bit Sine look up Table +**************************************/ +wire signed [10:0] chroma_SIN_LUT[256] = '{ + 11'h000, 11'h006, 11'h00C, 11'h012, 11'h018, 11'h01F, 11'h025, 11'h02B, 11'h031, 11'h037, 11'h03D, 11'h044, 11'h04A, 11'h04F, + 11'h055, 11'h05B, 11'h061, 11'h067, 11'h06D, 11'h072, 11'h078, 11'h07D, 11'h083, 11'h088, 11'h08D, 11'h092, 11'h097, 11'h09C, + 11'h0A1, 11'h0A6, 11'h0AB, 11'h0AF, 11'h0B4, 11'h0B8, 11'h0BC, 11'h0C1, 11'h0C5, 11'h0C9, 11'h0CC, 11'h0D0, 11'h0D4, 11'h0D7, + 11'h0DA, 11'h0DD, 11'h0E0, 11'h0E3, 11'h0E6, 11'h0E9, 11'h0EB, 11'h0ED, 11'h0F0, 11'h0F2, 11'h0F4, 11'h0F5, 11'h0F7, 11'h0F8, + 11'h0FA, 11'h0FB, 11'h0FC, 11'h0FD, 11'h0FD, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FF, 11'h0FE, 11'h0FE, 11'h0FE, 11'h0FD, 11'h0FD, + 11'h0FC, 11'h0FB, 11'h0FA, 11'h0F8, 11'h0F7, 11'h0F5, 11'h0F4, 11'h0F2, 11'h0F0, 11'h0ED, 11'h0EB, 11'h0E9, 11'h0E6, 11'h0E3, + 11'h0E0, 11'h0DD, 11'h0DA, 11'h0D7, 11'h0D4, 11'h0D0, 11'h0CC, 11'h0C9, 11'h0C5, 11'h0C1, 11'h0BC, 11'h0B8, 11'h0B4, 11'h0AF, + 11'h0AB, 11'h0A6, 11'h0A1, 11'h09C, 11'h097, 11'h092, 11'h08D, 11'h088, 11'h083, 11'h07D, 11'h078, 11'h072, 11'h06D, 11'h067, + 11'h061, 11'h05B, 11'h055, 11'h04F, 11'h04A, 11'h044, 11'h03D, 11'h037, 11'h031, 11'h02B, 11'h025, 11'h01F, 11'h018, 11'h012, + 11'h00C, 11'h006, 11'h000, 11'h7F9, 11'h7F3, 11'h7ED, 11'h7E7, 11'h7E0, 11'h7DA, 11'h7D4, 11'h7CE, 11'h7C8, 11'h7C2, 11'h7BB, + 11'h7B5, 11'h7B0, 11'h7AA, 11'h7A4, 11'h79E, 11'h798, 11'h792, 11'h78D, 11'h787, 11'h782, 11'h77C, 11'h777, 11'h772, 11'h76D, + 11'h768, 11'h763, 11'h75E, 11'h759, 11'h754, 11'h750, 11'h74B, 11'h747, 11'h743, 11'h73E, 11'h73A, 11'h736, 11'h733, 11'h72F, + 11'h72B, 11'h728, 11'h725, 11'h722, 11'h71F, 11'h71C, 11'h719, 11'h716, 11'h714, 11'h712, 11'h70F, 11'h70D, 11'h70B, 11'h70A, + 11'h708, 11'h707, 11'h705, 11'h704, 11'h703, 11'h702, 11'h702, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, 11'h701, + 11'h702, 11'h702, 11'h703, 11'h704, 11'h705, 11'h707, 11'h708, 11'h70A, 11'h70B, 11'h70D, 11'h70F, 11'h712, 11'h714, 11'h716, + 11'h719, 11'h71C, 11'h71F, 11'h722, 11'h725, 11'h728, 11'h72B, 11'h72F, 11'h733, 11'h736, 11'h73A, 11'h73E, 11'h743, 11'h747, + 11'h74B, 11'h750, 11'h754, 11'h759, 11'h75E, 11'h763, 11'h768, 11'h76D, 11'h772, 11'h777, 11'h77C, 11'h782, 11'h787, 11'h78D, + 11'h792, 11'h798, 11'h79E, 11'h7A4, 11'h7AA, 11'h7B0, 11'h7B5, 11'h7BB, 11'h7C2, 11'h7C8, 11'h7CE, 11'h7D4, 11'h7DA, 11'h7E0, + 11'h7E7, 11'h7ED, 11'h7F3, 11'h7F9 +}; + +logic [39:0] phase_accum; +logic PAL_FLIP = 1'd0; +logic PAL_line_count = 1'd0; + +/************************************** + Generate Luma and Chroma Signals +***************************************/ + +always_ff @(posedge clk) begin + for (logic [3:0] x = 0; x < (MAX_PHASES - 1'd1); x = x + 1'd1) begin + phase[x + 1] <= phase[x]; + end + + // delay red / blue signals to align luma with U/V calculation (Fixes colorbleeding) + red_1 <= red; + blue_1 <= blue; + red_2 <= red_1; + blue_2 <= blue_1; + + // Calculate Luma signal + yr <= {red, 8'd0} + {red, 5'd0}+ {red, 4'd0} + {red, 1'd0}; + yg <= {green, 9'd0} + {green, 6'd0} + {green, 4'd0} + {green, 3'd0} + green; + yb <= {blue, 6'd0} + {blue, 5'd0} + {blue, 4'd0} + {blue, 2'd0} + blue; + phase[0].y <= yr + yg + yb; + + // Generate the LUT values using the phase accumulator reference. + phase_accum <= phase_accum + PHASE_INC; + chroma_LUT <= phase_accum[39:32]; + + // Adjust SINE carrier reference for PAL (Also adjust for PAL Switch) + if (PAL_EN) begin + if (PAL_FLIP) + chroma_LUT_BURST <= chroma_LUT + 8'd160; + else + chroma_LUT_BURST <= chroma_LUT + 8'd96; + end else // Adjust SINE carrier reference for NTSC + chroma_LUT_BURST <= chroma_LUT + 8'd128; + + // Prepare LUT values for sin / cos (+90 degress) + chroma_LUT_SIN <= chroma_LUT; + chroma_LUT_COS <= chroma_LUT + 8'd64; + + // Calculate for U, V - Bit Shift Multiple by u = by * 1024 x 0.492 = 504, v = ry * 1024 x 0.877 = 898 + phase[0].u <= $signed({2'b0 ,(blue_2)}) - $signed({2'b0 ,phase[0].y[17:10]}); + phase[0].v <= $signed({2'b0 , (red_2)}) - $signed({2'b0 ,phase[0].y[17:10]}); + phase[1].u <= 21'($signed({phase[0].u, 8'd0}) + $signed({phase[0].u, 7'd0}) + $signed({phase[0].u, 6'd0}) + $signed({phase[0].u, 5'd0}) + $signed({phase[0].u, 4'd0}) + $signed({phase[0].u, 3'd0})); + phase[1].v <= 21'($signed({phase[0].v, 9'd0}) + $signed({phase[0].v, 8'd0}) + $signed({phase[0].v, 7'd0}) + $signed({phase[0].v, 1'd0})); + + phase[0].c <= vref; + phase[1].c <= phase[0].c; + phase[2].c <= phase[1].c; + phase[3].c <= phase[2].c; + + if (hsync) begin // Reset colorburst counter, as well as the calculated cos / sin values. + cburst_phase <= 'd0; + phase[2].u <= 21'b0; + phase[2].v <= 21'b0; + phase[4].c <= phase[3].c; + + if (PAL_line_count) begin + PAL_FLIP <= ~PAL_FLIP; + PAL_line_count <= ~PAL_line_count; + end + end + else begin // Generate Colorburst for 9 cycles + if (cburst_phase >= COLORBURST_RANGE[16:10] && cburst_phase <= COLORBURST_RANGE[9:0]) begin // Start the color burst signal at 40 samples or 0.9 us + // COLORBURST SIGNAL GENERATION (9 CYCLES ONLY or between count 40 - 240) + phase[2].u <= $signed({chroma_SIN_LUT[chroma_LUT_BURST],5'd0}); + phase[2].v <= 21'b0; + + // Division to scale down the results to fit 8 bit. + if (PAL_EN) + phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]); + else + phase[3].u <= $signed(phase[2].u[20:8]) + $signed(phase[2].u[20:11]) + $signed(phase[2].u[20:12]) + $signed(phase[2].u[20:13]); + + phase[3].v <= phase[2].v; + end else begin // MODULATE U, V for chroma + /* + U,V are both multiplied by 1024 earlier to scale for the decimals in the YUV colorspace conversion. + U and V are both divided by 2^10 which introduce chroma subsampling of 4:1:1 (25% or from 8 bit to 6 bit) + */ + phase[2].u <= $signed((phase[1].u)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_SIN]); + phase[2].v <= $signed((phase[1].v)>>>10) * $signed(chroma_SIN_LUT[chroma_LUT_COS]); + + // Divide U*sin(wt) and V*cos(wt) to fit results to 8 bit + phase[3].u <= $signed(phase[2].u[20:9]) + $signed(phase[2].u[20:10]) + $signed(phase[2].u[20:14]); + phase[3].v <= $signed(phase[2].v[20:9]) + $signed(phase[2].v[20:10]) + $signed(phase[2].u[20:14]); + end + + // Stop the colorburst timer as its only needed for the initial pulse + if (cburst_phase <= COLORBURST_RANGE[9:0]) + cburst_phase <= cburst_phase + 9'd1; + + // Calculate for chroma (Note: "PAL SWITCH" routine flips V * COS(Wt) every other line) + if (PAL_EN) begin + if (PAL_FLIP) + phase[4].c <= vref + phase[3].u - phase[3].v; + else + phase[4].c <= vref + phase[3].u + phase[3].v; + PAL_line_count <= 1'd1; + end else + phase[4].c <= vref + phase[3].u + phase[3].v; + end + + // Adjust sync timing correctly + phase[1].hsync <= hsync; phase[1].vsync <= vsync; phase[1].csync <= csync; phase[1].de <= de; + phase[2].hsync <= phase[1].hsync; phase[2].vsync <= phase[1].vsync; phase[2].csync <= phase[1].csync; phase[2].de <= phase[1].de; + phase[3].hsync <= phase[2].hsync; phase[3].vsync <= phase[2].vsync; phase[3].csync <= phase[2].csync; phase[3].de <= phase[2].de; + phase[4].hsync <= phase[3].hsync; phase[4].vsync <= phase[3].vsync; phase[4].csync <= phase[3].csync; phase[4].de <= phase[3].de; + hsync_o <= phase[4].hsync; vsync_o <= phase[4].vsync; csync_o <= phase[4].csync; de_o <= phase[4].de; + + phase[1].y <= phase[0].y; phase[2].y <= phase[1].y; phase[3].y <= phase[2].y; phase[4].y <= phase[3].y; phase[5].y <= phase[4].y; + + // Set Chroma / Luma output + C <= CVBS ? 8'd0 : phase[4].c[7:0]; + Y <= CVBS ? ({1'b0, phase[5].y[17:11]} + {1'b0, phase[4].c[7:1]}) : phase[5].y[17:10]; +end + +assign dout = {C, Y, 8'd0}; + +endmodule +