mirror of
https://github.com/MiSTer-devel/Arcade-BubSys_MiSTer.git
synced 2026-05-24 03:01:37 +00:00
update 20241123
This commit is contained in:
40
.gitignore
vendored
Normal file
40
.gitignore
vendored
Normal file
@@ -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
|
||||
31
BubSys.qpf
Normal file
31
BubSys.qpf
Normal file
@@ -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"
|
||||
102
BubSys.qsf
Normal file
102
BubSys.qsf
Normal file
@@ -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
|
||||
4
BubSys.sdc
Normal file
4
BubSys.sdc
Normal file
@@ -0,0 +1,4 @@
|
||||
derive_pll_clocks
|
||||
derive_clock_uncertainty
|
||||
|
||||
# core specific constraints
|
||||
29
BubSys.srf
Normal file
29
BubSys.srf
Normal file
@@ -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 <targets> 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 ""}
|
||||
468
BubSys.sv
Normal file
468
BubSys.sv
Normal file
@@ -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
|
||||
339
LICENSE
Normal file
339
LICENSE
Normal file
@@ -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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
|
||||
<signature of Ty Coon>, 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.
|
||||
@@ -1 +1,2 @@
|
||||
# ikacore_Bubsys
|
||||
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.
|
||||
36
clean.bat
Normal file
36
clean.bat
Normal file
@@ -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
|
||||
22
cr_ie_info.json
Normal file
22
cr_ie_info.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
21
files.qip
Normal file
21
files.qip
Normal file
@@ -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
|
||||
|
||||
|
||||
BIN
resources/BubbleSystem_schematics.pdf
Normal file
BIN
resources/BubbleSystem_schematics.pdf
Normal file
Binary file not shown.
1406
rtl/BubSys_bbd8/BubSys_bbd8.v
Normal file
1406
rtl/BubSys_bbd8/BubSys_bbd8.v
Normal file
File diff suppressed because it is too large
Load Diff
25
rtl/BubSys_bbd8/D0_outbuffer.txt
Normal file
25
rtl/BubSys_bbd8/D0_outbuffer.txt
Normal file
File diff suppressed because one or more lines are too long
25
rtl/BubSys_bbd8/D1_outbuffer.txt
Normal file
25
rtl/BubSys_bbd8/D1_outbuffer.txt
Normal file
File diff suppressed because one or more lines are too long
26
rtl/BubSys_bbd8/D2_outbuffer.txt
Normal file
26
rtl/BubSys_bbd8/D2_outbuffer.txt
Normal file
File diff suppressed because one or more lines are too long
26
rtl/BubSys_bbd8/D3_outbuffer.txt
Normal file
26
rtl/BubSys_bbd8/D3_outbuffer.txt
Normal file
File diff suppressed because one or more lines are too long
61
rtl/BubSys_components/BubSys_PROM.v
Normal file
61
rtl/BubSys_components/BubSys_PROM.v
Normal file
@@ -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
|
||||
26
rtl/BubSys_components/BubSys_SRAM.v
Normal file
26
rtl/BubSys_components/BubSys_SRAM.v
Normal file
@@ -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
|
||||
746
rtl/BubSys_cpu.v
Normal file
746
rtl/BubSys_cpu.v
Normal file
@@ -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
|
||||
476
rtl/BubSys_emu.v
Normal file
476
rtl/BubSys_emu.v
Normal file
@@ -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
|
||||
511
rtl/BubSys_sound.v
Normal file
511
rtl/BubSys_sound.v
Normal file
@@ -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
|
||||
351
rtl/BubSys_top.v
Normal file
351
rtl/BubSys_top.v
Normal file
@@ -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
|
||||
9
rtl/GX400_video/GX400_video.qip
Normal file
9
rtl/GX400_video/GX400_video.qip
Normal file
@@ -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 ]
|
||||
1082
rtl/GX400_video/GX400_video.v
Normal file
1082
rtl/GX400_video/GX400_video.v
Normal file
File diff suppressed because it is too large
Load Diff
69
rtl/GX400_video/GX400_video_dram.v
Normal file
69
rtl/GX400_video/GX400_video_dram.v
Normal file
@@ -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
|
||||
72
rtl/GX400_video/GX400_video_sim.v
Normal file
72
rtl/GX400_video/GX400_video_sim.v
Normal file
@@ -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
|
||||
44
rtl/GX400_video/GX400_video_sram.v
Normal file
44
rtl/GX400_video/GX400_video_sram.v
Normal file
@@ -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
|
||||
228
rtl/GX400_video/K005290.v
Normal file
228
rtl/GX400_video/K005290.v
Normal file
@@ -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
|
||||
150
rtl/GX400_video/K005291.v
Normal file
150
rtl/GX400_video/K005291.v
Normal file
@@ -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
|
||||
301
rtl/GX400_video/K005292.v
Normal file
301
rtl/GX400_video/K005292.v
Normal file
@@ -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
|
||||
545
rtl/GX400_video/K005293.v
Normal file
545
rtl/GX400_video/K005293.v
Normal file
@@ -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
|
||||
167
rtl/GX400_video/K005294.v
Normal file
167
rtl/GX400_video/K005294.v
Normal file
@@ -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
|
||||
1657
rtl/GX400_video/K005295.v
Normal file
1657
rtl/GX400_video/K005295.v
Normal file
File diff suppressed because it is too large
Load Diff
1
rtl/GX400_video/debug_bitmap_header.txt
Normal file
1
rtl/GX400_video/debug_bitmap_header.txt
Normal file
@@ -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
|
||||
1
rtl/GX400_video/debug_resnet_level.txt
Normal file
1
rtl/GX400_video/debug_resnet_level.txt
Normal file
@@ -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
|
||||
1530
rtl/ipcores/K005297/K005297.v
Normal file
1530
rtl/ipcores/K005297/K005297.v
Normal file
File diff suppressed because it is too large
Load Diff
93
rtl/ipcores/K005297/K005297_abspgcntr.v
Normal file
93
rtl/ipcores/K005297/K005297_abspgcntr.v
Normal file
@@ -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
|
||||
37
rtl/ipcores/K005297/K005297_accmodeflag.v
Normal file
37
rtl/ipcores/K005297/K005297_accmodeflag.v
Normal file
@@ -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
|
||||
69
rtl/ipcores/K005297/K005297_bubctrlfe.v
Normal file
69
rtl/ipcores/K005297/K005297_bubctrlfe.v
Normal file
@@ -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
|
||||
81
rtl/ipcores/K005297/K005297_bubrdfe.v
Normal file
81
rtl/ipcores/K005297/K005297_bubrdfe.v
Normal file
@@ -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
|
||||
69
rtl/ipcores/K005297/K005297_bubwrfe.v
Normal file
69
rtl/ipcores/K005297/K005297_bubwrfe.v
Normal file
@@ -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
|
||||
53
rtl/ipcores/K005297/K005297_busctrlfe.v
Normal file
53
rtl/ipcores/K005297/K005297_busctrlfe.v
Normal file
@@ -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
|
||||
68
rtl/ipcores/K005297/K005297_byteacqcntr.v
Normal file
68
rtl/ipcores/K005297/K005297_byteacqcntr.v
Normal file
@@ -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
|
||||
63
rtl/ipcores/K005297/K005297_cyclecntr.v
Normal file
63
rtl/ipcores/K005297/K005297_cyclecntr.v
Normal file
@@ -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
|
||||
72
rtl/ipcores/K005297/K005297_dlcntr.v
Normal file
72
rtl/ipcores/K005297/K005297_dlcntr.v
Normal file
@@ -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
|
||||
80
rtl/ipcores/K005297/K005297_dleval.v
Normal file
80
rtl/ipcores/K005297/K005297_dleval.v
Normal file
@@ -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
|
||||
115
rtl/ipcores/K005297/K005297_dmaaddrcntr.v
Normal file
115
rtl/ipcores/K005297/K005297_dmaaddrcntr.v
Normal file
@@ -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
|
||||
79
rtl/ipcores/K005297/K005297_dmadreg.v
Normal file
79
rtl/ipcores/K005297/K005297_dmadreg.v
Normal file
@@ -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
|
||||
130
rtl/ipcores/K005297/K005297_dmadregldctrl.v
Normal file
130
rtl/ipcores/K005297/K005297_dmadregldctrl.v
Normal file
@@ -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
|
||||
97
rtl/ipcores/K005297/K005297_dmafe.v
Normal file
97
rtl/ipcores/K005297/K005297_dmafe.v
Normal file
@@ -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
|
||||
148
rtl/ipcores/K005297/K005297_dmatiming.v
Normal file
148
rtl/ipcores/K005297/K005297_dmatiming.v
Normal file
@@ -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
|
||||
355
rtl/ipcores/K005297/K005297_fsm.v
Normal file
355
rtl/ipcores/K005297/K005297_fsm.v
Normal file
@@ -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
|
||||
128
rtl/ipcores/K005297/K005297_functrig.v
Normal file
128
rtl/ipcores/K005297/K005297_functrig.v
Normal file
@@ -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
|
||||
48
rtl/ipcores/K005297/K005297_invalpgdet.v
Normal file
48
rtl/ipcores/K005297/K005297_invalpgdet.v
Normal file
@@ -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
|
||||
115
rtl/ipcores/K005297/K005297_invalpgdgen.v
Normal file
115
rtl/ipcores/K005297/K005297_invalpgdgen.v
Normal file
@@ -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
|
||||
52
rtl/ipcores/K005297/K005297_mskldtimer.v
Normal file
52
rtl/ipcores/K005297/K005297_mskldtimer.v
Normal file
@@ -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
|
||||
66
rtl/ipcores/K005297/K005297_mskreg.v
Normal file
66
rtl/ipcores/K005297/K005297_mskreg.v
Normal file
@@ -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
|
||||
112
rtl/ipcores/K005297/K005297_pgcmp.v
Normal file
112
rtl/ipcores/K005297/K005297_pgcmp.v
Normal file
@@ -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
|
||||
77
rtl/ipcores/K005297/K005297_pgreg.v
Normal file
77
rtl/ipcores/K005297/K005297_pgreg.v
Normal file
@@ -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
|
||||
180
rtl/ipcores/K005297/K005297_primitives.v
Normal file
180
rtl/ipcores/K005297/K005297_primitives.v
Normal file
@@ -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
|
||||
93
rtl/ipcores/K005297/K005297_relpgcntr.v
Normal file
93
rtl/ipcores/K005297/K005297_relpgcntr.v
Normal file
@@ -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
|
||||
91
rtl/ipcores/K005297/K005297_spdet.v
Normal file
91
rtl/ipcores/K005297/K005297_spdet.v
Normal file
@@ -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
|
||||
124
rtl/ipcores/K005297/K005297_sumcmp.v
Normal file
124
rtl/ipcores/K005297/K005297_sumcmp.v
Normal file
@@ -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
|
||||
84
rtl/ipcores/K005297/K005297_supbdlcntr.v
Normal file
84
rtl/ipcores/K005297/K005297_supbdlcntr.v
Normal file
@@ -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
|
||||
291
rtl/ipcores/K005297/K005297_supervisor.v
Normal file
291
rtl/ipcores/K005297/K005297_supervisor.v
Normal file
@@ -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
|
||||
49
rtl/ipcores/K005297/K005297_tempdet.v
Normal file
49
rtl/ipcores/K005297/K005297_tempdet.v
Normal file
@@ -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
|
||||
107
rtl/ipcores/K005297/K005297_timer25k.v
Normal file
107
rtl/ipcores/K005297/K005297_timer25k.v
Normal file
@@ -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
|
||||
138
rtl/ipcores/K005297/K005297_z14eval.v
Normal file
138
rtl/ipcores/K005297/K005297_z14eval.v
Normal file
@@ -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
|
||||
5
rtl/ipcores/fx68k/fx68k.qip
Normal file
5
rtl/ipcores/fx68k/fx68k.qip
Normal file
@@ -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 ]
|
||||
2709
rtl/ipcores/fx68k/fx68k.sv
Normal file
2709
rtl/ipcores/fx68k/fx68k.sv
Normal file
File diff suppressed because it is too large
Load Diff
87
rtl/ipcores/fx68k/fx68k.txt
Normal file
87
rtl/ipcores/fx68k/fx68k.txt
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
|
||||
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
|
||||
839
rtl/ipcores/fx68k/fx68kAlu.sv
Normal file
839
rtl/ipcores/fx68k/fx68kAlu.sv
Normal file
@@ -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
|
||||
1024
rtl/ipcores/fx68k/microrom.mem
Normal file
1024
rtl/ipcores/fx68k/microrom.mem
Normal file
File diff suppressed because it is too large
Load Diff
336
rtl/ipcores/fx68k/nanorom.mem
Normal file
336
rtl/ipcores/fx68k/nanorom.mem
Normal file
@@ -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
|
||||
2192
rtl/ipcores/fx68k/uaddrPla.sv
Normal file
2192
rtl/ipcores/fx68k/uaddrPla.sv
Normal file
File diff suppressed because it is too large
Load Diff
56
rtl/ipcores/jt49/filter/jt49_dcrm.v
Normal file
56
rtl/ipcores/jt49/filter/jt49_dcrm.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
64
rtl/ipcores/jt49/filter/jt49_dcrm2.v
Normal file
64
rtl/ipcores/jt49/filter/jt49_dcrm2.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
67
rtl/ipcores/jt49/filter/jt49_dly.v
Normal file
67
rtl/ipcores/jt49/filter/jt49_dly.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
60
rtl/ipcores/jt49/filter/jt49_mave.v
Normal file
60
rtl/ipcores/jt49/filter/jt49_mave.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
11
rtl/ipcores/jt49/jt49.qip
Normal file
11
rtl/ipcores/jt49/jt49.qip
Normal file
@@ -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]
|
||||
258
rtl/ipcores/jt49/jt49.v
Normal file
258
rtl/ipcores/jt49/jt49.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
105
rtl/ipcores/jt49/jt49_bus.v
Normal file
105
rtl/ipcores/jt49/jt49_bus.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
55
rtl/ipcores/jt49/jt49_cen.v
Normal file
55
rtl/ipcores/jt49/jt49_cen.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
52
rtl/ipcores/jt49/jt49_div.v
Normal file
52
rtl/ipcores/jt49/jt49_div.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
88
rtl/ipcores/jt49/jt49_eg.v
Normal file
88
rtl/ipcores/jt49/jt49_eg.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
205
rtl/ipcores/jt49/jt49_exp.v
Normal file
205
rtl/ipcores/jt49/jt49_exp.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
62
rtl/ipcores/jt49/jt49_noise.v
Normal file
62
rtl/ipcores/jt49/jt49_noise.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
105
rtl/ipcores/jtframe_sdram/jtframe_ram1_1slot.v
Normal file
105
rtl/ipcores/jtframe_sdram/jtframe_ram1_1slot.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
344
rtl/ipcores/jtframe_sdram/jtframe_rom.v
Normal file
344
rtl/ipcores/jtframe_sdram/jtframe_rom.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
168
rtl/ipcores/jtframe_sdram/jtframe_rom_2slots.v
Normal file
168
rtl/ipcores/jtframe_sdram/jtframe_rom_2slots.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
37
rtl/ipcores/jtframe_sdram/jtframe_rom_sync.v
Normal file
37
rtl/ipcores/jtframe_sdram/jtframe_rom_sync.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
271
rtl/ipcores/jtframe_sdram/jtframe_romrq.v
Normal file
271
rtl/ipcores/jtframe_sdram/jtframe_romrq.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<shortest) shortest <= cur;
|
||||
total <= total + cur;
|
||||
end
|
||||
first <= 0;
|
||||
cnt_en <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initial begin
|
||||
forever begin
|
||||
/* verilator lint_off STMTDLY */
|
||||
#16_666_667;
|
||||
/* verilator lint_on STMTDLY */
|
||||
if( !first )
|
||||
$display("Latency %m %2d - %2d - %2d",
|
||||
shortest, total/acc_cnt, longest );
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
`endif
|
||||
10
rtl/ipcores/jtframe_sdram/jtframe_sdram64.qip
Normal file
10
rtl/ipcores/jtframe_sdram/jtframe_sdram64.qip
Normal file
@@ -0,0 +1,10 @@
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_sdram64.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_sdram64_bank.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_sdram64_init.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_sdram64_rfsh.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_sdram64_latch.v ]
|
||||
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_ram1_1slot.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_rom_2slots.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_romrq.v ]
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jtframe_rom.v ]
|
||||
603
rtl/ipcores/jtframe_sdram/jtframe_sdram64.v
Normal file
603
rtl/ipcores/jtframe_sdram/jtframe_sdram64.v
Normal file
@@ -0,0 +1,603 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
256
rtl/ipcores/jtframe_sdram/jtframe_sdram64_bank.v
Normal file
256
rtl/ipcores/jtframe_sdram/jtframe_sdram64_bank.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<<ACT;
|
||||
if(do_read ) next_st = ONE<<READ;
|
||||
end
|
||||
if( ( st[PRE_RD] && bg && !all_dqm ) ||
|
||||
( st[PRE_ACT] && bg && !all_dqm && !all_act) ||
|
||||
( !st[IDLE] && !st[PRE_ACT] && !st[PRE_RD] ) )
|
||||
next_st = rot_st;
|
||||
if( st[READ] && wr && !AUTOPRECH)
|
||||
next_st = 1; // writes finish earlier
|
||||
end
|
||||
|
||||
wire row_match = match && actd && !AUTOPRECH[0];
|
||||
|
||||
always @(*) begin
|
||||
do_prech = 0;
|
||||
do_act = 0;
|
||||
do_read = 0;
|
||||
if( bg ) begin
|
||||
do_prech = !prechd && !row_match // not a good address
|
||||
&& (st[IDLE]&&rd_wr);
|
||||
|
||||
do_act = ((st[IDLE] & rd_wr & prechd & ~actd) | st[PRE_ACT])
|
||||
& ~all_act & ~all_dqm;
|
||||
|
||||
do_read = ((st[IDLE] & rd_wr & row_match) | st[PRE_RD]) &
|
||||
(~all_dbusy & (~all_dbusy64 | rd) & ~all_dqm);
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
if( HF==1 ) begin
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
br <= 0;
|
||||
end else begin
|
||||
br <= 0;
|
||||
if( (st[IDLE] || next_st[IDLE] || next_st[PRE_ACT] || next_st[PRE_RD]) && rd_wr ) begin
|
||||
br <= 1;
|
||||
if( next_st[PRE_RD] & (all_dbusy | (all_dbusy64&wr)) ) br <= 0; // Do not try to request
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
always @(*) begin
|
||||
br = 0;
|
||||
if( (st[IDLE] || st[PRE_ACT] || st[PRE_RD]) && rd_wr ) begin
|
||||
br = 1;
|
||||
if( st[PRE_RD] & (all_dbusy | (all_dbusy64&wr)) ) br = 0; // Do not try to request
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// module outputs
|
||||
always @(*) begin
|
||||
wr_busy = do_read & wr;
|
||||
cmd = do_prech ? CMD_PRECHARGE : (
|
||||
do_act ? CMD_ACTIVE : (
|
||||
do_read ? (rd ? CMD_READ : CMD_WRITE ) : CMD_NOP ));
|
||||
sdram_a[12:11] = addr_row[12:11];
|
||||
sdram_a[10:0] = do_act ? addr_row[10:0] :
|
||||
{ do_read ? AUTOPRECH[0] : PRECHARGE_ALL[0], addr[AW-1], addr[8:0]};
|
||||
end
|
||||
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
prechd <= 0;
|
||||
actd <= 0;
|
||||
row <= 0;
|
||||
st <= 1; // IDLE
|
||||
last_act <= 0;
|
||||
written <= 0;
|
||||
end else begin
|
||||
st <= next_st;
|
||||
if( do_act ) begin
|
||||
post_act <= 1;
|
||||
last_act <= 1;
|
||||
end else begin
|
||||
last_act <= 0;
|
||||
post_act <= last_act;
|
||||
end
|
||||
|
||||
if( do_act ) begin
|
||||
row <= addr_row;
|
||||
prechd <= 0;
|
||||
actd <= 1;
|
||||
end
|
||||
|
||||
if( do_read ) written <= wr;
|
||||
else if(st[0]) written<=0;
|
||||
|
||||
if( do_prech || set_prech || (do_read && AUTOPRECH)) begin
|
||||
prechd <= 1;
|
||||
actd <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
98
rtl/ipcores/jtframe_sdram/jtframe_sdram64_init.v
Normal file
98
rtl/ipcores/jtframe_sdram/jtframe_sdram64_init.v
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
92
rtl/ipcores/jtframe_sdram/jtframe_sdram64_latch.v
Normal file
92
rtl/ipcores/jtframe_sdram/jtframe_sdram64_latch.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
119
rtl/ipcores/jtframe_sdram/jtframe_sdram64_rfsh.v
Normal file
119
rtl/ipcores/jtframe_sdram/jtframe_sdram64_rfsh.v
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<<CW)-1 ) begin
|
||||
$display("ERROR: RFSHCNT is too large for the size of CW (%m)");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
assign sdram_a = 13'h400; // used for precharging all banks
|
||||
|
||||
reg [CW-1:0] cnt;
|
||||
reg [STW-1:0] st;
|
||||
reg last_start;
|
||||
wire [CW:0] next_cnt;
|
||||
|
||||
assign next_cnt = {1'b0, cnt} + RFSHCNT[CW-1:0];
|
||||
|
||||
always @(posedge clk, posedge rst) begin
|
||||
if( rst ) begin
|
||||
st <= 1;
|
||||
cmd <= CMD_NOP;
|
||||
cnt <= 0;
|
||||
br <= 0;
|
||||
rfshing <= 0;
|
||||
help <= 0;
|
||||
end else begin
|
||||
// Forces a refresh if we have built up too much debt
|
||||
if( next_cnt[CW] )
|
||||
help <= 1;
|
||||
if( next_cnt[CW:CW-1]==0 ) // at least half the debt must go
|
||||
help <= 0;
|
||||
|
||||
last_start <= start;
|
||||
if( start && !last_start ) begin
|
||||
cnt <= help ? {CW{1'b1}} : next_cnt[CW-1:0]; // carry over from previous "frame"
|
||||
end
|
||||
if( cnt!=0 && !rfshing ) begin
|
||||
br <= 1;
|
||||
st <= 1;
|
||||
end
|
||||
if( bg ) begin
|
||||
br <= 0;
|
||||
rfshing <= 1;
|
||||
end
|
||||
if( rfshing || bg ) begin
|
||||
st <= { st[STW-2:0], st[STW-1] };
|
||||
end
|
||||
if( st[STW-1] ) begin
|
||||
if( cnt!=0 ) begin
|
||||
cnt <= cnt - 1'd1;
|
||||
if( !noreq ) begin
|
||||
rfshing <= 0;
|
||||
end else begin
|
||||
st <= ONE << RFRSH; // do another refresh cycle as there are no requests
|
||||
end
|
||||
end else begin
|
||||
rfshing <= 0;
|
||||
end
|
||||
end
|
||||
cmd <= st[0] ? CMD_PRECHARGE : ( st[RFRSH] ? CMD_REFRESH : CMD_NOP );
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
193
rtl/ipcores/k5289.v
Normal file
193
rtl/ipcores/k5289.v
Normal file
@@ -0,0 +1,193 @@
|
||||
//================================================================================
|
||||
// K0005289 Pre-SCC Wavetable Sound Generator
|
||||
//
|
||||
// Nemesis sound module
|
||||
// Copyright © 2020-2022 LMN-san (@LmnSama),
|
||||
// Olivier Scherler (@oscherler),
|
||||
// Raki (Sehyeon Kim, @RCAVictorCo)
|
||||
//
|
||||
// Commercial use is prohibited.
|
||||
//================================================================================
|
||||
|
||||
// CUSTOM CHIP pinout:
|
||||
/* _____________
|
||||
_| |_
|
||||
GND(0) |_|1 42|_| VCC
|
||||
_| |_
|
||||
A(0) |_|2 41|_| /RESET
|
||||
_| |_
|
||||
A(1) |_|3 40|_| 1QE(4)
|
||||
_| |_
|
||||
A(2) |_|4 39|_| 1QD(3)
|
||||
_| |_
|
||||
A(3) |_|5 38|_| 1QC(2)
|
||||
_| |_
|
||||
A(4) |_|6 37|_| 1QB(1)
|
||||
_| |_
|
||||
A(5) |_|7 36|_| 1QA(0)
|
||||
_| |_
|
||||
A(6) |_|8 35|_| 2QE(4)
|
||||
_| |_
|
||||
A(7) |_|9 34|_| 2QD(3)
|
||||
_| |_
|
||||
A(8) |_|10 8A 33|_| 2QC(2)
|
||||
_| |_
|
||||
A(9) |_|11 32|_| 2QB(1)
|
||||
_| |_
|
||||
A(10) |_|12 31|_| 2QA(0)
|
||||
_| |_
|
||||
A(11) |_|13 30|_| T1(connect to gnd)
|
||||
_| |_
|
||||
CLK() |_|14 29|_| T0(connect to gnd)
|
||||
_| |_
|
||||
LD1() |_|15 28|_|
|
||||
_| |_
|
||||
TG1() |_|16 27|_|
|
||||
_| |_
|
||||
LD2() |_|17 26|_|
|
||||
_| |_
|
||||
TG2() |_|18 25|_|
|
||||
_| |_
|
||||
|_|19 24|_|
|
||||
_| |_
|
||||
|_|20 23|_|
|
||||
_| |_
|
||||
GND |_|21 22|_| GND
|
||||
|_____________|
|
||||
*/
|
||||
|
||||
module K005289
|
||||
(
|
||||
input i_RST_n, // RESET signal
|
||||
input i_CLK, // Main clock
|
||||
input i_CEN, // Clock enable
|
||||
|
||||
input i_LD1, //
|
||||
input i_TG1, //
|
||||
|
||||
input i_LD2, //
|
||||
input i_TG2, //
|
||||
|
||||
input [11:0] i_COUNTER, // 12 bits input counter to play frequency
|
||||
|
||||
output [4:0] o_Q1, // 5 bits output
|
||||
output [4:0] o_Q2 // 5 bits output
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wire [11:0] addrLD1, addrTG1, addrLD2, addrTG2;
|
||||
|
||||
// the 17 bits counters will serve 2 purposes count on the lower part on 12 bits and output
|
||||
// the accumulated upper 5 bits part
|
||||
reg [16:0] r_count1, r_count2;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Channel 1 LATCH
|
||||
|
||||
|
||||
bus_ff #( .W( 12 ) ) ch1_ld_latch(
|
||||
.rst ( ~i_RST_n ),
|
||||
.clk ( i_CLK ),
|
||||
.trig ( ~i_LD1 ),
|
||||
.d ( i_COUNTER ),
|
||||
.q ( addrLD1 ),
|
||||
.q_n ( )
|
||||
);
|
||||
|
||||
bus_ff #( .W( 12 ) ) ch1_tg_latch(
|
||||
.rst ( ~i_RST_n ),
|
||||
.clk ( i_CLK ),
|
||||
.trig ( ~i_TG1 ),
|
||||
.d ( addrLD1 ),
|
||||
.q ( addrTG1 ),
|
||||
.q_n ( )
|
||||
);
|
||||
|
||||
// Channel 2 LATCH
|
||||
|
||||
bus_ff #( .W( 12 ) ) ch2_ld_latch(
|
||||
.rst ( ~i_RST_n ),
|
||||
.clk ( i_CLK ),
|
||||
.trig ( ~i_LD2 ),
|
||||
.d ( i_COUNTER ),
|
||||
.q ( addrLD2 ),
|
||||
.q_n ( )
|
||||
);
|
||||
|
||||
bus_ff #( .W( 12 ) ) ch2_tg_latch(
|
||||
.rst ( ~i_RST_n ),
|
||||
.clk ( i_CLK ),
|
||||
.trig ( ~i_TG2 ),
|
||||
.d ( addrLD2 ),
|
||||
.q ( addrTG2 ),
|
||||
.q_n ( )
|
||||
);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Channel 1 COUNTERS
|
||||
|
||||
// addrTG1 = IN : 12 bits data input
|
||||
// i_CLK = IN : clock input
|
||||
// i_CEN = IN : clock enable
|
||||
// i_RST_n = IN : reset at 0
|
||||
always @( posedge i_CLK ) begin
|
||||
if (~i_RST_n) begin // if n_reset = 0
|
||||
r_count1 <= 17'd0; // 12 bits + 5 bits for the counter output
|
||||
r_count2 <= 17'd0; // 12 bits + 5 bits for the counter output
|
||||
end else if (i_CEN) begin // if i_CEN pulse = 1
|
||||
// COUNTER 1
|
||||
if(r_count1[11:0] == 12'hFFF) begin
|
||||
r_count1 <= r_count1 + 17'd1; // we need to add 1 before the re-set of the lower value to be sure we increment the upper part for the output
|
||||
r_count1[11:0] <= addrTG1; // re-set to the tone in addrTG1 memory register
|
||||
end else begin
|
||||
r_count1 <= r_count1 + 17'd1;
|
||||
end
|
||||
|
||||
// COUNTER 2
|
||||
if(r_count2[11:0] == 12'hFFF) begin
|
||||
r_count2 <= r_count2 + 17'd1; // we need to add 1 before the re-set of the lower value to be sure we increment the upper part for the output
|
||||
r_count2[11:0] <= addrTG2; // re-set to the tone in addrTG2 memory register
|
||||
end else begin
|
||||
r_count2 <= r_count2 + 17'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign o_Q1 = r_count1[16:12]; // we output only the upper part of the counter
|
||||
assign o_Q2 = r_count2[16:12]; // we output only the upper part of the counter
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
module bus_ff #( parameter W=1 ) (
|
||||
input clk,
|
||||
input rst,
|
||||
input trig,
|
||||
input [W-1:0] d,
|
||||
|
||||
output [W-1:0] q,
|
||||
output [W-1:0] q_n
|
||||
);
|
||||
|
||||
reg trig_prev;
|
||||
reg [W-1:0] state;
|
||||
|
||||
always @( posedge clk ) begin
|
||||
if( rst ) begin
|
||||
state <= {W{1'b0}};
|
||||
trig_prev <= 1'b1;
|
||||
end else begin
|
||||
if( trig & ~trig_prev ) begin
|
||||
state <= d;
|
||||
end
|
||||
|
||||
trig_prev <= trig;
|
||||
end
|
||||
end
|
||||
|
||||
assign q = state;
|
||||
assign q_n = ~state;
|
||||
|
||||
endmodule
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user